forked from jasder/antlr
Fix errors tracking current state on rule return
This commit is contained in:
parent
aa34f33846
commit
e8765ef241
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
>>
|
||||
|
||||
|
|
Loading…
Reference in New Issue