我正在尝试使用llvm来实现一种简单,愚蠢的c语言。 我一直坚持设计一个好的AST。
例如,我想知道将变量分成两种节点是一个好主意: 一个用于分配,一个用于加载。我试过了,但是遇到了一些障碍:
Foo = asd = 3;
在这种情况下,Foo和add将是一个分配,但添加也是一个加载。 但是ast节点通过它们的code()方法连接起来。
设计ast有什么好的资源吗? (我试图找到clang的,但是从它的源文件中轻松理解它有点复杂。)
答案 0 :(得分:2)
在大多数允许这种输入的语言中,将被解析为
Foo = (asd = 3);
和Foo
将分配表达式asd = 3
的结果。这通常恰好是asd
的值,但AST不需要代表那个。
AST通常不代表像“读取访问”这样的语义。它是语法的图形表示,语法只是“使用左侧变量Foo
和右侧(使用左侧变量asd
赋值和右侧的赋值手边整数常量3
)“。
如果我正确记住了Kaleidoscope示例,您会看到它们的每个语句都返回一个值。其中大多数将在链中进一步优化,但它们是获得嵌套赋值等有用行为的最简单方法。显然,任务的左侧需要特殊处理,但没有任何难以理解或难以实现的内容。
答案 1 :(得分:1)
您可以从Go的AST包中获取灵感:http://golang.org/pkg/go/ast/
它是一种类似C的语言,虽然您的示例不适用,因为Go中的赋值是一个语句而不返回值。如果是这样,你的代码会解析为这样的东西: (这是伪Go,但希望可以被不了解它的人理解)
AssignExpr{
Lhs: Ident{
Name: "Foo",
},
Tok: token.ASSIGN
Rhs: AssignExpr{
Lhs: Ident{
Name: "asd",
},
Rhs: BasicLit{
Kind: token.INT,
Value: "3",
},
},
}