Antlr学习与探索
注: 本篇属于博主早期学习编程时编写,可能会出现一些误区,不恰当,不适合的内容,仅供参考
2023-12-01
刚开始建博客的时候,在markdown这里呢,没有适合我需求的框架。于是就自己去写。
不过回想起来,拿正则去解析markdown,未免也太抽象了~~~
最近了解到了antlr,发现确实是个好东西。于是就去学了学一下。
然后就用上自己的博客。
antlr的一些注意事项
- 语法解析器和词法解析器分别编写
antlr可以直接一个文件直接写就行,不区分语法解析器和词法解析器,但是这样就少了词法解析器的一些比较好用的功能。
所以,我的习惯是,新建两个文件,将语法解析器和词法解析器区分就好了。
那么这个时候,两个文件的开头应该是这样
// m.g4 |
// mLexer.g4 |
注意如果你的的第一个文件名为m.g4,那么另一个就应为mLexer.g4,要不然后期是编译不了的
其实也可以把
m.g4改为mParser.g4的,之后mParser.g4开头grammar改为parser grammar,不过笔者也没尝试过(程序能跑就行哈哈)
如何去编写antlr内容
本文需要对antlr的语法有一定的了解
本来,antlr拥有动作,语义判定,错误处理等强大的功能的。但是,这些似乎是语言相关的(笔者也没验证过,只是我是这样理解的)
另一方面,也存在着解析的目标,逻辑比较复杂的情况
所以,我就围绕着antlr的pushMode,popMode,mode这些功能来编写词法解析器。
只需要按照这个下面这个简单的模板来设计,就能很快编写好词法解析器文件了
入口(pushMode) + 内容 + 出口(popMode) |
有了词法解析器,也就能很快的编写语法解析器
而语法解析器,就对每一个mode内部各个词法进行打包一下,比如将一个字符组成一个字符串之类的
每一处语法对应一处词法的mode,之后再整合起来,就能实现一个完整的解析器了。
下面这些是我总结出来的经验
词法解析器里面少用
+或者*号,这些建议留到语法解析器里面处理
因为这可能会导致词法解析器死啃一个词法导致其他词法失效的问题只要有入口,有出口,就直接无脑写出一个mode来就好了。剩下的交给语法解析器
自已编写的markdown
下面就开源一份我自己编写的markdown的g4文件
这份为md.g4
grammar md; |
这份为mdLexer.g4
lexer grammar mdLexer; |
其中CODE_TEXT处为
CODE_TEXT: (‘ ‘ | ‘\t’)* (‘```’ | ‘~~~’) ~(‘\n’)* ‘\n’ -> pushMode(CODE_TEXT_MODE);
而CODE_TEXT_END处为
CODE_TEXT_END: (‘ ‘ | ‘\t’)* (‘```’ | ‘~~~’) ~(‘\n’)* ‘\n’ -> popMode;
你问我为什么不把这两个填到上面一起,因为这个博客就是用这个来解析markdown的,而我的markdown解析器在解析代码文本是存在bug的(就是一旦识别出两处代码文本的标记符,就直接归为代码文本了),而且也懒得去改了(反正一般情况下也不会出现)