编制一个能够进行语法分析并生成三地址代码的微型编译程序。1、考虑给定的文法,消除左递归,提取左因子; 2、编制并化简语法图;3、编制各个递归子程序的算法; 4、编制各个递归子程序的函数; 5、连接实验一的词法分析函数scan( ),进行测试6、设计三地址代码生成的数据结构和算法.输入示例:while (a3+15)>0xa do if x2 = 07 then while y<z do y =x * y / z;7、将各个递归子程序函数改写为代码生成函数 8、编制测试程序(main函数)
时间: 2024-03-21 15:38:36 浏览: 110
这是一个比较复杂的任务,需要多方面的知识和技能才能完成。以下是一个简单的实现思路和伪代码示例,供参考:
1. 消除左递归和提取左因子,得到消除左递归和提取左因子后的文法。
2. 根据消除左递归和提取左因子后的文法,绘制语法图,对其进行化简和优化。
3. 编制递归子程序的算法,将其转换为代码生成函数。
4. 编制各个代码生成函数,根据文法规则生成相应的三地址代码。
5. 连接实验一的词法分析函数scan(),对输入的代码进行词法分析和语法分析,生成相应的三地址代码。
6. 设计三地址代码的数据结构和算法,将生成的三地址代码存储在数据结构中。
7. 编制测试程序(main函数),调用词法分析函数、语法分析函数和三地址代码生成函数,输出生成的三地址代码。
以下是伪代码示例:
```
// 定义三地址码结构体
struct Code {
string operator; // 运算符
string arg1; // 第一个操作数
string arg2; // 第二个操作数
string result; // 结果
};
// 定义符号表结构体
struct SymbolTable {
string name; // 变量名
string type; // 变量类型
int addr; // 变量地址
};
// 定义语法分析器
class Parser {
public:
Parser(Lexer& lexer) : lexer(lexer) {}
void parse() {
program();
}
private:
Lexer& lexer;
Token current_token;
// 获取下一个token
void eat(string token_type) {
if (current_token.type == token_type) {
current_token = lexer.get_next_token();
} else {
error();
}
}
// 抛出异常
void error() {
throw runtime_error("Invalid syntax");
}
// 代码生成函数
Code gen(string op, string arg1, string arg2, string result) {
Code code = {op, arg1, arg2, result};
codes.push_back(code);
return code;
}
// 定义递归子程序
void program() {
while (current_token.type != EOF) {
statement();
eat(SEMI);
}
}
void statement() {
if (current_token.type == IF) {
if_statement();
} else if (current_token.type == WHILE) {
while_statement();
} else {
assignment_statement();
}
}
void if_statement() {
eat(IF);
eat(LPAREN);
string expr_result = expr();
eat(RPAREN);
int if_jump = gen("if_false", expr_result, "", "");
statement();
if (current_token.type == ELSE) {
int else_jump = gen("goto", "", "", "");
codes[if_jump].result = to_string(codes.size());
eat(ELSE);
statement();
codes[else_jump].result = to_string(codes.size());
} else {
codes[if_jump].result = to_string(codes.size());
}
}
void while_statement() {
eat(WHILE);
int start = codes.size();
eat(LPAREN);
string expr_result = expr();
eat(RPAREN);
int if_jump = gen("if_false", expr_result, "", "");
statement();
gen("goto", "", "", to_string(start));
codes[if_jump].result = to_string(codes.size());
}
void assignment_statement() {
string variable = current_token.value;
eat(ID);
eat(ASSIGN);
string expr_result = expr();
gen("=", expr_result, "", variable);
}
string expr() {
string term_result = term();
while (current_token.type == PLUS || current_token.type == MINUS) {
string op = current_token.value;
eat(current_token.type);
string term2_result = term();
term_result = gen(op, term_result, term2_result, "");
}
return term_result;
}
string term() {
string factor_result = factor();
while (current_token.type == MUL || current_token.type == DIV) {
string op = current_token.value;
eat(current_token.type);
string factor2_result = factor();
factor_result = gen(op, factor_result, factor2_result, "");
}
return factor_result;
}
string factor() {
if (current_token.type == LPAREN) {
eat(LPAREN);
string expr_result = expr();
eat(RPAREN);
return expr_result;
} else if (current_token.type == ID) {
string variable = current_token.value;
eat(ID);
return variable;
} else if (current_token.type == NUM) {
string num = current_token.value;
eat(NUM);
return num;
} else {
error();
}
}
// 输出生成的三地址代码
void output_code() {
for (Code code : codes) {
cout << code.result << " = " << code.arg1 << " " << code.operator << " " << code.arg2 << endl;
}
}
};
// 测试程序
int main() {
Lexer lexer("while (a3+15)>0xa do if x2 = 07 then while y<z do y =x * y / z;");
Parser parser(lexer);
try {
parser.parse();
parser.output_code();
} catch (const exception& e) {
cerr << e.what() << endl;
}
return 0;
}
```
以上代码仅供参考,实际实现中还需要考虑诸如符号表、数据类型、运算符优先级等因素的影响。
阅读全文