一个简单的语言的语法(二):ANTLR的重写规则

上一篇我们使用ANTLR来描述了Jerry语言的基本语法,并通过ANTLRWorks来实验该语法对样本代码生 成的解析树。但如同上一篇最后所述,这样得到的解析树中有太多对后续处理来说无用的冗余信息。我们 需要消除这些冗余信息,得到抽象语法树(AST)。

本篇将以之前做的语法为基础,通过添加树重写规则来将ANTLR默认生成的解析树简化整理为抽象语法 树。

本文涉及的源码和运行时库打包在附件里了,懒得复制粘贴的话就直接下载附件的版本,用 ANTLRWorks来查看和编辑语法文件吧~

修改后的语法文件如下:

Jerry.g(ANTLR 3.1语法文件,以Java为生成目标语言)

Java代码

1.grammar Jerry;
2.
3.options {
4. language = Java;
5. output = AST;
6. ASTLabelType = CommonTree;
7.}
8.
9.tokens {
10. // imaginary tokens
11. VAR_DECL;
12. SIMPLE_TYPE;
13. ARRAY_TYPE;
14. ARRAY_LITERAL;
15. SIMPLE_VAR_ACCESS;
16. ARRAY_VAR_ACCESS;
17. UNARY_MINUS;
18. BLOCK;
19. EXPR_STMT;
20.}
21.
22.// parser rules
23.
24.program : statementList EOF!
25. {
26. System.out.println(
27. null == $statementList.tree ?
28. "null" :
29. $statementList.tree.toStringTree());
30. }
31. ;
32.
33.statementList
34. : statement*
35. ;
36.
37.statement
38. : expressionStatement
39. | variableDeclaration
40. | blockStatement
41. | ifStatement
42. | whileStatement
43. | breakStatement
44. | readStatement
45. | writeStatement
46. ;
47.
48.expressionStatement
49. : expression SEMICOLON
50. -> ^( EXPR_STMT expression )
51. ;
52.
53.variableDeclaration
54. : typeSpecifier
55. ( Identifier
56. ( -> ^( VAR_DECL ^( SIMPLE_TYPE typeSpecifier ) Identifier )
57. | ( LBRACK Integer RBRACK )+
58. - > ^( VAR_DECL ^( ARRAY_TYPE typeSpecifier Integer+ ) Identifier )
59. | EQ expression
60. -> ^( VAR_DECL ^( SIMPLE_TYPE typeSpecifier ) Identifier expression )
61. | ( LBRACK Integer RBRACK )+ EQ arrayLiteral
62. -> ^( VAR_DECL ^( ARRAY_TYPE typeSpecifier Integer+ ) Identifier arrayLiteral )
63. )
64. )
65. ( COMMA id=Identifier
66. ( -> $variableDeclaration ^( VAR_DECL ^( SIMPLE_TYPE typeSpecifier ) $id )
67. | ( LBRACK dim1+=Integer RBRACK )+
68. -> $variableDeclaration ^( VAR_DECL ^( ARRAY_TYPE typeSpecifier $dim1+ ) $id )
69. | EQ exp=expression
70. -> $variableDeclaration ^( VAR_DECL ^( SIMPLE_TYPE typeSpecifier ) $id $exp )
71. | ( LBRACK dim2+=Integer RBRACK )+ EQ al=arrayLiteral
72. -> $variableDeclaration ^( VAR_DECL ^( ARRAY_TYPE typeSpecifier $dim2+ ) $id $al )
73. )
74. { if (null != $dim1) $dim1.clear(); if (null != $dim2) $dim2.clear(); }
75. )*
76. SEMICOLON
77. ;
78.
79.typeSpecifier
80. : INT | REAL
81. ;
82.
83.arrayLiteral
84. : LBRACE
85. arrayLiteralElement ( COMMA arrayLiteralElement )*
86. RBRACE
87. -> ^( ARRAY_LITERAL arrayLiteralElement+ )
88. ;
89.
90.arrayLiteralElement
91. : expression
92. | arrayLiteral
93. ;
94.
95.blockStatement
96. : LBRACE statementList RBRACE
97. -> ^( BLOCK statementList )
98. ;
99.
100.ifStatement
101. : IF^ LPAREN! expression RPAREN! statement ( ELSE! statement )?
102. ;
103.
104.whileStatement
105. : WHILE^ LPAREN! expression RPAREN! statement
106. ;
107.
108.breakStatement
109. : BREAK SEMICOLON!
110. ;
111.
112.readStatement
113. : READ^ variableAccess SEMICOLON!
114. ;
115.
116.writeStatement
117. : WRITE^ expression SEMICOLON!
118. ;
119.
120.variableAccess
121. : Identifier
122. ( -> ^( SIMPLE_VAR_ACCESS Identifier )
123. | ( LBRACK Integer RBRACK ) +
124. -> ^( ARRAY_VAR_ACCESS Identifier Integer+ )
125. )
126. ;
127.
128.expression
129. : assignmentExpression
130. | logicalOrExpression
131. ;
132.
133.assignmentExpression
134. : variableAccess EQ^ expression
135. ;
136.
137.logicalOrExpression
138. : logicalAndExpression ( OROR^ logicalAndExpression )*
139. ;
140.
141.logicalAndExpression
142. : relationalExpression ( ANDAND^ relationalExpression )*
143. ;
144.
145.relationalExpression
146. : additiveExpression ( relationalOperator^ additiveExpression )?
147. | BANG^ relationalExpression
148. ;
149.
150.additiveExpression
151. : multiplicativeExpression ( additiveOperator^ multiplicativeExpression )*
152. ;
153.
154.multiplicativeExpression
155. : primaryExpression ( multiplicativeOperator^ primaryExpression )*
156. ;
157.
158.primaryExpression
159. : variableAccess
160. | Integer
161. | RealNumber
162. | LPAREN! expression RPAREN!
163. | MINUS primaryExpression
164. -> ^( UNARY_MINUS primaryExpression )
165. ;
166.
167.relationalOperator
168. : LT | GT | EQEQ | LE | GE | NE
169. ;
170.
171.additiveOperator
172. : PLUS | MINUS
173. ;
174.
175.multiplicativeOperator
176. : MUL | DIV
177. ;
178.
179.// lexer rules
180.
181.LPAREN : '('
182. ;
183.
184.RPAREN : ')'
185. ;
186.
187.LBRACK : '['
188. ;
189.
190.RBRACK : ']'
191. ;
192.
193.LBRACE : '{'
194. ;
195.
196.RBRACE : '}'
197. ;
198.
199.COMMA : ','
200. ;
201.
202.SEMICOLON
203. : ';'
204. ;
205.
206.PLUS : '+'
207. ;
208.
209.MINUS : '-'
210. ;
211.
212.MUL : '*'
213. ;
214.
215.DIV : '/'
216. ;
217.
218.EQEQ : '=='
219. ;
220.
221.NE : '!='
222. ;
223.
224.LT : '<'
225. ;
226.
227.LE : '<='
228. ;
229.
230.GT : '>'
231. ;
232.
233.GE : '>='
234. ;
235.
236.BANG : '!'
237. ;
238.
239.ANDAND : '&&'
240. ;
241.
242.OROR : '||'
243. ;
244.
245.EQ : '='
246. ;
247.
248.IF : 'if'
249. ;
250.
251.ELSE : 'else'
252. ;
253.
254.WHILE : 'while'
255. ;
256.
257.BREAK : 'break'
258. ;
259.
260.READ : 'read'
261. ;
262.
263.WRITE : 'write'
264. ;
265.
266.INT : 'int'
267. ;
268.
269.REAL : 'real'
270. ;
271.
272.Identifier
273. : LetterOrUnderscore ( LetterOrUnderscore | Digit )*
274. ;
275.
276.Integer : Digit+
277. ;
278.
279.RealNumber
280. : Digit+ '.' Digit+
281. ;
282.
283.fragment
284.Digit : '0'..'9'
285. ;
286.
287.fragment
288.LetterOrUnderscore
289. : Letter | '_'
290. ;
291.
292.fragment
293.Letter : ( 'a'..'z' | 'A'..'Z' )
294. ;
295.
296.WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; }
297. ;
298.
299.Comment
300. : '/*' ( options { greedy = false; } : . )* '*/' { $channel = HIDDEN; }
301. ;
302.
303.LineComment
304. : '//' ~ ('\n'|'\r')* '\r'? '\n' { $channel = HIDDEN; }
305. ;

时间: 2024-11-05 05:47:02

一个简单的语言的语法(二):ANTLR的重写规则的相关文章

一个简单的语言的语法(一):用ANTLR描述语法

在JavaEye的博客频道逛,看到NeuronR的blog上有关于他的编译器实践的帖子,觉得有点意思,于是 平行的用别的方法来做那个编译器.那边要求是用C来实现,我这边就用些方便些的语言来实现吧. 本篇将通过ANTLR 3.1描述Jerry语言,并在ANTLRWorks里实验,通过生成的解析器来得到Jerry程序代 码对应的解析树. 关注过解析器生成器的话,ANTLR应该不会是个陌生的名字才对.Anyway简短说几句.ANTLR在生成解 析器方面正得到越来越多的应用,几个实例,XRuby项目用了

一个简单的语言的语法(三):做些小调整,并将生成目标换到CSharp2

为了后面的tree grammar更简洁,本篇对上一篇的树重写规则和一些语法细节做了些调整.并且,将 生成的lexer和parser的源码目标换到了CSharp2,以便后面能使用一些.NET的库. 要使用CSharp2的目标,需要从官网下载相应的运行时库.当前的最新版是3.1.1,可以从这里获取. CSharp/CSharp2目标的详细情况,可以查阅官网上的文档.以上一篇的语法为基础,要换到CSharp2目标 只要把几个嵌入动作里的System.out.println换成Console.Writ

Emit学习-实战篇-实现一个简单的AOP框架(二)

已经9点了,就不废话了,直接开讲,今天就简单的介绍下框架中用到的一些接口和属性.昨天把我们关注的切面分成了三类,现在给出这3个接口的定义: 接口定义 /// <summary> /// 在调用方法体前执行的处理接口 /// </summary> public interface IPreProcess { bool PreProcess(MethodContext methodContext); } /// <summary> /// 在调用方法体后执行的处理接口 //

一个简单的记事本代码(二)

/**************************************************/ //调用的函数 public void File_new_actionPerformed(ActionEvent e){ FileNew(); } public void File_open_actionPerformed(ActionEvent e){ FileOpen(); } public void File_save_actionPerformed(ActionEvent e){ F

求一个简单多线程例子

问题描述 求一个简单多线程例子 解决方案 解决方案二:http://blog.csdn.net/jinjazz/archive/2008/05/06/2397136.aspx

我的编程学习路-想做一个简单对对碰游戏,如何实现游戏界面啊?

问题描述 想做一个简单对对碰游戏,如何实现游戏界面啊? 我目前是大一的学生,编程方面的东西不是很懂,想做一个简单的对对碰游戏,可是运行结果总是不能出现游戏界面,请问我要怎么让那个界面出现呢,是否还要建立包含游戏图片的库??求大神们能和我说一下都需要做些什么 解决方案 做一个简单的游戏服务器 解决方案二: 不知到你的编程环境是什么,windows下可以考虑用MFC.他是windows API 的图形界面库,因该可以满足你的要求.

linux-awk脚本 一个简单的报错问题

问题描述 awk脚本 一个简单的报错问题 awk脚本 $linux@ubuntu:~/jwx$ awk -F:'{print $0}' passwd.txt >>bak.txt $awk: passwd.txt $awk: ^ syntax error 刚学脚本 不知道为什么会报错? 解决方案 一个简单的awk脚本 解决方案二: 一个简单的awk脚本 解决方案三: awk -F ':' '{print $1}' /etc/passwd >>bak.txt

ANTLR#1:描述一个简单计算器

ANTLR是什么鬼?引用官网的说明, What is ANTLR? ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files. It's widely used to build languages, tools, and framewo

中文字符-如何用C语言编写一个简单的输入法程序,要求可以输入汉字。

问题描述 如何用C语言编写一个简单的输入法程序,要求可以输入汉字. 不太清楚汉字在计算机中是如何存储的,想知道例如微软的智能ABC以及搜狗输入法是怎样实现拼音拼写下的汉字输入. 解决方案 首先要有一个汉字的编码库,比如GB2312编写的是拼音输入法的话,还要建立一个拼音与汉字对应的数据库然后根据用户输入的拼音,提示出对应的汉字(汉字的优先顺序由数据库决定,同时还可以学习该用户的使用习惯)如果输入法还支持智能联想输入的话,还要加入词库(也有优先级),这样可以根据前一个字来推断出下一个可能的字 解决