hi. I've added Jim Idle style error recovery for loops; a sync call tries to
recover upon error instead of immediately exiting loop. Oh, also exceptions
track set of expected elements for better messages (auto-completion type
stuff). Here's an LL(1) sample rule.
a : A+
| (B|C)+
;
The output is pretty close to human written:
public final ParserRuleContext a(ParserRuleContext _ctx) throws
RecognitionException {
state.ctx.push(_ctx);
Token _la;
try {
switch ( state.input.LA(1) ) {
case A:
sync(EXPECTING_in_a_0);
_la = state.input.LA(1);
do {
match(A, FOLLOW_A_in_a_11);
_la = state.input.LA(1);
sync(EXPECTING_in_a_0);
} while ( _la==A );
break;
case B:
case C:
sync(EXPECTING_in_a_0);
int cnt21 = 0;
loop21:
while (true) {
switch ( state.input.LA(1) ) {
case B:
match(B, FOLLOW_B_in_a_17);
break;
case C:
match(C, FOLLOW_C_in_a_19);
break;
case EOF:
if ( cnt21 >= 1 ) break loop21;
else throw new ThrowEarlyExitException(this,
EXPECTING_in_a_0);
}
sync(EXPECTING_in_a_0);
}
break;
default :
}
}
catch (RecognitionException re) {
reportError(re);
recover();
}
finally {
return (ParserRuleContext)state.ctx.pop();
}
}
and to show how clean the templates are; here are the loops:
LL1PlusBlock(choice, alts, error, earlyExitError, sync) ::= <<
<sync>
int <choice.loopCounterVar> = 0;
<choice.loopLabel>:
while (true) {
switch ( state.input.LA(1) ) {
<choice.altLook,alts:{look,alt| <cases(ttypes=look)>
<alt>
break;}; separator="\n">
<cases(ttypes=choice.exitLook)>
if ( <choice.loopCounterVar> >= 1 ) break
<choice.loopLabel>;
else <earlyExitError>
}
<sync>
}
>>
LL1PlusBlockSingleAlt(choice, expr, alts, preamble, iteration,
error, earlyExitError, sync) ::=
<<
<sync>
<preamble; separator="\n">
do {
<alts; separator="\n">
<iteration>
<sync>
} while ( <expr> );
>>
:)
Ter_______________________________________________
antlr-dev mailing list
[email protected]
http://www.antlr.org/mailman/listinfo/antlr-dev