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

Reply via email to