用SLR(1)分析法对简单赋值语句做语法分析
简单赋值语句的文法如下:
〈赋值语句〉∷= 〈标识符〉=〈表达式〉
〈表达式〉∷= 〈项〉|〈表达式〉〈加法运算符〉〈项〉
〈项〉∷= 〈因子〉|〈项〉〈乘法运算符〉〈因子〉
〈因子〉∷= 〈标志符〉|〈无符号整数〉|(〈表达式〉)
〈无符号整数〉∷= 〈数字〉|〈无符号整数〉〈数字〉
〈标志符〉∷= 〈字母〉|〈标志符〉〈字母〉|〈标志符〉〈数字〉
〈加法运算符〉∷= +|-
〈乘法运算符〉∷= *|/
进行简写并加入S’—>S进行拓广:
(0)产生式:S'——>S
(1)产生式:S——>x=A
(2)产生式:A——>B
(3)产生式:A——>ADB
(4)产生式:B——>H
(5)产生式:B——>BMH
(6)产生式:H——>x
(7)产生式:H——>n
(8)产生式:H——>(A)
(9)产生式:D——>+
(10)产生式:D——>-
(11)产生式:M——>*
(12)产生式:M——>/
对照表:
x <标识符>
n <无符号整数>
+ +
- -
* *
/ /
( (
) )
= =
; ;
S <赋值语句>
A <表达式>
B <项>
D <加法运算符>
M <乘法运算符>
H <因子>
SLR(1)分析表
SLR(1)分析法实现(C++描述)
//语法分析
stack<int> statusStack;//状态栈
stack<char> wordStack;//符号栈
//初始化
statusStack.push(0);
wordStack.push(';');
int i = 0;
while (1) {
//分析步骤:
char type = actionType(statusStack.top(), wordType[i][0]);
if (type == 'S') {
int ACTION = action(statusStack.top(), wordType[i][0]);
statusStack.push(ACTION);
wordStack.push(wordType[i][0]);
if (i < num - 1)i++;//防止错误串引起越界
}
else if (type == 'r') {
int index = action(statusStack.top(), wordType[i][0]);
int t = formulaRLength[index];
while (t-- > 0) {
statusStack.pop();
wordStack.pop();
}
int GOTO = goTo(statusStack.top(), formulaL[index][0]);
statusStack.push(GOTO);
wordStack.push(formulaL[index][0]);
}
else if (type == 'a') {
cout << "该字符串是文法的句子,接受" << endl;
break;
}
else {
cout << "该字符串不是文法的句子!!!" << endl;
break;
}
}
完整代码实现(C++)
使用文件d:/input.txt 输入,输出到文件 d:/output.txt中
示例:(一条简单的赋值语句,用分号结尾)
pgvddd=(m9F/3-dd)+(890+er)*67;
#include<iostream>
#include<stack>
#include<fstream>
#include<string.h>
using namespace std;
ofstream fout;
//读取单词
char word[500][20];
char wordType[500][2];// n,x,...
int num = 0;
//SLR(1)分析法
char sym[] = {
'x','n','+','-','*','/','(',')','=',';','S','A','B','D','M','H' };
int symI[255];
char formulaL[13][5] = {
"S\'","S", "A" , "A" , "B" , "B" , "H" ,"H" ,"H" , "D" ,"D" ,"M" ,"M" };
char formulaR[13][5] = {
"S", "x=A","B" , "ADB" ,"H" , "BMH" ,"x" ,"n" ,"(A)" ,"+" ,"-" ,"*" ,"/" };
int formulaRLength[13] = {
1, 3, 1, 3, 1, 3, 1, 1, 3, 1, 1, 1, 1 };
// 'x','n','+','-','*','/','(',')','=',';','S','A','B','D','M','H'
char typeTable[][16] = {
'S','e','e','e','e','e','e','e','e','e','S','e','e','e','e','e',//0
'e','e','e','e','e','e','e','e','e','a','e','e','e','e','e','e',//1
'e','e','e','e','e','e','e','e','S','e','e','e','e','e','e','e',//2
'S','S','e','e','e','e','S','e','e','e','e','S','S','e','e','S',//3
'e','e','S','S','e','e','e','e','e','r','e','e','e','S','e','e',//4
'e','e','r','r','S','S','e','r','e','r','e','e','e','e','S','e',//5
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//6
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//7
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//8
'S','S','e','e','e','e','S','e','e','e','e','S','S','e','e','S',//9
'S','S','e','e','e','e','S','e','e','e','e','e','S','e','e','S',//10
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//11
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//12
'S','S','e','e','e','e','S','e','e','e','e','e','e','e','e','S',//13
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//14
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//15
'e','e','S','S','e','e','e','S','e','e','e','e','e','S','e','e',//16
'e','e','r','r','S','S','e','r','e','r','e','e','e','e','S','e',//17
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e',//18
'r','r','r','r','r','r','r','r','r','r','e','e','e','e','e','e' //19
};
// 'x','n','+','-','*','/','(',')','=',';','S','A','B','D','M','H'
int numberTable[][16] = {
2 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 , 1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//0
-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//1
-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 , 3 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//2
8 , 7 ,-1 ,-1 ,-1 ,-1 , 9 ,-1 ,-1 ,-1 ,-1 , 4 , 5 ,-1 ,-1 , 6 ,//3
-1 ,-1 ,11 ,12 ,-1 ,-1 ,-1 ,-1 ,-1 , 1 ,-1 ,-1 ,-1 ,10 ,-1 ,-1 ,//4
-1 ,-1 , 2 , 2 ,14 ,15 ,-1 , 2 ,-1 , 2 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 ,//5
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//6
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//7
6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//8
8 , 7 ,-1 ,-1 ,-1 ,-1 , 9 ,-1 ,-1 ,-1 ,-1 ,16 , 5 ,-1 ,-1 , 6 ,//9
8 , 7 ,-1 ,-1 ,-1 ,-1 , 9 ,-1 ,-1 ,-1 ,-1 ,-1 ,17 ,-1 ,-1 , 6 ,//10
9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//11
10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,10 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//12
8 , 7 ,-1 ,-1 ,-1 ,-1 , 9 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,18 ,//13
11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,11 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//14
12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,12 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//15
-1 ,-1 ,11 ,12 ,-1 ,-1 ,-1 ,19 ,-1 ,-1 ,-1 ,-1 ,-1 ,10 ,-1 ,-1 ,//16
-1 ,-1 , 3 , 3 ,14 ,15 ,-1 , 3 ,-1 , 3 ,-1 ,-1 ,-1 ,-1 ,13 ,-1 ,//17
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,//18
8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 //19
};
void getWords(const char* filename) {
FILE* file;
fopen_s(&file, filename, "r");
int i = 0;//第i号单词
int j = 0;//单词的第j号字符
char c = fgetc(file);
while (c != EOF) {
//遇到空格,制表符,回车,换行自动跳过
if (c == 9 || c == 10 || c == 13 || c == 32) {
c = fgetc(file);
}
else {
//读取无符号整数
if (c >= '0' && c <= '9') {
j = 0;
do {
word[i][j++] = c;
c = fgetc(file);
} while (c >= '0' && c <= '9');
word[i][j] = '\0';//补上字符串结束符
wordType[i][0] = 'n';
wordType[i][1] = '\0';//补上字符串结束符
}//读取标识符(不考虑关键字问题)
else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
j = 0;
do {
word[i][j++] = c;
c = fgetc(file);
} while ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
word[i][j] = '\0';//补上字符串结束符
wordType[i][0] = 'x';
wordType[i][1] = '\0';//补上字符串结束符
}
else {
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '(' || c == ')' || c == ';') {
wordType[i][0] = word[i][0] = c;
wordType[i][1] = word[i][1] = '\0';
}
c = fgetc(file);
}
}
i++;
}
num = i;
cout << "单词" << "\t\t" << "文法符号" << endl;