用 JavaScript 编写的 C 解释器

33

有没有用JavaScript或Java编写的C语言解释器?

我不需要完整的解释器,但我需要能够逐步执行程序并能够在Web界面中查看变量、堆栈等所有内容。

这个想法是通过展示程序的逐步执行来帮助C语言初学者。

我们正在使用GWT构建界面,因此如果Java中存在某些东西,我们应该能够使用它。

我可以修改它以满足我的需求,但如果我可以避免编写解析器/抽象语法树遍历器/堆栈操作...那就太好了。


编辑:

明确一下,我不想模拟完整的C语言,因为有些程序可能非常棘手。

所谓“逐步”,指的是基本操作,如:表达式求值、赋值、函数调用。

我想要模拟的C语言将包含:变量、for循环、while循环、函数、数组、指针、数学函数。没有goto、字符串函数、ctypes.h、setjmp.h...(至少目前没有)。

以下是一个原型:http://www.di.ens.fr/~fevrier/war/simu.html

在这个例子中,我们已经手动将C代码转换为javascript表示,但它是有限的(例如,a == 2 || a = 1等表达式未处理),并且仅限于手动转换的程序。
我们可以使用远程服务器上的C编译器来检查代码是否正确(并且没有任何未定义的行为)。解析/AST构建也可以在远程完成(因此可以使用任何语言),但AST遍历需要在javascript中进行,以便在客户端上运行。

5
你可以看一下这个JavaScript PC模拟器,它也能运行一种Linux系统并有一个C编译器(但可能有些超出本项目的范畴)。 - Felix Kling
3
@Felix说:“那很有趣,但与OP想要的相当分离。”@Loïc说:“C并不真正按照‘步骤’执行,或者至少没有必要这样做。最接近的东西应该是序列点。我提到这个只是因为按照源代码中执行‘高级汇编’步骤学习C是初学者误解的主要原因之一。” - R.. GitHub STOP HELPING ICE
@Felix:这大概有50个抽象层。JS代码模拟了一些x86硬件,Linux内核运行在其之上,并运行各种可执行文件,包括用C语言编写但以x86操作码形式运行的tcc。TCC将C程序直接编译为x86可执行文件,而该x86代码再次由上述堆栈运行。祝你在JavaScript中使用它好运! - user395760
@全体成员:是的,仅用于检查值和堆栈确实不适合...我道歉。 - Felix Kling
C是一种非常小的语言。你的要求要求“不是整个C”并不能真正给你带来任何松动。我认为这并不是轻而易举就能做到的。 - Noufal Ibrahim
显示剩余12条评论
7个回答

7

有一个C语言可用于antlr,你可以使用它来在Java中生成C解析器,可能也可以在JavaScript中使用。


1
C语言语法的链接已经失效。 - shitpoet
1
@ataylor 您可以使用Wayback Machine链接替换该链接:http://web.archive.org/web/20120614203958/http://www.antlr.org/grammar/1153358328744/C.g - user202729

4

FelixhJSCPP项目提供了一个基于Javascript的C++解释器,但是有一些限制。

https://github.com/felixhao28/JSCPP

因此,一个示例程序可能如下所示:

var JSCPP = require('JSCPP');
var launcher = JSCPP.launcher;
var code = 'int main(){int a;cin>>a;cout<<a;return 0;}';
var input = '4321';
var exitcode = launcher.run(code, input);
console.info('program exited with code ' + exitcode);

截至2015年3月,此项目正在积极开发中,因此虽然可用,但仍存在可能继续扩展的领域。请查看文档以了解限制。目前看来,您可以将其作为纯C解释器使用,具有有限的库支持,而无需进一步解决问题。

很遗憾,该解释器在 printf("foo") 上已经失败了。 - kungfooman
printf需要#include <cstdio>才能正常工作.. 这里有一个在线版本https://felixhao28.github.io/JSCPP/ - milahu

4

有一个名为em-scripten的工具,可以将LLVM语言转换为JS代码。通过一些小技巧,您可能能够生成一个C解释器。


1
picoc是使用C语言编写的C解释器。使用Emscripten编译可能可以将其编译成JavaScript。 - Anderson Green

2
我不知道有没有用JavaScript编写的C解释器,但这里有一些可用的C解释器的讨论:Is there an interpreter for C? 你可能更好地寻找任何在JavaScript上运行的虚拟机,并查找一个能够为该虚拟机发出适当机器代码的C编译器。一个可能的选择似乎是LLVM;如果你能找到一个可以运行LLVM的JavaScript VM,那么你将会处于极佳状态。
我进行了一些谷歌搜索并找到了Emscripten,它直接将C代码转换为JavaScript!也许你可以用它来做些什么:https://github.com/kripken/emscripten/wiki 也许你可以修改Emscripten,在每个已编译的C行之后发出“序列点”,然后你可以使你的模拟环境从序列点单步执行到序列点。
我相信Emscripten正在实现LLVM,因此它可能实际上具有虚拟寄存器;如果是这样,它可能非常适合你的目的。

2
我知道你指定了C代码,但你可能考虑使用一个更简单语言的JavaScript仿真。特别是,请考虑FORTH。
在FORTH中,有两个堆栈:数据堆栈和流程控制堆栈(称为“返回”堆栈);还有一些全局内存。最初FORTH是一个16位语言,但现在有很多32位的FORTH实现。
因为FORTH代码与机器比较接近,所以当你看到它工作时,很容易理解它是如何工作的。我在学习C之前学习了FORTH,并发现它是一次非常宝贵的学习经历。
已经有几个JavaScript中的FORTH解释器可用了。FORTH虚拟机非常简单,不需要花费太长时间来实现它!
你甚至可以得到一个C到FORTH的翻译器,让学生们观看FORTH虚拟机解释编译后的C代码。
我认为这个答案对你来说是一个冒险,所以我会在这里停止写作。如果你确实对这个想法感兴趣,请在下面发表评论并要求更多细节,我将很乐意分享。我很久没有写过任何FORTH代码了,但我仍然对它怀有深深的回忆,并且很乐意谈论更多关于FORTH的内容。
编辑:尽管这个答案被投票为负分,但我仍然会把它留在这里。我认为,如果模拟是简单易懂的话,那么教育目的上的仿真更有价值。FORTH虚拟机的简单基于堆栈的结构非常简单,但你可以编译C代码来在其上运行。(在80年代甚至有一种CPU芯片,其本地机器码指令集就是FORTH指令。)并且,正如我所说,我在完全初学者时就学习了FORTH,这有助于我理解汇编语言和C。
问题没有被采纳的答案,而是在两年后才提出。Loïc Février可能没有找到合适的JavaScript解释器。正如我所说,已经存在几个JavaScript解释器可用于FORTH虚拟机。因此,这个答案是一个实用的答案。

0

C是一种编译型语言,而不是解释型语言,并且具有指针等JS完全不支持的特性,因此在Javascript中解释C并没有真正意义。


抱歉,这样的二元答案并没有什么意义:因为存在C解释器!请参见上文。 - Næreen

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接