1

I have this grammar which is supposed to generate java byte code out of java code. I know this warning has been addressed before in many questions but I couldn't find a problem similar to mine. it displays out this warning for this two rules in particular:

statement_list: 
    {
        $<stmt_type>$.next = $<stmt_type>0.next;
    }
     statement 
    | 
    {
        $<stmt_type>$.next = strdup(genLabel().c_str());    //generate label for statement and assign it to statement list next
    }
    statement_list 
    {
        $<stmt_type>$.next = $<stmt_type>0.next;
        fout<<$<stmt_type>1.next<<":"<<endl;    //mark statement with statement list next label
    }
    statement 
    ;

and this one

b_expression:
expression RELA_OP expression       
    {$$ = $<bexpr_type>0;relaCast(string($2),$$.nTrue,$$.nFalse);}
|{/* addding some strings to this action */ } b_expression BOOL_OP b_expression

I need here to mark every statement with its next before parsing it to use it in code generation. when I remove the semantic actions from statement_list its error goes away, but I didn't try the same for b_expression.

mohRamadan
  • 571
  • 6
  • 15
  • If you leave out the actions, your `b_expression` rule is: `b_expression: /* empty */ | expression RELA_OP expression | b_expression`. The empty production is almost certainly wrong and the last production is obviously useless, since it is pure recursion. The problem with your `statement_list` production is certainly covered in the bison manual and probably in some duplicate question on SO. – rici May 16 '16 at 02:26
  • Such as [these questions](http://stackoverflow.com/search?q=[yacc]+or+[bison]+mid-rule+action+conflict) and [this manual chapter](https://www.gnu.org/software/bison/manual/bison.html#Mid_002dRule-Conflicts) – rici May 16 '16 at 04:41
  • first thanks for the manual I must have passed this part. for the b_expression something wrong happened when copying the question, now it has the correct grammar. – mohRamadan May 16 '16 at 22:31
  • b_expression still has an empty production, which cannot be right. If BOOL_OP doesn't have an associativity declaration, the third production will cause a shift/reduce conflict. – rici May 16 '16 at 23:39
  • another copying mistake ! sorry for this. – mohRamadan May 17 '16 at 21:10
  • I think you want to look at [this question](http://stackoverflow.com/questions/21276726/how-does-backpatching-work-with-markers) and its answer, and then the bison file in the project pointed to in that question (which seems to still exist). – rici May 17 '16 at 21:28
  • thanks, sadly I started this project (for compilers course) without reading about backpatching knowing that bison can be of help for that, but it didn't turn out good anyway. so I decided to deliver it late and start it over but with backpatching this time. another implementation I saw of this problem is to use stack which I think a very good solution, what do you think ? – mohRamadan May 17 '16 at 23:21
  • I'm not crazy about one-pass compilation. It's not 1990 any more and there are no resource constraints keeping you from constructing an entire AST and the walking it in any order(s) you want, which makes everything much cleaner. – rici May 17 '16 at 23:26
  • But if you are going to write a one-pass codegen, backpatching is quite straightforward. See the code in the bison file in the project referenced in that question. Also observe how they use an explicit marker rather than MRAs to avoid r/r conflicts, as suggested also in the bison manual. – rici May 17 '16 at 23:32
  • I read the first rules actually, empty rules are pretty neat way. thanks for the help. – mohRamadan May 17 '16 at 23:58
  • Thank you @rici for all the explanations and links in your comments - they helped me solve *my* problem today! – barfuin Mar 21 '21 at 13:03
  • @barfuin no thanks for the question author ? :P – mohRamadan Mar 31 '21 at 16:04

2 Answers2

3

Bison only looks ahead 1 token to decide which production to apply. Your two productions for statement both have code blocks before the parser has read any tokens to know which production is going to apply.

brian beuning
  • 2,836
  • 18
  • 22
  • so what's the solution if I have to pass some attributes to `statement` ? – mohRamadan May 16 '16 at 22:33
  • You can't pass attributes that way, because it causes conflicts. You need to do it some other way. What are you actually trying to do? Why do you need these attributes? Why can't you generate them in the `statement` rule after parsing the start of the statement? – Chris Dodd May 17 '16 at 04:35
  • first thanks for the help, comments helped. statement has to have a next label which will be used if statement goes to a conditional statement (if, while) so that every statement will know what label to got next. suppose we have and if { statement } else {statement } the first statement needs to know where to jump after finishing. – mohRamadan May 17 '16 at 21:15
  • @DragonKoko: usually you want labels *between* statements, and you create them in your `if` and `while` productions as needed, not in every statement. – Chris Dodd May 18 '16 at 00:23
1

If you're generating assembly-like stack code with labels directly in your yacc rules, you usually use something like:

if_statement: IF condition {
                      $$ = gen_label();
                      gen_code(JUMP_FALSE, $$); }
              THEN block {
                      $$ = gen_label();
                      gen_code(JUMP, $$);
                      gen_code(LABEL, $3); }
              ELSE block {
                      gen_code(LABEL, $6); }

while_statement: WHILE { gen_code(LABEL, $$ = gen_label()); }
                 condition { gen_code(JUMP_FALSE, $$ = gen_label); }
                 block { gen_code(JUMP, $2); gen_code(LABEL, $4); }

If you're generating byte-code directly, you don't have 'labels' as such -- when you generate a forward branch you remember the spot in the bytecode where the target offset should go and when you get to the spot where you would output the label, you backpatch the branch to jump to the current location.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226