构造一个从中缀表达式到后缀形式的表达式翻译器,初步了解递归下降语法分析原理及语法制导翻译的过程。考虑简单的报错,如非法变量名、非法常量、非法字符、缺少操作数、括号不匹配等。
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include<string>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
int LookAhead;
#define TKN_NUM 500
#define TKN_ID 600
int tokenval = 0; char lexeme[1024];
void term();
void expr();
void reste();
void restt();
void factor();
int GetToken();
int l=0;
void Match(int t);
int GetToken()
{
int t, i;
while (1) {
t=-1;
t = getchar();
if (t == ' ' || t == '\t')
;
// else if (t == '\n') //因为在该程序中,回车符作为表达式的结束,所以不能把回车符当成空白符
// exit(1) ; //lineno++;
else if (isdigit(t)) {
tokenval = 0;
do {
tokenval = tokenval * 10 + t -'0';
t = getchar();
} while (isdigit(t));
if(isalpha(t) ) {
printf("\n非法常/变量名\n");
exit(1);
}
ungetc(t, stdin);
return TKN_NUM;
}
else if( isalpha(t) ) {
i=0;
do {
lexeme[i++]=t; t = getchar();
}while( isalpha(t) || isdigit(t) );
lexeme[i]='\0'; ungetc(t, stdin);
return TKN_ID;
}
else {
if(t==')')
{
if(l==0)
{
printf("\n括号不匹配");
exit(0);
}
else {
l--;
tokenval = 0;
return t;
}
}
if(t=='+'|t=='-'|t=='*'|t=='/'||t=='\n'||t==-1||t=='(')
{tokenval = 0;
return t;//例如t=’+’,则把’+’的ASCII作为’+’的TokenName。
}
else{
printf("\n非法字符\n");
exit(1);
}
}
}
}
void Match(int t)
{
if( LookAhead==t )
{
if(t=='(') l++;
LookAhead = GetToken(); //继续往前看后一个字符
}
else {
if(t==')' ) printf("\n括号不匹配\n");
else printf("\n表达式错误:Match函数中需要输入的字符为%c,但是实际输入的是%c\n", t, LookAhead );
exit(1); //结束程序
}
}
void term()
{
factor();
restt();
}
void expr()
{
term();reste();
}
void reste()
{
switch (LookAhead)
{
case '+':
Match('+');term();printf(" +");reste();
break;
case '-':
Match('-');term();printf(" -");reste();
default:
//if(LookAhead==')' ) {printf("\n括号不匹配\n");exit(1);}
break;
}
}
void restt()
{
switch (LookAhead)
{
case '*':
Match('*');factor();printf(" * ");restt();
break;
case '/':
Match('/');factor();printf(" / ");restt();
default:
break;
}
}
void factor()
{
switch (LookAhead)
{
case '('/* constant-expression */:
/* code */
Match('('); expr();Match(')');
break;
default:
if(LookAhead==500) printf(" %d",tokenval);
else if(LookAhead==600) printf(" %s",lexeme);
else{printf("\n缺少操作数\n");exit(1);}
//else if(LookAhead==')') {printf("\n括号不匹配\n");exit(1);}
Match(LookAhead);
}
}
int main()
{
freopen("expression.txt","r",stdin);
printf("请输入要转换的中缀表达式:\n");
LookAhead=GetToken();
expr();
return 0;
}
文法: