Search code examples
cbisonglr

C Bison GLR const stack item


I started writing a simple LR(1) parser with Bison. When processing lists I used a simple implementation of a vector, for example when parsing a list of expressions:

tuple-expression-list: expression[first] ',' expression[second] { 
    foo_vector_init(&$$); 
    foo_vector_push_back(&$$, $first); 
    foo_vector_push_back(&$$, $second); }

tuple-expression-list: tuple-expression-list[list] ',' expression[expr] { 
    foo_vector_push_back(&$list, $expr); $$ = $list; }

This worked fine. But then the grammar changed and I had to go for the GLR parser. Suddenly the compiler complained about $list being constant. I found that for GLR parsers:

  1. when the parser splits actions are recorded and not executed until either:
    • all but one parsers have died
    • two parsers are merged
  2. One should never modify yyval in an action (which is the lookahead).

Questions:

  1. when I never have to merge am I sure that only the actions that result in the final parse are executed?
  2. Is assigning $list to a local variable first a valid fix or should I copy the vector deeply?

Solution

    1. when I never have to merge am I sure that only the actions that result in the final parse are executed?

    Yes. The documentation specifies that

    During the time that there are multiple parsers, semantic actions are recorded, but not performed. When a parser disappears, its recorded semantic actions disappear as well, and are never performed.

    The point is precisely that the semantic actions performed are (only) those associated with the actual reductions accepted for the overall parse.

    1. Is assigning $list to a local variable first a valid fix or should I copy the vector deeply?

    It's hard to be sure without knowing anything about your particular vector implementation, or about what other semantic actions are present in the grammar. Supposing that

    • such an assignment produces a shallow copy of the vector (as opposed, say, to a pointer or reference to the existing object), and that
    • the preceding contents of the vector are not subject to change in any possible line of reductions that performs the semantic action in question, and that
    • the copy, not the original, is presented as the semantic value of the action,

    a shallow copy should be sufficient.