forked from jasder/antlr
*.g cmdline works now to topologically sort by tokenVocab dependencies.
This commit is contained in:
parent
fcb67d8d93
commit
3638073efe
|
@ -14,7 +14,7 @@ member
|
||||||
stat: expr ';'
|
stat: expr ';'
|
||||||
{System.out.println("found expr: "+$stat.text);}
|
{System.out.println("found expr: "+$stat.text);}
|
||||||
| ID '=' expr ';'
|
| ID '=' expr ';'
|
||||||
{System.out.println("found assign: "+$stat.text);}
|
{System.out.println("found assign: "+$stat.text+$ID.text);}
|
||||||
;
|
;
|
||||||
|
|
||||||
expr: INT
|
expr: INT
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
grammar T;
|
lexer grammar T;
|
||||||
|
A : 'a';
|
||||||
tokens { A,B }
|
|
||||||
|
|
||||||
s : A ;
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
package org.antlr.v4;
|
package org.antlr.v4;
|
||||||
|
|
||||||
|
import org.antlr.misc.Graph;
|
||||||
import org.antlr.runtime.ANTLRFileStream;
|
import org.antlr.runtime.ANTLRFileStream;
|
||||||
import org.antlr.runtime.ANTLRStringStream;
|
import org.antlr.runtime.ANTLRStringStream;
|
||||||
import org.antlr.runtime.CharStream;
|
import org.antlr.runtime.CharStream;
|
||||||
|
@ -221,7 +222,7 @@ public class Tool {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( arg.charAt(0)!='-' ) { // file name
|
if ( arg.charAt(0)!='-' ) { // file name
|
||||||
grammarFiles.add(arg);
|
if ( !grammarFiles.contains(arg) ) grammarFiles.add(arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
@ -316,14 +317,11 @@ public class Tool {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processGrammarsOnCommandLine() {
|
public void processGrammarsOnCommandLine() {
|
||||||
for (String fileName : grammarFiles) {
|
List<GrammarRootAST> sortedGrammars = sortGrammarByTokenVocab(grammarFiles);
|
||||||
GrammarAST t = loadGrammar(fileName);
|
|
||||||
if ( t==null || t instanceof GrammarASTErrorNode) return; // came back as error node
|
|
||||||
if ( ((GrammarRootAST)t).hasErrors ) return;
|
|
||||||
GrammarRootAST ast = (GrammarRootAST)t;
|
|
||||||
|
|
||||||
final Grammar g = createGrammar(ast);
|
for (GrammarRootAST t : sortedGrammars) {
|
||||||
g.fileName = fileName;
|
final Grammar g = createGrammar(t);
|
||||||
|
g.fileName = t.fileName;
|
||||||
process(g, true);
|
process(g, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +335,6 @@ public class Tool {
|
||||||
public void process(Grammar g, boolean gencode) {
|
public void process(Grammar g, boolean gencode) {
|
||||||
g.loadImportedGrammars();
|
g.loadImportedGrammars();
|
||||||
|
|
||||||
|
|
||||||
GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
|
GrammarTransformPipeline transform = new GrammarTransformPipeline(g, this);
|
||||||
transform.process();
|
transform.process();
|
||||||
|
|
||||||
|
@ -367,13 +364,12 @@ public class Tool {
|
||||||
if ( g.ast!=null && internalOption_PrintGrammarTree ) System.out.println(g.ast.toStringTree());
|
if ( g.ast!=null && internalOption_PrintGrammarTree ) System.out.println(g.ast.toStringTree());
|
||||||
//g.ast.inspect();
|
//g.ast.inspect();
|
||||||
|
|
||||||
if ( errMgr.getNumErrors()>0 ) return;
|
int prevErrors = errMgr.getNumErrors();
|
||||||
|
|
||||||
// MAKE SURE GRAMMAR IS SEMANTICALLY CORRECT (FILL IN GRAMMAR OBJECT)
|
// MAKE SURE GRAMMAR IS SEMANTICALLY CORRECT (FILL IN GRAMMAR OBJECT)
|
||||||
SemanticPipeline sem = new SemanticPipeline(g);
|
SemanticPipeline sem = new SemanticPipeline(g);
|
||||||
sem.process();
|
sem.process();
|
||||||
|
|
||||||
if ( errMgr.getNumErrors()>0 ) return;
|
if ( errMgr.getNumErrors()>prevErrors ) return;
|
||||||
|
|
||||||
// BUILD ATN FROM AST
|
// BUILD ATN FROM AST
|
||||||
ATNFactory factory;
|
ATNFactory factory;
|
||||||
|
@ -389,7 +385,7 @@ public class Tool {
|
||||||
|
|
||||||
//if ( generate_DFA_dot ) generateDFAs(g);
|
//if ( generate_DFA_dot ) generateDFAs(g);
|
||||||
|
|
||||||
if ( g.tool.getNumErrors()>0 ) return;
|
if ( g.tool.getNumErrors()>prevErrors ) return;
|
||||||
|
|
||||||
// GENERATE CODE
|
// GENERATE CODE
|
||||||
if ( gencode ) {
|
if ( gencode ) {
|
||||||
|
@ -398,6 +394,63 @@ public class Tool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<GrammarRootAST> sortGrammarByTokenVocab(List<String> fileNames) {
|
||||||
|
// System.out.println(fileNames);
|
||||||
|
Graph<String> g = new Graph<String>();
|
||||||
|
List<GrammarRootAST> roots = new ArrayList<GrammarRootAST>();
|
||||||
|
for (String fileName : fileNames) {
|
||||||
|
GrammarAST t = loadGrammar(fileName);
|
||||||
|
if ( t==null || t instanceof GrammarASTErrorNode) continue; // came back as error node
|
||||||
|
if ( ((GrammarRootAST)t).hasErrors ) continue;
|
||||||
|
GrammarRootAST root = (GrammarRootAST)t;
|
||||||
|
roots.add(root);
|
||||||
|
root.fileName = fileName;
|
||||||
|
String grammarName = root.getChild(0).getText();
|
||||||
|
|
||||||
|
GrammarAST tokenVocabNode = findOptionValueAST(root, "tokenVocab");
|
||||||
|
// Make grammars depend on any tokenVocab options
|
||||||
|
if ( tokenVocabNode!=null ) {
|
||||||
|
String vocabName = tokenVocabNode.getText();
|
||||||
|
g.addEdge(grammarName, vocabName);
|
||||||
|
}
|
||||||
|
// add cycle to graph so we always process a grammar if no error
|
||||||
|
// even if no dependency
|
||||||
|
g.addEdge(grammarName, grammarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> sortedGrammarNames = g.sort();
|
||||||
|
// System.out.println("sortedGrammarNames="+sortedGrammarNames);
|
||||||
|
|
||||||
|
List<GrammarRootAST> sortedRoots = new ArrayList<GrammarRootAST>();
|
||||||
|
for (String grammarName : sortedGrammarNames) {
|
||||||
|
for (GrammarRootAST root : roots) {
|
||||||
|
if ( root.getGrammarName().equals(grammarName) ) {
|
||||||
|
sortedRoots.add(root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedRoots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Manually get option node from tree; return null if no defined. */
|
||||||
|
public static GrammarAST findOptionValueAST(GrammarRootAST root, String option) {
|
||||||
|
GrammarAST options = (GrammarAST)root.getFirstChildWithType(ANTLRParser.OPTIONS);
|
||||||
|
if ( options!=null ) {
|
||||||
|
for (Object o : options.getChildren()) {
|
||||||
|
GrammarAST c = (GrammarAST)o;
|
||||||
|
if ( c.getType() == ANTLRParser.ASSIGN &&
|
||||||
|
c.getChild(0).getText().equals(option) )
|
||||||
|
{
|
||||||
|
return (GrammarAST)c.getChild(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Given the raw AST of a grammar, create a grammar object
|
/** Given the raw AST of a grammar, create a grammar object
|
||||||
associated with the AST. Once we have the grammar object, ensure
|
associated with the AST. Once we have the grammar object, ensure
|
||||||
that all nodes in tree referred to this grammar. Later, we will
|
that all nodes in tree referred to this grammar. Later, we will
|
||||||
|
|
|
@ -46,6 +46,7 @@ public class GrammarRootAST extends GrammarASTWithOptions {
|
||||||
/** Track stream used to create this tree */
|
/** Track stream used to create this tree */
|
||||||
public TokenStream tokens;
|
public TokenStream tokens;
|
||||||
public Map<String, String> cmdLineOptions; // -DsuperClass=T on command line
|
public Map<String, String> cmdLineOptions; // -DsuperClass=T on command line
|
||||||
|
public String fileName;
|
||||||
|
|
||||||
public GrammarRootAST(GrammarAST node) {
|
public GrammarRootAST(GrammarAST node) {
|
||||||
super(node);
|
super(node);
|
||||||
|
@ -60,6 +61,11 @@ public class GrammarRootAST extends GrammarASTWithOptions {
|
||||||
super(type,t,text);
|
super(type,t,text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGrammarName() {
|
||||||
|
Tree t = getChild(0);
|
||||||
|
if ( t!=null ) return t.getText();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getOptionString(String key) {
|
public String getOptionString(String key) {
|
||||||
|
|
Loading…
Reference in New Issue