类 C 语言的良好 AST 设计(针对 llvm)

发布于 2024-12-04 08:18:52 字数 292 浏览 1 评论 0原文

我正在尝试使用 llvm 来实现一种简单、愚蠢的类 C 语言。 我一直致力于设计一个好的 AST。

例如,我想知道将变量分成两种节点是否是一个好主意: 一个用于分配,一个用于加载。我尝试过,但遇到了一些障碍:

Foo = asd = 3; 

在这种情况下 Foo 和 add 将是一个分配,但 add 也将是一个加载。 但 ast 节点是通过其 code() 方法连接的。

有没有关于设计AST的好资源? (我试图找到 clang,但从它的源文件中轻松理解它有点复杂。)

I am trying to use llvm to implement a simple, dumb c-like language.
And i'm stucked at designing a good AST.

For example i'm wondering if separating a variable into two kind of nodes is a good idea:
one for allocating and one for loading it. I tried that, but i got into some obstacles:

Foo = asd = 3; 

At this case Foo and add would be an allocating, but add would be a loading as well.
But the ast nodes are joined at their code() methods.

Is there any good resources on designing ast?
(I tried to find clang's but it's kinda complex to easily comprehend from it's source files.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

简单 2024-12-11 08:18:52

在大多数允许此类输入的语言中,该输入将被解析为

Foo = (asd = 3);

Foo 并将被分配表达式 asd = 3 的结果。这通常恰好是 asd 的值,但 AST 不需要表示它。

无论如何,AST 通常不表示“读访问”之类的语义。它是语法的图形表示,语法只是“用左手边变量Foo和右手边赋值(用左手边变量asd赋值”) 和右侧整数常量 3)”。

如果我没记错万花筒示例,您会看到它们的每个语句都返回一个值。其中大多数将在链中进一步优化,但它们是获得嵌套赋值等有用行为的最简单方法。显然,作业的左侧需要特殊处理,但没有什么难以理解或难以实现的。

In most languages that allow this kind of input, that would be parsed as

Foo = (asd = 3);

and Foo would be assigned the result of the expression asd = 3. Which usually happens to be the value of asd, but the AST doesn't need to represent that.

The AST usually does not represent semantics like “read access” anyway. It's a graph representation of the syntax, and the syntax is just “assignment with left hand side variable Foo and right hand side (assignment with left hand side variable asd and right hand side integer constant 3)”.

If I remember the Kaleidoscope example correctly, you'll see they have every statement return a value. Most of those will be optimized away further down the chain, but they are the easiest way of getting useful behavior for nested assignments and the like. The left hand side of an assignment, obviously, needs special treatment, but nothing that is difficult to understand or hard to implement.

梦巷 2024-12-11 08:18:52

您也许可以从 Go 的 AST 包中获得一些灵感: http://golang.org/pkg/go /ast/

它是一种类似 C 的语言,尽管您的示例不适用,因为 Go 中的赋值是一个语句并且不返回值。如果是这样,您的代码将解析为如下内容:
(这是伪围棋,但希望不了解它的人能够理解)

AssignExpr{
    Lhs: Ident{
        Name: "Foo",
    },
    Tok: token.ASSIGN
    Rhs: AssignExpr{
        Lhs: Ident{
            Name: "asd",
        },
        Rhs: BasicLit{
            Kind: token.INT,
            Value: "3",
        },
    },
}

You might be able to take some inspiration from Go's AST package: http://golang.org/pkg/go/ast/

It's a C-like language, although your example doesn't apply since assignment in Go is a statement and doesn't return a value. If it did, your code would parse to something like this:
(this is pseudo-Go, but will hopefully be understandable by people who don't know it)

AssignExpr{
    Lhs: Ident{
        Name: "Foo",
    },
    Tok: token.ASSIGN
    Rhs: AssignExpr{
        Lhs: Ident{
            Name: "asd",
        },
        Rhs: BasicLit{
            Kind: token.INT,
            Value: "3",
        },
    },
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文