前言
本程序参考了TINY1的实现源代码,并添加了一些简单新的语法规则,最终结果是生成可阅读中间代码。部分地方没有考虑过多的容错,纯属自娱自乐。采用的语法为TINY v2的语法,老师实验课给的,自行百度。
文件读取器
头部定义一些变量
#include "FILEHANDLE.h"
#include "SCAN.h"
/* 定义一行能读取的最大字符数 */
#define BUFLEN 256
static char lineBuf[BUFLEN]; /* 储存当前行字符 */
static int linepos = 0; /* 当前读取到的列的位数 */
static int bufsize = 0; /* 当前行的总列数 */
int lineno = 0;
int EOF_flag;
接下来主要是两个函数,一个获取字符,一个回退字符
/* 获取一个字符 */
int getNextChar(void)
{
EOF_flag = FALSE;
if (!(linepos < bufsize))//判断当前行是否已经结束
{
lineno++;
if (fgets(lineBuf, BUFLEN - 1, source))//如果结束则读出新的一行
{
//if (fprintf(listing, "%4d: %s", lineno, lineBuf));
bufsize = strlen(lineBuf);
linepos = 0;
return lineBuf[linepos++];
}
else//读取下一行失败,说明文件到头,返回EOF标识
{
EOF_flag = TRUE;
return EOF;
}
}
else return lineBuf[linepos++];//没有结束,则返回当前行的下一个字符
}
//回退一个字符
void ungetNextChar(void)
{
if (!EOF_flag) linepos--;
}
词法扫描器
定义状态机的状态表,和保留关键字词典
const int MAXRESERVED = 22;
/* 定义能识别的所有字符 */
/* 定义DFA的状态 */
typedef enum
{
START, INASSIGN, INCOMMENT, INNUM, INID, DONE, INCOMPARED, INSTRING
}StateType;
char tokenString[MAXTOKENLEN + 1];
/* 定义保留字字典 */
struct
{
char* str;
TokenType tok;
} reservedWords[MAXRESERVED] = { { "true",TRUES },{ "false",FALSES },{ "or",OR },{ "and",AND },
{ "not",NOT },{ "int",INT },{ "bool",BOOL },{ "string",STRING},{ "while",WHILE },{ "do",DO },
{ "if",IF },{ "then",THEN },{ "else",ELSE },{ "end",END },{ "repeat",REPEAT },{ "until",UNTIL },{ "read",READ },
{ "write",WRITE },{ "<",LT },{ "<=",LTEQ },{ ">",RT },{ ">=",RTEQ } };
匹配关键字词典函数,没有对应的string则认为是ID词条
static TokenType reservedLookup(char * s)
{
int i;
for (i = 0; i < MAXRESERVED; i++)
if (!strcmp(s, reservedWords[i].str))
return reservedWords[i].tok;
return ID;
}
编写对应的状态转移函数
static void changeBySTART(StateType& state, int& save, TokenType& currentToken, const char c) {
if (isdigit(c)) {
state = INNUM;//如果是数字的话,将状态置为数字态
}
else if (isalpha(c)) {
state = INID;//如果是字母的话,将状态置为字母态
}
else if (c == ':') {
state = INASSIGN;//如果是:则将状态置为赋值态
}
else if ((c == '>') || (c == '<')) {
state = INCOMPARED;//如果是>或者<则将状态置为比较态
}
else if (c == '\'') {
save = FALSE;
state = INSTRING;//如果是'则将状态置为字符串态
}
else if ((c == ' ') || (c == '\t') || (c == '\n')) {
save = FALSE;//如果是空格,换行,制表符则跳过
}
else if (c == '{') {
save = FALSE;
state = INCOMMENT;//如果是 { 的话,将状态置为注释态
}
else {
state = DONE;//剩下的是特殊标志符
switch (c)
{
case EOF:
save = FALSE;
currentToken = ENDFILE;
break;
case ',':
currentToken = COMMA;
break;
case ';':
currentToken = SEMI;
break;
case '+':
currentToken = PLUS;
break;
case '-':
currentToken = MINUS;
break;
case '*':
currentToken = TIMES;
break;
case '/':
currentToken = OVER;
break;
case '(':
currentToken = LPAREN;
break;
case ')':
currentToken = RPAREN;
break;
case '=':
currentToken = EQ;
break;
case '}':
currentToken = MISSLCOMMENT;
break;
default:
break;
}
}
}
static void changeByINASSIGN(StateType& state, int& save, TokenType& currentToken, const char c) {
state = DONE;
if (c == '=')//如果下一个字符为=,则判断为赋值符号,否则出错
currentToken = ASSIGN;
else
{
ungetNextChar();
save = FALSE;
currentToken = MISSEQ;
}
}
static void changeByINCOMMENT(StateType& state, int& save, TokenType& currentToken, const char c) {
save = FALSE;
if ((c == EOF) || (c == '\n'))//缺少右括号就换行或者结束,则报错
{
state = DONE;
currentToken = MISSRCOMMENT;
}
else if (c == '}') state = START;
}
static void changeByINNUM(StateType& state, int& save, TokenType& currentToken, const char c) {
if (isalpha(c))//如果是字母,则报错
{
save = FALSE;
state = DONE;
currentToken = ERRORNUM;
char a = getNextChar();
while (isalpha(a) || isdigit(a)) {
a = getNextChar();
}
ungetNextChar();
}
else if (!isdigit(c)) {//如果不是数字,则退回,标识当前为NUM
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = NUM;
}
}
static void changeByINID(StateType& state, int& save, TokenType& currentToken, const char c) {
if (!(isalpha(c) || isdigit(c))) {//如果不是字符或者数字,则退回,标识当前为ID
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = ID;
}
}
static void changeByINCOMPARED(StateType& state, int& save, TokenType& currentToken, const char c) {
if (c == '=') {//如果是=,则标识当前为ID
state = DONE;
currentToken = ID;
}
else {//否则回退标识当前为ID
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = ID;
}
}
static void changeByINSTRING(StateType& state, int& save, TokenType& currentToken, const char c) {
if (c == '\'') {//如果是’,则标识当前为STR
save = FALSE;
state = DONE;
currentToken = STR;
}
else if ((c == '\n') || (c == EOF)) {//缺少‘报错
save = FALSE;
state = DONE;
currentToken = ERROR;
}
}
扫描器入口函数
TokenType getToken(void)
{
int tokenStringIndex = 0;
TokenType currentToken;
StateType state = START;
int save;
while (state != DONE) {
char c = getNextChar();
save = TRUE;
switch (state) {
case START:
changeBySTART(state, save, currentToken, c); break;
case INASSIGN:
changeByINASSIGN(state, save, currentToken, c); break;
case INCOMMENT:
changeByINCOMMENT(state, save, currentToken, c); break;
case INNUM:
changeByINNUM(state, save, currentToken, c); break;
case INID:
changeByINID(state, save, currentToken, c); break;
case INCOMPARED:
changeByINCOMPARED(state, save, currentToken, c); break;
case INSTRING:
changeByINSTRING(state, save, currentToken, c); break;
case DONE:
default:
break;
}
if ((save) && (tokenStringIndex <= MAXTOKENLEN))
tokenString[tokenStringIndex++] = (char)c;
if (state == DONE)
{
tokenString[tokenStringIndex] = '\0';
if (currentToken == ID)
currentToken = reservedLookup(tokenString);
if (currentToken == ERROR) {
if (tokenStringIndex != 0) {
currentToken = MISSRQUOTE;
}
else {
currentToken = MISSLQUOTE;
}
}
}
}
printf(" %d %s\n", currentToken,tokenString);
printToken(currentToken, tokenString);
return currentToken;
}
语法解析器
匹配函数和异常输出函数
static void syntaxError(char * message)
{
fprintf(listing, "\n>>> ");
fprintf(listing, "Syntax error at line %d: %s", lineno, message);
Error = TRUE;
}
static void match(TokenType expected)
{
if (token == expected) token = getToken();
else {
syntaxError("unexpected token -> ");
printToken(token, tokenString);
fprintf(listing, " ");
}
}
解析定义区语法
static void declarations(){
while ((token==INT)|| (token == BOOL) ||(token == STRING)) {
match(token);
do {
match(ID);
if (token == COMMA)match(COMMA);
else break;
} while (1);//逗号
match(SEMI); // 匹配分号
}
}
stmt逻辑语句分析函数
//stmt-sequence -> statement [ ; stmt-sequence ]
TreeNode * stmt_sequence(void)
{
TreeNode * t = statement();
TreeNode * p = t;
while ((token != ENDFILE) && (token != END) &&
(token != ELSE) && (token != UNTIL))
{
TreeNode * q;
match(SEMI);
q = statement();
if (q != NULL) {
if (t == NULL) t = p = q;
else /* now p cannot be NULL either */
{
p->sibling = q;
p = q;
}
}
}
return t;
}
//statement -> if-stmt | repeat-stmt | assign-stmt | read-stmt | write-stmt | while-stmt
TreeNode * statement(void)
{
TreeNode * t = NULL;
switch (token) {
case IF: t = if_stmt(); break;
case REPEAT: t = repeat_stmt(); break;
case ID: t = assign_stmt(); break;
case READ: t = read_stmt(); break;
case WRITE: t = write_stmt(); break;
case WHILE: t = while_stmt(); break;
default: syntaxError("unexpected token -> ");
printToken(token, tokenString);
token = getToken();
break;
} /* end case */
return t;
}
//if-stmt -> if logical-or-exp then stmt-sequence [else stmt-sequence] end
TreeNode * if_stmt(void)
{
TreeNode * t = newStmtNode(IfK);
match(IF);
if (t != NULL) t->child[0] = log_exp();
match(THEN);
if (t != NULL) t->child[1] = stmt_sequence();
if (token == ELSE) {
match(ELSE);
if (t != NULL) t->child[2] = stmt_sequence();
}
match(END);
return t;
}
//repeat-stm -> repeat stmt-sequence until logical-or-exp
TreeNode * repeat_stmt(void)
{
TreeNode * t = newStmtNode(RepeatK);
match(REPEAT);
if (t != NULL) t->child[0] = stmt_sequence();
match(UNTIL);
if (t != NULL) t->child[1] = log_exp();
return t;
}
//assign-stmt -> identifier := logical-or-exp
TreeNode * assign_stmt(void)
{
TreeNode * t = newStmtNode(AssignK);
if ((t != NULL) && (token == ID))
t->attr.name = copyString(tokenString);
match(ID);
match(ASSIGN);
if (t != NULL) t->child[0] = log_exp();
return t;
}
//read-stmt -> read identifier
TreeNode * read_stmt(void)
{
TreeNode * t = newStmtNode(ReadK);
match(READ);
if ((t != NULL) && (token == ID))
t->attr.name = copyString(tokenString);
match(ID);
return t;
}
//write-stmt -> write logical-or-exp
TreeNode * write_stmt(void)
{
TreeNode * t = newStmtNode(WriteK);
match(WRITE);
if (t != NULL) t->child[0] = log_exp();
return t;
}
//while-stmt -> while logical-or-exp do stmt-sequence end
TreeNode * while_stmt(void)
{
TreeNode * t = newStmtNode(WhileK);
match(WHILE);
if (t != NULL) t->child[0] = log_exp();
match(DO);
if (t != NULL) t->child[1] = stmt_sequence();
match(END);
return t;
}
exp算术语句分析函数
TreeNode * log_exp(void) {
TreeNode * t = exp();
if (token == AND || token == OR) {
TreeNode * p = newExpNode(OpK);
if (p != NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
}
match(token);
if (t != NULL)
t->child[1] = exp();
}
return t;
}
TreeNode * exp(void)
{
TreeNode * t = simple_exp();
if ((token == LT) || (token == RT) || (token == EQ) || (token == LTEQ) || (token == RTEQ)) {
TreeNode * p = newExpNode(OpK);
if (p != NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
}
match(token);
if (t != NULL)
t->child[1] = simple_exp();
}
return t;
}
TreeNode * simple_exp(void)
{
TreeNode * t = term();
while ((token == PLUS) || (token == MINUS))
{
TreeNode * p = newExpNode(OpK);
if (p != NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
match(token);
t->child[1] = term();
}
}
return t;
}
TreeNode * term(void)
{
TreeNode * t = factor();
while ((token == TIMES) || (token == OVER))
{
TreeNode * p = newExpNode(OpK);
if (p != NULL) {
p->child[0] = t;
p->attr.op = token;
t = p;
match(token);
p->child[1] = factor();
}
}
return t;
}
变量因子解析
//factor -> number | string | identifier | true | false| ( logical-or-exp )
TreeNode * factor(void)
{
TreeNode * t = NULL;
switch (token) {
case NUM:
t = newExpNode(ConstK);
if ((t != NULL) && (token == NUM))
t->attr.val = atoi(tokenString);
match(NUM);
break;
case ID:
t = newExpNode(IdK);
if ((t != NULL) && (token == ID))
t->attr.name = copyString(tokenString);
match(ID);
break;
case TRUES:
t = newExpNode(BoolK);
if ((t != NULL) && (token == TRUES))
t->attr.trust = true;
match(TRUES);
break;
case FALSES:
t = newExpNode(BoolK);
if ((t != NULL) && (token == FALSES))
t->attr.trust = false;
match(FALSES);
break;
case STR:
t = newExpNode(IdK);
if ((t != NULL) && (token == STR))
t->attr.name = copyString(tokenString);
match(STR);
break;
case LPAREN:
match(LPAREN);
t = log_exp();
match(RPAREN);
break;
default:
syntaxError("unexpected token -> ");
printToken(token, tokenString);
token = getToken();
break;
}
return t;
}
解析器入口函数
TreeNode * parse(void)
{
TreeNode * t;
token = getToken();
declarations();
t = stmt_sequence();
if (token != ENDFILE)
syntaxError("Code ends before file\n");
return t;
}
中间代码生成器
前序遍历语法树,对不同的叶子节点进行输出,该部分写点有点乱,因为期末了没有时间做重复语句的优化等。将就的把语句逻辑表达了出来。
static void genStmt(TreeNode * tree) {
TreeNode * p1, *p2, *p3;
p1 = tree->child[0];
p2 = tree->child[1];
p3 = tree->child[2];
int tem1,tem2,tem3;
switch (tree->kind.stmt)
{
case IfK:
if (p3 != NULL) {
tem1 = label++;
tem2 = label++;
tem3 = label++;
genExp(p1, tem1,tem2);
fprintf(listing, "%d) label L%d \n", linesum++, tem1);
cGen(p2);
fprintf(listing, "%d) goto L%d \n", linesum++, tem3);
fprintf(listing, "%d) label L%d \n", linesum++, tem2);
cGen(p3);
fprintf(listing, "%d) label L%d \n", linesum++, tem3);
}
else {
tem1 = label++;
tem2 = label++;
genExp(p1, tem1,tem2);
fprintf(listing, "%d) label L%d \n", linesum++, tem1);
cGen(p2);
fprintf(listing, "%d) label L%d \n", linesum++, tem2);
}
break;
case ReadK:
fprintf(listing, "%d) read %s \n", linesum++, tree->attr.name); break;
case WriteK:
fprintf(listing, "%d) write %s \n", linesum++, p1->attr.name); break;
case RepeatK:
tem1 = label++;
tem2 = label++;
fprintf(listing, "%d) label L%d \n", linesum++, tem1);
cGen(p1);
genExp(p2, tem2,0);
fprintf(listing, "%d) goto L%d \n", linesum++, tem1);
fprintf(listing, "%d) label L%d \n", linesum++, tem2);
break;
case AssignK:
switch (p1->kind.exp)
{
case OpK:
genExp(p1, 0,0);
fprintf(listing, "%d) %s:=%s \n", linesum++, tree->attr.name, p1->attr.name); break;
break;
case ConstK:
fprintf(listing, "%d) %s:=%d \n", linesum++, tree->attr.name, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) %s:=%s \n", linesum++, tree->attr.name, p1->attr.name); break;
case BoolK:
fprintf(listing, "%d) %s:=%d \n", linesum++, tree->attr.name, p1->attr.trust); break;
default:
break;
}
break;
case WhileK:
tem1 = label++;
tem2 = label++;
tem3 = label++;
fprintf(listing, "%d) label L%d \n", linesum++, tem3);
genExp(p1, tem1, tem2);
//fprintf(listing, "%d) goto L%d \n", linesum++, tem2);
fprintf(listing, "%d) label L%d \n", linesum++, tem1);
cGen(p2);
fprintf(listing, "%d) goto L%d \n", linesum++, tem3);
fprintf(listing, "%d) label L%d \n", linesum++, tem2);
default:
break;
}
}
static void genExp(TreeNode * tree,int sym1,int sym2) {
TreeNode * p1, *p2;
p1 = tree->child[0];
p2 = tree->child[1];
int tem1;
switch (tree->attr.op) {
case AND:
tem1 = label++;
genExp(p1, tem1, 0);
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
fprintf(listing, "%d) label L%d \n", linesum++, tem1);
genExp(p2, sym1, 0);
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
break;
case OR:
genExp(p1, sym1, 0);
genExp(p2, sym1, 0);
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
break;
case LT:
if (p1->kind.exp == OpK)genExp(p1, 0, 0);
if (p2->kind.exp == OpK)genExp(p2, 0, 0);
switch (p1->kind.exp) {
case OpK:
fprintf(listing, "%d) if %s<", linesum++, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) if %d<", linesum++, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) if %s<", linesum++,p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
case ConstK:
fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break;
case IdK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
default:
break;
}
if (sym2 != 0) {
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
}
break;
case RT:
if (p1->kind.exp == OpK)genExp(p1, 0, 0);
if (p2->kind.exp == OpK)genExp(p2, 0, 0);
switch (p1->kind.exp) {
case OpK:
fprintf(listing, "%d) if %s>", linesum++, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) if %d>", linesum++, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) if %s>", linesum++, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
case ConstK:
fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break;
case IdK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
default:
break;
}
if (sym2 != 0) {
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
}
break;
case EQ:
if (p1->kind.exp == OpK)genExp(p1, 0, 0);
if (p2->kind.exp == OpK)genExp(p2, 0, 0);
switch (p1->kind.exp) {
case OpK:
fprintf(listing, "%d) if %s=", linesum++, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) if %d=", linesum++, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) if %s=", linesum++, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
case ConstK:
fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break;
case IdK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
default:
break;
}
if (sym2 != 0) {
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
}
break;
case LTEQ:
if (p1->kind.exp == OpK)genExp(p1, 0, 0);
if (p2->kind.exp == OpK)genExp(p2, 0, 0);
switch (p1->kind.exp) {
case OpK:
fprintf(listing, "%d) if %s<=", linesum++, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) if %d<=", linesum++, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) if %s<=", linesum++, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
case ConstK:
fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break;
case IdK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
default:
break;
}
if (sym2 != 0) {
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
}
break;
case RTEQ:
if(p1->kind.exp== OpK)genExp(p1, 0, 0);
if (p2->kind.exp == OpK)genExp(p2, 0, 0);
switch (p1->kind.exp) {
case OpK:
fprintf(listing, "%d) if %s>=", linesum++, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) if %d>=", linesum++, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) if %s>=", linesum++, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
case ConstK:
fprintf(listing, "%d goto L%d \n", p2->attr.val, sym1); break;
case IdK:
fprintf(listing, "%s goto L%d \n", p2->attr.name, sym1); break;
default:
break;
}
if (sym2 != 0) {
fprintf(listing, "%d) goto L%d \n", linesum++, sym2);
}
break;
case MINUS:
tree->attr.name = (char*)malloc(5);
tree->attr.name[0] = 't';
char str[3];
sprintf(str, "%d", number++);
if (number >= 10) {
tree->attr.name[1] = str[0];
tree->attr.name[2] = str[1];
tree->attr.name[3] = '\0';
}
else {
tree->attr.name[1] = str[0];
tree->attr.name[2] = '\0';
}
switch (p1->kind.exp) {
case OpK:
genExp(p1, 0, 0);
fprintf(listing, "%d) %s:=%s-", linesum++, tree->attr.name, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) %s:=%d-", linesum++, tree->attr.name, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) %s:=%s-", linesum++, tree->attr.name, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
genExp(p2, 0, 0);
fprintf(listing, "%s \n", p2->attr.name); break;
case ConstK:
fprintf(listing, "%d \n", p2->attr.val); break;
case IdK:
fprintf(listing, "%s \n", p2->attr.name); break;
default:
break;
}
break;
case PLUS:
tree->attr.name = (char*)malloc(5);
tree->attr.name[0] = 't';
sprintf(str, "%d", number++);
if (number >= 10) {
tree->attr.name[1] = str[0];
tree->attr.name[2] = str[1];
tree->attr.name[3] = '\0';
}
else {
tree->attr.name[1] = str[0];
tree->attr.name[2] = '\0';
}
switch (p1->kind.exp) {
case OpK:
genExp(p1, 0, 0);
fprintf(listing, "%d) %s:=%s+", linesum++, tree->attr.name, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) %s:=%d+", linesum++, tree->attr.name, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) %s:=%s+", linesum++, tree->attr.name, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
genExp(p2, 0, 0);
fprintf(listing, "%s \n", p2->attr.name); break;
case ConstK:
fprintf(listing, "%d \n", p2->attr.val); break;
case IdK:
fprintf(listing, "%s \n", p2->attr.name); break;
default:
break;
}
break;
case TIMES:
tree->attr.name = (char*)malloc(5);
tree->attr.name[0] = 't';
sprintf(str, "%d", number++);
if (number > 10) {
tree->attr.name[1] = str[0];
tree->attr.name[2] = str[1];
tree->attr.name[3] = '\0';
}
else {
tree->attr.name[1] = str[0];
tree->attr.name[2] = '\0';
}
switch (p1->kind.exp) {
case OpK:
genExp(p1, 0, 0);
fprintf(listing, "%d) %s:=%s*", linesum++, tree->attr.name, p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) %s:=%d*", linesum++, tree->attr.name, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) %s:=%s*", linesum++, tree->attr.name, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
genExp(p2, 0, 0);
fprintf(listing, "%s \n", p2->attr.name); break;
case ConstK:
fprintf(listing, "%d \n", p2->attr.val); break;
case IdK:
fprintf(listing, "%s \n", p2->attr.name); break;
default:
break;
}
break;
case OVER:
tree->attr.name = (char*)malloc(5);
tree->attr.name[0] = 't';
sprintf(str, "%d", number++);
if (number >= 10) {
tree->attr.name[1] = str[0];
tree->attr.name[2] = str[1];
tree->attr.name[3] = '\0';
}
else {
tree->attr.name[1] = str[0];
tree->attr.name[2] = '\0';
}
switch (p1->kind.exp) {
case OpK:
genExp(p1, 0, 0);
fprintf(listing, "%d) %s:=%s/", linesum++, tree->attr.name,p1->attr.name); break;
case ConstK:
fprintf(listing, "%d) %s:=%d/", linesum++, tree->attr.name, p1->attr.val); break;
case IdK:
fprintf(listing, "%d) %s:=%s/", linesum++, tree->attr.name, p1->attr.name); break;
default:
break;
}
switch (p2->kind.exp) {
case OpK:
genExp(p2, 0, 0);
fprintf(listing, "%s \n", p2->attr.name); break;
case ConstK:
fprintf(listing, "%d \n", p2->attr.val); break;
case IdK:
fprintf(listing, "%s \n", p2->attr.name); break;
default:
break;
}
break;
}
}
static void cGen(TreeNode * tree)
{
if (tree != NULL)
{
switch (tree->nodekind) {
case StmtK:
genStmt(tree);
break;
case ExpK:
genExp(tree,0,0);
break;
default:
break;
}
cGen(tree->sibling);
}
}
生成器入口函数
void codeGen(TreeNode * syntaxTree)
{
cGen(syntaxTree);
}
方便调试输出的工具类
新建Stmt和Exp节点函数
TreeNode * newStmtNode(StmtKind kind){
TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));
int i;
if (t == NULL)
fprintf(listing, "Out of memory error at line %d\n", lineno);
else {
for (i = 0; i<MAXCHILDREN; i++) t->child[i] = NULL;
t->sibling = NULL;
t->nodekind = StmtK;
t->kind.stmt = kind;
t->lineno = lineno;
}
return t;
}
TreeNode * newExpNode(ExpKind kind){
TreeNode * t = (TreeNode *)malloc(sizeof(TreeNode));
int i;
if (t == NULL)
fprintf(listing, "Out of memory error at line %d\n", lineno);
else {
for (i = 0; i<MAXCHILDREN; i++) t->child[i] = NULL;
t->sibling = NULL;
t->nodekind = ExpK;
t->kind.exp = kind;
t->lineno = lineno;
t->type = Void;
}
return t;
}
输出空格和字符串复制输出函数
char * copyString(char * s){
int n;
char * t;
if (s == NULL) return NULL;
n = strlen(s) + 1;
t = (char*)malloc(n);
if (t == NULL)
fprintf(listing, "Out of memory error at line %d\n", lineno);
else strcpy(t, s);
return t;
}
static void printSpaces(void){
int i;
for (i = 0; i<indentno; i++)
fprintf(listing, " ");
}
输出语法树函数
void printTree(TreeNode * tree){
int i;
INDENT;
while (tree != NULL) {
printSpaces();
if (tree->nodekind == StmtK)
{
switch (tree->kind.stmt) {
case IfK:
fprintf(listing, "If\n");
break;
case RepeatK:
fprintf(listing, "Repeat\n");
break;
case AssignK:
fprintf(listing, "Assign to: %s\n", tree->attr.name);
break;
case ReadK:
fprintf(listing, "Read: %s\n", tree->attr.name);
break;
case WriteK:
fprintf(listing, "Write\n");
break;
case WhileK:
fprintf(listing, "While\n");
break;
default:
fprintf(listing, "Unknown ExpNode kind\n");
break;
}
}
else if (tree->nodekind == ExpK)
{
switch (tree->kind.exp) {
case OpK:
fprintf(listing, "Op: ");
printToken(tree->attr.op, "\0");
break;
case ConstK:
fprintf(listing, "Const: %d\n", tree->attr.val);
break;
case IdK:
fprintf(listing, "Id: %s\n", tree->attr.name);
break;
default:
fprintf(listing, "Unknown ExpNode kind\n");
break;
}
}
else fprintf(listing, "Unknown node kind\n");
for (i = 0; i<MAXCHILDREN; i++)
printTree(tree->child[i]);
tree = tree->sibling;
}
UNINDENT;
}
测试主函数
using namespace std;
#include"SCAN.h"
#include"PARSE.h"
#include"UTIL.h"
#include"CGEN.h"
#include"FILEHANDLE.h"
#include <iostream>
FILE *source;
FILE *listing;
int main() {
char sourceName[120];
cin >> sourceName;
char listingName[120];
cin >> listingName;
source = fopen(sourceName,"r");
listing = fopen(listingName,"w");
codeGen(parse()); //进行中间代码生成
//printTree(parse());//输出语法树
//while (getToken() != ENDFILE);//进行词法分析
system("pause");
}