$ cd /usr/local/lib $ curl -O http://www.antlr.org/download/antlr-4.7-complete.jar $ export CLASSPATH=".:/usr/local/lib/antlr-4.7-complete.jar:$CLASSPATH" $ alias antlr4='java -jar /usr/local/lib/antlr-4.7-complete.jar' $ alias grun='java org.antlr.v4.gui.TestRig'
# cd; mkdir antlr; cd antlr # curl -O http://media.pragprog.com/titles/tpantlr2/code/tpantlr2-code.tgz # tar xvf tpantlr2-code.tgz # cd code/install $ git clone https://github.com/azru0512/antlr.git $ cd install $ antlr4 Hello.g4 $ javac *.java # grun grammer_name start_rule $ grun Hello r -tokens $ grun Hello r -gui
// import ANTLR's runtime libraries import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.*; public class Test { public static void main(String[] args) throws Exception { // create a CharStream that reads from standard input ANTLRInputStream input = new ANTLRInputStream(System.in); // create a lexer that feeds off of input CharStream ArrayInitLexer lexer = new ArrayInitLexer(input); // create a buffer of tokens pulled from the lexer CommonTokenStream tokens = new CommonTokenStream(lexer); // create a parser that feeds off the tokens buffer ArrayInitParser parser = new ArrayInitParser(tokens); ParseTree tree = parser.init(); // begin parsing at init rule // 處理 parse 得到的 AST,tree。 } }
/** Convert short array inits like {1,2,3} to "\u0001\u0002\u0003" */ public class ShortToUnicodeString extends ArrayInitBaseListener { /** Translate { to " */ @Override public void enterInit(ArrayInitParser.InitContext ctx) { System.out.print('"'); } /** Translate } to " */ @Override public void exitInit(ArrayInitParser.InitContext ctx) { System.out.print('"'); } /** Translate integers to 4-digit hexadecimal strings prefixed with \\u */ @Override public void enterValue(ArrayInitParser.ValueContext ctx) { // Assumes no nested array initializers int value = Integer.valueOf(ctx.INT().getText()); System.out.printf("\\u%04x", value); } }
// Create a generic parse tree walker that can trigger callbacks ParseTreeWalker walker = new ParseTreeWalker(); // Walk the tree created during the parse, trigger callbacks walker.walk(new ShortToUnicodeString(), tree);
$ antlr4 Expr.g4 $ javac Expr*.java $ grun Expr prog -gui t.expr
grammer
開頭。語法規則小寫字母開頭,語彙規則大寫字母開頭。語法和語彙規則可以寫在同一個檔案,或是寫在不同檔案,透過 import
載入。$ antlr4 -no-listener -visitor LabeledExpr.g4 $ javac Calc.java LabeledExpr*.java $ java Calc t.expr
ParseTree tree = parser.prog(); // parse EvalVisitor eval = new EvalVisitor(); eval.visit(tree);
$ antlr4 Java.g4 $ javac Java*.java Extract*.java $ java ExtractInterfaceTool Demo.java
ParseTree tree = parser.compilationUnit(); // parse ParseTreeWalker walker = new ParseTreeWalker(); // create standard walker ExtractInterfaceListener extractor = new ExtractInterfaceListener(parser); walker.walk(extractor, tree); // initiate walk of tree with listener
import
語句。@Override public void enterImportDeclaration(JavaParser.ImportDeclarationContext ctx) { System.out.println("import "+parser.getTokenStream().getText(ctx)); }
$ antlr4 -no-listener Rows.g4 $ javac Rows*.java Col.java $ java Col 1 < t.rows
exprList: expr (',' expr)* ;
type: 'float' | 'int' | 'void' ;
vector: '[' INT+ ']' ;
expr: expr '+' expr ;
ID: [a-zA-Z]+ ;
INT: [0-9]+' ;
.*
匹配任意字元,但是這樣會連後面的 "
都被匹配。.*?
是 nongreedy 規則,匹配任意字元直到 "
。STRING: '"' .*? '"' ;
skip
跟 Flex 的 empty action (8 Actions) 相同。WS: [ \t\r\n]+ → skip ;
NUMBER: INT | FLOAT
。如果 parsing 不區分 int 和 float,統一交給語彙規則處理。$ cd code/example $ antlr4 CSV.g4 $ javac CSV.*.java $ grun CSV file -tokens data.csv
$ antlr4 JSON.g4 $ javac JSON*.java $ grun JSON json -tokens [1, "\u0049", 1.3e9]
%parse-param {Compiler* compiler}
指示 yyparse
將會接受 Compiler 指針。爾後透過該 Compiler 指針調用 method 執行 action。Compiler 類除了 method 之外,所有編譯過程中所需要紀錄的資訊都可以當作 member 加以保存。ParseTree tree = parser.file(); // create a standard ANTLR parse tree walker ParseTreeWalker walker = new ParseTreeWalker(); // create listener then feed to walker PropertyFileLoader loader = new PropertyFileLoader(); walker.walk(loader, tree); // walk parse tree
$ cd code/listeners $ antlr4 LExpr.g4 $ javac LExpr*.java TestLEvaluator.java $ java TestLEvaluator 1+2*3
ParseTree tree = parser.file(); PropertyFileVisitor loader = new PropertyFileVisitor(); loader.visit(tree);
$ cd code/listeners $ antlr4 -visitor LExpr.g4 $ javac LExpr*.java TestLEvalVisitor.java $ java TestLEvalVisitor 1+2*3
$ cd code/listeners $ antlr4 CSV.g4 $ javac CSV*.java LoadCSV.java $ java LoadCSV t.csv
$ antlr4 JSON.g4 $ javac JSON*.java $ java JSON2XML t.json
ParseTreeProperty<T>
每個節點可以儲存資料 T。$ antlr4 Cymbol.g4 $ javac Cymbol*.java CallGraph.java $ java CallGraph t.cymbol
$ antlr4 Cymbol.g4 $ javac Cymbol*.java CheckSymbols.java *Phase.java *Scope.java *Symbol.java $ java CheckSymbols vars.cymbol
ParseTreeWalker walker = new ParseTreeWalker(); DefPhase def = new DefPhase(); walker.walk(def, tree); // create next phase and feed symbol table info from def to ref phase RefPhase ref = new RefPhase(def.globals, def.scopes); walker.walk(ref, tree);
$ antlr4 Simple.g4 $ javac Simple*.java $ grun Simple prog class T { int i; }
$ javac TestE_Listener.java TestE_Listener.java:10: error: cannot find symbol import org.antlr.v4.runtime.Nullable; ^ $ java TestE_Listener class T T { int i; }
BaseErrorListener
,override syntaxError
。