ANTLR (ANother Tool for Language Recognition)是一项开源的java编写的语法/词法分析器套件.
通过ANTLR可以生成语法处理器来对进行文本或二进制文件进行解析处理.
ANTLR由定义语法,编译工具和运行时库组成.
使用ANTLR需要先依据其定义语法编写语法解析文件(.g4),然后通过java编译器输出对应平台的解析器源代码
解析器源代码结合运行库即可进行语法树解析.
解析之后
解析之后,通过读取语法树即可将你的语法转换为对应平台的真实执行.
限制
只支持LR语法
- Java
- C#
- Python2 Python3
- javascript
- Go
- C++
- Swift
- Php
ANTLR 生成的对应平台解析器都需要对应平台的运行时进行支持!
-
.g4 作为扩展名 (grammar 4 的缩写)
-
语法文件定义语法中的模式
-
解析文件定义语法解析的规则
-
上两者可以合并为 语法解析文件 就是写一起完事儿
-
基本格式
//单行注释 /* 多行注释 */ /** * java 文档型注释 */ lexer grammar NameLexer;//定于语法文件和语法名称 import OtherG4;//导入文件 Token //定义一个语法标记 : Param //语法标记的模式 ;//结束 //--------这是同文件夹的另外一个g4 parser grammar NameParser;//某个语法的解析规则 options { tokenVocab = NameLexer; }//上面定义的语法 Statement : Pattern //语句的模式 ;//结束 //-------这是一个独立的g4 grammar NameLanguage;
-
注释: 同Java就一毛一样
-
语句: 最终由分号结束
-
Token: 标记,代表你的语法中的一个元素,Token名字必须是大写字母开头
-
Rule: 规则,规则名字必须是小写字母开头
-
Label: 标签,是规则一条匹配项后面以
#
开始的标注,对不同的标签会生成对应的visitor方法 -
Identifier: Token和Statement的统称,可以包含Unicode的字面值(中文编程不是梦)
-
Literals:字面值,由单引号
'
包围起来的一个或多个字符 -
Actions: 目标平台的代码片段
-
EmbeddedCode: 嵌入的目标平台代码行,包括
@header
@member
-
Keywords: 关键词,这个是ANTLR定义语法的关键词
关键词 说明 import 导入另外一个语法规则文件 fragment 定义一个语法片段 lexer 定义语法,一般同grammar联用 parser 定义解析规则,一般同grammar联用 returns 定义返回值 locals 定义局部变量 throws 定义异常 catch 定义异常捕获 finally 不想注释了,同java一样一样嘚 mode 定义模式 options 定义选项值(后面细说) tokens 就是Token加s rule : 不是关键字,但是不要用,其他目标平台的关键字也不能用..so.中文考虑下🤔
-
具体格式(🙂又是格式)
/** 可选的像java一样的备注 */ /** * lexer grammar 开头的文件只能有语法规则 * parser grammar 开头的文件只能有解析规则 * grammar 文件是上两者其一或同时兼具(懒就用这个) */ grammar Name; //语法名字必须同文件名一样,比如这个文件就应该是Name.g4 options {...}//这些操作是顺序无关的 import ... ; //导入另外一个文件,必须是同类文件(语法或者解析规则或者又是语法又是解析规则) tokens {...} //定义一堆没有语法规则的Token channels {...} // 只有语法文件可以有 @actionName {...} rule1 // parser and lexer rules, possibly intermingled ... ruleN
-
import: 导入,引入另外一个同类 文件.相当于就写在一起了,
- 被导入文件中已经有的规则会被当前文件所覆盖
- 对于复合导入的文件,除了当前文件中的规则优先之外,最深的规则优先
- A[r:'1';] B:[<-A;c'1';] C:[r:'2';] D[<-A,B;e:'3';] ==>D[r:'1';c:'1';e:'3';]
-
流转:
->
-
-> skip
忽略 常用于注释等WS:[\t\r\n]+ -> skip;
-
-> channel(NAME)
发送到通道WS : [ \r\t\n]+ -> channel(HIDDEN) //等同 -> skip ;
-