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
* 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.start = _input.LT(1);
_ctx.ruleIndex = ruleIndex;
@ -388,6 +389,7 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator<Token>
public void exitRule() {
// trigger event on _ctx, before it reverts to parent
if ( _parseListeners != null) triggerExitRuleEvent();
setState(_ctx.invokingState);
_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. */
public void pushNewRecursionContext(ParserRuleContext<Token> localctx, int ruleIndex) {
public void pushNewRecursionContext(ParserRuleContext<Token> localctx, int state, int ruleIndex) {
setState(state);
_ctx = localctx;
_ctx.start = _input.LT(1);
_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)
// unroll so _ctx is as it was before call to recursive method
if ( _parseListeners != null ) {
while ( _ctx != _parentctx ) {
triggerExitRuleEvent();
setState(_ctx.invokingState);
_ctx = (ParserRuleContext<Token>)_ctx.parent;
}
}
else {
setState(_parentState);
_ctx = _parentctx;
}
// hook into tree
retctx.invokingState = _parentState;
retctx.parent = _parentctx;
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;
private int _stateNumber;
private int _stateNumber = -1;
/** Used to print out token names like ID during debugging and
* 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">
<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>}>);
enterRule(_localctx, RULE_<currentRule.name>);
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, getState()<currentRule.args:{a | , <a.name>}>);
enterRule(_localctx, <currentRule.startState>, RULE_<currentRule.name>);
<namedActions.init>
<locals; separator="\n">
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 {
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;
int _startState = <currentRule.startState>;
pushNewRecursionContext(_localctx, RULE_<currentRule.name>);
pushNewRecursionContext(_localctx, <currentRule.startState>, RULE_<currentRule.name>);
<namedActions.init>
<locals; separator="\n">
try {
@ -275,7 +276,7 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
}
finally {
<finallyAction>
unrollRecursionContexts(_parentctx);
unrollRecursionContexts(_parentctx, _parentState);
}
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> {
<attrs:{a | <a>}; separator="\n">
<getters:{g | <g>}; separator="\n">
<if(struct.ctorAttrs)>public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state) { super(parent, state); }<endif>
public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<struct.ctorAttrs:{a | , <a>}>) {
super(parent, state);
<if(struct.ctorAttrs)>public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int invokingState) { super(parent, invokingState); }<endif>
public <struct.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int invokingState<struct.ctorAttrs:{a | , <a>}>) {
super(parent, invokingState);
<struct.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n">
}
<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);"
recRuleAltStartAction(ruleName, ctxName, label) ::= <<
_localctx = new <ctxName>Context(_parentctx, _startState, _p);
_localctx = new <ctxName>Context(_parentctx, _parentState, _p);
_localctx.addChild(_prevctx);
<if(label)>_localctx.<label> = _prevctx;<endif>
pushNewRecursionContext(_localctx, RULE_<ruleName>);
pushNewRecursionContext(_localctx, _startState, RULE_<ruleName>);
_localctx.start = _prevctx.start;
>>
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);
<if(label)>((<currentAltLabel; format="cap">Context)_localctx).<label> = _prevctx;<endif>
pushNewRecursionContext(_localctx, RULE_<ruleName>);
pushNewRecursionContext(_localctx, _startState, RULE_<ruleName>);
_localctx.start = _prevctx.start;
>>