C++ parse analysis Save and restore parser state 2019.03.18 Kei Hasegawa
Example 1 void f() { } int (n); // Declaration statement ... int (n+n); // Expression statement }
Derivation `int’ at Ex 1 (n+n); int (n); int simple-type-specifier decl-specifier If next token is ‘(‘ after simple-type-specifier, it’s not obvious remained program text is init-declarator-list or ‘(‘ expression-list ‘)’ decl-specifier-seq
Give priority to declaration rule Report file of yacc/bison State X1 R11 type_specifier: simple_type_specifier . R12 postfix_expression: simple_type_specifier . '(' expression_list ')' R13 | simple_type_specifier . '(' ')' '(' shift, and go to state Y1 '(' [reduce using rule R11 (type_specifier)] $default reduce using rule R11 (type_specifier) This says that for ‘(‘ after simple-type-specifier, R11 is not used.
Give priority to declaration rule (continue) Insert bellow code to `yyparse’ of appropriate location: if ( yystate == X1 && yychar == ‘(‘ ) { yyn = R11 + 1; goto yyreduce; } Of cause, this cause sytax error for function style cast.
Save parser state Again fix previous code: if (yystate == X1 && yychar == ‘(‘ ) { if (!retry[X1] ) { // At 1st time save(yystate, ...); // Save parser state yyn = R11 + 1; // parse as declaration goto yyreduce; }
Restore parser state Insert bellow code to `yyparse’ where calls `yyerror’: if (parser states are saved) { restore(&yystate, ...); // Restore parser state ++retry[yystate]; // Increment retry counter goto yynewstate; }
Also save tokens which cause 1st syntax error int get_token() { int ret = ... ... if (parser states are saved) { // Save token for retrying // Also save token’s property if it has. } return ret;
Ex 2 struct T { ... }; int a; ... T t1(); // Function declaration whose return type is `T’ T t2(a); // Type `T’ object definition initialized with `a’
Even though giving priority to functio declaration, ... Report file of yacc/bison State X2 R21 declarator: direct_declarator . R22 direct_declarator: direct_declarator . '(' parameter_declaration_clause ')' ... '(' shift, and go to state Y2 '(' [reduce using rule R21 (declarator)] $default reduce using rule R21 (declarator) This says that, for ‘(‘ after declarator, R21 is not used: Object definition of Ex 2 cause syntax error.
Save parser state Insert code to `yyparse’ of appropriate location: if (yystate == X2 && yychar == ‘(‘ ) { if (!retry[X2] ) // At 1st time save(yystate, ...); // Save parser state else { yyn = R21 + 1; goto yyreduce; }
Ex 3 double f(); void g(int a) { int(f())+a; }
int(f())+a; Reading ‘(‘ after `int’, yystate becomes X1. Reading ‘(‘ after `f’, yystate becomes X2. Reading ‘+‘, discard state saved at X2 , and restore state saved at X1 . Note that it’s not correct to add `f’ into symbol table.
Discard the last saved state Insert code to `yyparse’ of appropriate location: if (yystate == X2) { switch (yychar) { case ‘(‘ : case ‘[‘ : ... break; // Not cause syntax error as declaration default: if (The last state is saved at X2) { Discard the last saved state; goto yyerrlab; }