概述
构造一个从中缀表达式到后缀形式的表达式翻译器,初步了解递归下降语法分析原理及语法制导翻译的过程。
要求
- 表达式文法及其翻译模式定义如下:
expr -> expr + term {
print(‘+’)}
| expr - term {
print(‘-’)}
| term
term -> term * factor {
print(‘*’)}
| term / factor {
print(‘/’)}
| factor
factor -> ( expr )
| id {
print(id.lexeme)}
| num {
print(num.value)}
- num为无符号整数。
- 在后缀形式输出时,为了能区分每个单词,单词之间用空格间隔,例如,
输入: a+18*b
输出: a 18 b * +
- 改写文法,消除该文法的左递归,然后使用语法制导翻译方案方法实现表达式的翻译。
- 考虑简单的报错。如非法变量名、非法常量、非法字符、缺少操作数、括号不匹配等。
消除左递归
改写文法如下:
expr -> term restterm
term -> factor restfactor
restterm -> + term {
print(‘+’)} restterm
| - term {
print(‘-’)} restterm
| ε
restfactor -> * factor {
print(‘*’)} restfactor
| / factor {
print(‘/’)} restfactor
| ε
factor -> ( expr )
| id {
print(id.lexeme)}
| num {
print(num.value)}
实现方法
1.词法分析
词法分析部分主要是区分数字常量和字符串变量,其中在此规定字符串变量由大小写字母和数字组成。为判断读取的字符是否是数字或字母,可以利用库中自带的函数isdigit和isalpha判断。
每次读取一个词法单元都是边读取边判断,直至判断到另一类词法单元,再将读取的最后一个字符放回缓冲区,最后返回其词法单元的对应类。同时,对于运算符,就将其单独作为一类词法单元,直接返回其ASCII码值。
2.语法分析
根据上面消除左递归的改编文法,可以构造以下子函数:
void Expr()
{
Term();
Restterm();
}
void Term()
{
Factor();
Restfactor();
}
void Restterm()
{
switch (LookAhead) {
case '+':
Match('+'); Term(); printf("+ "); Restterm(); // rest --> + term {print('+')} rest
break;
case '-':
Match('-'); Term(); printf("- "); Restterm();
break;
default: // rest --> 空
break;
}
}
void Restfactor()
{
// 与restterm类似,此处省略
}
void Factor()
{
if (LookAhead == '(')
{
Match('(');
Expr();
Match(')');
}
else if (LookAhead == TKN_NUM) {
printf("%d ", tokenval