我看到这个回复有点晚了,但是由于当我搜索编写解释器时这个线程出现在结果列表中的第二位,并且没有人提到任何非常具体的内容,我将提供以下示例:
免责声明:这只是我匆忙写的一些简单代码,以便为下面的解释奠定基础,因此并不完美,但它可以编译和运行,并且似乎给出了预期的答案。
从下往上阅读以下 C 代码:
#include <stdio.h>
#include <stdlib.h>
double expression(void);
double vars[26]; // variables
char get(void) { char c = getchar(); return c; } // get one byte
char peek(void) { char c = getchar(); ungetc(c, stdin); return c; } // peek at next byte
double number(void) { double d; scanf("%lf", &d); return d; } // read one double
void expect(char c) { // expect char c from stream
char d = get();
if (c != d) {
fprintf(stderr, "Error: Expected %c but got %c.\n", c, d);
}
}
double factor(void) { // read a factor
double f;
char c = peek();
if (c == '(') { // an expression inside parantesis?
expect('(');
f = expression();
expect(')');
} else if (c >= 'A' && c <= 'Z') { // a variable ?
expect(c);
f = vars[c - 'A'];
} else { // or, a number?
f = number();
}
return f;
}
double term(void) { // read a term
double t = factor();
while (peek() == '*' || peek() == '/') { // * or / more factors
char c = get();
if (c == '*') {
t = t * factor();
} else {
t = t / factor();
}
}
return t;
}
double expression(void) { // read an expression
double e = term();
while (peek() == '+' || peek() == '-') { // + or - more terms
char c = get();
if (c == '+') {
e = e + term();
} else {
e = e - term();
}
}
return e;
}
double statement(void) { // read a statement
double ret;
char c = peek();
if (c >= 'A' && c <= 'Z') { // variable ?
expect(c);
if (peek() == '=') { // assignment ?
expect('=');
double val = expression();
vars[c - 'A'] = val;
ret = val;
} else {
ungetc(c, stdin);
ret = expression();
}
} else {
ret = expression();
}
expect('\n');
return ret;
}
int main(void) {
printf("> "); fflush(stdout);
for (;;) {
double v = statement();
printf(" = %lf\n> ", v); fflush(stdout);
}
return EXIT_SUCCESS;
}
这是一个简单的recursive descend parser,用于支持单字母变量的基本数学表达式。运行它并输入一些语句会产生以下结果:
> (1+2)*3
= 9.000000
> A=1
= 1.000000
> B=2
= 2.000000
> C=3
= 3.000000
> (A+B)*C
= 9.000000
您可以更改 get()、peek() 和 number() 以从文件或代码行列表中读取。此外,您应该创建一个函数来读取标识符(基本上是单词)。然后扩展 statement() 函数,以便能够更改它接下来运行的行以进行分支。最后你将你想要的分支操作添加到语句函数中,比如
if "condition" then
"statements"
else
"statements"
endif.
while "condition" do
"statements"
endwhile
function fac(x)
if x = 0 then
return 1
else
return x*fac(x-1)
endif
endfunction
显然,您可以根据自己的喜好决定语法。您需要考虑定义函数的方法以及如何处理参数/参数变量、局部变量和全局变量。如果更喜欢数组和数据结构。参考文献∕指针。输入输出?
为了处理递归函数调用,您可能需要使用堆栈。
在我看来,使用 C++ 和 STL 来完成这一切会更容易。例如,一个 std::map 可用于保存局部变量,而另一个映射可用于全局变量...
当然可以编写一个从代码中构建抽象语法树的编译器。然后遍历这棵树以生成在虚拟机(如 Java 和 .Net)上执行的机器代码或某种字节代码。这比天真地逐行解析并执行它们提供了更好的性能,但在我看来,这并不是在编写解释器。那就是编写编译器及其目标虚拟机。
如果有人想学习编写解释器,他们应该尝试制作最基本的简单实用的工作解释器。