forked from jasder/antlr
crap; was messing with lexers but anyway just added depth back to closure
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6915]
This commit is contained in:
parent
0e4fbf903d
commit
6414fa00c6
|
@ -319,9 +319,9 @@ public class <lexerName> extends Lexer {
|
||||||
|
|
||||||
<namedActions.members>
|
<namedActions.members>
|
||||||
|
|
||||||
|
<dfas>
|
||||||
<actions>
|
<actions>
|
||||||
<sempreds>
|
<sempreds>
|
||||||
<dfas>
|
|
||||||
<pdas>
|
<pdas>
|
||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
|
@ -2,8 +2,17 @@ package org.antlr.v4.analysis;
|
||||||
|
|
||||||
import org.antlr.v4.automata.DFA;
|
import org.antlr.v4.automata.DFA;
|
||||||
import org.antlr.v4.automata.DecisionState;
|
import org.antlr.v4.automata.DecisionState;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.automata.NFA;
|
||||||
import org.antlr.v4.tool.LexerGrammar;
|
import org.antlr.v4.misc.BitSet;
|
||||||
|
import org.antlr.v4.misc.IntervalSet;
|
||||||
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
|
import org.antlr.v4.semantics.UseDefAnalyzer;
|
||||||
|
import org.antlr.v4.tool.*;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class AnalysisPipeline {
|
public class AnalysisPipeline {
|
||||||
public Grammar g;
|
public Grammar g;
|
||||||
|
@ -26,6 +35,9 @@ public class AnalysisPipeline {
|
||||||
void processLexer() {
|
void processLexer() {
|
||||||
LexerGrammar lg = (LexerGrammar)g;
|
LexerGrammar lg = (LexerGrammar)g;
|
||||||
for (String modeName : lg.modes.keySet()) {
|
for (String modeName : lg.modes.keySet()) {
|
||||||
|
|
||||||
|
Set<Rule> rulesInNFA = getRulesInNFA(lg, modeName);
|
||||||
|
|
||||||
LexerNFAToDFAConverter conv = new LexerNFAToDFAConverter(lg);
|
LexerNFAToDFAConverter conv = new LexerNFAToDFAConverter(lg);
|
||||||
DFA dfa = conv.createDFA(modeName);
|
DFA dfa = conv.createDFA(modeName);
|
||||||
lg.modeToDFA.put(modeName, dfa);
|
lg.modeToDFA.put(modeName, dfa);
|
||||||
|
@ -85,4 +97,52 @@ public class AnalysisPipeline {
|
||||||
|
|
||||||
return dfa;
|
return dfa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Rule> getRulesInNFA(LexerGrammar lg, String modeName) {
|
||||||
|
Set<Rule> rulesInNFA = getRulesTooComplexForDFA(lg, modeName);
|
||||||
|
System.out.println("rules in NFA: "+rulesInNFA);
|
||||||
|
|
||||||
|
IntervalSet charsPredictingNFARules = new IntervalSet();
|
||||||
|
for (Rule r : rulesInNFA) {
|
||||||
|
if ( !r.isFragment() ) {
|
||||||
|
LinearApproximator approx = new LinearApproximator(lg, NFA.INVALID_DECISION_NUMBER);
|
||||||
|
IntervalSet fset = approx.FIRST(lg.nfa.ruleToStartState.get(r));
|
||||||
|
System.out.println("first of "+r.name+"="+fset);
|
||||||
|
charsPredictingNFARules.addAll(fset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("charsPredictingNFARules="+charsPredictingNFARules);
|
||||||
|
// now find any other rules that start with that set
|
||||||
|
for (Rule r : lg.modes.get(modeName)) {
|
||||||
|
if ( !r.isFragment() && !rulesInNFA.contains(r) ) {
|
||||||
|
LinearApproximator approx = new LinearApproximator(lg, NFA.INVALID_DECISION_NUMBER);
|
||||||
|
IntervalSet fset = approx.FIRST(lg.nfa.ruleToStartState.get(r));
|
||||||
|
if ( !fset.and(charsPredictingNFARules).isNil() ) {
|
||||||
|
System.out.println("rule "+r.name+" collides");
|
||||||
|
rulesInNFA.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rulesInNFA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: oops. find all nongreedy loops too!
|
||||||
|
public Set<Rule> getRulesTooComplexForDFA(LexerGrammar lg, String modeName) {
|
||||||
|
Set<Rule> complexRules = new HashSet<Rule>();
|
||||||
|
Map<Rule, Set<Rule>> dep = UseDefAnalyzer.getRuleDependencies(lg, modeName);
|
||||||
|
System.out.println("dep="+dep);
|
||||||
|
for (Rule r : lg.modes.get(modeName)) {
|
||||||
|
if ( dep.containsKey(r) ) { complexRules.add(r); continue; }
|
||||||
|
BitSet labelTypes = BitSet.of(ANTLRParser.ASSIGN);
|
||||||
|
labelTypes.add(ANTLRParser.PLUS_ASSIGN);
|
||||||
|
List<GrammarAST> labels = r.ast.getNodesWithType(labelTypes);
|
||||||
|
if ( labels.size()>0 ) { complexRules.add(r); continue; }
|
||||||
|
List<GrammarAST> actions = r.ast.getNodesWithType(ANTLRParser.ACTION);
|
||||||
|
ActionAST actionOnFarRight = r.ast.getLexerAction();
|
||||||
|
for (GrammarAST action : actions) {
|
||||||
|
if ( action != actionOnFarRight ) complexRules.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return complexRules;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,9 @@ public class NFAConfig {
|
||||||
if (resolvedWithPredicate) {
|
if (resolvedWithPredicate) {
|
||||||
buf.append("|resolveWithPredicate");
|
buf.append("|resolveWithPredicate");
|
||||||
}
|
}
|
||||||
|
if ( context.approximated ) {
|
||||||
|
buf.append("|approx");
|
||||||
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,34 @@ import org.antlr.v4.automata.NFAState;
|
||||||
* on the path from this node thru the parent pointers to the root.
|
* on the path from this node thru the parent pointers to the root.
|
||||||
*/
|
*/
|
||||||
public class NFAContext {
|
public class NFAContext {
|
||||||
|
/** This is similar to Bermudez's m constant in his LAR(m) where
|
||||||
|
* he bounds the stack so your state sets don't explode. The main difference
|
||||||
|
* is that I bound only recursion on the stack, not the simple stack size.
|
||||||
|
* This looser constraint will let the conversion roam further to find
|
||||||
|
* lookahead to resolve a decision.
|
||||||
|
*
|
||||||
|
* We restrict the size of an NFA configuration to be finite because a
|
||||||
|
* stack component may mention the same NFA invocation state at
|
||||||
|
* most m times. Hence, the number of DFA states will not grow forever.
|
||||||
|
*
|
||||||
|
* m=0 implies you can make as many calls as you want--you just
|
||||||
|
* can't ever visit a state that is on your rule invocation stack.
|
||||||
|
* I.e., you cannot ever recurse.
|
||||||
|
* m=1 implies you are able to recurse once (i.e., call a rule twice
|
||||||
|
* from the same place).
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* This tracks recursion to a rule specific to an invocation site!
|
||||||
|
* It does not detect multiple calls to a rule from different rule
|
||||||
|
* invocation states. We are guaranteed to terminate because the
|
||||||
|
* stack can only grow as big as the number of NFA states * m.
|
||||||
|
*
|
||||||
|
* I noticed that the Java grammar didn't work with m=1 in ANTLR v3,
|
||||||
|
* but it did work with m=4. Let's set to 4. Recursion is sometimes
|
||||||
|
* needed to resolve some fixed lookahead decisions.
|
||||||
|
*/
|
||||||
|
public static int MAX_RECURSION_DEPTH_PER_NFA_CONFIG_STACK = 0;
|
||||||
|
|
||||||
public NFAContext parent;
|
public NFAContext parent;
|
||||||
|
|
||||||
/** The NFA state following state that invoked another rule's start state
|
/** The NFA state following state that invoked another rule's start state
|
||||||
|
@ -56,7 +84,7 @@ public class NFAContext {
|
||||||
/** Indicates this config led to recursive closure request. Everything
|
/** Indicates this config led to recursive closure request. Everything
|
||||||
* derived from here is approximation.
|
* derived from here is approximation.
|
||||||
*/
|
*/
|
||||||
public boolean recursed;
|
public boolean approximated;
|
||||||
|
|
||||||
/** Computing the hashCode is very expensive and closureBusy()
|
/** Computing the hashCode is very expensive and closureBusy()
|
||||||
* uses it to track when it's seen a state|ctx before to avoid
|
* uses it to track when it's seen a state|ctx before to avoid
|
||||||
|
@ -152,19 +180,12 @@ public class NFAContext {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given an NFA state number, how many times has the NFA-to-DFA
|
/** Given an NFA state number, how many times does it appear on stack?
|
||||||
* conversion pushed that state on the stack? In other words,
|
* The NFA-to-DFA conversion pushes "return" states as it does
|
||||||
* the NFA state must be a rule invocation state and this method
|
* rule invocations. The NFA state number must be a rule return state
|
||||||
* tells you how many times you've been to this state. If none,
|
* (following state from invocation state).
|
||||||
* then you have not called the target rule from this state before
|
|
||||||
* (though another NFA state could have called that target rule).
|
|
||||||
* If n=1, then you've been to this state before during this
|
|
||||||
* DFA construction and are going to invoke that rule again.
|
|
||||||
*
|
|
||||||
* Note that many NFA states can invoke rule r, but we ignore recursion
|
|
||||||
* unless you hit the same rule invocation state again.
|
|
||||||
*/
|
*/
|
||||||
public int recursionDepthEmanatingFromState(int state) {
|
public int occurrences(int state) {
|
||||||
NFAContext sp = this;
|
NFAContext sp = this;
|
||||||
int n = 0; // track recursive invocations of target from this state
|
int n = 0; // track recursive invocations of target from this state
|
||||||
//System.out.println("this.context is "+sp);
|
//System.out.println("this.context is "+sp);
|
||||||
|
|
|
@ -338,7 +338,7 @@ public class PredictionDFAFactory {
|
||||||
// if we have context info and we're at rule stop state, do
|
// if we have context info and we're at rule stop state, do
|
||||||
// local follow for invokingRule and global follow for other links
|
// local follow for invokingRule and global follow for other links
|
||||||
void ruleStopStateClosure(DFAState d, NFAConfig c, boolean collectPredicates) {
|
void ruleStopStateClosure(DFAState d, NFAConfig c, boolean collectPredicates) {
|
||||||
if ( !c.context.recursed ) {
|
if ( !c.context.approximated ) {
|
||||||
//System.out.println("dynamic FOLLOW of "+c.state+" context="+c.context);
|
//System.out.println("dynamic FOLLOW of "+c.state+" context="+c.context);
|
||||||
if ( c.context.isEmpty() ) {
|
if ( c.context.isEmpty() ) {
|
||||||
commonClosure(d, c, collectPredicates); // do global FOLLOW
|
commonClosure(d, c, collectPredicates); // do global FOLLOW
|
||||||
|
@ -389,25 +389,59 @@ public class PredictionDFAFactory {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
Transition t = c.state.transition(i);
|
Transition t = c.state.transition(i);
|
||||||
if ( t instanceof RuleTransition) {
|
if ( t instanceof RuleTransition) {
|
||||||
NFAState retState = ((RuleTransition)t).followState;
|
RuleTransition rt = (RuleTransition) t;
|
||||||
|
// have we called rt.target before? If so, rt.followState will be in c.context
|
||||||
|
int depth = c.context.occurrences(rt.followState.stateNumber);
|
||||||
|
System.out.println("ctx "+c.context+" c.state "+c.state+" ret state is "+rt.followState.stateNumber);
|
||||||
|
// Even if not on context stack already, must consider self-recursion.
|
||||||
|
// If a state in rule r's NFA invokes r's start state (only state
|
||||||
|
// rule trans can invoke) then it's yet more recursion.
|
||||||
|
// So we count previous invocations of r first and then
|
||||||
|
// increment if we're jumping to start state from within r.
|
||||||
|
if ( c.state.rule == t.target.rule ) depth++;
|
||||||
|
System.out.println("recur depth "+depth);
|
||||||
|
// Detect an attempt to recurse too high
|
||||||
|
// if this context has hit the max recursions,
|
||||||
|
// don't allow it to enter rule again
|
||||||
NFAContext newContext = c.context;
|
NFAContext newContext = c.context;
|
||||||
if ( c.state.rule != t.target.rule &&
|
if ( depth > NFAContext.MAX_RECURSION_DEPTH_PER_NFA_CONFIG_STACK ) {
|
||||||
!c.context.contains(((RuleTransition)t).followState) ) { // !recursive?
|
//System.out.println("# recursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
||||||
|
// don't record recursion, but record we approximated so we know
|
||||||
|
// what to do at end of rule and for error msgs.
|
||||||
|
c.context.approximated = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// otherwise, it's cool to (re)enter target of this rule ref
|
||||||
// first create a new context and push onto call tree,
|
// first create a new context and push onto call tree,
|
||||||
// recording the fact that we are invoking a rule and
|
// recording the fact that we are invoking a rule and
|
||||||
// from which state.
|
// from which state.
|
||||||
//System.out.println("nonrecursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
//System.out.println("nonrecursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
||||||
|
NFAState retState = ((RuleTransition)t).followState;
|
||||||
newContext = new NFAContext(c.context, retState);
|
newContext = new NFAContext(c.context, retState);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
//System.out.println("# recursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
|
||||||
// don't record recursion, but record we did so we know
|
|
||||||
// what to do at end of rule.
|
|
||||||
c.context.recursed = true;
|
|
||||||
}
|
|
||||||
// traverse epsilon edge to new rule
|
// traverse epsilon edge to new rule
|
||||||
closure(d, new NFAConfig(c, t.target, newContext),
|
closure(d, new NFAConfig(c, t.target, newContext),
|
||||||
collectPredicates);
|
collectPredicates);
|
||||||
|
|
||||||
|
// NFAState retState = ((RuleTransition)t).followState;
|
||||||
|
// NFAContext newContext = c.context;
|
||||||
|
// if ( c.state.rule != t.target.rule &&
|
||||||
|
// !c.context.contains(((RuleTransition)t).followState) ) { // !recursive?
|
||||||
|
// // first create a new context and push onto call tree,
|
||||||
|
// // recording the fact that we are invoking a rule and
|
||||||
|
// // from which state.
|
||||||
|
// //System.out.println("nonrecursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
||||||
|
// newContext = new NFAContext(c.context, retState);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// //System.out.println("# recursive invoke of "+t.target+" ret to "+retState+" ctx="+c.context);
|
||||||
|
// // don't record recursion, but record we did so we know
|
||||||
|
// // what to do at end of rule.
|
||||||
|
// c.context.recursed = true;
|
||||||
|
// }
|
||||||
|
// // traverse epsilon edge to new rule
|
||||||
|
// closure(d, new NFAConfig(c, t.target, newContext),
|
||||||
|
// collectPredicates);
|
||||||
}
|
}
|
||||||
else if ( t instanceof ActionTransition ) {
|
else if ( t instanceof ActionTransition ) {
|
||||||
collectPredicates = false; // can't see past actions
|
collectPredicates = false; // can't see past actions
|
||||||
|
@ -500,14 +534,14 @@ public class PredictionDFAFactory {
|
||||||
MachineProbe probe = new MachineProbe(dfa);
|
MachineProbe probe = new MachineProbe(dfa);
|
||||||
|
|
||||||
for (DFAState d : resolver.ambiguousStates) {
|
for (DFAState d : resolver.ambiguousStates) {
|
||||||
Set<Integer> alts = resolver.getAmbiguousAlts(d);
|
Set<Integer> ambigAlts = Resolver.getAmbiguousAlts(d);
|
||||||
List<Integer> sorted = new ArrayList<Integer>(alts);
|
List<Integer> sorted = new ArrayList<Integer>(ambigAlts);
|
||||||
Collections.sort(sorted);
|
Collections.sort(sorted);
|
||||||
//System.err.println("ambig alts="+sorted);
|
//System.err.println("ambig alts="+sorted);
|
||||||
List<DFAState> dfaStates = probe.getAnyDFAPathToTarget(d);
|
List<DFAState> dfaStates = probe.getAnyDFAPathToTarget(d);
|
||||||
//System.out.print("path =");
|
//System.out.print("path =");
|
||||||
for (DFAState d2 : dfaStates) {
|
for (DFAState d2 : dfaStates) {
|
||||||
System.out.print(" "+d2.stateNumber);
|
// System.out.print(" "+d2.stateNumber);
|
||||||
}
|
}
|
||||||
//System.out.println("");
|
//System.out.println("");
|
||||||
|
|
||||||
|
@ -541,6 +575,10 @@ public class PredictionDFAFactory {
|
||||||
if ( !d.resolvedWithPredicates &&
|
if ( !d.resolvedWithPredicates &&
|
||||||
(incompletelyCoveredAlts==null || incompletelyCoveredAlts.size()==0) )
|
(incompletelyCoveredAlts==null || incompletelyCoveredAlts.size()==0) )
|
||||||
{
|
{
|
||||||
|
Set<Integer> approxContextAlts = Resolver.getAltsWithApproximateContext(d);
|
||||||
|
Set<Integer> certainAmbiguousAlt = ambigAlts;
|
||||||
|
if ( approxContextAlts!=null ) certainAmbiguousAlt.removeAll(approxContextAlts);
|
||||||
|
//if ( ambigAlts.containsAll()
|
||||||
g.tool.errMgr.ambiguity(g.fileName, d, sorted, input, altPaths,
|
g.tool.errMgr.ambiguity(g.fileName, d, sorted, input, altPaths,
|
||||||
hasPredicateBlockedByAction);
|
hasPredicateBlockedByAction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,19 @@ public class Resolver {
|
||||||
return ambiguousAlts;
|
return ambiguousAlts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<Integer> getAltsWithApproximateContext(DFAState d) {
|
||||||
|
Set<Integer> approxContextAlts = new HashSet<Integer>();
|
||||||
|
|
||||||
|
for (NFAConfig c : d.nfaConfigs) {
|
||||||
|
if ( c.context.approximated ) {
|
||||||
|
approxContextAlts.add(Utils.integer(c.alt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( approxContextAlts.size()==0 ) return null;
|
||||||
|
return approxContextAlts;
|
||||||
|
}
|
||||||
|
|
||||||
public void resolveAmbiguities(DFAState d) {
|
public void resolveAmbiguities(DFAState d) {
|
||||||
if ( PredictionDFAFactory.debug ) {
|
if ( PredictionDFAFactory.debug ) {
|
||||||
System.out.println("resolveNonDeterminisms "+d.toString());
|
System.out.println("resolveNonDeterminisms "+d.toString());
|
||||||
|
|
|
@ -8,8 +8,6 @@ import org.antlr.v4.tool.TerminalAST;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
// TODO: i don't think we create lexer NFAs anymore
|
|
||||||
|
|
||||||
public class LexerNFAFactory extends ParserNFAFactory {
|
public class LexerNFAFactory extends ParserNFAFactory {
|
||||||
public LexerNFAFactory(LexerGrammar g) { super(g); }
|
public LexerNFAFactory(LexerGrammar g) { super(g); }
|
||||||
|
|
||||||
|
@ -41,6 +39,7 @@ public class LexerNFAFactory extends ParserNFAFactory {
|
||||||
return nfa;
|
return nfa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Handle range(GrammarAST a, GrammarAST b) {
|
public Handle range(GrammarAST a, GrammarAST b) {
|
||||||
BasicState left = newState(a);
|
BasicState left = newState(a);
|
||||||
BasicState right = newState(b);
|
BasicState right = newState(b);
|
||||||
|
@ -57,6 +56,7 @@ public class LexerNFAFactory extends ParserNFAFactory {
|
||||||
* the DFA. Machine== o-'f'->o-'o'->o-'g'->o and has n+1 states
|
* the DFA. Machine== o-'f'->o-'o'->o-'g'->o and has n+1 states
|
||||||
* for n characters.
|
* for n characters.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Handle stringLiteral(TerminalAST stringLiteralAST) {
|
public Handle stringLiteral(TerminalAST stringLiteralAST) {
|
||||||
String chars = stringLiteralAST.getText();
|
String chars = stringLiteralAST.getText();
|
||||||
chars = CharSupport.getStringFromGrammarStringLiteral(chars);
|
chars = CharSupport.getStringFromGrammarStringLiteral(chars);
|
||||||
|
|
|
@ -33,6 +33,10 @@ public interface NFAFactory {
|
||||||
|
|
||||||
NFAState newState();
|
NFAState newState();
|
||||||
|
|
||||||
|
Handle label(Handle t);
|
||||||
|
|
||||||
|
Handle listLabel(Handle t);
|
||||||
|
|
||||||
Handle tokenRef(TerminalAST node);
|
Handle tokenRef(TerminalAST node);
|
||||||
|
|
||||||
/** From set build single edge graph o->o-set->o. To conform to
|
/** From set build single edge graph o->o-set->o. To conform to
|
||||||
|
|
|
@ -403,6 +403,14 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Handle label(Handle t) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Handle listLabel(Handle t) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
public NFAState newState(Class nodeType, GrammarAST node) {
|
public NFAState newState(Class nodeType, GrammarAST node) {
|
||||||
try {
|
try {
|
||||||
Constructor ctor = nodeType.getConstructor(NFA.class);
|
Constructor ctor = nodeType.getConstructor(NFA.class);
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class LexerFactory {
|
||||||
lexerST.add("modes", lg.modes.keySet());
|
lexerST.add("modes", lg.modes.keySet());
|
||||||
fileST.add("fileName", gen.getRecognizerFileName());
|
fileST.add("fileName", gen.getRecognizerFileName());
|
||||||
fileST.add("lexer", lexerST);
|
fileST.add("lexer", lexerST);
|
||||||
|
|
||||||
for (String modeName : lg.modes.keySet()) { // for each mode
|
for (String modeName : lg.modes.keySet()) { // for each mode
|
||||||
injectDFAs(lg, lexerST, modeName);
|
injectDFAs(lg, lexerST, modeName);
|
||||||
//injectPDAs(lg, lexerST, modeName);
|
//injectPDAs(lg, lexerST, modeName);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ANTLRLexer.g 2010-06-14 12:35:30
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ANTLRLexer.g 2010-06-16 13:46:52
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD licence"]
|
[The "BSD licence"]
|
||||||
|
@ -264,7 +264,7 @@ public class ANTLRLexer extends Lexer {
|
||||||
if ( (( input.LA(2) != '/')) ) {
|
if ( (( input.LA(2) != '/')) ) {
|
||||||
alt3=1;
|
alt3=1;
|
||||||
}
|
}
|
||||||
else if ( (((( true )&&( !(input.LA(1) == '*' && input.LA(2) == '/') ))||( true ))) ) {
|
else if ( ((( true )||(( true )&&( !(input.LA(1) == '*' && input.LA(2) == '/') )))) ) {
|
||||||
alt3=2;
|
alt3=2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ANTLRParser.g 2010-06-14 12:35:32
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ANTLRParser.g 2010-06-16 13:46:54
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD licence"]
|
[The "BSD licence"]
|
||||||
|
@ -339,7 +339,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: id, prequelConstruct, grammarType, mode, rules, DOC_COMMENT
|
// elements: DOC_COMMENT, id, rules, mode, grammarType, prequelConstruct
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -1184,7 +1184,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: IMPORT, delegateGrammar
|
// elements: delegateGrammar, IMPORT
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -1465,7 +1465,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: TOKENS, tokenSpec
|
// elements: tokenSpec, TOKENS
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -1620,7 +1620,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: id, STRING_LITERAL, ASSIGN
|
// elements: ASSIGN, id, STRING_LITERAL
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -1914,7 +1914,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ACTION, actionScopeName, AT, id
|
// elements: id, AT, ACTION, actionScopeName
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -2214,7 +2214,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: MODE, id, rule
|
// elements: rule, id, MODE
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -2606,7 +2606,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ruleModifiers, ruleReturns, id, ruleBlock, ARG_ACTION, exceptionGroup, DOC_COMMENT, rulePrequels
|
// elements: exceptionGroup, id, ARG_ACTION, ruleReturns, DOC_COMMENT, ruleBlock, ruleModifiers, rulePrequels
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -2918,7 +2918,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ACTION, FINALLY
|
// elements: FINALLY, ACTION
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -3352,7 +3352,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: THROWS, qid
|
// elements: qid, THROWS
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -3482,7 +3482,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ACTION, SCOPE
|
// elements: SCOPE, ACTION
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -3561,7 +3561,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: SCOPE, id
|
// elements: id, SCOPE
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -3660,7 +3660,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ACTION, id, AT
|
// elements: ACTION, AT, id
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -4178,7 +4178,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: rewrite, elements
|
// elements: elements, rewrite
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -4550,7 +4550,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: labeledElement, ebnfSuffix
|
// elements: ebnfSuffix, labeledElement
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -5257,7 +5257,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: element, TREE_BEGIN
|
// elements: TREE_BEGIN, element
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -5372,7 +5372,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: block, blockSuffixe
|
// elements: blockSuffixe, block
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -5830,7 +5830,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: id, ruleref, DOT
|
// elements: ruleref, DOT, id
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -6177,7 +6177,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: NOT, terminal
|
// elements: terminal, NOT
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -6396,7 +6396,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: altList, optionsSpec, ra
|
// elements: optionsSpec, ra, altList
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -6571,7 +6571,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: RULE_REF, ARG_ACTION, op
|
// elements: ARG_ACTION, RULE_REF, op
|
||||||
// token labels: op
|
// token labels: op
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -7909,7 +7909,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ebnfSuffix, rewriteTreeAtom
|
// elements: rewriteTreeAtom, ebnfSuffix
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -7992,7 +7992,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: rewriteTree, ebnfSuffix
|
// elements: ebnfSuffix, rewriteTree
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -8231,7 +8231,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: TOKEN_REF, ARG_ACTION, elementOptions
|
// elements: elementOptions, ARG_ACTION, TOKEN_REF
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -8472,7 +8472,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ebnfSuffix, rewriteTreeAlt
|
// elements: rewriteTreeAlt, ebnfSuffix
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -8609,7 +8609,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: rewriteTreeAtom, rewriteTreeElement, TREE_BEGIN
|
// elements: TREE_BEGIN, rewriteTreeElement, rewriteTreeAtom
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -8764,7 +8764,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: rewriteTemplateArgs, str, TEMPLATE
|
// elements: str, TEMPLATE, rewriteTemplateArgs
|
||||||
// token labels: str
|
// token labels: str
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -8913,7 +8913,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: rewriteTemplateArgs, id
|
// elements: id, rewriteTemplateArgs
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
@ -9271,7 +9271,7 @@ public class ANTLRParser extends Parser {
|
||||||
|
|
||||||
|
|
||||||
// AST REWRITE
|
// AST REWRITE
|
||||||
// elements: ACTION, id
|
// elements: id, ACTION
|
||||||
// token labels:
|
// token labels:
|
||||||
// rule labels: retval
|
// rule labels: retval
|
||||||
// token list labels:
|
// token list labels:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ASTVerifier.g 2010-06-14 12:35:33
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ASTVerifier.g 2010-06-16 13:46:55
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD license"]
|
[The "BSD license"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ActionSplitter.g 2010-06-14 12:35:32
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 ActionSplitter.g 2010-06-16 13:46:55
|
||||||
|
|
||||||
package org.antlr.v4.parse;
|
package org.antlr.v4.parse;
|
||||||
|
|
||||||
|
|
|
@ -98,10 +98,10 @@ element returns [NFAFactory.Handle p]
|
||||||
;
|
;
|
||||||
|
|
||||||
labeledElement returns [NFAFactory.Handle p]
|
labeledElement returns [NFAFactory.Handle p]
|
||||||
: ^(ASSIGN ID atom) {$p = $atom.p;}
|
: ^(ASSIGN ID atom) {$p = factory.label($atom.p);}
|
||||||
| ^(ASSIGN ID block) {$p = $block.p;}
|
| ^(ASSIGN ID block) {$p = factory.label($block.p);}
|
||||||
| ^(PLUS_ASSIGN ID atom) {$p = $atom.p;}
|
| ^(PLUS_ASSIGN ID atom) {$p = factory.listLabel($atom.p);}
|
||||||
| ^(PLUS_ASSIGN ID block) {$p = $block.p;}
|
| ^(PLUS_ASSIGN ID block) {$p = factory.listLabel($block.p);}
|
||||||
;
|
;
|
||||||
|
|
||||||
treeSpec returns [NFAFactory.Handle p]
|
treeSpec returns [NFAFactory.Handle p]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 NFABuilder.g 2010-06-14 12:35:33
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 NFABuilder.g 2010-06-16 13:46:55
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD license"]
|
[The "BSD license"]
|
||||||
|
@ -579,7 +579,7 @@ public class NFABuilder extends TreeParser {
|
||||||
|
|
||||||
|
|
||||||
match(input, Token.UP, null);
|
match(input, Token.UP, null);
|
||||||
p = (atom10!=null?atom10.p:null);
|
p = factory.label((atom10!=null?atom10.p:null));
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -597,7 +597,7 @@ public class NFABuilder extends TreeParser {
|
||||||
|
|
||||||
|
|
||||||
match(input, Token.UP, null);
|
match(input, Token.UP, null);
|
||||||
p = block11;
|
p = factory.label(block11);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -615,7 +615,7 @@ public class NFABuilder extends TreeParser {
|
||||||
|
|
||||||
|
|
||||||
match(input, Token.UP, null);
|
match(input, Token.UP, null);
|
||||||
p = (atom12!=null?atom12.p:null);
|
p = factory.listLabel((atom12!=null?atom12.p:null));
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -633,7 +633,7 @@ public class NFABuilder extends TreeParser {
|
||||||
|
|
||||||
|
|
||||||
match(input, Token.UP, null);
|
match(input, Token.UP, null);
|
||||||
p = block13;
|
p = factory.listLabel(block13);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 BasicSemanticTriggers.g 2010-06-14 12:35:34
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 BasicSemanticTriggers.g 2010-06-16 13:46:56
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD license"]
|
[The "BSD license"]
|
||||||
|
|
|
@ -156,7 +156,7 @@ rule
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int numAlts = $RULE.getFirstChildWithType(BLOCK).getChildCount();
|
int numAlts = $RULE.getFirstChildWithType(BLOCK).getChildCount();
|
||||||
Rule r = new Rule(g, $name.text, (GrammarASTWithOptions)$RULE, numAlts);
|
Rule r = new Rule(g, $name.text, (RuleAST)$RULE, numAlts);
|
||||||
if ( g.isLexer() ) r.mode = currentMode;
|
if ( g.isLexer() ) r.mode = currentMode;
|
||||||
if ( modifiers.size()>0 ) r.modifiers = modifiers;
|
if ( modifiers.size()>0 ) r.modifiers = modifiers;
|
||||||
rules.add(r);
|
rules.add(r);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 CollectSymbols.g 2010-06-14 12:35:34
|
// $ANTLR 3.2.1-SNAPSHOT May 24, 2010 15:02:05 CollectSymbols.g 2010-06-16 13:46:56
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[The "BSD license"]
|
[The "BSD license"]
|
||||||
|
@ -864,7 +864,7 @@ public class CollectSymbols extends org.antlr.v4.runtime.tree.TreeFilter {
|
||||||
if ( state.backtracking==1 ) {
|
if ( state.backtracking==1 ) {
|
||||||
|
|
||||||
int numAlts = RULE8.getFirstChildWithType(BLOCK).getChildCount();
|
int numAlts = RULE8.getFirstChildWithType(BLOCK).getChildCount();
|
||||||
Rule r = new Rule(g, (name!=null?name.getText():null), (GrammarASTWithOptions)RULE8, numAlts);
|
Rule r = new Rule(g, (name!=null?name.getText():null), (RuleAST)RULE8, numAlts);
|
||||||
if ( g.isLexer() ) r.mode = currentMode;
|
if ( g.isLexer() ) r.mode = currentMode;
|
||||||
if ( modifiers.size()>0 ) r.modifiers = modifiers;
|
if ( modifiers.size()>0 ) r.modifiers = modifiers;
|
||||||
rules.add(r);
|
rules.add(r);
|
||||||
|
|
|
@ -106,9 +106,8 @@ public class SemanticPipeline {
|
||||||
if ( g.isLexer() ) assignLexerTokenTypes(g, collector);
|
if ( g.isLexer() ) assignLexerTokenTypes(g, collector);
|
||||||
else assignTokenTypes(g, collector, symcheck);
|
else assignTokenTypes(g, collector, symcheck);
|
||||||
|
|
||||||
UseDefAnalyzer usedef = new UseDefAnalyzer();
|
UseDefAnalyzer.checkRewriteElementsPresentOnLeftSide(g);
|
||||||
usedef.checkRewriteElementsPresentOnLeftSide(g, collector.rules);
|
UseDefAnalyzer.trackTokenRuleRefsInActions(g);
|
||||||
usedef.trackTokenRuleRefsInActions(g);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void identifyStartRules(CollectSymbols collector) {
|
void identifyStartRules(CollectSymbols collector) {
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package org.antlr.v4.semantics;
|
package org.antlr.v4.semantics;
|
||||||
|
|
||||||
import org.antlr.v4.automata.Label;
|
import org.antlr.v4.automata.Label;
|
||||||
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.tool.*;
|
import org.antlr.v4.tool.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
|
||||||
/** Look for errors and deadcode stuff */
|
/** Look for errors and deadcode stuff */
|
||||||
public class UseDefAnalyzer {
|
public class UseDefAnalyzer {
|
||||||
public void checkRewriteElementsPresentOnLeftSide(Grammar g, List<Rule> rules) {
|
public static void checkRewriteElementsPresentOnLeftSide(Grammar g) {
|
||||||
for (Rule r : rules) {
|
for (Rule r : g.rules.values()) {
|
||||||
for (int a=1; a<=r.numberOfAlts; a++) {
|
for (int a=1; a<=r.numberOfAlts; a++) {
|
||||||
Alternative alt = r.alt[a];
|
Alternative alt = r.alt[a];
|
||||||
for (GrammarAST e : alt.rewriteElements) {
|
for (GrammarAST e : alt.rewriteElements) {
|
||||||
|
@ -26,7 +27,7 @@ public class UseDefAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// side-effect: updates Alternative with refs in actions
|
// side-effect: updates Alternative with refs in actions
|
||||||
public void trackTokenRuleRefsInActions(Grammar g) {
|
public static void trackTokenRuleRefsInActions(Grammar g) {
|
||||||
for (Rule r : g.rules.values()) {
|
for (Rule r : g.rules.values()) {
|
||||||
for (int i=1; i<=r.numberOfAlts; i++) {
|
for (int i=1; i<=r.numberOfAlts; i++) {
|
||||||
Alternative alt = r.alt[i];
|
Alternative alt = r.alt[i];
|
||||||
|
@ -38,4 +39,31 @@ public class UseDefAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Find all rules reachable from r directly or indirectly for all r in g */
|
||||||
|
public static Map<Rule, Set<Rule>> getRuleDependencies(Grammar g) {
|
||||||
|
return getRuleDependencies(g, g.rules.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Rule, Set<Rule>> getRuleDependencies(LexerGrammar g, String modeName) {
|
||||||
|
return getRuleDependencies(g, g.modes.get(modeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Rule, Set<Rule>> getRuleDependencies(Grammar g, Collection<Rule> rules) {
|
||||||
|
Map<Rule, Set<Rule>> dependencies = new HashMap<Rule, Set<Rule>>();
|
||||||
|
|
||||||
|
for (Rule r : rules) {
|
||||||
|
List<GrammarAST> tokenRefs = r.ast.getNodesWithType(ANTLRParser.TOKEN_REF);
|
||||||
|
for (GrammarAST tref : tokenRefs) {
|
||||||
|
Set<Rule> calls = dependencies.get(r);
|
||||||
|
if ( calls==null ) {
|
||||||
|
calls = new HashSet<Rule>();
|
||||||
|
dependencies.put(r, calls);
|
||||||
|
}
|
||||||
|
calls.add(g.getRule(tref.getText()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package org.antlr.v4.tool;
|
package org.antlr.v4.tool;
|
||||||
|
|
||||||
import org.antlr.runtime.BitSet;
|
|
||||||
import org.antlr.runtime.CommonToken;
|
import org.antlr.runtime.CommonToken;
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.runtime.tree.Tree;
|
import org.antlr.runtime.tree.Tree;
|
||||||
import org.antlr.v4.automata.NFAState;
|
import org.antlr.v4.automata.NFAState;
|
||||||
|
import org.antlr.v4.misc.BitSet;
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.runtime.tree.CommonTree;
|
import org.antlr.v4.runtime.tree.CommonTree;
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ public class GrammarAST extends CommonTree {
|
||||||
GrammarAST t = null;
|
GrammarAST t = null;
|
||||||
while ( work.size()>0 ) {
|
while ( work.size()>0 ) {
|
||||||
t = work.remove(0);
|
t = work.remove(0);
|
||||||
if ( types.member(t.getType()) ) nodes.add(this);
|
if ( types.member(t.getType()) ) nodes.add(t);
|
||||||
work.addAll(children);
|
if ( t.children!=null ) work.addAll(t.children);
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class Rule implements AttributeResolver {
|
||||||
public String name;
|
public String name;
|
||||||
public List<GrammarAST> modifiers;
|
public List<GrammarAST> modifiers;
|
||||||
|
|
||||||
public GrammarASTWithOptions ast;
|
public RuleAST ast;
|
||||||
public AttributeDict args;
|
public AttributeDict args;
|
||||||
public AttributeDict retvals;
|
public AttributeDict retvals;
|
||||||
public AttributeDict scope; // scope { int i; }
|
public AttributeDict scope; // scope { int i; }
|
||||||
|
@ -86,7 +86,7 @@ public class Rule implements AttributeResolver {
|
||||||
/** All rules have unique index 1..n */
|
/** All rules have unique index 1..n */
|
||||||
public int index;
|
public int index;
|
||||||
|
|
||||||
public Rule(Grammar g, String name, GrammarASTWithOptions ast, int numberOfAlts) {
|
public Rule(Grammar g, String name, RuleAST ast, int numberOfAlts) {
|
||||||
this.g = g;
|
this.g = g;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.ast = ast;
|
this.ast = ast;
|
||||||
|
|
Loading…
Reference in New Issue