ANTLR4初学【打造你我方的语法按序】

广州康符商贸有限公司

  • 首页
  • 公司简介
  • 联系我们
  • 产品中心
  • 新闻动态
  • 你的位置:广州康符商贸有限公司 > 新闻动态 > ANTLR4初学【打造你我方的语法按序】
    ANTLR4初学【打造你我方的语法按序】
    发布日期:2024-11-12 15:17    点击次数:160

    ANTLR4初学【打造你我方的语法按序】

    著述目次 什么是ANTLR4ANTLR4的特色ANTLR4的语法按序语法按序的声明.g4文献的代码按序词法按序语法按序语法按序中的操作 奈何使用ANTLR4实战IDEA装配ANTLR插件新建名堂创建一个.g4文献通过插件生成java代码创建一个EvalVisitor遍历AST测试 什么是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成果如图:

    图片

    本站仅提供存储奇迹,悉数履行均由用户发布,如发现存害或侵权履行,请点击举报。

    上一篇:售11.98万-16.58万 埃安AION RT阐扬上市
    下一篇:#每天学习英语少许点 #不骄不躁永握住歇英文 #常识点回归 #整年累月 #英语语法教师视频