我目前正在研究C下的编译器,我在构建AST数据结构的部分丢失了,特别是对于构建ID结构的部分,它被称为"符号表条目"
我看到网上的结构如:
struct ste {
struct id *name; /* pointer into hash table for assoc. id */
struct decl *decl; /* pointer into symbol table for its decl */
struct ste *prev; /* pointer to previous entry in symbol table */
};
Run Code Online (Sandbox Code Playgroud)
它看起来像一个链表,因为它包含一个指向前一个条目的指针(*prev)但这背后的逻辑是什么?
主要是作为一个学习练习,我从头开始编写虚拟机,汇编器和编译器,这取决于没有外部工具.
我相信我对虚拟机和汇编器的工作方式以及编译器的某些部分有一个相当概念性的理解.
这就是我想知道的: 在编译器中,假设我已将源代码转换为语法树.我将通过什么过程将此语法树转换为汇编?
(让我们假设一些简单的语言结构,比如if和while.我在这里寻找一个简单而简单的解释.)
我对复杂的解决方案或基于现有工具的解决方案并不特别感兴趣.相反,我想要对从语法树到汇编的背后的想法进行一页1页的广泛描述.
有人知道这样的资源吗?
谢谢 :)
我正在使用ocamllex/yacc在ocaml中编写编译器.事情进展顺利,但我遇到了设计问题.对于我创建的每个AST节点,最好在源代码中获得有关该节点的行/字符位置的信息.这对于稍后向用户提供错误消息将是有用的.
现在,我可以为我的节点添加某种元类型:
type node = Node1 of ... * meta | Node2 of ... * meta
Run Code Online (Sandbox Code Playgroud)
但这似乎是多余的.后来,当我完成验证AST时,我将不得不写
match n with
| NodeX(..., _) -> ...
Run Code Online (Sandbox Code Playgroud)
在每match一个浪费空间的地方.
解决这个问题的最佳方法是什么?
给定eclipse中的ASTNode,有没有办法获得相应的源代码行号?
所以我一直在研究和试验几个月的语言设计,我比几个月前的理解要好得多.我仍然对一些事情感到困惑...我已经在没有研究的情况下砍掉了一些糟糕的解析器,但我需要更好的东西.所以我正在尝试编写一个递归下降解析器,因为我已经读过它是手工编写的最合理的解析器.据我所知,每个规则都实现在它自己的功能中.所以我想我理解我将如何写这些但只有前半部分...解析器的工作是创建一个语法树或类似的东西,对吗?我也一直在尝试研究这个主题,但我还没有找到任何关于如何用语言表示树的例子.我正在写D因为它是我最喜欢的语言,但它'
我所看到的有很多类互相继承,所以可能有一个语句类,例如IfStatement类扩展.但是我无法找到所有这些在树中的表现方式,甚至以后如何走路.
如果有人能够向我展示一个例子或者更深入地谈论这些事情,那将是太棒了.任何帮助真的意味着很多,并有助于我的好奇心和目标,提前感谢!
我正在努力用Python动态生成代码.
为了解决这个问题,我编写了一个辅助方法,它接受一串Python代码并转储出AST.这是方法:
# I want print treated as a function, not a statement.
import __future__
pfcf = __future__.print_function.compiler_flag
from ast import dump, PyCF_ONLY_AST
def d(s):
print(dump(compile(s, '<String>', 'exec', pfcf|PyCF_ONLY_AST))
Run Code Online (Sandbox Code Playgroud)
当我在一个简单的Hello World上运行此函数时,它会吐出以下内容(格式化以便于阅读):
d("print('Hello World!')")
Module(body=[Expr(value=Call(func=Name(id='print',
ctx=Load()),
args=[Str(s='Hello World!')],
keywords=[],
starargs=None,
kwargs=None))])
Run Code Online (Sandbox Code Playgroud)
我能够动态生成这个代码并运行它 - 一切都很棒.
然后我试着动态生成
print(len('Hello World!'))
Run Code Online (Sandbox Code Playgroud)
应该很简单 - 只是另一个函数调用.这是我的代码动态生成的:
Module(body=[Expr(value=Call(func=Name(id='print',
ctx=Load()),
args=[Expr(value=Call(func=Name(id='len',
ctx=Load()),
args=[Str(s='Hello World!')],
keywords=[],
starargs=None,
kwargs=None))],
keywords=[],
starargs=None,
kwargs=None))])
Run Code Online (Sandbox Code Playgroud)
但是,运行它不起作用.相反,我收到了这条消息:
TypeError: expected some sort of expr, but got <_ast.Expr object at 0x101812c10>
Run Code Online (Sandbox Code Playgroud)
所以我运行了前面提到的辅助方法,看看它会输出什么:
d("print(len('Hello World!')")
Module(body=[Expr(value=Call(func=Name(id='print',
ctx=Load()),
args=[Call(func=Name(id='len', …Run Code Online (Sandbox Code Playgroud) 有许多要检测的节点类型,即:
eslint网站解释了规则,但未提供所有可用的节点类型检测。
我找到了一个检测IfStatement的教程示例,但这没有获取我的if语句,因此想知道我是否有语法错误。
我正在阅读Mark Seemann的这篇优秀文章.
在其中,他简单地演示了如何使用自由monad来使用纯函数来模拟交互.
我理解它足以能够编写这样的程序,我可以理解这种方法的优点.虽然有一点代码,但我想知道它的含义.
let rec bind f = function
| Free instruction -> instruction |> mapI (bind f) |> Free
| Pure x -> f x
Run Code Online (Sandbox Code Playgroud)
该函数是递归的.
我可能(可能)错过了一些基本的东西,这意味着递归永远不会走得太远,请让我知道.
有谁知道为什么这在MATLAB中有效?
>> 1 ++ 2
ans =
3
Run Code Online (Sandbox Code Playgroud)
来自C,python,Java等编码,我觉得最有效的是它应该可以工作.据推测,解析器有一些重要的东西我不明白?
这与关于访问POD的这个问题有关,但它远不止于此.您可以使用以下命令轻松访问Perl 6程序的抽象语法树:
perl6 --target=ast -e '"Þor is mighty!".say'
Run Code Online (Sandbox Code Playgroud)
这将打印整个Q抽象语法树.如何从你自己的程序中做到这一点还不太清楚,或者我还没有找到如何做到这一点.实际上,该CoreHackers::Q模块将其作为外部脚本运行.但是能够从你自己的程序中访问它,比如
use QAST; # It does not exist
my $this-qast = QAST::Load("some-external-file.p6") # Would want something like this
Run Code Online (Sandbox Code Playgroud)
会很好.我很确定它应该是可能的,在NQP级别并且可能以Rakudo依赖的方式.有人知道热吗?