我目前正在阅读这一版的编译器:原理、技术和工具。
我以前从未用 C 编写过代码(尽管我曾涉足 C++),但从其他编程知识来看,大多数代码都是有意义的,但我注意到一个怪癖,即函数是这样定义的:
emit(t, tval)
int t, tval
{
}
发现有什么不对劲,我查了一下,果然,定义函数的方法似乎已经过时了。我希望有人可以阅读我在下面重新输入的代码片段,并警告我任何我可能不会注意到和接受的不良做法或过时的技术。此外,任何有关 C 的新功能的提醒,这可能有助于我编写更整洁的代码,我们将不胜感激。我主要是在寻找利用标准 C 规范中不再存在的语义、特性、函数等的代码,而不是从风格的角度来看。
另外,如果您有这本书的副本,并且不介意翻阅它并查看(甚至从记忆中)是否可以发现其他一些过时或多余的做事方法,那也太棒了!
我不确定这是否更适合 CodeReview,如果是,请发表评论,我会在那里删除并重新发布,但我认为由于它来自流行的编程文本,它可能更适合这里。抱歉,如果我不正确。
全局.h
#include <stdio.h>
#include <ctype.h>
#define BSIZE 128
#define NONE -1
#define EOS '\0'
#define NUM 256
#define DIV 257
#define MOD 258
#define ID 259
#define DONE 260
int tokenval;
int lineno;
struct entry {
char *lexptr;
int token;
};
struct entry symtable[];
词法分析器
#include "global.h"
char lexbuf[BSIZE];
int lineno = 1;
int tokenval = NONE;
int lexan()
{
int t;
while (1) {
t = getchar();
if (t == ' ' || t == '\t')
;
else if (t == '\n')
lineno++;
else if (isdigit(t)) {
ungetc(t, stdin);
scanf("%d", &tokenval);
return NUM;
}
else if (isalpha(t)) {
int p, b = 0;
while (isalnum(t)) {
lexbuf[b] = t;
b++;
if (b >= BSIZE)
error("compiler error");
}
lexbuf[b] = EOS;
if (t != EOF)
ungetc(t, stdin);
p = lookup(lexbuf);
if (p == 0)
p = insert(lexbuf, ID);
tokenval = p;
return symtable[p].token
}
else if (t == EOF)
return DONE;
}
}
解析器.c
#include "global.h"
int lookahead;
parse()
{
lookahead = lexan();
while (lookahead != DONE) {
expr(); match(';');
}
}
expr()
{
int t;
term();
while (1)
switch (lookahead) {
case '+': case '-':
t = lookahead;
match(lookahead); term(); emit(t, NONE);
continue;
default:
return;
}
}
term()
{
int t;
factor();
while (1)
switch (lookahead) {
case '*': case '/':
t = lookahead;
match(lookahead); factor(); emit(t, NONE);
continue;
default:
return;
}
}
factor()
{
switch (lookahead) {
case '(':
match('('); expr(); match(')'); break;
case NUM:
emit(NUM, tokenval); match(NUM); break;
case ID:
emit(ID, tokenval); match(ID); break;
default:
error("Syntax error");
}
}
match (t)
int t;
{
if (lookahead == t)
lookahead = lexan();
else error("Syntax error");
}