Search code examples
c++bisonsemantic-analysis

Bison if statements - setting symbol table prior to parsing block statements


In my language I have the ability to declare a variable in the current symbol table scope and also create a if statement which will generate a new symbol table scope for its statements.

stmts : stmt { $$ = new Block(); $$->addStatement($1); }
      | stmts stmt { $1->addStatement($2); }
      | /*blank*/ { $$ = new Block(); }
      ;

stmt : vardecl
     | ifstmt
     ;

ifstmt : TIF TLPAREN exprBase TRPAREN TOPENBLOCK stmts TCLOSEBLOCK {
                                                                     semanticAnalyzerParser->enterScope("if statement scope");
                                                                     $$ = new IfStatement($3, $7);
                                                                   }
       ;

assign :  ident ident TASSIGN exprBase {
                                        Var* typeName = $1;
                                        Var* varName = $2;
                                        ExpressionBase* exprBase = $4;
                                        semanticAnalyzerParser->getScope()->registerVariable(typeName->identifier, varName->identifier, exprBase);
                                        $$ = new VarDecl(typeName, varName, exprBase);
       }
       ;

What I'd like to do is set a new scope before bison enters the if statement block of statements. E.g. semanticAnalyzerParser->enterScope("if statement scope");, so that when grammar for declaring variables are recognised it will declare it on the correct scope with semanticAnalyzerParser->getScope()->registerVariable(typeName->identifier, varName->identifier, exprBase);

However, since bison has to recognise the complete grammar of a if statement, it only creates the scope after it finishes parsing and thus registers the variables on the wrong scope.

How can I execute code prior to parsing the stmts part of the ifstmt grammar, so that it can set the correct scope? I know that one option is to walk the AST tree afterwards but I want to avoid this since the ASTs to create in bison are largely determined by information gathered in the semantic analysis.


Solution

  • Usually you would do this with an "embedded" action:

    ifstmt : TIF TLPAREN exprBase TRPAREN {
                     semanticAnalyzerParser->enterScope("if statement scope"); }
             TOPENBLOCK stmts TCLOSEBLOCK {
                     semanticAnalyzerParser->leaveScope("if statement scope");
                     $$ = new IfStatement($3, $7); }
       ;
    

    The embedded action will be executed after the first part of the ifstmt is recognized (up to the TRPAREN, with the TOPENBLOCK as lookahead), before the body (stmts) is parsed.