我想练习C,所以我决定写一个C解释器的精神python解释器。我有一些C的知识,但我一直是一个学习的类型的程序员。
到目前为止,我所做的非常简单。只是解析用户的输入,一次一行,并区分声明,例如:
int x = 10;
char c = 'a';
在这里我创建了一个表示变量类型、名称的结构体,对于int value,我使用了i值,对于char value,我使用了c值。
我也可以解析函数调用,如下所示:
printf("value of x = %d\n, x);
在这里我提取函数的名称,并将参数存储在char**args中。
这听起来很傻,但我想避免为每个标准c库函数编写一个Map器,以执行对printf或strstr或strcpy之类的调用。有没有办法动态调用标准c函数而不使用这种方法?
此外,对这个东西的设计建议是非常欢迎的。
2条答案
按热度按时间mm9b1k5b1#
你不能(如我所想)写一个C解释器。
我猜你会很难写一个C解释器,你可能不得不写一个编译器。
当然,您可以动态地“剖析”语言,在进行过程中解析代码。
真实的的问题(在我看来)是处理外部引用。
在Python中,使用
import
关键字处理外部引用。如您所知,一些库可能具有冲突的方法(例如
lxml
和libxml2
)。通过
import
正确的库解决此冲突。当然,您可以考虑某种机制来有效地“链接”或导入所有需要的外部引用。
这可能会有一些非常具体的假设。
这样,当你遇到
#include <stdlib.h>
时,你实际上是import
它。因此,导入它可能意味着在windows下使用类似
LoadLibrary()
或LoadLibraryEx
的东西加载stdlib
的dll。在加载了你遇到的所有
#include's
之后,如果你没有找到一个引用的定义,那么你可能会遍历本地目录以找到其他的C文件,直到你遇到所寻找的引用,在这一点上我不确定应该做什么。这是关于链接问题(老实说,我不知道如果没有适当的编译,你将如何克服)。
另一部分实际上也很难,你需要写一个词法分析器。
这就是那个解析所有C代码行的小恶魔。
我假设您已经尝试过Scheme/List解释器的编写,或者甚至是一些更复杂的解析器。
小心!C不是Scheme!
它是一种解析起来非常复杂的语言,它的描述文档跨越数百页。
编写C词法分析器不是编写解释器的练习。
C有一些讨厌的上下文相关解析--这基本上意味着它不是CFL(上下文无关语言)--这意味着你不能写一个很好的有限自动机来解析它。
我将以an example作为结束,它摘自Eli Bendersky的精彩博客。
这正好说明了上下文相关语法是多么的棘手。
7tofc5zh2#
除了解析C语法的麻烦之外,它实际上非常适合解释,因为它被设计为在一个单一的通道中处理,以解决20世纪70年代设备的内存限制。
事实上,赫伯特Schildt所著的C: The Complete Reference, Fourth Edition的第6部分(第713-787页)致力于通过指导您编写这样一个解释器来将本书其余部分所教的内容结合在一起(它也在第三版中,在Internet Archive的借阅图书馆中是available)。
我没有检查过书中的版本是否有任何修改,但他的“小C”是在Dr. Dobb's Journal, August, 1989中首次呈现给世界的。
Schildt还在《The Craft of C:负责编程”,这也是available通过互联网档案馆的借阅图书馆。
此外,this question有一堆列出现有C解释器的答案。
至于动态调用C函数,在POSIX平台上比在Windows上更容易,因为您可能需要
.lib
文件来解析.dll
中的符号,而.so
文件没有等效的。对于
.so
文件,您只需dlopen
库的路径,并使用dlsym
按名称检索函数指针。在dlopen的Linux手册页中可以找到一个这样做的例子,运行
man dlopen
。