如何使用 JJTree 中的 AST 重现原始代码
How to reproduce the original code using an AST from JJTree
我接到了一项任务,我必须使用 JavaCC 解析器来制作编译器。我有一个合成语言的语法,我们称之为 K。给定一个输入程序,我必须能够读取该程序,创建一个 AST,然后遍历该 AST 以更清晰的方式重现原始程序上表格。
例如,给定代码:
begin a := 2
s := 0 while - a
12 begin
s := + s * a a a := + a 2
end end
一旦我将其输入到我的程序中,我将得到一个由 Op、Const、ID 等元素组成的 AST...
但我需要能够获取代码中使用的实际数字和变量,以便我可以像这样重现代码:
begin
a := 2
s := 0
while - a 12
begin
s := + s * a a
a := + a 2
end
end
我已经通读了展示如何制作 AST 的示例 here,据我所知我可以正常工作。我感到困惑的是如何从 AST 中获取生成节点的实际文本。这个问题中的人使用了 dump 方法,但这只会让你返回节点的类型。我只需要了解如何在遍历节点时从节点获取实际标识符。
非常感谢这里的一些建议。
在 SimpleNode
class 中有一个名为 value
的字段,您可以随意使用它。在 Bart Kiers 对 this question 的回答中,您可以看到他使用值字段来存储标识符名称和常量等信息。
例如,他写
void id() #ID :
{Token t;}
{
t=<ID> {jjtThis.value = t.image;}
}
这意味着 .id
等于 ID
的任何节点都将在其 value
字段中包含标识符(作为字符串)。
要遍历树来重现输入,你可以写一个单一的大递归方法来遍历树,也可以使用访问者。
这是单个大方法的样子
static void buildString( SimpleNode n, String indentation, StringBuilder out ) {
swtich( n.id ) {
...
case ID: out.append( n.jjtGetValue() ) ; break ;
...
}
}
由于 id
字段被保护,上面的代码不会编译。您可以执行以下操作之一:
- 将
id
更改为 public
。 (最好添加一个 public 访问器并使用它。)
- 将
buildString
方法放在SimpleNode中class
- Subclass SimpleNode 与您自己的 class 具有 id 访问器,并确保解析器通过使用
NODE_CLASS
选项使用该 class。同时更改 buildString 参数的类型。
我接到了一项任务,我必须使用 JavaCC 解析器来制作编译器。我有一个合成语言的语法,我们称之为 K。给定一个输入程序,我必须能够读取该程序,创建一个 AST,然后遍历该 AST 以更清晰的方式重现原始程序上表格。
例如,给定代码:
begin a := 2
s := 0 while - a
12 begin
s := + s * a a a := + a 2
end end
一旦我将其输入到我的程序中,我将得到一个由 Op、Const、ID 等元素组成的 AST...
但我需要能够获取代码中使用的实际数字和变量,以便我可以像这样重现代码:
begin
a := 2
s := 0
while - a 12
begin
s := + s * a a
a := + a 2
end
end
我已经通读了展示如何制作 AST 的示例 here,据我所知我可以正常工作。我感到困惑的是如何从 AST 中获取生成节点的实际文本。这个问题中的人使用了 dump 方法,但这只会让你返回节点的类型。我只需要了解如何在遍历节点时从节点获取实际标识符。
非常感谢这里的一些建议。
在 SimpleNode
class 中有一个名为 value
的字段,您可以随意使用它。在 Bart Kiers 对 this question 的回答中,您可以看到他使用值字段来存储标识符名称和常量等信息。
例如,他写
void id() #ID :
{Token t;}
{
t=<ID> {jjtThis.value = t.image;}
}
这意味着 .id
等于 ID
的任何节点都将在其 value
字段中包含标识符(作为字符串)。
要遍历树来重现输入,你可以写一个单一的大递归方法来遍历树,也可以使用访问者。
这是单个大方法的样子
static void buildString( SimpleNode n, String indentation, StringBuilder out ) {
swtich( n.id ) {
...
case ID: out.append( n.jjtGetValue() ) ; break ;
...
}
}
由于 id
字段被保护,上面的代码不会编译。您可以执行以下操作之一:
- 将
id
更改为public
。 (最好添加一个 public 访问器并使用它。) - 将
buildString
方法放在SimpleNode中class - Subclass SimpleNode 与您自己的 class 具有 id 访问器,并确保解析器通过使用
NODE_CLASS
选项使用该 class。同时更改 buildString 参数的类型。