ANTLR4(全称为'ANother Tool for Language Recognition')是一种用于构建谈话识别器的弘远器用。它是一个自动生成的贯通器生成器,使用ANTLR4不错匡助设立东说念主员快速创建自界说的谈话或DSL。
ANTLR4的特色 复古多种方针谈话,包括Java、C#、Python、JavaScript等。复古LL(*)(LL star)语法分析器,不错处分包含苟且数见识上前看秀气(lookahead)的语法。复古词法和语法失实处分,不错生成明晰的失实音问和还原战略。复古生成AST(轮廓语法树),简单谈话处分器进行语法分析和代码生成。提供了丰富的API和器用集,不错自界说和优化ANTLR4生成的贯通器。 ANTLR4的语法按序 语法按序的声明ANTLR4的语法按序必须以“grammar”要道字开动,后头随着语法按序的称呼。举例:
grammar MyGrammar;
这里声明了一个名为'MyGrammar'的语法按序。
.g4文献的代码按序 词法按序ANTLR4语法按序以词法按序(lexer rules)开动。词法按序界说了输入文本中的各个单词(或秀气),这些单词将被语法按序使用。每个词法按序界说一个单词的称呼和匹配该单词的正则抒发式。
以下是一个轻佻的例子:
// 界说变量名为一个字母后跟零个或多个字母、数字或下划线 ID : [a-zA-Z] [a-zA-Z0-9_]*;
在这个例子中,咱们界说了一个名为ID的词法按序,该按序匹配一个以字母开端,后跟零个或多个字母、数字或下划线的字符串。在语法按序中,咱们不错使用ID来匹配变量名。
语法按序ANTLR4语法按序界说了输入文本的结构。语法按序由词法按序和其他语法按序构成,界说了输入文本的结构。语法按序时时以一个称为start的语法按序开动,这个语法按序界说了通盘输入文本的结构。
以下是一个轻佻的例子:
// 界说一个轻佻的算术抒发式语法按序 expr : INT | expr op=('*' | '/') expr | expr op=('+' | '-') expr | '(' expr ')' ; INT : [0-9]+;
在这个例子中,咱们界说了一个名为expr的语法按序,该按序界说了一个轻佻的算术抒发式。该按序由四个子按序构成,每个子按序界说了一种抒发式。第一个子按序匹配整数,第二个和第三个子按序匹配乘法、除法、加法和减法,终末一个子按序匹配括号中的抒发式。咱们还界说了一个名为INT的词法按序,该按序匹配一个或多个数字。在这个例子中,咱们使用INT来匹配整数。
语法按序中的操作// 界说一个带有语义谓词的语法按序 expr : INT { $INT.text.equals('0')}
在这个例子中,咱们界说了一个名为expr的语法按序,该按序匹配整数,并使用语义谓词来指定该按序是否适用于输入文本。在这个例子中,语义谓词查验整数是否为零。
奈何使用ANTLR4下载并装配ANTLR4:只需要下载官方网站上提供的ANTLR4 JAR文献,然后将其添加到您的Java类旅途中即可。您还不错遴荐装配ANTLR4插件来集成到您的IDE中,以便更简单地使用ANTLR4。底下咱们演示如安在IDEA中使用ANTLR4插件。
编写语法文献:在ANTLR4中,您需要编写一个.g4文献来界说词法和语法按序。您不错使用文本裁剪器编写.g4文献。
生成代码:一朝您编写了.g4文献,您不错使用ANTLR4生成Java代码。使用以下呐喊不错生成Java代码:
java -jar antlr-4.9.2-complete.jar YourGrammar.g4
在上头的呐喊中,您需要将YourGrammar.g4替换为您的.g4文献的称呼。
编写贯通器:一朝您生成了Java代码,您不错编写一个Java贯通器来贯通输入文本。您不错使用ANTLR4提供的Java API来编写贯通器。CharStream input = CharStreams.fromStream(System.in); YourGrammarLexer lexer = new YourGrammarLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); YourGrammarParser parser = new YourGrammarParser(tokens); YourGrammarParser.StartContext tree = parser.start();
在上头的代码中,您需要将YourGrammarLexer和YourGrammarParser替换为您生成的Lexer和Parser类的称呼。您还需要替换start()次第,该次第应该复返您的语法按序中的start按序的ParseTree对象。
实战咱们来作念一个具体的例子,经典的接洽器,主若是完毕四则运算,带括号等等。
IDEA装配ANTLR插件File->Settings->Plugins->Marketplace
图片
新建名堂新建一个maven名堂
图片
pom.xml引入antlr的依赖<dependency> <groupId>org.antlr</groupId> <artifactId>antlr4-runtime</artifactId> <version>4.10.1</version> </dependency>创建一个.g4文献
图片
grammar Arithmetic; /* * Parser rules */ parse : expr EOF ; expr : term (('+'|'-') term)* ; term : factor (('*'|'/') factor)* ; factor : NUMBER | '(' expr ')' ; /* * Lexer rules */ NUMBER : DIGIT+ ('.' DIGIT+)? ; DIGIT : [0-9] ; WHITESPACE : [ \t\n\r] -> skip ;
在这个语法按序中,咱们界说了四个按序:
parse:最高等别的按序,暗示一个齐全的抒发式。它由一个expr按序后头随着一个EOF秀气构成。expr:暗示一个加法或减法抒发式。它由一个term按序后头随着零个或多个加法或减法秀气,后头再随着一个term按序构成。term:暗示一个乘法或除法抒发式。它由一个factor按序后头随着零个或多个乘法或除法秀气,后头再随着一个factor按序构成。factor:暗示一个数字或括号内的抒发式。它不错是一个数字,粗略是一个由左括号、一个抒发式和右括号构成的组合。遏制,在这个示例中,咱们还界说了一些Lexer按序,用于识别数字和忽略空格和换行符。
咱们不错通过idea的antlr插件来查验咱们的语法按序: 如下图,点击ANTLR Preview不错来到如下界面。左边的框填写需要校验的抒发式,右边等于语法树贯通的成果。
图片
接下来,咱们需要使用ANTLR来生成Java代码。 通过插件生成java代码右键.g4文献,遴荐Configure ANTLR,建树java文献的生成旅途。
图片
图片
再次右键.g4文献,遴荐Generate ANTLR Reconizer 即可生成java代码
图片
创建一个EvalVisitor遍历AST咱们创建一个EvalVisitor遍历AST,并接洽抒发式的值。最终,咱们打印接洽成果。 EvalVisitor是一个咱们需要我方完毕的类,它接管了ArithmeticBaseVisitor,并重写了其中的次第。底下是一个轻佻的完毕示例: 新建类EvalVisitor.java
public class EvalVisitor extends ArithmeticBaseVisitor<Double> { // 使用一个Map来存储变量名和值的映射关连 Map<String, Double> memory = new HashMap<String, Double>(); // 重写visitExpr次第,用于接洽加法和减法 @Override public Double visitExpr(ArithmeticParser.ExprContext ctx) { Double result = visit(ctx.term(0)); for (int i = 1; i < ctx.term().size(); i++) { String op = ctx.getChild(2*i - 1).getText(); Double term = visit(ctx.term(i)); if (op.equals('+')) { result += term; } else { result -= term; } } return result; } // 重写visitTerm次第,用于接洽乘法和除法 @Override public Double visitTerm(ArithmeticParser.TermContext ctx) { Double result = visit(ctx.factor(0)); for (int i = 1; i < ctx.factor().size(); i++) { String op = ctx.getChild(2*i - 1).getText(); Double factor = visit(ctx.factor(i)); if (op.equals('*')) { result *= factor; } else { result /= factor; } } return result; } // 重写visitFactor次第,用于接洽数字和括号内的抒发式 @Override public Double visitFactor(ArithmeticParser.FactorContext ctx) { if (ctx.NUMBER() != null) { // 如果是一个数字,平直复返其值 return Double.parseDouble(ctx.NUMBER().getText()); } else { // 如果是括号内的抒发式,递归调用visit次第 return visit(ctx.expr()); } } }测试
新建测试类Test.java
public class Test { public static void main(String[] args) throws Exception { String input = '(1+2)*3-4'; // 创建一个词法分析器,用于将输入治疗为秀气 ArithmeticLexer lexer = new ArithmeticLexer(CharStreams.fromString(input)); // 创建一个秀气流,用于将秀气传递给贯通 CommonTokenStream tokens = new CommonTokenStream(lexer); // 创建一个贯通器,用于将秀气治疗为AST ArithmeticParser parser = new ArithmeticParser(tokens); // 调用贯通器的parse次第,生成AST ParseTree tree = parser.parse(); // 创建一个AST遍历器,用于接洽抒发式的值 EvalVisitor eval = new EvalVisitor(); // 遍历AST,并接洽抒发式的值 double result = eval.visit(tree); // 打印接洽成果 System.out.println(result); } }
测试(1+2)*3-4成果如图:
图片
本站仅提供存储奇迹,悉数履行均由用户发布,如发现存害或侵权履行,请点击举报。