ANTLR的语法文件使用扩展巴科斯范式EBNF描述,记得编译原理的用起来非常简单,需要进一步了解的是怎么构造自己的recognizer和translator。很多的语法不需要从头写,一方面很多语言标准中基本都使用EBNF描述,另一方面ANTLR网站http://www.antlr.org/grammar/list上有大量写好的语法文件,可以参考使用。
我已经忘得一干二净,从头大致了解一下。

巴科斯范式扩展符号 EBNF
() : 产生式组合
?  : 产生式出现0或1次
*  : 0或多次
+  : 1或多次
.   : 任意一个字符
~  : 不出现后面的字符
..  : 字符范围
可以参考http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html

例子1,整数定义:
integer : (HEX_PREFIX | OCTAL_PREFIX)? DIGITS; //可以有一个16进制或8进制前缀,没有则为10进制定义
HEX_PREFIX: '0x'; //16进制前缀
OCTAL_PREFIX: '0o'; //8进制前缀
DIGITS: '1'..'9' '0'..'9'*; //第一个字符必须为1-9,后面可以是任意多个0-9字符

例子2,多行注释符号/*和*/的定义:
ML_COMMENT : '/*' ( options {greedy=false;} : . )* '*/' ;
/*开头,*/结束,(.)*表示中间可以有任意多个字符,options {greedy=false;}是一个谓词选项,告诉分析器不要采用贪婪模式,即匹配到随后出现的第一个*/就结束,而不是试图去匹配输入字符流中的最后一个*/。

左递归、右递归 left/right recursion
如果一个产生式在最左开始位置包含它自己,叫左递归,例如exp: A | exp ',' A。而exp: A ',' exp | A则是右递归。用实际例子来看。
1. 右递归
例如实现一个表达式: +8结果为9;++8结果为10;+++8结果为11,以此类推。右递归语法为:
expr: PLUS expr | INT;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';
用ANTLR笔记1中C#示例的方法来运行这个例子的语法文件内容如下:

left returns [int value] : e=expr { $value = $e.value; };
expr returns [int value] :
    PLUS e=expr { $value=$e.value+1; }
    | INT { $value=int.Parse( $INT.text ); };
INT: '1'..'9' '0'..'9'*;
PLUS: '+';

有个理解上容易产生歧义的地方,即expr应当解析成expr: (PLUS expr) | INT;还是expr: PLUS (expr | INT);?应当是前面这种方式。
2. 左递归
例如实现表达式: 8+结果为9;8++结果为10;8+++结果为11,以此类推。左递归语法为:
expr: expr | INT PLUS;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';
ANTLR不支持左递归,上面的语法在生成时会报错: error(210):  The following sets of rules are mutually left-recursive [expr]。
将这个语法改为下面这样,就不是左递归了。
expr: INT PLUS*;
INT: '1'..'9' '0'..'9'*;
PLUS: '+';

零散的概念
语法多义性: 语法设计最值得关注的问题。第一点是人的思维对语法描述理解的歧义,与语法解释器的实际结果不一致,例如上面提到的expr的问题。另外就是语法描述本身逻辑上存在多义性,即对同样的输入可以解释成多种结果,它们都符合语法描述的规则。

lexer: 词法分析器,从输入字符流解析出词汇序列(tokens)。
parser: 语法解析器,对词汇进行语法分析,生成语法树(抽象语法树AST)。
EBNF的语法不区分词法分析和语法分析,对应的只有终结符、非终结符,终结符描述输入,非终结符描述输入所表达的树结构。ANTLR使用词法分析器识别终结符,使用语法分析器分析非终结符(生成的分析器代码文件有两个,一个是词法分析器***Lexer,一个是语法分析器***Parser),并要求词法规则全部以大写开始,语法规则全部以小写开始。对每一个语法规则,最终都必须以词法规则结束,否则是一个无效语法,生成时会报错。

ANTLR生成的分析器代码中,语法规则都会有一个同名的方法,而词法规则的名称则跟语法文件给出的不一样。如果需要使用这些词法规则,可取的方法之一是定义一个语法规则与之对应;另外就是定义一个符号表,例如ANTLR笔记1中示例1里面的tokens{...}。定义符号表的优点是会优先匹配符号表,例如一些关键字等,可以避免他们被其它规则匹配上。
关于规则的定义顺序,语法文件中先出现的规则具有优先匹配的作用。

ANTLR笔记1中示例1的简单说明
1. grammar SimpleCalc;,定义语法名称。语法文件(.g文件)名称必须与这里指定的名称一致。默认情况生成的语法分析器类名为"语法名称"+Parser,词法分析器类名为"语法名称"+Lexer。
2. options {...},定义全局配置参数,设置ANTLR生成过程中的一些控制选项,示例中指定目标语言为C#。
3. tokens {...},定义全局的符号表。
4. @members {...},这里面给出的代码将放入到生成的语法分析器类中,作为分析器类的成员属性、方法等。
   示例中为分析器添加了一个Main方法,省得再格外写一个测试类。
   Main方法先从命令行读取输入字符,将输入字符传给生成的词法分析器SimpleCalcLexer,得到词汇序列CommonTokenStream。接下来使用生成的语法分析器SimpleCalcParser对词汇序列进行分析,在生成语法树的过程中直接由expr()方法返回计算结果。
5. 语法规则。
   把语法规则中的{...}、[...]等相关ANTLR的Action去掉就是EBNF。
   ANTLR生成的语法解析器代码中,对应每个语法规则都会生成一个方法,这个方法完成对应语法规则的分析逻辑。{...}、[...]等就是我们自己的recognizer、translator需要的一些额外控制(Action),分析匹配的逻辑由ANTLR完成,我们添加的这些控制就是对匹配到的结果怎样进行处理,是生成一个语法树,再由其它程序对语法树进行翻译,还是直接结合ANTLR的分析过程进行翻译转换或计算处理等,由我们进行控制。示例中是直接进行计算求值。
   returns [...]告诉ANTLR生成的方法需要返回什么内容,[int value]表示返回值类型为int,名字叫做value,就是声明了一个变量,用它来返回。在方法体里面,我们通过{...}中的内容进行求值运算,并把结果设置给value。{...}我们可以看作是一个宏,或者是一个模板,在里面我们可以使用ANTLR在代码生成时内置的一些变量/对象,它们以$开始(象StringTemplate语法,但不需要对应的$进行闭合),这些变量在代码生成过程中ANTLR为我们设置好。其它的代码保持不变,放入到方法的相应位置上。
6. 词法规则。
   { $channel = HIDDEN; }。默认情况下ANTLR在词法分析器和语法分析器之间使用两个通道通讯,一个default和一个hidden。语法分析器监听default通道接收词汇序列,所以如果将某个词汇发送到hidden通道,这个词汇就会被语法分析器忽略掉。示例中将回车换行等空白字符都过滤掉,不进行语法分析。
   fragment: 对词法规则有效(我没有看到对语法规则有作用),它在生成的语法树上不会有对应的节点,即可以这样理解,它是我们在语法中定义的一个宏,可以被其它语法规则调用,但它不会成为最终语法树上的节点。

转载于:https://www.cnblogs.com/RicCC/archive/2008/03/01/antlr-simple-grammar.html

ANTLR笔记2 - 简单语法说明相关推荐

  1. R语言学习笔记【简单语法总结-上】

    简单语法总结[上]: R语言特征总览: 对大小写敏感 通常,数字,字母,. 和 _都是允许的(在一些国家还包括重音字母).不过,一个命名必须以 . 或者字母开头,并且如果以 . 开头,第二个字符不允许 ...

  2. 使用ANTLR做一个简单的Python SQL语法解析器 - 推酷

    使用ANTLR做一个简单的Python SQL语法解析器 - 推酷 使用ANTLR做一个简单的Python SQL语法解析器 - 推酷 posted on 2016-11-14 13:11 lexus ...

  3. Programming Languages PartA Week2学习笔记——SML基本语法

    Programming Languages PartA Week2学习笔记--SML基本语法 首先简单介绍使用的SML语言,参考维基百科和百度百科: ML(Meta Language:元语言)是由爱丁 ...

  4. python 随机生成简单语法结构的中文句子

    简单的中文语句生成器 python 随机生成简单语法结构的中文句子 题目如下:Writing a programming which could generate random Chinese sen ...

  5. 《PHP学习笔记——PHP基本语法》

    <PHP学习笔记--PHP基本语法> 前言: PHP是一门服务端脚本语言,像JavaScript一样,也是一门弱类型语言.弱类型语言最大的特点是允许变量隐式转换.这样,相对于Java这种强 ...

  6. python基本语法语句-python学习笔记:基本语法

    原标题:python学习笔记:基本语法 缩进:必须使用4个空格来表示每级缩进,支持Tab字符 if语句,经常与else, elif(相当于else if) 配合使用. for语句,迭代器,依次处理迭代 ...

  7. 嵌入式基础认识2:shell脚本的一些简单语法规则

    一.关于shell的一些认识 1.shell语言,是一类编程语言.常用shell语言有sh.bash.csh.ksh.perl.python等.linux下最常用的脚本就是bash. 2.shell脚 ...

  8. 编译原理简单语法分析器(first,follow,分析表)源码下载

    编译原理(简单语法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E5%8A%A0%E5%85%A5%E5%90%8C%E6%AD%A5%E7%AC ...

  9. python3语法都相同吗_python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样...

    python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样,IDLE shell编辑器,快捷键:ALT+p,上一个历史输入内容,ALT+n 下一个历史输入 ...

最新文章

  1. 代码生成器:IDEA 强大的 Live Templates
  2. LeetCode Bulb Switcher(约数个数为奇数)
  3. 报名 | 东南大学周张泉:基于知识图谱的推理技术
  4. ajax的交互流程有哪几步
  5. Mybatis参数传递及返回类型
  6. 程序员选择公司的8个标准
  7. C# Lock的基本使用和声明
  8. carmaker/matlab联合仿真(二) 新建测试场景
  9. java分页数据再次进行分页操作
  10. iOS虚拟定位原理与预防
  11. Snipaste操作指南
  12. 3D Photography using Context-aware Layered Depth Inpainting-论文主要内容翻译
  13. 典型相关性分析(清风建模学习笔记)
  14. 5G业务测试方法与验证
  15. PAP和CHAP的区别
  16. 达尔优键盘Mac Command-c和Command-v复制粘贴快捷键失效问题解决方案
  17. Kaggle | 金融交易欺诈检测(Synthetic Financial Datasets For Fraud Detection)
  18. 低头玩手机 不如抬头说英语
  19. linux-ARM开发板--嵌入式开发平台-选型
  20. TestDirector用户手册

热门文章

  1. ES9新特性_ES9正则扩展-dotAll模式---JavaScript_ECMAScript_ES6-ES11新特性工作笔记056
  2. 区块链工作笔记0001---以太坊流程简介
  3. C#.net工作笔记001---Linq对象查询,排序,分组,去重在工作中的使用_随时更新
  4. html5学习笔记---01.HTML5介绍,02.HTML5的新特性
  5. 基于BS模式的航材电子商务交易平台(2)
  6. adt变频器故障代码ol2_误诊实例换来的变频器维修经验
  7. java 线程局部存储,转载boost::thread简要分析(3):线程局部存储及其它
  8. 简述sd卡2.0协议_【正点原子FPGA连载】第十二章SD卡读写TXT文本实验-领航者 ZYNQ 之嵌入式开发指南...
  9. c语言if全部用法,关于if的用法
  10. 柱底反力求和lisp软件_AutoLISP 基础——认识自定义函数