Either I have tickled a bug, or there's a simple explanation. Below is a fragment of the current GCC Cobol grammar. (The compiler is based on gcc; it's not yet officially part of the project.)
search_1_cases is a recursive rule. It takes 1 or more occurences of search_1_case. Each search_1_case starts with the keyword WHEN. The grammar is meant to handle a series of phrases WHEN conditional search_stmts WHEN conditional search_stmts ... Parsing a sequence of those phrases, Bison reduces the first one according to the first (non-recursive) rule for search_1_cases. It reports the lookahead as WHEN. Instead of parsing the remaining WHEN phrases, it concludes the whole statement, and then complains the 2nd WHEN is invalid syntax. I don't understand how that's possible. Because WHEN heads every search_1_case rule, I think an LALR(1) parser would obviously choose the recursive path when WHEN is the lookahead token. FTR, WHEN has %right recursion, and lower precedence than search_stmts (which have dynamic %prec ADD precedence). In the interest of full disclosure, I am ignoring a shift/reduce warning regarding WHEN, but in a different part of the grammar, related to a different verb: > State 1008 > > 530 eval_switch: eval_whens ? > 532 eval_whens: eval_whens ? eval_when > > WHEN shift, and go to state 1005 > > WHEN [reduce using rule 530 (eval_switch)] > $default reduce using rule 530 (eval_switch) > > eval_when go to state 1312 > when go to state 1010 Testing shows Bison's preference for shift in that case results in correct behavior. Why might Bison behave the way it does for search_1_cases? Grammar fragment follows. --jkl [snip] search_1_cases: search_1_case { if( yydebug ) { const char *lookahead = "?"; switch( yychar ) { case 0: lookahead = "YYEOF"; break; case -2: lookahead = "YYEMPTY"; break; default: if( yychar > 0 ) { lookahead = keyword_str(yychar); } } warnx("lookahead is '%s'",lookahead); } } | search_1_cases search_1_case ; search_1_case: WHEN { parser_lsearch_conditional(); } conditional { parser_lsearch_when( $conditional.cond ); } search_stmts ; [pins]