ANTLR3完全参考指南读书笔记[07]
前言
//demo.stg decl(type, name, value) ::= " ;" init(v) ::= " = "
decl(type, name, value)、init(v)为模板名和模板参数,为条件表达式(conditions),其它<...>为占位符。
STGroup group = new STGroupFile("demo.stg");//绝对路径
ST st = group.getInstanceOf("decl");//获取模板实例
st.add("type", "int");//填充占位符
st.add("name", "x");
st.add("value", 0);
String result = st.render();//模板输出
| 语法 | 说明 |
| %foo(a={}, b={},...) | 模板构建语法:创建模板foo,设置其属性a、b... |
| %({<<nameExpr>>}(a={}...)) | 间接模板构造引用,nameExpr是计算出的模板名称,其他部分与模板构造语法相同 |
| %x.y=<<z>> | 将模板x的属性y赋值为值z |
| %{<<expr>>}.y=<<z>> | 将StringTemplate类型表达式expr的属性赋值为表达式z的值 |
| %{<<stringExpr>>} | 从String类型stringExpr创建匿名模板 |
3+4*5
output:
; public class Calc extends Object { ...}
.class public Calc
.super java/lang/Object
; public Calc() { super(); } // calls java.lang.Object()
.method public ()V
aload_0
invokenonvirtual java/lang/Object/()V
return
.end method
; main(): Expr.g will generate bytecode in this method
.method public static main([Ljava/lang/String;)V
.limit stack ; how much stack space do we need?
.limit locals ; how many locals do we need?
getstatic java/lang/System/out Ljava/io/PrintStream;
; code translated from input stream
; compute 3+4*5
ldc
ldc
ldc
imul
iadd
; print result on top of stack
invokevirtual java/io/PrintStream/println(I)V
return
.end method
int x;
void foo(){
int y;
y = 1;
g(34, y);
x = h();
}
int x;
void foo(){
int y;
y = 1; write_to("y", y)
g(34, y); call("g");
x = eval_r("h", h()); write_to("x", x)
}
grammar Expr;
options{output=AST;ASTLabelType=CommonTree;}
@header{
package template;
import java.util.HashMap;
}
@members {
int numOps = 0;//operation count
HashMap locals = new HashMap();//local variable name-count map
int localVarNum = 1;//local variable count
}
prog : stat+;
stat : expr NEWLINE -> expr
| ID '=' expr NEWLINE
{
if(locals.get($ID.text)==null){
locals.put($ID.text, new Integer(localVarNum++));
}
}
-> ^('=' ID expr)
| NEWLINE ->
;
expr : multExpr ('+'^|'-'^) multExpr {numOps++;}
;
multExpr: atom ('*'^ atom {numOps++;})*
;
atom : INT
| ID
| '('! expr ')'!;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
INT : '0'..'9'+;
WS : ( ' '| '\t'| '\r'| '\n') {$channel=HIDDEN;} ;
NEWLINE : '\r'?'\n';
tree grammar Gen;
options {
tokenVocab=Expr;
ASTLabelType=CommonTree;
output=template;
}
@header {
package template;
import java.util.HashMap;
}
@members {
HashMap locals;
}
prog[int numOps, HashMap locals]
@init {this.locals= locals;}
: (s+=stat)+ -> jasminFile(instructions={$s}, maxStackDepth={numOps+1+1}, maxLocals={locals.size()+1})
;
stat : expr -> exprStat(v={$expr.st}, descr={$expr.text})
| ^('=' ID expr) -> assign(id={$ID.text}, descr={$text}, varNum={locals.get($ID.text)}, v={$expr.st})
;
expr returns [int value]
: ^('+' a=expr b=expr) -> add(a={$a.st}, b={$b.st})
| ^('-' a=expr b=expr) -> sub(a={$a.st}, b={$b.st})
| ^('*' a=expr b=expr) -> mult(a={$a.st}, b={$b.st})
| INT -> int(v={$INT.text})
| ID -> var(id={$ID.text}, varNum={locals.get($ID.text)})
;
group ByteCode;
jasminFile(maxStackDepth, maxLocals, instructions) ::= <<
; public class Calc extends Object { ...}
.class public Calc
.super java/lang/Object
; public Calc() { super(); } // calls java.lang.Object()
.method public \()V
aload_0
invokenonvirtual java/lang/Object/\()V
return
.end method
; main(): Expr.g will generate bytecode in this method
.method public static main([Ljava/lang/String;)V
.limit stack ; how much stack space do we need?
.limit locals ; how many locals do we need?
getstatic java/lang/System/out Ljava/io/PrintStream;
; code translated from input stream
; print result on top of stack
invokevirtual java/io/PrintStream/println(I)V
return
.end method
>>
assign(varNum, v ,descr, id) ::= <<
;compute descr
istore : id
>>
exprStat(v, descr) ::= <<
; compute
>>
add(a, b) ::= <<
iadd
>>
sub(a, b) ::= <<
isub
>>
mult(a, b) ::= <<
imul
>>
int(v) ::= "ldc "
var(id, varNum) ::= "iload ; "
package template;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
public class ByteCodeGeneratorTest {
public static void main(String[] args) throws Exception {
FileReader groupFileReader = new FileReader("D:/workspace/maven/antlrv3/grammar/template/generator/ByteCode.stg");
StringTemplateGroup templateGroup = new StringTemplateGroup(groupFileReader);
groupFileReader.close();
// [1]3+4*5
// [2]a=3+4
// a
InputStream is = new FileInputStream(new File("D:/workspace/maven/antlrv3/language/template.test"));
ANTLRInputStream inputStream = new ANTLRInputStream(is);
ExprLexer lexer = new ExprLexer(inputStream);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokenStream);
ExprParser.prog_return r = parser.prog();
// tree walker to generate template's value
CommonTree tree = (CommonTree) r.getTree();
CommonTreeNodeStream treeNodeStream = new CommonTreeNodeStream(tree);
treeNodeStream.setTokenStream(tokenStream);
Gen walker = new Gen(treeNodeStream);
walker.setTemplateLib(templateGroup);
Gen.prog_return r2 = walker.prog(parser.numOps, parser.locals);
StringTemplate output = (StringTemplate) r2.getTemplate();
System.out.println(output.toString());
}
}
grammar CMinus;
options{output=template;rewrite=true;}
program : declaration+;
declaration
: variable
| function
;
variable: type ID';';
function: type ID '(' (formalParameter (',' formalParameter)* )? ')' block;
formalParameter
: type ID;
type : 'int'|'void';
stat
scope{boolean isAssign;}
: expr ';'
| block
| ID '=' {$stat::isAssign=true;} expr ';'
-> template(id={$ID.text}, assign={$text})
" write_to(\"\", )"
| ';'
;
block : '{' variable* stat* '}';
expr : ID
| INT
| ID '(' (expr (',' expr)* )? ')'
-> {$stat::isAssign}? template(id={$ID.text}, e={$text})
"eval_r(\"\", )"
->template(id={$ID.text}, e={$text})
"; call(\"\")"
| '(' expr ')'
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
INT : '0'..'9'+ ;
COMMENT : '' {$channel=HIDDEN;} ;
WS : ( ' '| '\t'| '\r'| '\n') {$channel=HIDDEN;};
package template.rewriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.TokenRewriteStream;
public class Test {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream(new File("D:/workspace/maven/antlrv3/language/rewriter/CMinus.test"));
ANTLRInputStream input = new ANTLRInputStream(is);
CMinusLexer lexer = new CMinusLexer(input);
TokenRewriteStream tokens = new TokenRewriteStream(lexer);
CMinusParser parser = new CMinusParser(tokens);
parser.program();
System.out.println(tokens.toString());
}
}
ANTLR3完全参考指南读书笔记[07]的更多相关文章
- 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完全参考指南读书笔记[05]
前言 仅生成给出true/false的识别器是没有多大用处的,自然的就有在识别过程中遇到某一结构时执行一段代码.存储该结构中信息的想法. ANTLR提供了在文法中嵌入属性和动作超级混合“文法”,可以生 ...
- ANTLR3完全参考指南读书笔记[04]
前言 学习框架或第三方库的方法是什么 (1)少量的浏览manual或tutoral,只关注程序所需的特征,再完善其详细内容和特征的认识? (2)花大量的时间研究详细内容,再考虑程序实现? 这是个先有鸡 ...
- ANTLR3完全参考指南读书笔记[03]
前言 文中第4章内容有点多,有点枯燥,但不坚持一下,之前所做的工作就白做了. 再次确认一下总体目标: protege4编辑器中Class Definition中语法解析和错误提示: Java虚拟机规范 ...
- 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...
- HTTP权威指南读书笔记
HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...
随机推荐
- L1 - 运行机制
var name = 'kl'; function person(){ alert(name); var name = 'ko'; } person(); 这段代码输出 ‘undefined’,这种现 ...
- CCocos2Dx 一段遍历子节点的代码
CCLog("Lein will hide account!CS_FAST_REGISTER_REQ"); <p> CCNode* child1 = (CCNode*) ...
- 二模 (8) day1
第一题: 题目大意: 梦幻城市每年为全市高中生兴办一次运动会.为促使各校同学之间的交流,采用特别的分队方式:每一个学校的同学,必须被均匀分散到各队,使得每一队中该校的人数皆相同.为增加比赛的竞争性,希 ...
- winform插入sql的事务处理
实现目的:点击按钮,原子性执行两条sql语句,同时成功或同时失败 数据库有这三个字段(忽略已有的一条记录): 一.用事务的sql语句 按钮事件完整代码: //事务处理插入sql语句 using (SQ ...
- Windows的同步I/O和异步I/O
同步I/O操作 执行步骤 1. 程序通过FileStream对象来打开磁盘文件,然后调用Read方法(内部调用Win32 ReadFile函数),从文件中读取数据.这时,线程从托管代码转 ...
- SrcollView分页加载数据(布局)
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=& ...
- switch… case 语句的用法(二)
总结来说:switch的用法是判断case后面的表达式和switch后面的表达式是否相匹配,一旦case匹配,就会顺序执行后面的程序代码,而不管后面的case是否匹配,直到遇见break.都不匹配找d ...
- 《day11---内部类&匿名内部类》
//79-80-面向对象-内部类-体现 /* 当A类中的内容要被B类直接访问,而A类还需要去创建B类的对象,访问B的内容时, 这时可以将B类定义到A类的内部,这样访问更为便捷. 将B类称之为内部类(内 ...
- mysql 与 oracle 比较(一)group by 容易产生的误解
注:本文并不是列举出两者之间的所有不同,而是在实际应用中发现的不同的功能点或者处理模式,之所以记录下来,就是为了提醒自己,勿忘 group by : (1)oracle 中,总所周知,select ( ...
- hdu 2050
PS:真是醉了..之前觉得这题很难..然后在网上找到了大神给的深入解析,跪谢...这里贴大神博客的网址:http://blog.csdn.net/lishuhuakai/article/details ...