ANTLR4初学【打造你我方的语规则定】
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效果如图:
图片
本站仅提供存储工作,通盘本色均由用户发布,如发现存害或侵权本色,请点击举报。热点资讯
- 是否患上多系统萎缩,这三项查验就满盈,别再毫无条理地乱用钱!
- 高中:函数主张及性质13类题型(说明式,界说域,值域)含word
- 说说《红楼梦》中的药方
- 德国空军A350VIP输送机将装配定向红外起义设置
- 5个养肝胆的中成药,一文归来:1、肝囊肿:推崇:部分东说念主用餐时很快
- 新京雅会——洞开它,仿佛跻身一座全天开放的“私东谈主订制”博物馆
- 探秘梨花造就:培养创造力的特有方法
- 大夫警告:上了年岁后,冬季宁可在家打麻将,也别在这个时期段外出分布
- 韩歌手泄漏火速成婚原因,曾对婚配不抱但愿,在演唱会上决定来去
- 一年卖两万斤面条配方来了,学会了就不错开店