06 | 编译器前端工具(一):用Antlr生成词法、语法分析器
06 | 编译器前端工具(一):用Antlr生成词法、语法分析器
讲述:宫文学
时长16:12大小14.85M
初识 Antlr
用 Antlr 生成词法分析器
用 Antlr 生成语法分析器
课程小结
一课一思
赞 16
提建议
精选留言(59)
- 京京beaver2019-09-101. windows环境下配置 可执行文件,放在D:\tools\antlr\antlr-4.7.2-complete.jar下面 2.配置环境文件 CLASSPATH=%CLASSPATH%;D:\tools\antlr\antlr-4.7.2-complete.jar PATH=%PATH%n;D:\tools\antlr 3.手写文件antlr4.bat和grun.bat antlr4.bat java org.antlr.v4.Tool %* grun.bat @ECHO OFF SET TEST_CURRENT_DIR=%CLASSPATH:.;=% if "%TEST_CURRENT_DIR%" == "%CLASSPATH%" ( SET CLASSPATH=.;%CLASSPATH% ) @ECHO ON java org.antlr.v4.gui.TestRig %* 4.然后就可以执行antlr4和grun命令了 比如antlr4 Hello.g4, javac Hello*.java, $ grun Hello r -gui hello parrt ^Z (windows) 5.java执行路径要注意事项 在命令行执行java命令,记得把目录设置到src/main/java这里,然后输入包名.类名,才能找到。 这是java执行的基本规则,一般IDE里面替你做了路径转换,在命令行要自己敲入。切记。 例如 F:\study_repo\mygeek_time\myclang-03-grammar-analysis\src\main\java> grun com.babayetu.myclang03gramm aranalysis.antlrtest.PlayScript expression -gui展开
作者回复: 非常感谢你的整理! 其他同学可以参考你的配置方法!
共 4 条评论20 - Smallfly2019-09-05这一讲走的有点艰难,记录一下: 1、 开始执行下面的命令,报找不到 CommonLexer。 antlr PlayScript.g4 看了下 Github 才发现有这个文件。 import CommonLexer, 在语法规则文件 PlayScript.g4 中导入词法规则。 2、 antlr PlayScript.g4 上面的命令后应该先 cd .. 回退一级目录,再执行: javac antlrtest/*.java 或者,直接: javac ./*java 3、 grun antlrtest.PlayScript expression -gui 文中说执行这条命令结果会以图形化界面显示,我执行之后什么都没有输出,以为前面步骤有什么问题,重新来了一次,还是这样,往下看才意识到没输出才是正常的。。。 —— 看到最后弹出的 AST 树还是蛮有意思的。 我写了一版简单的 Swfit 规则文件: https://github.com/iostalks/PlayWithCompiler/tree/lecture-6/PlayWithCompiler/Antlr展开
作者回复: 哇,练习自己写规则,太帮了! 自己动手所获得的感觉是难以替代的。 中间过程遇到的每个坑,都是自己的积累! 另外,这里也有几个swift的规则文件可以参考: https://github.com/antlr/grammars-v4
6 - kaixiao72019-08-26在Windows下需要用 ^z 即Ctrl+z 来弹出AST窗口 That ^D means EOF on unix; it's ^Z in Windows.
作者回复: windows下用^Z?我都没注意到这点。 好的,一个有用的知识,应该加到文稿中去。 谢谢你的提醒! 20年前开始学unix命令的时候,就一直用^D,完全没注意到在windows下的用法:-D
4 - 七月有风2019-12-23macOS下,需要将把 Antlr 的 JAR 文件设置到 CLASSPATH 环境变量中: 如果是用Homebrew 安装的 Antlr,安装路径是:/usr/local/Cellar/antlr/4.7.2/antlr-4.7.2-complete.jar; 可以使用vi ~/.bash_profile命令打开bash_profile文件,将export CLASSPATH=".:/usr/local/Cellar/antlr/4.7.2/antlr-4.7.2-complete.jar:$CLASSPATH"这段代码复制到里面。 然后就可以运行javac *.java了展开
作者回复: 感谢分享! 我这两天整理了Antlr使用的要点,可以参见这里: https://github.com/RichardGong/PlayWithCompiler/blob/master/antlr_install.md
3 - PythonAI2019-08-26➜ antlr grun antlrtest.PlayScriptexpression -gui Can't load antlrtest.PlayScriptexpression as lexer or parser
作者回复: expression前要有空格,前面没有antlr。 grun antlrtest.PlayScript expression -gui 我请编辑把那个空格加上。
共 3 条评论3 - 江世民2020-06-28遇到了一个大坑。 Windows环境下,添加jar包到CLASSPATH中时,最好写在前面。如果是追加在后面,系统很可能不识别。
作者回复: 感谢分享你的经验! 你遇到的坑,会让其他同学少走弯路!
2 - 七月有风2019-12-25不知道是什么问题? $ grun Hello tokens -tokens Hello.play Exception in thread "main" java.lang.NoClassDefFoundError: antlrtest/Hello (wrong name: Hello) at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at org.antlr.v4.gui.TestRig.process(TestRig.java:135) at org.antlr.v4.gui.TestRig.main(TestRig.java:119)展开
作者回复: 可能是CLASSPATH设置的问题,或者是运行grun命令的目录不对。参见我整理的一篇文字,梳理了antlr使用的要点: https://github.com/RichardGong/PlayWithCompiler/blob/master/antlr_install.md
共 2 条评论2 - mudfrog2019-09-01老师,我的程序能编译通过,也能正常运行,能正常的解析和运算出来,但就是想看看语法树直观一些。我使用grun的时候总是提示Can't load CalExpr as lexer or parser,这里CalExpr到底是G4文件还是tokens文件呢,我把这两个文件都拷贝到src目录下了。我用的是win7底下的eclipse,
作者回复: 1.grun是用的Class文件,是java类。 2.但运行grun的时候,最好就在CLASSPATH的目录下。 假设,class和g4文件位于: playscript-java/src/main/play 其中play是包名,而CLASSPATH设置的是: playscript-java/src/main 那么你就在main这个目录下运行grun。 如果都不带包,就更简单一些,让grun就在带有class和.g4的目录中运行就好。 如果还有问题的话,请继续再问!
共 2 条评论2 - 式溪Chon W. Lam2022-05-06我开发了一个vscode插件, 把antlr的功能封装进去, 安装java就可以使用: https://marketplace.visualstudio.com/items?itemName=ChonLam.justAntlr (暂时只有windows可以使用antlr的测试功能)1
- Geek_6304e32022-02-10'grun antlrtest.PlayScript expression -gui' 执行的时候提示 'Can't load antlrtest.PlayScript as lexer or parser',前面步骤都正常1
- minghu62021-03-18ANTLR的使用一定要有 “The Definitive ANTLR 4 Reference” 推荐电子版 https://github.com/antlr/antlr4/blob/master/doc/index.md 可以做关键字搜索,查点儿语法概念性的东西比较方便,用一位网友说的话: If you do not already have "The Definitive ANTLR 4 Reference" book I recommend getting hold of it. Will save you a lot of time. 话说极客时间的内容还不错,没有那么多花里胡哨的噱头,但是这个书签笔记和评论的体验太差! 书签笔记甚至没有结构,留言也不支持markdown 一定要ommonLexer.g4展开
作者回复: 谢谢推荐Antlr4电子书! 以及提出的建议!
1 - englefly2020-06-16宫老师,Antlr的性能怎样?我们用antlr做了一个sql解析,当遇到比较长的sql语句是,antlr解析花了100ms,而mysql 只用了9ms。不知道是我们用法的问题,还是antlr本身为了使用简单牺牲了一些性能。
作者回复: 我要了解更多一点信息:你用Antlr生成的是C++代码还是Java代码?这两个不太一样。因为JVM只对热点代码做优化编译。如果只是解释执行或者用C1编译器编译,就会比较慢。详细你可以参考《编译原理实战课》中Java JIT编译器的部分。 另外,在实战课中,我也介绍了MySQL的编译器。MySQL的语法分析器也是用工具生成的,用的是Bison,生成的是C++代码。我估计,同样都使用C++代码的情况下,性能可能不会差很多。但具体也要测试一下。 或者,你就像MySQL一样,用Bison生成就好了,并且可以参考MySQL的源代码。 另外补充一下,MySQL Workbench这个客户端工具采用了Antlr来生成语法解析器,也是基于C++的,你也可以参考。
1 - 漏网之渔2020-03-24弄了三个小时,终于好了。老师文档写的很清楚。 https://github.com/RichardGong/PlayWithCompiler/blob/master/antlr_install.md 我遇到的问题有两点: 1.执行 grun 的时候 没带package名如grun Hello tokens -tokens hello.play,会提示java.lang.NoClassDefFoundError: Hello (wrong name: antlrtest/Hello),这是因为老师源码Hello带了pack保命antlrtest 我的解决方法是在src\antlrtest\目录下执行命令grun antlrtest.Hello tokens -tokens hello.play 2.执行grun命令报错误java.nio.file.NoSuchFileException: hello.play,这是因为我在antlrtest\src\目录下运行的grun,而hello.play在antlrtest\src\antlrtest\下,解决方法是在antlrtest\src\antlrtest\下执行grun命令 ,或者把hello.play文件代码拷贝到src\目录下再执行grun命令。 另外如果遇到javac命令遇见GBK错误,是因为编码格式问题,解决方法:javac -encoding utf-8 PlayScript.java 如果遇到找不到parse lexer问题,Class Path需要添加src目录展开
作者回复: 感谢详细的分享! 你遇到的某些问题,如GBK问题,我都没遇到过。其他人如果遇到类似的问题,可以从你的分享中受益!
共 2 条评论1 - 火火2019-11-28Hello.java:2: 错误: 程序包org.antlr.v4.runtime不存在 import org.antlr.v4.runtime.Lexer; ^ Hello.java:3: 错误: 程序包org.antlr.v4.runtime不存在 import org.antlr.v4.runtime.CharStream; ^ Hello.java:4: 错误: 程序包org.antlr.v4.runtime不存在 import org.antlr.v4.runtime.Token; ^ Hello.java:5: 错误: 程序包org.antlr.v4.runtime不存在 import org.antlr.v4.runtime.TokenStream; ^ Hello.java:8: 错误: 程序包org.antlr.v4.runtime.dfa不存在 import org.antlr.v4.runtime.dfa.DFA; ^ Hello.java:12: 错误: 找不到符号展开
作者回复: 这个问题的原因是antlr的jar包没有放到CLASSPATH中。 我这两天整理了antlr安装、配置、使用的一些信息,写了一个说明文件,你可以参考一下: https://github.com/RichardGong/PlayWithCompiler/blob/master/antlr_install.md
共 3 条评论1 - 沉淀的梦想2019-08-29老师,为什么我用antlr生成的AdditiveExpressionContext就没有示例程序中的ADD() SUB()这些直接以token名字命名的方法呢?
作者回复: 再检查一下规则文件。 你看看你的词法规则里是否给加号和减号起了ADD和SUB这样的名字,就像下面这样。 ADD : '+'; SUB : '-'; 只要有这样的定义,在语法里无论用ADD还是用'+',都会生成ADD()这样的方法。
共 2 条评论1 - 雲至2019-08-26老师可以讲一下规则文件里主要单词的意义吗? 看的有点懵1
- 温雅小公子2022-11-09 来自河北为什么我没有生成 Hello.class 文件,只有 Hello Lexer.class 文件呢
- Geek_216bc52022-05-25我为什么没有生成 PlayScriptBaseVisitor.java文件。
- A君2022-05-07如果源文件有多个且不在同一目录,是要对每个文件都单独做词法语法分析吗,那多个AST树要如何合并?
- gggggggb2022-04-11D:\antlr 的目录 2022/04/11 22:45 <DIR> . 2022/04/11 22:45 <DIR> .. 2021/08/07 12:16 2,100,564 antlr-4.9.2-complete.jar 2022/04/11 21:45 63 antlr4.bat 2022/04/11 21:45 71 grun.bat 2022/04/11 22:45 5,663 Hello.class 2022/04/11 21:34 872 Hello.g4 2022/04/11 22:45 4,525 Hello.interp 2022/04/11 22:45 6,322 Hello.java 2022/04/11 22:38 0 hello.play 2022/04/11 22:45 374 Hello.tokens 9 个文件 2,118,454 字节 2 个目录 262,626,590,720 可用字节 D:\antlr>grun Hello tokens -tokens hello.play D:\antlr>java -cp D:\antlr\antlr-4.9.2-complete.jar org.antlr.v4.gui.TestRig Hello tokens -tokens hello.play Can't load Hello as lexer or parser 这个是什么情况?展开