一个简单的语言的语法(三):做些小调整,并将生成目标换到CSharp22011-10-07 javaeye RednaxelaFX为了后面的tree grammar更简洁,本篇对上一篇的树重写规则和一些语法细节做了些调整。并且,将 生成的lexer和parser的源码目标换到了CSharp2,以便后面能使用一些.NET的库。要使用CSharp2的目标,需要从官网下载相应的运行时库。当前的最新版是3.1.1,可以从这里获取。 CSharp/CSharp2目标的详细情况,可以查阅官网上的文档。以上一篇的语法为基础,要换到CSharp2目标 只要把几个嵌入动作里的System.out.println换成Console.WriteLine,把toStringTree换成 ToStringTree,把clear换成Clear就可以了。编译的时候至少需要引用Antlr3.Runtime.dll。那么除去更换生成目标带来的影响,这次做了些怎样的修改呢?首先,语法做了些细微的调整。例如说,program规则从原本允许没有语句到现在要求至少有一条语句 ;blockStatement为空block写了条专门的分支;expressionStatement也添加了一个EXPR_STMT的虚构 token为根节点,等等。变化最大的还是variableDeclaration及相关规则。上一篇里这条规则的重写规则并不区分有初始化与 无初始化、简单类型与数组类型的区别;本篇里则将这两个区别都明确的写在了重写规则里,以不同的虚 构token来作为生成的树的根节点。这样,到写后面的tree grammar的时候,需要的lookahead数就可以减 少。ANTLR所生成的AST,以深度优先的方式遍历,可以看做一个一维的流:每一层父子关系都可以表示为 :root -> "down" -> element1 -> element2 -> ... -> elementN -> "up" -> ...其中"down"和"up"是ANTLR插入的虚构token,用于指定树的层次。这样,后面使用tree grammar来遍历AST时,实际上遍历的就是这样一个一维的流 (CommonTreeNodeStream)。所以我们也可以把tree grammar看做是隐含了"down"和"up"虚构token的普 通parser grammar。那么,tree grammar中需要的lookahead个数的分析,也就跟parser grammar的一样 。看看下面的例子。对于上一篇variableDeclaration的重写规则中出现的变量声明的类型,可以用这样 的tree grammar来匹配:Java代码
type: ^( SIMPLE_TYPE INT )| ^( SIMPLE_TYPE REAL )| ^( ARRAY_TYPE INT Integer+ )| ^( ARRAY_TYPE REAL Integer+ );
树语法的^( ... )就隐含了"down"和"up"这两个虚构token。实际上这条规则匹配的是: