Search code examples
parsingcompiler-constructionbison

Bison zero or one occurrences in grammar file


I need to parse a JSON like object {"f": 1, "i": 2, "g": 5, ...} but unlike regular JSON object, the input can have zero or one occurrences in the object...

So, this is wrong object {"f": 1, "f": 1, "i": 2, ...} because it has the key "f twice".

And, this object is fine {"i": 2} because it has just the key "i" and it doesn't occur more than once.

Here is what I have tried. I know that it doesn't work, but I don't know how to set it to be right.

RuleMemberList
    : RuleMember
        {{$$ = {}; $$[$1[0]] = $1[1];}}
    | RuleMemberList ',' RuleMember
        {$$ = $1; $1[$3[0]] = $3[1];}
    ;

RuleMember
    : I ':' RuleString
          {$$ = [$1, $3];}
    | G ':' RuleString
          {$$ = [$1, $3];}
    | F ':' RuleFinder
          {$$ = [$1, $3];}
    | A ':' RuleAction
          {$$ = [$1, $3];}
    | T ':' RuleTarget
          {$$ = [$1, $3];}
    | P ':' RuleNumber
          {$$ = [$1, $3];}
    | C ':' RuleChance
          {$$ = [$1, $3];}
    | L ':' RuleLayers
          {$$ = [$1, $3];}
    | R ':' RuleString
          {$$ = [$1, $3];}
    | E ':' RuleEvents
          {$$ = [$1, $3];}
    | B ':' RuleBinds
          {$$ = [$1, $3];}
    ;

Can I define it to be zero or one occurrences somehow?


Solution

  • Check for duplicates when adding elements to the map. Something like:

    | RuleMemberList ',' RuleMember
        { $$ = $1;
          if ($3[0] in $1)
            error("duplicate key ", $3[0], " in map");
          else
            $1[$3[0]] = $3[1];}
    ;