added method to get context for non-arg rules
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8921]
This commit is contained in:
parent
cce6c70b2e
commit
dcfb804ed3
|
@ -56,9 +56,7 @@ public class ParserRuleContext extends RuleContext {
|
|||
public ParserRuleContext() { super(); }
|
||||
|
||||
public ParserRuleContext(RuleContext parent, int stateNumber) {
|
||||
// capture state that called us as we create this context; use later for
|
||||
// return state in closure
|
||||
super(parent, parent!=null ? parent.s : -1, stateNumber);
|
||||
super(parent, stateNumber);
|
||||
}
|
||||
|
||||
public Object getTree() { return tree; }
|
||||
|
|
|
@ -226,7 +226,17 @@ public class Recognizer<ATNInterpreter> {
|
|||
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
|
||||
}
|
||||
|
||||
public ParserRuleContext newContext(RuleContext _localctx, int s, int ruleIndex, int actionIndex) {
|
||||
/** Create context for a rule reference IN fromRuleIndex using parent _localctx.
|
||||
* Used only when there are arguments to the rule function.
|
||||
*/
|
||||
public RuleContext newContext(RuleContext _localctx, int s, int fromRuleIndex, int actionIndex) {
|
||||
return new ParserRuleContext(_localctx, s);
|
||||
}
|
||||
|
||||
/** Map a rule index to appropriate RuleContext subclass. Used when rule
|
||||
* has no arguments.
|
||||
*/
|
||||
public RuleContext newContext(RuleContext _localctx, int s, int targetRuleIndex) {
|
||||
return new ParserRuleContext(_localctx, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,13 +69,11 @@ public class RuleContext {
|
|||
|
||||
public RuleContext() {}
|
||||
|
||||
// public RuleContext(RuleContext parent) {
|
||||
// this.parent = parent;
|
||||
//// while ( p!=null ) {
|
||||
//// System.out.println();
|
||||
//// p = p.parent;
|
||||
//// }
|
||||
// }
|
||||
public RuleContext(RuleContext parent, int stateNumber) {
|
||||
// capture state that called us as we create this context; use later for
|
||||
// return state in closure
|
||||
this(parent, parent!=null ? parent.s : -1, stateNumber);
|
||||
}
|
||||
|
||||
public RuleContext(RuleContext parent, int invokingState, int stateNumber) {
|
||||
this.parent = parent;
|
||||
|
|
|
@ -108,10 +108,11 @@ public abstract class ATNSimulator {
|
|||
int ttype = toInt(data[p+2]);
|
||||
int arg1 = toInt(data[p+3]);
|
||||
int arg2 = toInt(data[p+4]);
|
||||
Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, sets);
|
||||
int arg3 = toInt(data[p+5]);
|
||||
Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
|
||||
ATNState srcState = atn.states.get(src);
|
||||
srcState.addTransition(trans);
|
||||
p += 5;
|
||||
p += 6;
|
||||
}
|
||||
int ndecisions = toInt(data[p++]);
|
||||
for (int i=1; i<=ndecisions; i++) {
|
||||
|
@ -130,24 +131,25 @@ public abstract class ATNSimulator {
|
|||
|
||||
public static Transition edgeFactory(ATN atn,
|
||||
int type, int src, int trg,
|
||||
int arg1, int arg2,
|
||||
int arg1, int arg2, int arg3,
|
||||
List<IntervalSet> sets)
|
||||
{
|
||||
ATNState target = atn.states.get(trg);
|
||||
switch (type) {
|
||||
case Transition.EPSILON : return new EpsilonTransition(target);
|
||||
case Transition.RANGE : return new RangeTransition(arg1, arg2, target);
|
||||
case Transition.RULE : return new RuleTransition(arg2, atn.states.get(arg1), target);
|
||||
case Transition.PREDICATE : return new PredicateTransition(target, arg1, arg2);
|
||||
case Transition.DEPENDENT_PREDICATE :
|
||||
PredicateTransition p = new PredicateTransition(target, arg1, arg2);
|
||||
p.isCtxDependent = true;
|
||||
return p;
|
||||
case Transition.RULE :
|
||||
RuleTransition rt = new RuleTransition(arg2, atn.states.get(arg1), target);
|
||||
rt.argIndex = arg3;
|
||||
return rt;
|
||||
case Transition.PREDICATE :
|
||||
PredicateTransition pt = new PredicateTransition(target, arg1, arg2);
|
||||
pt.isCtxDependent = arg3==1;
|
||||
return pt;
|
||||
case Transition.ATOM : return new AtomTransition(arg1, target);
|
||||
case Transition.ACTION : return new ActionTransition(target, arg1, arg2);
|
||||
case Transition.FORCED_DEPENDENT_ACTION :
|
||||
case Transition.ACTION :
|
||||
ActionTransition a = new ActionTransition(target, arg1, arg2);
|
||||
a.isCtxDependent = true;
|
||||
a.isCtxDependent = arg3==1;
|
||||
return a;
|
||||
case Transition.FORCED_ACTION : return new ActionTransition(target, arg1, arg2);
|
||||
case Transition.SET : return new SetTransition(sets.get(arg1), target);
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.stringtemplate.v4.misc.MultiMap;
|
|||
import java.util.*;
|
||||
|
||||
public class ParserATNSimulator extends ATNSimulator {
|
||||
public static boolean debug = true;
|
||||
public static boolean debug = false;
|
||||
public static boolean dfa_debug = false;
|
||||
|
||||
public static int ATN_failover = 0;
|
||||
|
@ -492,8 +492,24 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
ATNState p = config.state;
|
||||
RuleContext newContext;
|
||||
if ( parser != null ) {
|
||||
// System.out.println("rule trans to rule "+parser.getRuleNames()[t.target.ruleIndex]);
|
||||
newContext = parser.newContext(config.context, t.target.stateNumber, t.target.ruleIndex, -999);
|
||||
RuleContext ctx = getCurrentExecContext(config);
|
||||
int argIndex = ((RuleTransition) t).argIndex;
|
||||
if ( debug ) {
|
||||
System.out.println("CALL rule "+parser.getRuleNames()[t.target.ruleIndex]+
|
||||
", arg="+ argIndex +
|
||||
", using context="+ctx);
|
||||
}
|
||||
int fromRuleIndex = config.state.ruleIndex;
|
||||
if ( argIndex>=0 ) {
|
||||
newContext = parser.newContext(ctx, t.target.stateNumber,
|
||||
fromRuleIndex,
|
||||
argIndex);
|
||||
}
|
||||
else {
|
||||
int targetRuleIndex = t.target.ruleIndex;
|
||||
newContext = parser.newContext(ctx, t.target.stateNumber, targetRuleIndex);
|
||||
}
|
||||
|
||||
newContext.invokingState = p.stateNumber;
|
||||
// System.out.println("new ctx type is "+newContext.getClass().getSimpleName());
|
||||
}
|
||||
|
@ -514,11 +530,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
// preds are epsilon if we're not doing preds (we saw an action).
|
||||
// if we are doing preds, pred must eval to true
|
||||
// Cannot exec preds out of context if they are context dependent
|
||||
RuleContext ctx = config.context; // use context created after entry into interp
|
||||
if ( ctx == RuleContext.EMPTY ) {
|
||||
if ( config.reachesIntoOuterContext==0 ) ctx = originalContext;
|
||||
else ctx = null; // no context if we in outer context
|
||||
}
|
||||
RuleContext ctx = getCurrentExecContext(config);
|
||||
boolean ctxIssue = pt.isCtxDependent && config.reachesIntoOuterContext>0;
|
||||
boolean seeThroughPred =
|
||||
ignorePreds || ctxIssue ||
|
||||
|
@ -534,11 +546,7 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
if ( debug ) System.out.println("ACTION edge "+at.ruleIndex+":"+at.actionIndex);
|
||||
if ( at.actionIndex>=0 ) {
|
||||
if ( debug ) System.out.println("DO ACTION "+at.ruleIndex+":"+at.actionIndex);
|
||||
RuleContext ctx = config.context;
|
||||
if ( ctx == RuleContext.EMPTY ) {
|
||||
if ( config.reachesIntoOuterContext==0 ) ctx = originalContext;
|
||||
else ctx = null; // no context if we in outer context
|
||||
}
|
||||
RuleContext ctx = getCurrentExecContext(config);
|
||||
boolean ctxIssue = at.isCtxDependent && config.reachesIntoOuterContext>0;
|
||||
// Only exec forced action that isCtxDependent if we are not
|
||||
// doing global FOLLOW; we don't know context
|
||||
|
@ -587,6 +595,15 @@ public class ParserATNSimulator extends ATNSimulator {
|
|||
return alt;
|
||||
}
|
||||
|
||||
public RuleContext getCurrentExecContext(ATNConfig config) {
|
||||
RuleContext ctx = config.context; // use context created after entry into interp
|
||||
if ( ctx == RuleContext.EMPTY ) {
|
||||
if ( config.reachesIntoOuterContext==0 ) ctx = originalContext;
|
||||
else ctx = null; // no context if we in outer context
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public Set<Integer> getAmbiguousAlts(OrderedHashSet<ATNConfig> configs) {
|
||||
// System.err.println("check ambiguous "+configs);
|
||||
Set<Integer> ambigAlts = null;
|
||||
|
|
|
@ -32,8 +32,8 @@ package org.antlr.v4.runtime.atn;
|
|||
/** */
|
||||
public class RuleTransition extends Transition {
|
||||
/** Ptr to the rule definition object for this rule ref */
|
||||
//public Rule rule;
|
||||
public int ruleIndex; // no Rule object at runtime
|
||||
public int ruleIndex; // no Rule object at runtime
|
||||
public int argIndex = -1; // args are forced actions
|
||||
|
||||
/** What node to begin computations following ref to rule */
|
||||
public ATNState followState;
|
||||
|
|
|
@ -50,15 +50,13 @@ public abstract class Transition {
|
|||
public static final int EPSILON = 1;
|
||||
public static final int RANGE = 2;
|
||||
public static final int RULE = 3;
|
||||
public static final int PREDICATE = 4; // e.g., {isType(input.LT(1))}?
|
||||
public static final int DEPENDENT_PREDICATE = 5; // e.g., {$p>3}?
|
||||
public static final int ATOM = 6;
|
||||
public static final int ACTION = 7;
|
||||
public static final int FORCED_ACTION = 8;
|
||||
public static final int FORCED_DEPENDENT_ACTION = 9;
|
||||
public static final int SET = 10; // ~(A|B) or ~atom, wildcard, which convert to next 2
|
||||
public static final int NOT_SET = 11;
|
||||
public static final int WILDCARD = 12;
|
||||
public static final int PREDICATE = 4; // e.g., {isType(input.LT(1))}?
|
||||
public static final int ATOM = 5;
|
||||
public static final int ACTION = 6;
|
||||
public static final int FORCED_ACTION = 7;
|
||||
public static final int SET = 8; // ~(A|B) or ~atom, wildcard, which convert to next 2
|
||||
public static final int NOT_SET = 9;
|
||||
public static final int WILDCARD = 10;
|
||||
|
||||
|
||||
public static String[] serializationNames = {
|
||||
|
@ -67,11 +65,9 @@ public abstract class Transition {
|
|||
"RANGE",
|
||||
"RULE",
|
||||
"PREDICATE",
|
||||
"DEPENDENT_PREDICATE",
|
||||
"ATOM",
|
||||
"ACTION",
|
||||
"FORCED_ACTION",
|
||||
"FORCED_DEPENDENT_ACTION",
|
||||
"SET",
|
||||
"NOT_SET",
|
||||
"WILDCARD",
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
grammar T;
|
||||
options {output=AST;}
|
||||
|
||||
s returns [int j=9999] : e[9] {{System.out.println("after-e "+$j);}} {true}? ';' ;
|
||||
s : e EOF ;
|
||||
|
||||
e[int i]
|
||||
: {$i>=0}? {{System.out.println("i=="+$i);}} ID
|
||||
| ID '!'
|
||||
;
|
||||
e : e_[0] ;
|
||||
|
||||
foo[int j] : e[8] {$j==2}? '$' ; // not called but in FOLLOW(e)
|
||||
e_[int _p]
|
||||
: e_primary
|
||||
( {$_p <= 5}? '*'^ e_[6]{}
|
||||
| {$_p <= 4}? '+'^ e_[5]{}
|
||||
| {$_p <= 2}? '='<assoc=right>^ e_[2]{}
|
||||
| {$_p <= 3}? '?'<assoc=right>^ e ':'! e_[3]{}
|
||||
)*
|
||||
;
|
||||
|
||||
e_primary
|
||||
: ID
|
||||
;
|
||||
|
||||
ID : 'a'..'z'+;
|
||||
|
||||
|
|
|
@ -60,18 +60,29 @@ public class <parser.name> extends Parser {
|
|||
public ATN getATN() { return _ATN; }
|
||||
|
||||
<dumpActions(parser, argFuncs, actionFuncs, sempredFuncs)>
|
||||
|
||||
/** Map a rule index to appropriate RuleContext subclass */
|
||||
public RuleContext newContext(RuleContext _localctx, int s, int targetRuleIndex) {
|
||||
switch ( targetRuleIndex ) {
|
||||
<parser.funcs:{rf |
|
||||
case <rf.index> : return new <rf.ctxType>(_localctx, s);}; separator="\n">
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
<atn>
|
||||
}
|
||||
>>
|
||||
|
||||
dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= <<
|
||||
<if(argFuncs)>
|
||||
public ParserRuleContext newContext(RuleContext _localctx, int s, int ruleIndex, int actionIndex) {
|
||||
switch ( ruleIndex ) {
|
||||
/** Create context for a rule reference IN fromRuleIndex using parent _localctx */
|
||||
public RuleContext newContext(RuleContext _localctx, int s, int fromRuleIndex, int actionIndex) {
|
||||
switch ( fromRuleIndex ) {
|
||||
<recog.argFuncs.values:{f|
|
||||
case <f.ruleIndex> : return <f.name>_argEval((<f.ctxType>)_localctx, s, actionIndex);}; separator="\n">
|
||||
case <f.ruleIndex> : return <f.name>_argEval(_localctx, s, actionIndex);}; separator="\n">
|
||||
}
|
||||
return new ParserRuleContext(_localctx, s);
|
||||
return new RuleContext(_localctx, s);
|
||||
}
|
||||
<argFuncs.values; separator="\n">
|
||||
<endif>
|
||||
|
@ -105,7 +116,7 @@ public <p.name>(TokenStream input) {
|
|||
|
||||
RuleArgFunction(r, actions) ::= <<
|
||||
/** arg computations for rules called FROM and evaluated in context of <r.name> */
|
||||
public ParserRuleContext <r.name>_argEval(ParserRuleContext _localctx, int s, int actionIndex) {
|
||||
public RuleContext <r.name>_argEval(RuleContext _localctx, int s, int actionIndex) {
|
||||
switch ( actionIndex ) {
|
||||
<actions:{index|
|
||||
case <index> : return new <r.actions.(index).ctxType>(_localctx, s, <actions.(index)>);}; separator="\n">
|
||||
|
@ -419,7 +430,8 @@ CaptureNextTokenType(d) ::= "<d.varName> = input.LA(1);"
|
|||
StructDecl(s,attrs) ::= <<
|
||||
public static class <s.name> extends ParserRuleContext {
|
||||
<attrs:{a | public <a>;}; separator="\n">
|
||||
public <s.name>(ParserRuleContext parent, int state<s.ctorAttrs:{a | , <a>}>) {
|
||||
<if(s.ctorAttrs)>public <s.name>(RuleContext parent, int state) { super(parent, state); }<endif>
|
||||
public <s.name>(RuleContext parent, int state<s.ctorAttrs:{a | , <a>}>) {
|
||||
super(parent, state);
|
||||
<s.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n">
|
||||
}
|
||||
|
|
|
@ -133,17 +133,20 @@ public class ATNSerializer {
|
|||
int edgeType = Transition.serializationTypes.get(t.getClass());
|
||||
int arg1 = 0;
|
||||
int arg2 = 0;
|
||||
int arg3 = 0;
|
||||
switch ( edgeType ) {
|
||||
case Transition.RULE :
|
||||
trg = ((RuleTransition)t).followState.stateNumber;
|
||||
arg1 = ((RuleTransition)t).target.stateNumber;
|
||||
arg2 = ((RuleTransition)t).ruleIndex;
|
||||
arg3 = ((RuleTransition)t).argIndex;
|
||||
break;
|
||||
case Transition.PREDICATE :
|
||||
PredicateTransition pt = (PredicateTransition)t;
|
||||
arg1 = pt.ruleIndex;
|
||||
arg2 = pt.predIndex;
|
||||
if ( pt.isCtxDependent ) edgeType = Transition.DEPENDENT_PREDICATE;
|
||||
// if ( pt.isCtxDependent ) edgeType = Transition.DEPENDENT_PREDICATE;
|
||||
arg3 = pt.isCtxDependent ? 1 : 0 ;
|
||||
break;
|
||||
case Transition.RANGE :
|
||||
arg1 = ((RangeTransition)t).from;
|
||||
|
@ -156,14 +159,12 @@ public class ATNSerializer {
|
|||
ActionTransition at = (ActionTransition)t;
|
||||
arg1 = at.ruleIndex;
|
||||
arg2 = at.actionIndex;
|
||||
if ( at.isCtxDependent ) edgeType = Transition.FORCED_DEPENDENT_ACTION;
|
||||
arg3 = at.isCtxDependent ? 1 : 0 ;
|
||||
// if ( at.isCtxDependent ) edgeType = Transition.FORCED_DEPENDENT_ACTION;
|
||||
break;
|
||||
case Transition.SET :
|
||||
arg1 = setIndex++;
|
||||
break;
|
||||
// case Transition.NOT_ATOM :
|
||||
// arg1 = ((NotAtomTransition)t).label;
|
||||
// break;
|
||||
case Transition.NOT_SET :
|
||||
arg1 = setIndex++;
|
||||
break;
|
||||
|
@ -175,6 +176,7 @@ public class ATNSerializer {
|
|||
data.add(edgeType);
|
||||
data.add(arg1);
|
||||
data.add(arg2);
|
||||
data.add(arg3);
|
||||
}
|
||||
}
|
||||
int ndecisions = atn.decisionToState.size();
|
||||
|
@ -230,11 +232,12 @@ public class ATNSerializer {
|
|||
int ttype = ATNSimulator.toInt(data[p + 2]);
|
||||
int arg1 = ATNSimulator.toInt(data[p + 3]);
|
||||
int arg2 = ATNSimulator.toInt(data[p + 4]);
|
||||
int arg3 = ATNSimulator.toInt(data[p + 5]);
|
||||
buf.append(src+"->"+trg+
|
||||
" "+Transition.serializationNames[ttype]+
|
||||
" "+arg1+","+arg2+
|
||||
" "+arg1+","+arg2+","+arg3+
|
||||
"\n");
|
||||
p += 5;
|
||||
p += 6;
|
||||
}
|
||||
int ndecisions = ATNSimulator.toInt(data[p++]);
|
||||
for (int i=1; i<=ndecisions; i++) {
|
||||
|
|
|
@ -191,6 +191,11 @@ public class ParserATNFactory implements ATNFactory {
|
|||
ATNState left = newState(node);
|
||||
ATNState right = newState(node);
|
||||
RuleTransition call = new RuleTransition(r.index, start, right);
|
||||
ActionAST arg = (ActionAST)node.getFirstChildWithType(ANTLRParser.ARG_ACTION);
|
||||
if ( arg!=null ) {
|
||||
call.argIndex = g.actions.get(arg);
|
||||
}
|
||||
|
||||
left.addTransition(call);
|
||||
|
||||
node.atnState = left;
|
||||
|
|
|
@ -151,7 +151,7 @@ public void finishAltWithRewrite(AltAST alt) { }
|
|||
public void discoverSTRewrite(GrammarAST rew) { }
|
||||
public void discoverTreeRewrite(GrammarAST rew) { }
|
||||
|
||||
public void ruleRef(GrammarAST ref, GrammarAST arg) { }
|
||||
public void ruleRef(GrammarAST ref, ActionAST arg) { }
|
||||
public void tokenRef(TerminalAST ref, GrammarAST options) { }
|
||||
public void terminalOption(TerminalAST t, GrammarAST ID, GrammarAST value) { }
|
||||
public void stringRef(TerminalAST ref, GrammarAST options) { }
|
||||
|
@ -412,7 +412,7 @@ block
|
|||
ruleref
|
||||
: ^(RULE_REF arg=ARG_ACTION?)
|
||||
{
|
||||
ruleRef($RULE_REF, $ARG_ACTION);
|
||||
ruleRef($RULE_REF, (ActionAST)$ARG_ACTION);
|
||||
if ( $arg!=null ) actionInAlt((ActionAST)$arg);
|
||||
}
|
||||
;
|
||||
|
|
|
@ -207,7 +207,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void ruleRef(GrammarAST ref, GrammarAST arg) {
|
||||
public void ruleRef(GrammarAST ref, ActionAST arg) {
|
||||
checkInvalidRuleRef(ref.token);
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ public class SymbolCollector extends GrammarTreeVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void ruleRef(GrammarAST ref, GrammarAST arg) {
|
||||
public void ruleRef(GrammarAST ref, ActionAST arg) {
|
||||
if ( inContext("DOT ...") ) qualifiedRulerefs.add((GrammarAST)ref.getParent());
|
||||
rulerefs.add(ref);
|
||||
if ( currentRule!=null ) {
|
||||
|
|
|
@ -134,15 +134,16 @@ public class Grammar implements AttributeResolver {
|
|||
*/
|
||||
public Map<String,ActionAST> namedActions = new HashMap<String,ActionAST>();
|
||||
|
||||
|
||||
/** Tracks all forced actions in all alternatives of all rules.
|
||||
* This is includes rule arguments.
|
||||
* Or if lexer all actions period. Doesn't track sempreds.
|
||||
* maps tree node to action index.
|
||||
*/
|
||||
public LinkedHashMap<ActionAST, Integer> actions = new LinkedHashMap<ActionAST, Integer>();
|
||||
|
||||
/** All sempreds found in grammar; maps tree node to sempred index;
|
||||
* sempred index is 0..n-1 */
|
||||
* sempred index is 0..n-1
|
||||
*/
|
||||
public LinkedHashMap<PredAST, Integer> sempreds = new LinkedHashMap<PredAST, Integer>();
|
||||
|
||||
public static final String AUTO_GENERATED_TOKEN_NAME_PREFIX = "T__";
|
||||
|
|
Loading…
Reference in New Issue