编写识别由下列文法G[E]所定义的表达式的递归下降语法分析器。
E
→
E
+
T
∣
E
−
T
∣
T
E \rightarrow E+T | E-T | T
E→E+T∣E−T∣T
T
→
T
∗
F
∣
T
/
F
∣
F
T \rightarrow T*F | T/F |F
T→T∗F∣T/F∣F
F
→
(
E
)
∣
i
F \rightarrow (E) | i
F→(E)∣i
输入:含有十进制数或十六进制数的表达式,如:75+(1ah-3*2)+68/2#。
输出:语法正确或语法错误信息。
这次实验的重点在于理解递归下降语法分析的代码实现,意在将文法当中的每一种符号利用函数进行封装,然后在符合语法的条件下进行互相调用,完成递归下降语法分析。
难点在于需要对实验1的代码进行微调,达到将含有十进制数或十六进制数的表达式转换为对应的含i的表达式
C++程序流程图如下:
#include
#include
#include
#include
#include
#define digit 1 // 1数字
#define space 2 // 2空格
#define Hh 3 // 3Hh
#define AF 4 // 4A-F
#define letter 5 //5其它字母
#define op 6
using namespace std;
char sym; // 保存当前读入字符
string line; // 保存读入的一行表达式
int cur; // 表达式字符串中的当前下标
int error; // 错误标志。0:正确; -1:错误
char q; // 指向输入符号串中当前的字符
char word[20]; // 存储当前识别的单词
int state; // 表示所处的状态
int i; // 单词的下标
int E(), E1(), T(), T1(), F(); // 函数声明
char read(string line, int k);
string change_i(string words); // 将含有十进制或十六进制数的表达式转换为用i代替的表达式
int isDigitOrChar(char ch);
int main() {
ifstream fin("D:/Compile_exp/exp2-test.txt");
if (!fin.is_open()) {
cout << "open file error." << endl;
_getch();
return -1;
}
while (getline(fin, line)) {
puts("------------------------------------");
cur = 0;
error = 0;
string temp = line;
line = change_i(line);
if (line == "-1") {
cout << temp << " is not a valid express." << endl;
continue;
}
cout << "Output string is: " << line << endl;
sym = read(line, cur); // 读取第一个字符
E();
if (error == -1)
cout << temp << " is not valid." << endl;
else if (error == 0)
cout << temp << " is valid." << endl;
}
fin.close();
_getch();
return 0;
}
// 递归分析函数实现
int E() {
T();
E1();
return 0;
}
int E1() {
if (sym == '+' || sym == '-') {
cur++;
sym = read(line, cur);
T();
E1();
}
else if (sym == '#' || sym == ')')
return 0;
else
error = -1;
return 0;
}
int T() {
F();
T1();
return 0;
}
int T1() {
if (sym == '*' || sym == '/') {
cur++;
sym = read(line, cur);
F();
T1();
}
else {
if (sym == '#' || sym == ')' || sym == '+' || sym == '-')
return 0;
else
error = -1;
}
return 0;
}
int F() {
if (sym == 'i') {
cur++;
sym = read(line, cur);
}
else if (sym == '(') {
cur++;
sym = read(line, cur);
E();
if (sym == ')') {
cur++;
sym = read(line, cur);
}
else
error = -1;
}
else
error = -1;
return 0;
}
char read(string line, int k) {
return line[k];
}
int isDigitOrChar(char ch) {
if (ch >= 48 && ch <= 57) // 数字
return digit;
else if (ch == 32) // 空格
return space;
else if (ch == 72 || ch == 104) // H or h
return Hh;
else if ((ch >= 65 && ch <= 70) || (ch >= 97 && ch <= 102)) // 字母A,B,C,D,E,F
return AF;
else if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) // 除A~F外的其它字母
return letter;
else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '#')
return op;
}
// 将含有十进制或十六进制数的表达式转换为用i代替的表达式
string change_i(string words) {
memset(word, 0, sizeof word);
state = 0;
i = 0;
cout << "Input string is: " << words << endl;
string result = "";
int cnt = 0;
q = words[cnt++];
while (cnt <= words.size()) {
// 先判断状态,再判断字符
switch (state) {
case 0: // 0状态
//puts("状态0");
switch (isDigitOrChar(q)) {
case digit: // 数字
word[i++] = q;
state = 2; // 转移到2状态
break;
case Hh: // H or h
case AF: // 字母A,B,C,D,E,F or a,b,c,d,e,f
case letter: // 字母
word[i++] = q;
state = 1;
break;
case op: // 空格
result += q;
state = 0;
break;
default: // 其它(非法字符 )
word[i++] = q;
state = 5;
}
break;
case 1: // 1状态
switch (isDigitOrChar(q)) {
case Hh: // 当前状态遇到字母、数字往下读入
case AF:
case digit:
case letter:
word[i++] = q;
state = 1;
break;
case op: // 读入完毕,识别为标识符
word[i] = ';'printf
("%s is an identifier.\n",) word;//result += "i";
memset
(,word0 ,sizeof ) word;=
i 0 ;=
state 0 ;break
;default
:[
word++i]= ; q=
state 5 ;}
break
;case
2 :// 2状态 //puts("状态2");
//printf("%s\n", word);
switch
( isDigitOrChar()q)case {
: digit// 若为数字,不改变状态往下读入 [
word++i]= ; q=
state 2 ;break
;case
: Hh// 若为Hh,转移至状态3 [
word++i]= ; q=
state 3 ;break
;case
: AF// 若为AF,则有可能是16进制,转移至状态4 [
word++i]= ; q=
state 4 ;break
;case
: op// 成功识别为整数 [
word]i= ';' printf(
"%s is an Integer.\n",); word+="i"
result ; +=;
result //cout << result << endl; qmemset
(
,0word, sizeof) ; word=0
i ; =0
state ; break;
default:
[++
word]i=; //printf("%s\n", word); q=
5
state ; }break
;
case3
: // 3状态switch (
isDigitOrChar ())qcase: {
// 识别为16进制数 op[ ]
word=i';' printf ("%s is a Hex digit.\n"
,);+= word"i";
result += ;//cout << result << endl;
result memset q(
,
0,wordsizeof ); = word0;
i = 0;
state break ;default
:[
++]
word=i;= 5 q;
state } break;
case
4:
// 4状态 //puts("当前状态为4");switch (
isDigitOrChar
( ))caseq:// 若为数字或A~F,仍为状态4,往下读入 {
case digit: [
++ AF]
word=i;= 4 q;
state break ;case
:[
++ Hh]
word=i;= 3 q;
state break ;case
:// 如果16进制没有以h或H结尾,转移至错误状态
= op5 ;
state -- ;break
cnt;default
:[
++]
word=i;= 5 q;
state } break;
case
5:
// 出错状态 //puts("状态5");//printf("%s\n", word); if
(
isDigitOrChar
( )==)q// 若为空格,则识别为非标识符 [ op] { =
word';'iprintf ( "%s is not an identifier.\n",
);memset( word,0
,sizeofword) ;= 0 word;=
i 0 ;=
state "-1" ;return
result ; }else
// 出错序列还未读取完毕,往下读入 result[
++
] { =
word;i=[ ++ q]
q ; wordscontinuecnt;}break
;}
=
[++
]
q ; words// 指针下移(指向输入符号串中的下一个字符)cnt}return; }
result
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)