前言
文中第4章内容有点多,有点枯燥,但不坚持一下,之前所做的工作就白做了。
再次确认一下总体目标:
protege4编辑器中Class Definition中语法解析和错误提示;
Java虚拟机规范7版中描述符和签名语法的解析器。
 
内容
按照文中章节组织,记录重要知识点。
这部分内容需要在后面的学习过程中回来再做理解。
 
4 ANTLR Grammars
4.1 Describing Languages with Formal Grammars
4.2 Overall ANTLR Grammar File Structure
4.3 Rules
4.4 Tokens Specification
4.5 Global Dynamic Attribute Scopes
4.6 Grammar Actions
 
 
4 ANTLR Grammars
4.1 Describing Languages with Formal Grammars
翻译器(translator)是将每个输入语句s映射为输出语句t的程序;这里的翻译器包含了编译器(compiler)和解释器(interpreter)的含义。
文法(grammar)是用于描述其他语言的DSL,又称元语言(metalanguage)。
最常用的文法标记是BNF(Backus-Naur-Form),EBNF作为BNF的扩展(iso 14977 EBNF翻译(http://blog.sina.com.cn/s/blog_9c88479d010197cw.html)),添加了可选(optional)和重复(repeated)元素。
EBNF标记的文法成为上下文无关文法(context-free grammmar, CFG)。
ANTLR通过语义谓词和句法谓词,支持上下文相关文法的识别器和翻译器生成。
 
4.2 Overall ANTLR Grammar File Structure
ANTLR支持的文法类型有:lexer, parser, tree和combined lexer and parser
 
文法结构
  1. grammarType grammar name;
  2. <<optionSpec>>
  3. <<tokenSpec>>
  4. <<attributeScopes>>
  5. <<actions>>
  6. rule1 : ...|...|...;
  7. rule2 : ...|...|...;

文法词汇

comments: /**/, //,/***/
identifier: 词法规则名称全部大写,非词法规则名称以小写字符开始;只支持ASCII字符
literals:字符串以''表示,不支持非ASCII字符;ANTLR生成的识别器接收所有Unicode字符
actions:{}中以language选项一致的目标语言编写的代码块
templates:从翻译器中emit结构化文本时可以使用StringTemplate模板。需设置选项output=template。
两种方式:行内模板、另外定义的StringTemplate group
行内模板格式:单行("")、多行(<<>>),表示模板引用
 
4.3 Rules
规则的一般形式:
  1. access-modifier rule-name[<<arguments>>] returns [<<return-values>>]
  2. <<throws-spec>>
  3. <<options-spec>>
  4. <<rule-attribute-scopes>>
  5. <<rule-actions>>
  6. : <<alternative-1>> -> <<rewrite-rule-1>>
  7. | <<alternative-2>> -> <<rewrite-rule-2>>
  8. ...
  9. | <<alternative-n>> -> <<rewrite-rule-n>>
  10. ;
  11. <<exception-spec>>
选择项中的元素
 元素集合
'x'..'y':用于lexer规则,表征范围,x到y的任一字符
(A|B|...|C):用于parser或tree parser规则,任一token
('x'..'y'|'a'|...|'b'):用于lexer规则,任一字符
~x:用于任一类型规则,匹配不再x中的任一字符或token,这里x可以是单个元素、范围或子规则集合
 元素标签(label)
动作通过标签引用文法中的规则、token或字符
标签的类型:Toke, <<rule>>_return
 
 树操作符,均用于parser规则
T(Token), r(rule)
!: excluse, ^: 选择树的root
 
扩展的BNF子规则
(<<x>>|<<y>>|<<z>>)
 

x?
 
(<<x>>|<<y>>|<<z>>)?
 
x*
 
(<<x>>|<<y>>|<<z>>)*
 

x+
 
(<<x>>|<<y>>|<<z>>)+
<<...>>表示文法片段
 
子规则可以设置规则级选项
(options {<<>option-assignments>}): <<subrule-alternatives>>)
规则级选项
backtrack:设置为true时,LL(*)分析无法生成确定结果时,使用回溯。常与memoize选项一起使用,默认为true
memoize:回溯时,解析器记录部分解析结果,保证给定输入位置不会解析一条规则最多一次
k:启动LL(k)解析器,默认为*
greedy:最长匹配
 
在规则中嵌入规则
sample:
  1. rule returns [int n]
  2. @init {
  3. $n =0; // init return value
  4. }
  5. @after {
  6. System.out.println("n=" + $n);
  7. }
  8. : ID {$n=23;}
  9. | WS {$n=24;}
  10. ;

规则参数和返回值

sample:
  1. rule2[int a, String b] returns [int c, String d]
  2. : ID {$c=$a; $d=$b;}
  3. ;
 
ANTLR的parser和tree parser规则可以带参数和返回值,就像规则是方法一样;
但只有片段lexer规则(fragment lexer rule)可以携带参数。
规则引用Sample:
  1. rule3 : v=rule2[3, "test"] {System.out.println($v.d);}
  2. ;
 
动态的规则属性作用域
规则可以定义在其引用规则中可见的属性
sample:
  1. method
  2. @scope {
  3. String name;
  4. }
  5. : 'void' ID {$method::name = $ID.text;} '(' args ')' body
  6. ;
重写规则(rewrite rule)
为什么需要重写规则?在识别特定文法规则后,实施特定的操作,以生成内部表示(IR)。
通过设置output选项,ANTLR的解析器可以生成AST或StringTemplate模板。
所有文法规则都可以在动作中设置隐含的返回值。
重写规则以符号->开始。
sample:
  1. unaryID : '-' ID -> ^('-' ID);
  2. classDefinition
  3. : 'class' ID ('extends' sup=typename)?
  4. ('implements' i+=typename (',' i+=typename)*)?
  5. '{'
  6. (varibaleDefinition|methodDefinition|ctorDefinition)*
  7. '}'
  8. -> ^('class' ID ^('extends' $sup)? ^('implements' $i+)?
  9. varibaleDefinition* methodDefinition* ctorDefinition*);
构造AST时,重写规则是解析文法到树文法的映射。
生成模板时,重写规则描述创建的模板、以及模板中的placeholder属性。
 
规则异常处理
错误报告和恢复处理的方法。
sample:
  1. rule_with_exception
  2. : expr_temp
  3. ;
  4. catch[FailedPredicateException e] {;}
  5. catch[RecognitionException e] {;}
  6. finally {;}
 
句法谓词
sample:
  1. stat : (decl)=> decl ';'
  2. | expr ';'
  3. | 'return' expr ';'
  4. | 'break' ';'
  5. ;
//文法名称为T_template

替代方法:
  1. stat
  2. options{backtrack=true;}
  3. : decl ';'
  4. | 'return' expr ';'
  5. | 'break' ';'
  6. | expr ';'
  7. ;

 
词法规则
 片段词法规则
ANTLR要求所有的lexer规则必须描述一个有效的token,添加了fragment关键字的lexer规则不会提交一个token给解析器。
sample
  1. UNICODE_CHAR
  2. : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT;
  3.  
  4. fragment
  5. HEX_DIGIT
  6. : '0'..'9'|'a'..'f'|'A'..'F';
前面提到ANTLR词法规则中只有片段词法规则可以携带参数
sample:
  1. fragment
  2. CODE[boolean stripCurlies]
  3. : '{' CODE[stripCurlies] | ~('{'|'}')* '}'
  4. {
  5. if(stripCurlies) {
  6. setText(getText().subString(1, getText().length()));
  7. }
  8. }
  9. ;
 channel和skip()
ANTLR运行token对象存在于不同的channel中,解析器会忽略不在其channel中的token
sample:
  1. WS : (' '|'\t'|'\n'|'\r')+ {$channel=HIDDEN;};
skip动作会自动跳过匹配token,定位到下一token
sample:
  1. WS : (' '|'\t'|'\n'|'\r')+ {skip();};
 每条词法规则匹配时emit多个token
ANTLR词法规则允许手动调用emit()动作,一次提交多个token。
 
树匹配规则
在需要对输入流多次遍历时,可以采用解析器生成AST,再用某种tree walker或tree visitor遍历,或者用树文法(tree grammar)描述树的结构。
树文法规则同样可以携带参数和返回值,与其他规则不同的,其规则引用$T表示对节点T的指针引用。
 
4.4 Tokens Specification
用<<tokenSpec>>创建新的token类型或者创建token字面量的别名。
sample:
  1. tokens{
  2. VARDEF;
  3. MOD='%';
  4. }
  5. var : type ID ';' -> ^(VARDEF type ID);
  6. expr : INT (MOD INT)*;
4.5 Global Dynamic Attribute Scopes
规则间引用通过参数传递和返回值完成,但在嵌套层次比较深时,极易生成复杂的代码。
全局作用域中定义的变量在所有规则中可见,唯一不同的是每个声明了引用该作用的规则使用的变量是识别器维护的stack中的变量,即每个规则用到变量是不同的。
sample:
  1. scope SymbolScope {
  2. List symbols;
  3. }
  4. classDefinition
  5. scope SymbolScope;
  6. :
  7. 'class' ID ('extends' sup=typename)?
  8. ('implements' i+=typename (',' i+=typename)*)?
  9. '{'
  10. (varibaleDefinition|methodDefinition|ctorDefinition)*
  11. '}'
  12. -> ^('class' ID ^('extends' $sup)? ^('implements' $i+)?
  13. varibaleDefinition* methodDefinition* ctorDefinition*)
  14. ;
  15. methodDefinition
  16. scope SymbolScope;
  17. : WS
  18. ;
 
4.6 Grammar Actions
ANTLR提供了规则级动作(即由{}标识的动作)和命名动作,命名动作的语法为:
@action-name {...} //header, members
@action-scope-name::action-name {...} //action-scope-name可以是lexer, parser, treeparser

ANTLR3完全参考指南读书笔记[03]的更多相关文章

  1. ANTLR3完全参考指南读书笔记[01]

    引用 Terence Parr. The Definitive ANTLR Reference, Building Domain Specific Languages(antlr3 version). ...

  2. ANTLR3完全参考指南读书笔记[06]

    前言 这段时间在公司忙的跟狗似的,但忙的是没多少技术含量的活儿. 终于将AST IR和tree grammar过了一遍,计划明天写完这部分的读书笔记.   内容 1 内部表示AST构建 2 树文法   ...

  3. ANTLR3完全参考指南读书笔记[02]

    前言 程序语言是什么? 用wiki上的描述,程序语言是一种人工设计的语言,用于通过指令与机器交互:程序语言是编程程序的标记,而程序是一种计算或算法的描述.详细介绍和背景信息参考: Programmin ...

  4. ANTLR3完全参考指南读书笔记[08]

    前言 不要让用户被那些“专业术语”吓住! 用心设计的提示和反馈信息是软件设计者的“职业良心”.   内容 1 存在哪些错误? 2 美化错误提示 3 错误恢复策略   1 存在哪些错误? 在DSL语言开 ...

  5. ANTLR3完全参考指南读书笔记[07]

    前言 真正意义上的程序员都很懒,懒的连多余的一行代码也不写. 如果能将底层满手油污的活儿都可以交给别人去做,自己就扮演个智囊团成员的角色,生活会比想象中的还要惬意. 严格的按照指令执行长时间不知疲倦的 ...

  6. ANTLR3完全参考指南读书笔记[05]

    前言 仅生成给出true/false的识别器是没有多大用处的,自然的就有在识别过程中遇到某一结构时执行一段代码.存储该结构中信息的想法. ANTLR提供了在文法中嵌入属性和动作超级混合“文法”,可以生 ...

  7. ANTLR3完全参考指南读书笔记[04]

    前言 学习框架或第三方库的方法是什么 (1)少量的浏览manual或tutoral,只关注程序所需的特征,再完善其详细内容和特征的认识? (2)花大量的时间研究详细内容,再考虑程序实现? 这是个先有鸡 ...

  8. HTTP权威指南读书笔记

    HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...

  9. css权威指南读书笔记

    今天翻手机,翻到了许久之前看css权威指南时的笔记,遂移到博客中来. 1.属性选择器p.one class名为one的p元素p[class][name] 含有class和name属性的p元素p[cla ...

随机推荐

  1. ComboBox绑定

    this.ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend; this.ComboBox1.AutoCompleteSource ...

  2. hihocoder 1138 Islands Travel dijkstra+heap 难度:2

    http://hihocoder.com/problemset/problem/1138 很久不用最短路,几乎连基本性质也忘了,结果这道题就是某些最短路算法空间复杂度是o(n) 这里总结四种算法 算法 ...

  3. 一模 (3) day2

    第一题: 题目大意:和day1一样,给出m个小于n的数,求出出现次数大于m div 2 的数. 数据范围加大,1<=n<=2^31   1<=m<=3000000 解题过程: ...

  4. SA 的参数

    SA 的参数也只能是常数数组. http://www.cnblogs.com/del/archive/2009/10/27/1590692.html ja := SA([]); jo := SO(); ...

  5. Andoid activity 生命周期

    今天介绍一下Android中最常用的组件activity的生命周期.当activity处于Android应用中运行时,它的活动状态由Android以Activity栈的形式管理.当前活动的Activi ...

  6. CentOS SSH配置

    默认CentOS已经安装了OpenSSH,即使你是最小化安装也是如此.所以这里就不介绍OpenSSH的安装了. SSH配置: 1.修改vi /etc/ssh/sshd_config,根据模板将要修改的 ...

  7. goldengate 12c 针对oracle 12c配置的主要变化

    由于oracle 12c已经是多租户架构,在使用OGG同步的时候,需要考虑下面一些情况 一个 CDB包含多个PDB,源端部署的一个extract可访问所有pdb redo,理论上不需要每个pdb单独配 ...

  8. ARC以及MRC中setter方法

    ARC以及MRC中setter方法的差异 有时候,你会需要重写setter或者getter方法,你知道么,ARC与MRC的setter方法是有着差异的呢. 先看下MRC下的setter方法: 在看下A ...

  9. (转)iOS消息推送机制的实现

    原:http://www.cnblogs.com/qq78292959/archive/2012/07/16/2593651.html iOS消息推送机制的实现 iOS消息推送的工作机制可以简单的用下 ...

  10. BZOJ 3251 树上三角形

    NOIP的东西回成都再说吧... 这题暴力. #include<iostream> #include<cstdio> #include<cstring> #incl ...