ANTLR3完全参考指南读书笔记[05]
decl : type ID {System.out.println($ID.text);}';';
type : 'int' | 'float';
decl : type ID ';' {System.out.println("var " + $ID.text+":"+$type.text+";");};
type : 'int' | 'float';
decl : type ID ';' {System.out.println("var " + $ID.text+":"+$type.text+";");}
| t=ID id=ID ';' {System.out.println("var " + $id.text+":"+$t.text+";");};
decl : type ids+=ID (',' ids+=ID)* ';'; //ids是ID token的List
decl : type declarator[$type.text] ';' ;//使用规则参数
declarator[String typeText]
: '*' ID {"var " + $ID.text+":^"+$typeText+";")}
| ID {System.out.println("var " + $ID.text+":"+$typeText+";")};
field : d=decl ';'
{System.out.println("type=)+$d.type+", vars="+$d.vars);};//使用规则返回值
decl returns[String type, List vars]
: t=type ids+=ID (',' ids+=ID)* {$type=$t.text;$vars=ids;}
@members{String methodName;}//文法内全局作用域变量
method : type ID {methodName=$ID.text;} body ;
body : '{' statement+ '}' ;
statement : decl {...methodName...} ';'//引用变量
| ... ;
method scope {String name;}//规则作用域变量
: type ID {$method::name=$ID.text;} body ;
body : '{' statement+ '}' ;
statement : decl {...$method::name...} ';'//引用变量
| ... ;
| 名称 | 说明 |
| header | 生成的代码中类定义之前的代码,常是包定义和包导入语句 |
| memebers | 定义实例变量和方法 |
| rulecatch | 动作中语法错误的默认catch语句 |
| synpredgate | 句法谓词开关 |
| 名称 | 说明 |
| init | 放置解析规则的代码执行前的代码 |
| after | 放置解析规则的代码执行后的代码 |
| catch | 放置解析规则的代码出现异常的处理代码 |
| finally | 放置解析规则的代码出现异常的最终处理代码 |
parser grammar T;
@header{package p;}
@members{
int i;
public TParser(TokenStream input, int foo){
this(input);
i = foo;
}
}
a[int x] returns [int y]
@init {int z=0;}
@after {System.out.println("after matching rule, before finally");}
: {<<action1>>} A {<<action2>>}
;
catch[RecognitionException re] {
System.err.println("error");
}
finally {<<do-this-no-matter-what-happened>>}
| 属性 | 类型 | 说明 |
| text | String | token对应的文本,调用Token#getText() |
| type | int | token的类型(正整数),调用Token#getType() |
| line | int | token所在行(从1计数),调用Token#getLine() |
| pos | int | 该行中token首字符的位置(从0计数),调用Token#getCharPositionInLine() |
| index | int | token流中该token的索引(从0计数),调用Toekn#getTokenIndex() |
| channel | int | token的channel号码,两个值Token.DEFAULT_CHANNEL, Token.HIDDEN_CHANNEL |
| tree | Object | 构建AST时,该属性指向依据token创建的树节点 |
lexer grammar T;
R : a='c' b='hin' c=. {$a, $b.text, $c};// a,c都不是token,b是token
| 属性 | 类型 | 说明 |
| text | String | 匹配规则开始直至$text表示式求值时的文本,包含了hidden channel中token的文本 |
| start | Token | 非hidden channel中匹配该规则的第一个token |
| stop | Token | 非hidden channel中匹配该规则的最后一个token |
| tree | Object | 规则计算出的AST,通常是重写规则的结果。引用当前规则时,仅在after动作中可用 |
| st | StringTemplate | 规则计算出的模板,通常是重写规则的结果。引用当前规则时,仅在after动作中可用 |
| 属性 | 类型 | 说明 |
| text | String | 从匹配最外层规则的第一个token开始到当前位置的文本 |
| type | int | 包围规则的token类型 |
| line | int | 该规则的第一个字符所在行号(从1计数) |
| pos | int | 该规则的第一个字符在所在行中的位置(从0计数) |
| channel | int | 该规则所在channel |
| 属性 | 类型 | 说明 |
| text | String | 该规则匹配的第一个节点开始推导出的文本 |
| start | Object | 第一个匹配该规则的树节点 |
| st | StringTemplate | 规则计算出的模板,通常是重写规则的结果。引用当前规则时,仅在after动作中可用 |
void foo(){int x=0; bar();}
void bar(){int y=x;}
调用链中的方法可以访问之前定义的局部变量
| 名称 | 说明 |
| $tokenRef | token本身引用 ID {$ID}(ELSE stat)?{if($ELSE!=null)...} |
| $tokenRef.attr | token属性引用 id=ID {$id.text} INT {$INT.line} |
| $listLabel | 由+=操作符标识的标签,表示一个List ids+=ID (',' ids+=ID)* {$ids} |
| $ruleRef | 规则有动态作用域且无歧义的情况下,parser/tree grammar中规则才可这样引用。该表达式是Stack $block.size() |
| $ruleRef.attr | 规则属性 e=expr {$e.value, $expre.tree} |
| $lexerRuleRef | lexer规则引用,是个Token (DIGIT {$DIGIT, $DIGIT.text})+ |
| $attr | 规则返回值、参数或预定义属性 r[int x] returns[Token t]:{$t=$start; $x}; |
| $enclosingRule.attr | 规则返回值、参数或预定义属性的全限定名 r[int x] returns[Token t]:{$r.t=$r.start; $r.x}; |
| $globalScopeName | 全局动态作用域引用 $symbols.size() |
| $x::y | 动态作用域x中属性y引用 $CScope::symbols |
| $x[-1]::y | 动态作用域x前一个作用域中属性y引用 $block[-1]::symbols |
| $x[-i]::y | 动态作用域x前i个作用域中属性y引用 $block[-i]::symbols |
| $x[i]::y | 动态作用域Stack中从栈底第i个作用域中属性y引用(从0计数) $block[2]::symbols |
| $x[0]::y | 动态作用域Stack中栈底作用域中属性y引用(从0计数) $block[0]::symbols |
grammar T;
@members{
int level = 0;
boolean isDefined(String variable){
boolean result = false;
//注:不要将中文注释放到文法定义文件中,至少在我的环境中是这样
//这里索引i从level-1的原因是:代码块(block)层次从1计数,而block对应的Stack从0计数
for(int i=level-1; i>=0; i--){
if($block[i]::symbols.contains(variable)){
System.out.println(variable + " found in nesting level " + (i+1));
result = true;
}
}
return result;
}
}
prog : block;
block
scope{
List symbols;
}
@init{
$block::symbols = new ArrayList();
level++;
}
@after{
System.out.println("symbols level " + level + " = " + $block::symbols);
level--;
}
: '{'decl* stat+'}'
;
decl : 'int' ID {$block::symbols.add($ID.text);}';'
;
stat : ID '=' INT ';'
{
System.err.println("undefined variable level " + level + ": "+ $ID.text);
}
}
| block
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
INT : '0'..'9'+;
WS : ( ' '| '\t'| '\r'| '\n') {$channel=HIDDEN;};
{
int i;
int j;
i = 0;
{
int i;
int x;
x = 5;
}
x = 3;
}
grammar T;
scope CScope{
String name;
List symbols;
}
@members{
boolean isDefined(String variable){
boolean result = false;
for(int i=$CScope.size()-1; i>=0; i--){
if($CScope[i]::symbols.contains(variable)){
System.out.println(">" + variable + " found in " +$CScope[i]::name);
result = true;
}
}
return result;
}
}
prog scope CScope;
@init {
$CScope::symbols = new ArrayList();
$CScope::name = "global";
}
@after {
System.out.println("global symbols = " + $CScope::symbols);
}
: decl* func*;
func scope CScope;
@init {
$CScope::symbols = new ArrayList();
}
@after {
System.out.println("function " + $CScope::name + "()'s symbols = " +$CScope::symbols);
}
: 'void' ID{$CScope::name=$ID.text;} '(' ')' '{' decl* stat+ '}'
;
block scope CScope;
@init {
$CScope::symbols = new ArrayList();
$CScope::name = "level " + $CScope.size();
}
@after{
System.out.println("code block level " + $CScope.size() + " symbols = " +$CScope::symbols);
}
: '{'decl* stat+'}'
;
//注:不要将中文注释放到文法定义文件中,至少在我的环境中是这样
//查看生成的代码,decl()中调用了Stack#peek(),
//即,会使用动态作用域Stack中当前的作用域,最终还是使用block(引用该decl)的作用域
decl : 'int' ID {$CScope::symbols.add($ID.text);}';'
;
stat : ID '=' INT ';'
{
if(!isDefined($ID.text)){
System.err.println("undefined variable in " + $CScope::name + ": "+ $ID.text);
}
}
| block
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
INT : '0'..'9'+;
WS : ( ' '| '\t'| '\r'| '\n') {$channel=HIDDEN;};
int i;
void f() {
int i;
{
int i;
i = 2;
}
i = 1;
}
void g(){
i = 0;
x = 3;
}
ANTLR3完全参考指南读书笔记[05]的更多相关文章
- ANTLR3完全参考指南读书笔记[01]
引用 Terence Parr. The Definitive ANTLR Reference, Building Domain Specific Languages(antlr3 version). ...
- ANTLR3完全参考指南读书笔记[06]
前言 这段时间在公司忙的跟狗似的,但忙的是没多少技术含量的活儿. 终于将AST IR和tree grammar过了一遍,计划明天写完这部分的读书笔记. 内容 1 内部表示AST构建 2 树文法 ...
- ANTLR3完全参考指南读书笔记[02]
前言 程序语言是什么? 用wiki上的描述,程序语言是一种人工设计的语言,用于通过指令与机器交互:程序语言是编程程序的标记,而程序是一种计算或算法的描述.详细介绍和背景信息参考: Programmin ...
- ANTLR3完全参考指南读书笔记[08]
前言 不要让用户被那些“专业术语”吓住! 用心设计的提示和反馈信息是软件设计者的“职业良心”. 内容 1 存在哪些错误? 2 美化错误提示 3 错误恢复策略 1 存在哪些错误? 在DSL语言开 ...
- ANTLR3完全参考指南读书笔记[07]
前言 真正意义上的程序员都很懒,懒的连多余的一行代码也不写. 如果能将底层满手油污的活儿都可以交给别人去做,自己就扮演个智囊团成员的角色,生活会比想象中的还要惬意. 严格的按照指令执行长时间不知疲倦的 ...
- ANTLR3完全参考指南读书笔记[04]
前言 学习框架或第三方库的方法是什么 (1)少量的浏览manual或tutoral,只关注程序所需的特征,再完善其详细内容和特征的认识? (2)花大量的时间研究详细内容,再考虑程序实现? 这是个先有鸡 ...
- ANTLR3完全参考指南读书笔记[03]
前言 文中第4章内容有点多,有点枯燥,但不坚持一下,之前所做的工作就白做了. 再次确认一下总体目标: protege4编辑器中Class Definition中语法解析和错误提示: Java虚拟机规范 ...
- 强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods)
强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods) 学习笔记: Reinforcement Learning: An Introduction, Richard S ...
- HTTP权威指南读书笔记
HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...
随机推荐
- 在 CentOS 7 中安装并使用自动化工具 Ansible
Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具.它用Python写成,类似于Chef和Puppet,但是有一个不同和优点是我们不需要在节点中安装任何客户端.它使用SSH来和节点进 ...
- [Js]焦点图轮播效果
一.所用到的知识点 1.DOM操作 2.定时器 3.事件运用 4.Js动画 5.函数递归 6.无限滚动大法 二.结构和样式 <div id="banner" class=&q ...
- Redhat6.x下如何制作虚拟机快照和镜像封装
一.虚拟机快照 1.确认你的物理机上的vg还有足够的剩余空间 [root@hacker ~]# vgs VG #PV #LV #SN Attr VSize VFree vg_ ...
- RPI学习--环境搭建_默认启动桌面/终端修改
参见:http://elinux.org/RPi_raspi-config 首次运行Raspbian会自动进入设置,往后也可以重新进入设置: $ sudo raspi-config 选项3 Enabl ...
- 避免ajax中get方法产生缓存的解决办法
在参数中传一个随机数,就会避免浏览器对get方法异步修改数据缓存,导致不能及时看到最新效果 $.get("<?php echo U('Vip/VipHandouts/change_gr ...
- C++学习之类的构造函数、析构函数
在C++的类中,都会有一个或多个构造函数.一个析构函数.一个赋值运算操作符.即使我们自己定义的类中,没有显示定义它们,编译器也会声明一个默认构造函数.一个析构函数和一个赋值运算操作符.例如: //声明 ...
- 2013年7月底至8月初51Aspx源码发布详情
兼职人员信息管理系统源码 2013-8-2 [VS2008]2013.8.2更新内容:修改了一级菜单不能修改的bug.功能介绍:兼职人员信息管理:添加,修改,删除,查询,支持数据导出Excel,按多 ...
- HDU 1114 Piggy-Bank (poj1384)
储钱罐 [题目描述] 今年的ACM比赛在xxx国举行,为了比赛的顺利进行,必须提前预算好需要的费用,以及费用的来源.费用的主要来源是只进不出的金钱.其实原理很简单,每当ACM成员有任何一点小钱,他们就 ...
- Java基础毕向东day04
1. 数组 2.选择排序.冒泡排序.折半查找.
- UIViewController添加子控制器(addChildViewController)
// // TaskHallViewController.m // yybjproject // // Created by bingjun on 15/10/27. // Copyright ...