前言
文中第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
 
文法结构
grammarType grammar name;
<<optionSpec>>
<<tokenSpec>>
<<attributeScopes>>
<<actions>>
rule1 : ...|...|...;
rule2 : ...|...|...;

文法词汇

comments: /**/, //,/***/
identifier: 词法规则名称全部大写,非词法规则名称以小写字符开始;只支持ASCII字符
literals:字符串以''表示,不支持非ASCII字符;ANTLR生成的识别器接收所有Unicode字符
actions:{}中以language选项一致的目标语言编写的代码块
templates:从翻译器中emit结构化文本时可以使用StringTemplate模板。需设置选项output=template。
两种方式:行内模板、另外定义的StringTemplate group
行内模板格式:单行("")、多行(<<>>),表示模板引用
 
4.3 Rules
规则的一般形式:
access-modifier rule-name[<<arguments>>] returns [<<return-values>>]
<<throws-spec>>
<<options-spec>>
<<rule-attribute-scopes>>
<<rule-actions>>
: <<alternative-1>> -> <<rewrite-rule-1>>
| <<alternative-2>> -> <<rewrite-rule-2>>
...
| <<alternative-n>> -> <<rewrite-rule-n>>
;
<<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:
rule returns [int n]
@init {
$n =0; // init return value
}
@after {
System.out.println("n=" + $n);
}
: ID {$n=23;}
| WS {$n=24;}
;

规则参数和返回值

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

替代方法:
stat
options{backtrack=true;}
: decl ';'
| 'return' expr ';'
| 'break' ';'
| expr ';'
;

 
词法规则
 片段词法规则
ANTLR要求所有的lexer规则必须描述一个有效的token,添加了fragment关键字的lexer规则不会提交一个token给解析器。
sample
UNICODE_CHAR
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT;

fragment
HEX_DIGIT
: '0'..'9'|'a'..'f'|'A'..'F';
前面提到ANTLR词法规则中只有片段词法规则可以携带参数
sample:
fragment
CODE[boolean stripCurlies]
: '{' CODE[stripCurlies] | ~('{'|'}')* '}'
{
if(stripCurlies) {
setText(getText().subString(1, getText().length()));
}
}
;
 channel和skip()
ANTLR运行token对象存在于不同的channel中,解析器会忽略不在其channel中的token
sample:
WS : (' '|'\t'|'\n'|'\r')+ {$channel=HIDDEN;};
skip动作会自动跳过匹配token,定位到下一token
sample:
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:
tokens{
VARDEF;
MOD='%';
}
var : type ID ';' -> ^(VARDEF type ID);
expr  : INT (MOD INT)*;
4.5 Global Dynamic Attribute Scopes
规则间引用通过参数传递和返回值完成,但在嵌套层次比较深时,极易生成复杂的代码。
全局作用域中定义的变量在所有规则中可见,唯一不同的是每个声明了引用该作用的规则使用的变量是识别器维护的stack中的变量,即每个规则用到变量是不同的。
sample:
scope SymbolScope {
List symbols;
}
classDefinition
scope SymbolScope;
:
'class' ID ('extends' sup=typename)?
('implements' i+=typename (',' i+=typename)*)?
'{'
(varibaleDefinition|methodDefinition|ctorDefinition)*
'}'
-> ^('class' ID ^('extends' $sup)? ^('implements' $i+)?
varibaleDefinition* methodDefinition* ctorDefinition*)
;
methodDefinition
scope SymbolScope;
: WS
;
 
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. php 加密解密字符串

    /********************************************************************* 函数名称:encrypt 函数作用:加密解密字符串 使用方 ...

  2. 走进AngularJs(七) 过滤器(filter) - 吕大豹

    时间 2013-12-15 16:22:00  博客园-原创精华区 原文  http://www.cnblogs.com/lvdabao/p/3475426.html 主题 AngularJS 过滤器 ...

  3. C++封装库

    1.新建项目 -> Win32项目    选择DLL , 勾选 空项目 , 点击完成. 2.本例程,使用一个CPP文件 , 及一个头文件. 其中头文件包含函数声明,CPP文件实现函数声明. 3. ...

  4. 【STL】-迭代器的用法

    初始化: list<char>::iterator pos; 算法: 1. 遍历 for(pos = col1.begin(); pos != col1.end(); ++pos){... ...

  5. Hibernate对象映射类型

    Hibernate understands both the Java and JDBC representations of application data. The ability to rea ...

  6. jpcap

    1.System.out.println( System.getProperty("java.library.path")); 2.将jpcap.dll放到上边打印的路径中

  7. JDBC Thin Driver 的formats三种格式

    格式一:  Oracle JDBC Thin using a ServiceName: jdbc:oracle:thin:@//<host>:<port>/<servic ...

  8. [处理器、单片机]ARM

    1.ARM简介: ARM是Advanced RISC Machines的缩写.1985年4月26日,第一个ARM原型在英国剑桥的Acorn计算机有限公司诞生,由美国加州San Jose VLSI技术公 ...

  9. poj1141 区间dp+路径

    //Accepted 176 KB 47 ms //感谢大神们为我们这群渣渣铺平前进的道路!! //用scanf("%s",s)!=EOF WA到死 #include <cs ...

  10. Canopy测试IPython控制台输出

    Canopy测试IPython控制台输出