我正在努力用C ++实现编程语言,现在进入AST生成阶段。
我想使用3个步骤:
这是声明变量的示例,例如:
var MyVar : integer = 8 + 2;
临时形式(右值/节点/左值):
left:
-left:
"MyVar"
-node:
":"
-right:
"integer"
node:
"="
right:
-left:
"8"
-node:
"+"
-right:
"2"
代表经典的AST:
"="
/ \
/ \
/ \
":" "+"
/ \ / \
/ \ "8" "2"
/ \
"MyVar" "integer"
然后,将临时树添加到全局树,指定声明的类型:
[EXP]
|
VarDecl
|
{ ... }
这适用于除函数声明和函数调用以外的所有内容:
func add(a : integer, b : integer) : integer;
add(8, 2);
实际上,对于这种类型的表达式,没有节点可将左值与右值区分开。我也不知道如何表示函数参数。我曾想到过这样的事情:
left:
"add"
params:
[
-left:
"a"
-node:
":"
-right:
"integer"
]
[
-left:
"b"
-node:
":"
-right:
"integer"
]
node:
":"
right:
"integer"
通话提示:
left:
"add"
params:
[
"8"
]
[
"2"
]
但是我觉得如果这样做,就没有逻辑了。
所以,我想知道是否没有一种方法可以改善我的工作,还是必须对我的工作进行彻底的修改。
PS:在抽象语法分析和树的领域,我还是一个新手,但是我已经阅读了很多有关此主题的文档和教程。
答案 0 :(得分:3)
首先,我建议您针对C ++或其他解析器生成器使用bison / flex,因为您可以更轻松地将语句分组为树结构。
对于您的功能参数问题,AST不仅位于左侧的右节点。您可以在一个节点下具有多个(> 2)分支,并将这些分支视为其语法表达式而不是文字字符。在这里,词法分析器可以提供帮助,因为您可以将字符抽象为令牌,然后解析器会将令牌抽象为语法结构。通常,像a : integer
之类的东西都应该抽象为语法结构,可能称为类型化声明。
所以func add(a : integer, b : integer) : integer;
确实是
func identifier(params) : returnType
,AST中的节点可以跟踪特定信息。
也就是说,您的AST应该使用“字符”或“令牌”,但内部节点应该抽象该语言的语法结构。特别是对于参数列表,我建议将其作为逗号分隔的类型声明列表,然后params节点将具有子级声明节点列表。
从您还将语句添加到全局树的陈述中,将其视为将语句添加到AST的全局列表中可能会更有用。
无论如何,这是一个很奇怪的答案,希望对您有所帮助。