idea使用antlr_ANTLR开发环境入门指南

将Antlr4的语法文件生成辅助代码,有两种方法,一种是通过IDEA插件,一种是用运行jar包生成。

Antlr的遍历器有监听器(lister)与访问器(visiter)。在实际过程中,发现访问器更加好用,所以以下是采用访问器的例子。

1、一个简单的例子

以《Antlr4》书中第一章为例,记录基本的开发流程。

​ g4文件:

grammarHello;// Define a grammar called Helloparse:prog+;// match keyword hello followed by an identifierprog:'hello'ID;ID:[a-z]+;// match lower-case identifiersWS:[\t\r\n]+->skip;// skip spaces, tabs, newlines, \r (Windows)

该语法文件很简单,目的是识别hello开头的短句。生成解析器的方法如下:

1.1 利用IDEA ANTLR4插件

右键g4语法文件,选择Configure ANTLR...,配置输出路径和目标语言,勾选generate parse tree visitor。再右键g4语法文件,点击Generate ANTLR Recognizer生成代码。

1.2 直接命令行运行

在项目中引进antlr-4.7.2-complete.jar包,

java -jar antlr-4.7.2-complete.jar src/01-Hello/Hello.g4 -Dlanguage=Python3 -visitor -o src/01-Hello/py-parser -Xexact-output-dir

配置一个application,以运行org.antlr.v4.Tool类。

2、编写业务代码

针对这个例子,可以假设做个实现目标,如提取出下面文件中每一行以hello开头的第二个词。

test.txt

hello world

hello python

hello cpp

hello java

业务代码:

import sys

from antlr4 import *

from a1_Hello.py_parser.HelloLexer import HelloLexer

from a1_Hello.py_parser.HelloParser import HelloParser

from a1_Hello.py_parser.HelloVisitor import HelloVisitor

def main(argv):

input = FileStream(argv[1])

lexer = HelloLexer(input)

stream = CommonTokenStream(lexer)

parser = HelloParser(stream)

tree = parser.parse()

# print(tree.toStringTree(recog=parser))

visitor = NewHelloVisitor()

x = visitor.visit(tree)

print(x)

class NewHelloVisitor(HelloVisitor):

```重写visitor```

def __init__(self):

super().__init__()

def visitParse(self, ctx: HelloParser.ParseContext):

second_words = []

for x in ctx.getChildren():

second_words.append(self.visit(x))

return second_words

def visitProg(self, ctx: HelloParser.ProgContext):

return ctx.ID().getText()

if __name__ == '__main__':

main(sys.argv)

结果:

['world', 'python', 'cpp', 'java']

补一个目标代码为Java的实现代码:

package hello;

import org.antlr.v4.runtime.CharStream;

import org.antlr.v4.runtime.CharStreams;

import org.antlr.v4.runtime.CommonTokenStream;

import org.antlr.v4.runtime.tree.ParseTree;

import hello.parse.HelloLexer;

import hello.parse.HelloParser;

import hello.parse.HelloBaseVisitor;

import java.util.ArrayList;

public class TestHello {

public static void main(String[] args) {

CharStream input = CharStreams.fromString("hello world\rhello java\rhello python");

HelloLexer lexer = new HelloLexer(input);

CommonTokenStream tokens = new CommonTokenStream(lexer);

HelloParser parser = new HelloParser(tokens);

ParseTree tree = parser.parse(); // parse HelloVisitorTest vt = new HelloVisitorTest();

vt.visit(tree);

for (String s : vt.arrayList) {

System.out.println(s);

}

}

}

class HelloVisitorTest extends HelloBaseVisitor {

ArrayList arrayList = new ArrayList<>();

@Override

public String visitProg(HelloParser.ProgContext ctx) {

arrayList.add(ctx.ID().getText());

return "";

}

@Override

public String visitParse(HelloParser.ParseContext ctx) {

return super.visitParse(ctx);

}

}

当然上面有很多不完善的地方,这里就不再细说。

3、建议

3.1

我以前做过的项目,曾用Antlr4来做语言转换,比如把简单的SAS语言转成python来运行。这样的浅层应用是最合适的。但如果真要做成一个完整的语言编程器,只用Antlr4还太单薄。可以在语法解析前端采用antlr,中间构建语法抽象层,后台用LLVM优化。

3.2

在使用Antlr4解析语法时,有时为了处理一些特殊的语法,会采用一些在语法文件嵌入代码等高级的处理方法。虽然能解决问题,但代码耦合的厉害。所以不太建议用这种方法。当然也是因为自己不喜欢太复杂的东西。

【参考】By Developers, For Developers​pragprog.comantlr/antlr4​github.comjszheng/py3antlr4book​github.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值