forked from jasder/antlr
got left-recursion core in
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6738]
This commit is contained in:
parent
572aeb0071
commit
4125ed8fb4
|
@ -2,8 +2,8 @@ package org.antlr.v4;
|
||||||
|
|
||||||
import org.antlr.runtime.*;
|
import org.antlr.runtime.*;
|
||||||
import org.antlr.runtime.tree.TreeWizard;
|
import org.antlr.runtime.tree.TreeWizard;
|
||||||
|
import org.antlr.v4.analysis.AnalysisPipeline;
|
||||||
import org.antlr.v4.automata.LexerNFAFactory;
|
import org.antlr.v4.automata.LexerNFAFactory;
|
||||||
import org.antlr.v4.automata.NFA;
|
|
||||||
import org.antlr.v4.automata.NFAFactory;
|
import org.antlr.v4.automata.NFAFactory;
|
||||||
import org.antlr.v4.automata.ParserNFAFactory;
|
import org.antlr.v4.automata.ParserNFAFactory;
|
||||||
import org.antlr.v4.parse.ANTLRLexer;
|
import org.antlr.v4.parse.ANTLRLexer;
|
||||||
|
@ -370,10 +370,12 @@ public class Tool {
|
||||||
// BUILD NFA FROM AST
|
// BUILD NFA FROM AST
|
||||||
NFAFactory factory = new ParserNFAFactory(g);
|
NFAFactory factory = new ParserNFAFactory(g);
|
||||||
if ( g.getType()==ANTLRParser.LEXER ) factory = new LexerNFAFactory(g);
|
if ( g.getType()==ANTLRParser.LEXER ) factory = new LexerNFAFactory(g);
|
||||||
NFA nfa = factory.createNFA();
|
g.nfa = factory.createNFA();
|
||||||
|
|
||||||
// PERFORM GRAMMAR ANALYSIS ON NFA: BUILD DECISION DFAs
|
|
||||||
|
|
||||||
|
// PERFORM GRAMMAR ANALYSIS ON NFA: BUILD DECISION DFAs
|
||||||
|
AnalysisPipeline anal = new AnalysisPipeline();
|
||||||
|
anal.process(g);
|
||||||
|
|
||||||
// GENERATE CODE
|
// GENERATE CODE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.DecisionState;
|
||||||
|
import org.antlr.v4.tool.Grammar;
|
||||||
|
|
||||||
|
public class AnalysisPipeline {
|
||||||
|
public void process(Grammar g) {
|
||||||
|
// LEFT-RECURSION CHECK
|
||||||
|
LeftRecursionDetector lr = new LeftRecursionDetector(g.nfa);
|
||||||
|
lr.check();
|
||||||
|
if ( lr.listOfRecursiveCycles.size()>0 ) return; // bail out
|
||||||
|
|
||||||
|
// BUILD DFA FOR EACH DECISION
|
||||||
|
for (DecisionState s : g.nfa.decisionToNFAState) {
|
||||||
|
createDFA(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createDFA(DecisionState s) {
|
||||||
|
// TRY APPROXIMATE LL(*) ANALYSIS
|
||||||
|
|
||||||
|
// REAL LL(*) ANALYSIS IF THAT FAILS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.*;
|
||||||
|
import org.antlr.v4.tool.Rule;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class LeftRecursionDetector {
|
||||||
|
public NFA nfa;
|
||||||
|
|
||||||
|
/** Holds a list of cycles (sets of rule names). */
|
||||||
|
public List<Set<Rule>> listOfRecursiveCycles = new ArrayList<Set<Rule>>();
|
||||||
|
|
||||||
|
/** Which rule start states have we visited while looking for a single
|
||||||
|
* left-recursion check?
|
||||||
|
*/
|
||||||
|
Set<RuleStartState> rulesVisitedPerRuleCheck = new HashSet<RuleStartState>();
|
||||||
|
|
||||||
|
/** prevents epsilon-loop-induced infinite recursion. */
|
||||||
|
Set<NFAState> visitedStates = new HashSet<NFAState>();
|
||||||
|
|
||||||
|
public LeftRecursionDetector(NFA nfa) { this.nfa = nfa; }
|
||||||
|
|
||||||
|
public void check() {
|
||||||
|
for (RuleStartState start : nfa.ruleToStartState.values()) {
|
||||||
|
//System.out.print("check "+start.rule.name);
|
||||||
|
rulesVisitedPerRuleCheck.clear();
|
||||||
|
rulesVisitedPerRuleCheck.add(start);
|
||||||
|
FASerializer ser = new FASerializer(nfa.g, start);
|
||||||
|
//System.out.print(":\n"+ser+"\n");
|
||||||
|
|
||||||
|
check(start.rule, start);
|
||||||
|
}
|
||||||
|
//System.out.println("cycles="+listOfRecursiveCycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** From state s, look for any transition to a rule that is currently
|
||||||
|
* being traced. When tracing r, visitedPerRuleCheck has r
|
||||||
|
* initially. If you reach a rule stop state, return but notify the
|
||||||
|
* invoking rule that the called rule is nullable. This implies that
|
||||||
|
* invoking rule must look at follow transition for that invoking state.
|
||||||
|
*
|
||||||
|
* The visitedStates tracks visited states within a single rule so
|
||||||
|
* we can avoid epsilon-loop-induced infinite recursion here. Keep
|
||||||
|
* filling the cycles in listOfRecursiveCycles and also, as a
|
||||||
|
* side-effect, set leftRecursiveRules.
|
||||||
|
*/
|
||||||
|
public boolean check(Rule enclosingRule, NFAState s) {
|
||||||
|
if ( s instanceof RuleStopState ) return true;
|
||||||
|
if ( visitedStates.contains(s) ) return false;
|
||||||
|
visitedStates.add(s);
|
||||||
|
|
||||||
|
int n = s.getNumberOfTransitions();
|
||||||
|
boolean stateReachesStopState = false;
|
||||||
|
for (int i=0; i<n; i++) {
|
||||||
|
Transition t = s.transition(i);
|
||||||
|
if ( t instanceof RuleTransition ) {
|
||||||
|
RuleTransition rt = (RuleTransition) t;
|
||||||
|
Rule r = rt.rule;
|
||||||
|
if ( rulesVisitedPerRuleCheck.contains((RuleStartState)t.target) ) {
|
||||||
|
addRulesToCycle(enclosingRule, r);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rulesVisitedPerRuleCheck.add((RuleStartState)t.target);
|
||||||
|
boolean nullable = check(r, t.target);
|
||||||
|
if ( nullable ) {
|
||||||
|
stateReachesStopState |= check(enclosingRule, rt.followState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( t.isEpsilon() ) {
|
||||||
|
stateReachesStopState |= check(enclosingRule, t.target);
|
||||||
|
}
|
||||||
|
// ignore non-epsilon transitions
|
||||||
|
}
|
||||||
|
return stateReachesStopState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enclosingRule calls targetRule. Find the cycle containing
|
||||||
|
* the target and add the caller. Find the cycle containing the caller
|
||||||
|
* and add the target. If no cycles contain either, then create a new
|
||||||
|
* cycle.
|
||||||
|
*/
|
||||||
|
protected void addRulesToCycle(Rule enclosingRule, Rule targetRule) {
|
||||||
|
System.err.println("left-recursion to "+targetRule.name+" from "+enclosingRule.name);
|
||||||
|
boolean foundCycle = false;
|
||||||
|
for (int i = 0; i < listOfRecursiveCycles.size(); i++) {
|
||||||
|
Set<Rule> rulesInCycle = listOfRecursiveCycles.get(i);
|
||||||
|
// ensure both rules are in same cycle
|
||||||
|
if ( rulesInCycle.contains(targetRule) ) {
|
||||||
|
rulesInCycle.add(enclosingRule);
|
||||||
|
foundCycle = true;
|
||||||
|
}
|
||||||
|
if ( rulesInCycle.contains(enclosingRule) ) {
|
||||||
|
rulesInCycle.add(targetRule);
|
||||||
|
foundCycle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !foundCycle ) {
|
||||||
|
Set<Rule> cycle = new HashSet<Rule>();
|
||||||
|
cycle.add(targetRule);
|
||||||
|
cycle.add(enclosingRule);
|
||||||
|
listOfRecursiveCycles.add(cycle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class BlockStartState extends NFAState {
|
public class BlockStartState extends DecisionState {
|
||||||
public static final int INITIAL_NUM_TRANSITIONS = 4;
|
public static final int INITIAL_NUM_TRANSITIONS = 4;
|
||||||
|
|
||||||
BlockEndState endState;
|
BlockEndState endState;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.antlr.v4.automata;
|
||||||
|
|
||||||
|
public class DecisionState extends BasicState {
|
||||||
|
public DecisionState(NFA nfa) { super(nfa); }
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package org.antlr.v4.automata;
|
||||||
public class EpsilonTransition extends Transition {
|
public class EpsilonTransition extends Transition {
|
||||||
public EpsilonTransition(NFAState target) { super(target); }
|
public EpsilonTransition(NFAState target) { super(target); }
|
||||||
|
|
||||||
|
public boolean isEpsilon() { return true; }
|
||||||
|
|
||||||
public int compareTo(Object o) {
|
public int compareTo(Object o) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package org.antlr.v4.automata;
|
package org.antlr.v4.automata;
|
||||||
|
|
||||||
import org.antlr.runtime.RecognitionException;
|
|
||||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
|
||||||
import org.antlr.v4.codegen.Target;
|
import org.antlr.v4.codegen.Target;
|
||||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
import org.antlr.v4.tool.Grammar;
|
||||||
import org.antlr.v4.parse.NFABuilder;
|
import org.antlr.v4.tool.GrammarAST;
|
||||||
import org.antlr.v4.tool.*;
|
import org.antlr.v4.tool.TerminalAST;
|
||||||
import org.stringtemplate.v4.misc.Misc;
|
import org.stringtemplate.v4.misc.Misc;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
|
@ -13,18 +11,7 @@ public class LexerNFAFactory extends ParserNFAFactory {
|
||||||
public LexerNFAFactory(Grammar g) { super(g); }
|
public LexerNFAFactory(Grammar g) { super(g); }
|
||||||
|
|
||||||
public NFA createNFA() {
|
public NFA createNFA() {
|
||||||
createRuleStartAndStopNFAStates();
|
_createNFA();
|
||||||
|
|
||||||
GrammarASTAdaptor adaptor = new GrammarASTAdaptor();
|
|
||||||
for (Rule r : g.rules.values()) {
|
|
||||||
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,r.ast);
|
|
||||||
NFABuilder b = new NFABuilder(nodes,this);
|
|
||||||
try { b.rule(); }
|
|
||||||
catch (RecognitionException re) {
|
|
||||||
ErrorManager.fatalInternalError("bad grammar AST structure", re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nfa;
|
return nfa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.antlr.v4.automata;
|
package org.antlr.v4.automata;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class LoopbackState extends BasicState {
|
public class LoopbackState extends DecisionState {
|
||||||
EpsilonTransition loopBack; // edge 2 (transition is edge 1)
|
EpsilonTransition loopBack; // edge 2 (transition is edge 1)
|
||||||
|
|
||||||
/** What's its decision number from 1..n? */
|
/** What's its decision number from 1..n? */
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.antlr.v4.tool.Grammar;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.Rule;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -17,10 +17,10 @@ public class NFA {
|
||||||
* can go back later and build DFA predictors for them. This includes
|
* can go back later and build DFA predictors for them. This includes
|
||||||
* all the rules, subrules, optional blocks, ()+, ()* etc...
|
* all the rules, subrules, optional blocks, ()+, ()* etc...
|
||||||
*/
|
*/
|
||||||
public List<NFAState> decisionToNFAState = new ArrayList<NFAState>();
|
public List<DecisionState> decisionToNFAState = new ArrayList<DecisionState>();
|
||||||
|
|
||||||
public Map<Rule, RuleStartState> ruleToStartState = new HashMap<Rule, RuleStartState>();
|
public Map<Rule, RuleStartState> ruleToStartState = new LinkedHashMap<Rule, RuleStartState>();
|
||||||
public Map<Rule, RuleStopState> ruleToStopState = new HashMap<Rule, RuleStopState>();
|
public Map<Rule, RuleStopState> ruleToStopState = new LinkedHashMap<Rule, RuleStopState>();
|
||||||
|
|
||||||
int stateNumber = 0;
|
int stateNumber = 0;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class NFA {
|
||||||
state.stateNumber = stateNumber++;
|
state.stateNumber = stateNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int defineDecisionState(NFAState s) {
|
public int defineDecisionState(DecisionState s) {
|
||||||
decisionToNFAState.add(s);
|
decisionToNFAState.add(s);
|
||||||
return decisionToNFAState.size()-1;
|
return decisionToNFAState.size()-1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package org.antlr.v4.automata;
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||||
import org.antlr.v4.misc.IntSet;
|
import org.antlr.v4.misc.IntSet;
|
||||||
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.parse.GrammarASTAdaptor;
|
import org.antlr.v4.parse.GrammarASTAdaptor;
|
||||||
import org.antlr.v4.parse.NFABuilder;
|
import org.antlr.v4.parse.NFABuilder;
|
||||||
import org.antlr.v4.tool.*;
|
import org.antlr.v4.tool.*;
|
||||||
|
@ -23,20 +24,29 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
public ParserNFAFactory(Grammar g) { this.g = g; nfa = new NFA(g); }
|
public ParserNFAFactory(Grammar g) { this.g = g; nfa = new NFA(g); }
|
||||||
|
|
||||||
public NFA createNFA() {
|
public NFA createNFA() {
|
||||||
|
_createNFA();
|
||||||
|
addEOFTransitionToStartRules();
|
||||||
|
return nfa;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void _createNFA() {
|
||||||
createRuleStartAndStopNFAStates();
|
createRuleStartAndStopNFAStates();
|
||||||
|
|
||||||
GrammarASTAdaptor adaptor = new GrammarASTAdaptor();
|
GrammarASTAdaptor adaptor = new GrammarASTAdaptor();
|
||||||
for (Rule r : g.rules.values()) {
|
for (Rule r : g.rules.values()) {
|
||||||
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,r.ast);
|
// find rule's block
|
||||||
|
GrammarAST blk = (GrammarAST)r.ast.getFirstChildWithType(ANTLRParser.BLOCK);
|
||||||
|
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,blk);
|
||||||
NFABuilder b = new NFABuilder(nodes,this);
|
NFABuilder b = new NFABuilder(nodes,this);
|
||||||
try { b.rule(); }
|
try {
|
||||||
|
setCurrentRuleName(r.name);
|
||||||
|
Handle h = b.block();
|
||||||
|
rule(r.ast, r.name, h);
|
||||||
|
}
|
||||||
catch (RecognitionException re) {
|
catch (RecognitionException re) {
|
||||||
ErrorManager.fatalInternalError("bad grammar AST structure", re);
|
ErrorManager.fatalInternalError("bad grammar AST structure", re);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addEOFTransitionToStartRules();
|
|
||||||
return nfa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentRuleName(String name) {
|
public void setCurrentRuleName(String name) {
|
||||||
|
@ -51,8 +61,8 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
RuleStopState stop = nfa.ruleToStopState.get(r);
|
RuleStopState stop = nfa.ruleToStopState.get(r);
|
||||||
epsilon(blk.right, stop);
|
epsilon(blk.right, stop);
|
||||||
Handle h = new Handle(start, stop);
|
Handle h = new Handle(start, stop);
|
||||||
FASerializer ser = new FASerializer(g, h.left);
|
// FASerializer ser = new FASerializer(g, h.left);
|
||||||
System.out.println(ruleAST.toStringTree()+":\n"+ser);
|
// System.out.println(ruleAST.toStringTree()+":\n"+ser);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +155,7 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
* the SEMPRED token.
|
* the SEMPRED token.
|
||||||
*/
|
*/
|
||||||
public Handle sempred(GrammarAST pred) {
|
public Handle sempred(GrammarAST pred) {
|
||||||
System.out.println("sempred: "+ pred);
|
//System.out.println("sempred: "+ pred);
|
||||||
BasicState left = newState(pred);
|
BasicState left = newState(pred);
|
||||||
NFAState right = newState(pred);
|
NFAState right = newState(pred);
|
||||||
left.transition = new PredicateTransition(pred, right);
|
left.transition = new PredicateTransition(pred, right);
|
||||||
|
@ -162,7 +172,7 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
* having seen an action (5-5-2008).
|
* having seen an action (5-5-2008).
|
||||||
*/
|
*/
|
||||||
public Handle action(GrammarAST action) {
|
public Handle action(GrammarAST action) {
|
||||||
System.out.println("action: "+action);
|
//System.out.println("action: "+action);
|
||||||
BasicState left = newState(action);
|
BasicState left = newState(action);
|
||||||
NFAState right = newState(action);
|
NFAState right = newState(action);
|
||||||
left.transition = new ActionTransition(action, right);
|
left.transition = new ActionTransition(action, right);
|
||||||
|
@ -205,10 +215,10 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
epsilon(start, alt.left);
|
epsilon(start, alt.left);
|
||||||
epsilon(alt.right, end);
|
epsilon(alt.right, end);
|
||||||
}
|
}
|
||||||
Handle h = new Handle(start, end);
|
|
||||||
FASerializer ser = new FASerializer(g, h.left);
|
|
||||||
nfa.defineDecisionState(start);
|
nfa.defineDecisionState(start);
|
||||||
System.out.println(blkAST.toStringTree()+":\n"+ser);
|
Handle h = new Handle(start, end);
|
||||||
|
// FASerializer ser = new FASerializer(g, h.left);
|
||||||
|
// System.out.println(blkAST.toStringTree()+":\n"+ser);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,8 +244,8 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
public Handle optional(GrammarAST optAST, Handle blk) {
|
public Handle optional(GrammarAST optAST, Handle blk) {
|
||||||
if ( blk.left instanceof BlockStartState ) {
|
if ( blk.left instanceof BlockStartState ) {
|
||||||
epsilon(blk.left, blk.right);
|
epsilon(blk.left, blk.right);
|
||||||
FASerializer ser = new FASerializer(g, blk.left);
|
// FASerializer ser = new FASerializer(g, blk.left);
|
||||||
System.out.println(optAST.toStringTree()+":\n"+ser);
|
// System.out.println(optAST.toStringTree()+":\n"+ser);
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,8 +259,8 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
nfa.defineDecisionState(start);
|
nfa.defineDecisionState(start);
|
||||||
|
|
||||||
Handle h = new Handle(start, end);
|
Handle h = new Handle(start, end);
|
||||||
FASerializer ser = new FASerializer(g, h.left);
|
// FASerializer ser = new FASerializer(g, h.left);
|
||||||
System.out.println(optAST.toStringTree()+":\n"+ser);
|
// System.out.println(optAST.toStringTree()+":\n"+ser);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +282,7 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
epsilon(loop, blk.left);
|
epsilon(loop, blk.left);
|
||||||
epsilon(blk.right, loop);
|
epsilon(blk.right, loop);
|
||||||
epsilon(loop, end);
|
epsilon(loop, end);
|
||||||
|
nfa.defineDecisionState(loop);
|
||||||
return new Handle(start, end);
|
return new Handle(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +317,8 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
epsilon(loop, blk.left);
|
epsilon(loop, blk.left);
|
||||||
epsilon(blk.right, loop);
|
epsilon(blk.right, loop);
|
||||||
epsilon(loop, end);
|
epsilon(loop, end);
|
||||||
|
nfa.defineDecisionState(start);
|
||||||
|
nfa.defineDecisionState(loop);
|
||||||
return new Handle(start, end);
|
return new Handle(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ public class PredicateTransition extends Transition {
|
||||||
this.semanticContext = new SemanticContext.Predicate(predicateASTNode);
|
this.semanticContext = new SemanticContext.Predicate(predicateASTNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEpsilon() { return true; }
|
||||||
|
|
||||||
public int compareTo(Object o) {
|
public int compareTo(Object o) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ public class RuleTransition extends Transition {
|
||||||
this.followState = followState;
|
this.followState = followState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEpsilon() { return true; }
|
||||||
|
|
||||||
public int compareTo(Object o) {
|
public int compareTo(Object o) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,12 @@ package org.antlr.v4.automata;
|
||||||
*/
|
*/
|
||||||
public abstract class Transition implements Comparable {
|
public abstract class Transition implements Comparable {
|
||||||
/** The target of this transition */
|
/** The target of this transition */
|
||||||
public State target;
|
public NFAState target;
|
||||||
|
|
||||||
public Transition() { }
|
public Transition() { }
|
||||||
|
|
||||||
public Transition(NFAState target) { this.target = target; }
|
public Transition(NFAState target) { this.target = target; }
|
||||||
|
|
||||||
|
/** Are we epsilon, action, sempred? */
|
||||||
|
public boolean isEpsilon() { return false; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,6 @@ import org.antlr.v4.runtime.tree.CommonTree; // use updated v4 one not v3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rule returns [NFAFactory.Handle p]
|
|
||||||
: ^(RULE name=ID ~BLOCK* {factory.setCurrentRuleName($name.text);} block)
|
|
||||||
{$p = factory.rule($RULE, $name.text, $block.p);}
|
|
||||||
;
|
|
||||||
|
|
||||||
block returns [NFAFactory.Handle p]
|
block returns [NFAFactory.Handle p]
|
||||||
@init {List<NFAFactory.Handle> alts = new ArrayList<NFAFactory.Handle>();}
|
@init {List<NFAFactory.Handle> alts = new ArrayList<NFAFactory.Handle>();}
|
||||||
: ^(BLOCK (^(OPTIONS .+))? (a=alternative {alts.add($a.p);})+)
|
: ^(BLOCK (^(OPTIONS .+))? (a=alternative {alts.add($a.p);})+)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@ import org.antlr.runtime.*;
|
||||||
import org.antlr.runtime.tree.TreeWizard;
|
import org.antlr.runtime.tree.TreeWizard;
|
||||||
import org.antlr.v4.Tool;
|
import org.antlr.v4.Tool;
|
||||||
import org.antlr.v4.automata.Label;
|
import org.antlr.v4.automata.Label;
|
||||||
|
import org.antlr.v4.automata.NFA;
|
||||||
import org.antlr.v4.codegen.Target;
|
import org.antlr.v4.codegen.Target;
|
||||||
import org.antlr.v4.parse.ANTLRLexer;
|
import org.antlr.v4.parse.ANTLRLexer;
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
|
@ -34,7 +35,6 @@ public class Grammar implements AttributeResolver {
|
||||||
put("combined:TOKEN_LABEL", AttributeDict.predefinedTokenDict);
|
put("combined:TOKEN_LABEL", AttributeDict.predefinedTokenDict);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public Tool tool;
|
|
||||||
public String name;
|
public String name;
|
||||||
public GrammarRootAST ast;
|
public GrammarRootAST ast;
|
||||||
public String text; // testing only
|
public String text; // testing only
|
||||||
|
@ -49,6 +49,13 @@ public class Grammar implements AttributeResolver {
|
||||||
public List<Grammar> importedGrammars;
|
public List<Grammar> importedGrammars;
|
||||||
public Map<String, Rule> rules = new LinkedHashMap<String, Rule>();
|
public Map<String, Rule> rules = new LinkedHashMap<String, Rule>();
|
||||||
|
|
||||||
|
/** The NFA that represents the grammar with edges labelled with tokens
|
||||||
|
* or epsilon. It is more suitable to analysis than an AST representation.
|
||||||
|
*/
|
||||||
|
public NFA nfa;
|
||||||
|
|
||||||
|
public Tool tool;
|
||||||
|
|
||||||
/** Token names and literal tokens like "void" are uniquely indexed.
|
/** Token names and literal tokens like "void" are uniquely indexed.
|
||||||
* with -1 implying EOF. Characters are different; they go from
|
* with -1 implying EOF. Characters are different; they go from
|
||||||
* -1 (EOF) to \uFFFE. For example, 0 could be a binary byte you
|
* -1 (EOF) to \uFFFE. For example, 0 could be a binary byte you
|
||||||
|
@ -120,6 +127,8 @@ public class Grammar implements AttributeResolver {
|
||||||
}
|
}
|
||||||
initTokenSymbolTables();
|
initTokenSymbolTables();
|
||||||
|
|
||||||
|
if ( this.ast==null || this.ast.hasErrors ) return;
|
||||||
|
|
||||||
Tool antlr = new Tool();
|
Tool antlr = new Tool();
|
||||||
SemanticPipeline sem = new SemanticPipeline();
|
SemanticPipeline sem = new SemanticPipeline();
|
||||||
sem.process(this);
|
sem.process(this);
|
||||||
|
|
|
@ -203,11 +203,12 @@ public class Rule implements AttributeResolver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Rule{" +
|
StringBuilder buf = new StringBuilder();
|
||||||
"name='" + name + '\'' +
|
buf.append("Rule{name="+name);
|
||||||
", args=" + args +
|
if ( args!=null ) buf.append(", args=" + args);
|
||||||
", retvals=" + retvals +
|
if ( retvals!=null ) buf.append(", retvals=" + retvals);
|
||||||
", scope=" + scope +
|
if ( scope!=null ) buf.append(", scope=" + scope);
|
||||||
'}';
|
buf.append("}");
|
||||||
|
return buf.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.antlr.runtime.RecognitionException;
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.runtime.TokenSource;
|
import org.antlr.runtime.TokenSource;
|
||||||
import org.antlr.v4.Tool;
|
import org.antlr.v4.Tool;
|
||||||
import org.antlr.v4.semantics.SemanticPipeline;
|
|
||||||
import org.antlr.v4.tool.ANTLRErrorListener;
|
import org.antlr.v4.tool.ANTLRErrorListener;
|
||||||
import org.antlr.v4.tool.ErrorManager;
|
import org.antlr.v4.tool.ErrorManager;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.tool.Grammar;
|
||||||
|
@ -433,10 +432,6 @@ public abstract class BaseTest {
|
||||||
if ( g.ast!=null ) System.out.println(g.ast.toStringTree());
|
if ( g.ast!=null ) System.out.println(g.ast.toStringTree());
|
||||||
else System.out.println("null tree");
|
else System.out.println("null tree");
|
||||||
}
|
}
|
||||||
if ( g.ast!=null && !g.ast.hasErrors ) {
|
|
||||||
SemanticPipeline sem = new SemanticPipeline();
|
|
||||||
sem.process(g);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (RecognitionException re) {
|
catch (RecognitionException re) {
|
||||||
re.printStackTrace(System.err);
|
re.printStackTrace(System.err);
|
||||||
|
|
Loading…
Reference in New Issue