Fix errors tracking current state on rule return

This commit is contained in:
Sam Harwell 2012-03-26 23:29:53 -05:00
parent aa34f33846
commit e8765ef241
3 changed files with 23 additions and 16 deletions

View File

@ -377,7 +377,8 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator<Token>
* This is flexible because users do not have to regenerate parsers * This is flexible because users do not have to regenerate parsers
* to get trace facilities. * to get trace facilities.
*/ */
public void enterRule(ParserRuleContext<Token> localctx, int ruleIndex) { public void enterRule(ParserRuleContext<Token> localctx, int state, int ruleIndex) {
setState(state);
_ctx = localctx; _ctx = localctx;
_ctx.start = _input.LT(1); _ctx.start = _input.LT(1);
_ctx.ruleIndex = ruleIndex; _ctx.ruleIndex = ruleIndex;
@ -388,6 +389,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator<Token>
public void exitRule() { public void exitRule() {
// trigger event on _ctx, before it reverts to parent // trigger event on _ctx, before it reverts to parent
if ( _parseListeners != null) triggerExitRuleEvent(); if ( _parseListeners != null) triggerExitRuleEvent();
setState(_ctx.invokingState);
_ctx = (ParserRuleContext<Token>)_ctx.parent; _ctx = (ParserRuleContext<Token>)_ctx.parent;
} }
@ -404,26 +406,30 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator<Token>
} }
/* like enterRule but for recursive rules; no enter events for recursive rules. */ /* like enterRule but for recursive rules; no enter events for recursive rules. */
public void pushNewRecursionContext(ParserRuleContext<Token> localctx, int ruleIndex) { public void pushNewRecursionContext(ParserRuleContext<Token> localctx, int state, int ruleIndex) {
setState(state);
_ctx = localctx; _ctx = localctx;
_ctx.start = _input.LT(1); _ctx.start = _input.LT(1);
_ctx.ruleIndex = ruleIndex; _ctx.ruleIndex = ruleIndex;
} }
public void unrollRecursionContexts(ParserRuleContext<Token> _parentctx) { public void unrollRecursionContexts(ParserRuleContext<Token> _parentctx, int _parentState) {
ParserRuleContext<Token> retctx = _ctx; // save current ctx (return value) ParserRuleContext<Token> retctx = _ctx; // save current ctx (return value)
// unroll so _ctx is as it was before call to recursive method // unroll so _ctx is as it was before call to recursive method
if ( _parseListeners != null ) { if ( _parseListeners != null ) {
while ( _ctx != _parentctx ) { while ( _ctx != _parentctx ) {
triggerExitRuleEvent(); triggerExitRuleEvent();
setState(_ctx.invokingState);
_ctx = (ParserRuleContext<Token>)_ctx.parent; _ctx = (ParserRuleContext<Token>)_ctx.parent;
} }
} }
else { else {
setState(_parentState);
_ctx = _parentctx; _ctx = _parentctx;
} }
// hook into tree // hook into tree
retctx.invokingState = _parentState;
retctx.parent = _parentctx; retctx.parent = _parentctx;
if (_buildParseTrees) _parentctx.addChild(retctx); // add return ctx into invoking rule's tree if (_buildParseTrees) _parentctx.addChild(retctx); // add return ctx into invoking rule's tree
} }

View File

@ -47,7 +47,7 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
protected ATNInterpreter _interp; protected ATNInterpreter _interp;
private int _stateNumber; private int _stateNumber = -1;
/** Used to print out token names like ID during debugging and /** Used to print out token names like ID during debugging and
* error reporting. The generated parsers implement a method * error reporting. The generated parsers implement a method

View File

@ -220,8 +220,8 @@ RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAc
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n"> <altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException { <if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, <currentRule.startState><currentRule.args:{a | , <a.name>}>); <currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, getState()<currentRule.args:{a | , <a.name>}>);
enterRule(_localctx, RULE_<currentRule.name>); enterRule(_localctx, <currentRule.startState>, RULE_<currentRule.name>);
<namedActions.init> <namedActions.init>
<locals; separator="\n"> <locals; separator="\n">
try { try {
@ -254,10 +254,11 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException { <if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
ParserRuleContext\<Token> _parentctx = _ctx; ParserRuleContext\<Token> _parentctx = _ctx;
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, <currentRule.startState><currentRule.args:{a | , <a.name>}>); int _parentState = getState();
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, _parentState<currentRule.args:{a | , <a.name>}>);
<currentRule.ctxType> _prevctx = _localctx; <currentRule.ctxType> _prevctx = _localctx;
int _startState = <currentRule.startState>; int _startState = <currentRule.startState>;
pushNewRecursionContext(_localctx, RULE_<currentRule.name>); pushNewRecursionContext(_localctx, <currentRule.startState>, RULE_<currentRule.name>);
<namedActions.init> <namedActions.init>
<locals; separator="\n"> <locals; separator="\n">
try { try {
@ -275,7 +276,7 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
} }
finally { finally {
<finallyAction> <finallyAction>
unrollRecursionContexts(_parentctx); unrollRecursionContexts(_parentctx, _parentState);
} }
return _localctx; return _localctx;
} }
@ -603,9 +604,9 @@ StructDecl(struct,attrs,getters,dispatchMethods,interfaces,extensionMembers,
public static class <struct.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> { public static class <struct.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> {
<attrs:{a | <a>}; separator="\n"> <attrs:{a | <a>}; separator="\n">
<getters:{g | <g>}; separator="\n"> <getters:{g | <g>}; separator="\n">
<if(struct.ctorAttrs)>public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state) { super(parent, state); }<endif> <if(struct.ctorAttrs)>public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int invokingState) { super(parent, invokingState); }<endif>
public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<struct.ctorAttrs:{a | , <a>}>) { public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int invokingState<struct.ctorAttrs:{a | , <a>}>) {
super(parent, state); super(parent, invokingState);
<struct.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n"> <struct.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n">
} }
<if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !> <if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !>
@ -668,18 +669,18 @@ recRuleSetReturnAction(src,name) ::= "$<name>=$<src>.<name>;"
recRuleSetStopToken() ::= "_ctx.stop = _input.LT(-1);" recRuleSetStopToken() ::= "_ctx.stop = _input.LT(-1);"
recRuleAltStartAction(ruleName, ctxName, label) ::= << recRuleAltStartAction(ruleName, ctxName, label) ::= <<
_localctx = new <ctxName>Context(_parentctx, _startState, _p); _localctx = new <ctxName>Context(_parentctx, _parentState, _p);
_localctx.addChild(_prevctx); _localctx.addChild(_prevctx);
<if(label)>_localctx.<label> = _prevctx;<endif> <if(label)>_localctx.<label> = _prevctx;<endif>
pushNewRecursionContext(_localctx, RULE_<ruleName>); pushNewRecursionContext(_localctx, _startState, RULE_<ruleName>);
_localctx.start = _prevctx.start; _localctx.start = _prevctx.start;
>> >>
recRuleLabeledAltStartAction(ruleName, currentAltLabel, label) ::= << recRuleLabeledAltStartAction(ruleName, currentAltLabel, label) ::= <<
_localctx = new <currentAltLabel; format="cap">Context(new <ruleName; format="cap">Context(_parentctx, _startState, _p)); _localctx = new <currentAltLabel; format="cap">Context(new <ruleName; format="cap">Context(_parentctx, _parentState, _p));
_localctx.addChild(_prevctx); _localctx.addChild(_prevctx);
<if(label)>((<currentAltLabel; format="cap">Context)_localctx).<label> = _prevctx;<endif> <if(label)>((<currentAltLabel; format="cap">Context)_localctx).<label> = _prevctx;<endif>
pushNewRecursionContext(_localctx, RULE_<ruleName>); pushNewRecursionContext(_localctx, _startState, RULE_<ruleName>);
_localctx.start = _prevctx.start; _localctx.start = _prevctx.start;
>> >>