目的和内容
1、 实验目的:通过完成语法分析程序,了解语法分析的过程和作用
2、 实验内容:用递归子程序法实现对pascal的子集程序设计语言的分析程序
3、 实验要求:对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用
文法的改变
为适合递归子程序法,对实验一中的文法改写成无左递归和无左共因子的BNF如下:
<程序>→<程序首部><分程序>.
<程序首部>→PROGRAM标识符;
<分程序>→<常量说明部分><变量说明部分><过程说明部分> <复合语句>
<常量说明部>→CONST<常量定义><常量定义后缀> |ε
<常量定义>→标识符=无符号整数
<常量定义后缀>→,<常量定义><常量定义后缀> |ε
<变量说明部分>→VAR<变量定义><变量定义后缀> |ε
<变量定义>→标识符<标识符后缀>:<类型>;
<标识符后缀>→,标识符<标识符后缀> |ε
<变量定义后缀>→<变量定义><变量定义后缀> |ε
<类型>→INTEGER | LONG
<过程说明部分>→<过程首部><分程序>;<过程说明部分后缀>|ε
<过程首部>→PROCEDURE标识符<参数部分>;
<参数部分>→(标识符: <类型>)|ε
<过程说明部分后缀>→<过程首部><分程序>;<过程说明部分后缀>|ε
<语句>→<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句>
|<写语句>|<复合语句>|ε
<赋值或调用语句>→标识符<后缀>
<后缀>→:=<表达式>|(<表达式>)|ε
<条件语句>→IF<条件>THEN<语句>
<当型循环语句>→WHILE<条件>DO <语句>
<读语句>→READ(标识符<标识符后缀>)
<写语句>→WRITE(<表达式><表达式后缀>)
<表达式后缀>→,<表过式><表达式后缀>|ε
<复合语句>→BEGIN<语句><语句后缀>END
<语句后缀>→;<语句><语句后缀>|ε
<条件>→<表达式><关系运算符><表达式>|ODD<表达式>
<表达式>→+<项><项后缀>|-<项><项后缀>|<项><项后缀>
<项后缀>→<加型运算符><项><项后缀>|ε
<项>→<因子><因子后缀>
<因子后缀>→<乘型运算符><因子><因子后缀>|e
<因子>→标识符|无符号整数|(<表达式>)
<加型运算符>→+|-
<乘型运算型>→*|/
<关系运算符>→ =|<>|<|<=|>|>=
非终结符和函数名对照表
为适用递归子程序,下表为非终结符和函数名对照表
非终结符 | 函数名 | 非终结符 | 函数名 |
<程序> | program | <程序首部> | proghead |
<分程序> | block | <常量说明部分> | consexpl |
<常量定义> | consdefi | <变量说明部分> | varexl |
<常量定义后缀> | conssuff | <变量定义> | vardefi |
<变量定义后缀> | varsuff | <>过程说明部分> | procdefi |
<类型> | typeil | <过程首部> | procedh |
<过程说明部分后缀> | procsuff | <赋值或调用语句> | assipro |
<语句> | sentence | <后缀> | suffix |
<条件语句> | ifsent | <读语句> | read |
<当型循环语句> | whilsent | <标识符后缀> | idsuff |
<写语句> | Write | <复合语句> | compsent |
<表达式后缀> | Exprsuff | <语句后缀> | sentsuff |
<条件> | Conditio | <项后缀> | termsuff |
<表达式> | Express | <项> | term |
<因子后缀> | Factsuff | <参数部分> | argument |
<因子> | Factor | <加型运算符> | addoper |
<乘型运算符> | Muloper | <关系运算符> | respoper |
递归子程序的设计思想
为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。出错时,可以根据读字符的位置判断出错的位置。
实验流程
下面是部分子程序的流程图
实验代码
#include<bits/stdc++.h>
using namespace std;
#define PROGRAM 1
#define CONST 2
#define VAR 3
#define INTEGER 4
#define LONG 5
#define PROCEDURE 6
#define IF 7
#define THEN 8
#define WHILE 9
#define DO 10
#define READ 11
#define WRITE 12
#define BEGIN 13
#define END 14
#define ODD 15
#define ADD 16
#define SUB 17
#define MUL 18
#define DIV 19
#define EQU 20
#define NEQ 21
#define LES 22
#define LEQ 23
#define LAG 24
#define GEQ 25
#define DOT 26
#define COM 27
#define SEM 28
#define COL 29
#define ASS 30
#define LBR 31
#define RBR 32
#define INT 33
#define ID 34
#define EIN 35
#define lenth1 15
#define lenth2 17
struct Ident
{
char name[21];
int type;
int addr;
};
Ident indent[1000]; // 定义标识符表
struct St
{
char name[21];
int code;
};
St sym;
int lenth = 0; // 表示标识符表长度
FILE* f1, * f2; //f1、f2分别指向输入输出文件
int line = 0, row = 0, val;
void getsym();char getchr();void error(int);
void program(); void proghead();
void block(); void consexpl();
void consdefi(); void varexpl();
void conssuff(); void vardefi();
void varsuff(); void procdefi();
void typeil(); void procedh();
void procsuff(); void assipro();
void sentence(); void suffix();
void ifsent(); void read();
void whilsent(); void idsuff();
void write(); void compsent();
void exprsuff(); void sentsuff();
void conditio(); void termsuff();
void express(); void term();
void factsuff(); void argument();
void factor(); void addoper();
void muloper(); void respoper();
int main(int argc, char* argv[]) {
if ((f1 = fopen(argv[1], "r")) == NULL) { // 打开输入文件流
cout << "can not open the input file!" << endl;
exit(0);
}
getsym();
program();
cout << "该程序通过语法分析!" << endl;
fclose(f1);
return 0;
}
void getsym() {
static char a[lenth1][10] = {
"program","const","var","integer","long","procedure","if",
"then","while","do","read","write","begin","end","odd"
},
d[lenth2][3] = { "+","-","*","/","=","<>","<","<=",">",">=",
".",",",";",":",":=","(",")" },
str[21], ch = ' ';
int i, n; // n判断单词长度,i判断是哪个关键字
while (isspace(ch))
{
ch = getchr();
}
if (isalpha(ch)) { //判断字母开头的字符
n = 0;
while (isalpha(ch) || isdigit(ch)) {
if (isalpha(ch))
ch = tolower(ch);
str[n++] = ch;
ch = getchr();
}
str[n] = '\0';
for (i = 0;i < lenth1;i++) {
if (!strcmp(str, a[i]))
break;
}
if (i < lenth1) { //找到匹配关键字
strcpy(sym.name, a[i]);
sym.code = i + 1;
}
else {
for (i = 0;i < lenth;i++) { //遍历已记录的标识符记录表
if (!strcmp(str, indent[i].name))
break;
}
if (i == lenth) {
strcpy(indent[i].name, str);
}
strcpy(sym.name, indent[i].name);
sym.code = 34;
}
}
else if (isdigit(ch)) { // 判断数字开头的字符
val = 0;n = 0;
while (isdigit(ch)) {
val = val * 10 + ch - '0';
sym.name[n++] = ch;
ch = getchr();
}
sym.name[n] = '\0';
sym.code = 33;
}
else { // 判断特殊字符
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' ||
ch == '.' || ch == ',' || ch == ';' || ch == '(' || ch == ')') {
str[0] = ch; str[1] = '\0';
ch = getchr();
for (i = 0;i < lenth2;i++) {
if (!strcmp(str, d[i])) {
strcpy(sym.name, str);
sym.code = i + 16;
break;
}
}
}
else if (ch == '#') {
str[0] = ch; str[1] = '\0';
ch = getchr();
strcpy(sym.name, str);
sym.code = 35;
}
else if (ch == '<') {
char b = getchr();
if (b == '>') {
str[0] = '<';str[1] = '>';str[2] = '\0';
strcpy(sym.name, str);
sym.code = 21;
ch = getchr();
}
else if (b == '=') {
str[0] = '<';str[1] = '=';str[2] = '\0';
strcpy(sym.name, str);
sym.code = 23;
ch = getchr();
}
else {
str[0] = '<';str[1] = '\0';
strcpy(sym.name, str);
sym.code = 22;
ch = b;
}
}
else if (ch == '>') {
char b = getchr();
if (b == '=') {
str[0] = '>';str[1] = '=';str[2] = '\0';
strcpy(sym.name, str);
sym.code = 25;
ch = getchr();
}
else {
str[0] = '>';str[1] = '\0';
strcpy(sym.name, str);
sym.code = 24;
ch = b;
}
}
else if (ch == ':') {
char b = getchr();
if (b == '=') {
str[0] = ch;str[1] = b;str[2] = '\0';
strcpy(sym.name, str);
sym.code = 30;
ch = getchr();
}
else {
str[0] = ch;str[1] = '\0';
strcpy(sym.name, str);
sym.code = 29;
ch = b;
}
}
}
}
char getchr() { // 从文件中获取下一个非空字符
char ch = fgetc(f1);
if (ch == '\n') {
row = 1;
line++;
}
else {
if (ch != ' ' && ch != '\t') {
row++;
}
}
return ch;
}
void error(int n) {
printf("There are %d-error\n", n);
exit(0);
}
void program() { // 程序
proghead();block();
cout<<sym.code<<" "<<sym.name<<endl;
cout<<!feof(f1)<<endl;
if (sym.code == DOT && feof(f1)) {
return ;
}
else {
error(2);
}
}
void proghead() { // 程序首部
if (sym.code == PROGRAM) {
getsym(); // 获取next token
if (sym.code == ID) {
getsym();
if (sym.code == SEM)
getsym();
else
error(5);
}
else
error(4);
}
else
error(3);
}
void block() { // 分程序
consexpl();
varexpl();
procdefi();
compsent();
}
void consexpl() { // 常量说明部分
if (sym.code == CONST) {
getsym();
consdefi();
conssuff();
if (sym.code == SEM)
getsym();
else
error(6);
} // 无else表示可以为空
}
void consdefi() { // 常量定义
if (sym.code == ID) {
getsym();
if (sym.code == EQU) {
getsym();
if (sym.code == INT)
getsym();
else
error(9);
}
else
error(8);
}
else
error(7);
}
void conssuff() { // 常量定义后缀
if (sym.code == COM) {
getsym();
consdefi();
conssuff();
// if (sym.code == SEM)
// getsym();
//else
//error(10);
}// 无else表示可以为空
}
void varexpl() { // 变量说明部分
if (sym.code == VAR) {
getsym();
vardefi();
varsuff();
}// 无else表示可以为空
}
void vardefi() { // 变量定义
if (sym.code == ID) {
getsym();
idsuff();
if (sym.code == COL) {
getsym();
typeil();
if (sym.code == SEM)
getsym();
else
error(12);
}
else
error(11);
}
// else
// error(10);
}
void varsuff() {
if (sym.code == ID) {
vardefi();
varsuff();
}// 无else表示可以为空
}
void typeil() {
if (sym.code == INTEGER || sym.code == LONG)
getsym();
else
error(13);
}
void procdefi() {
if (sym.code == PROCEDURE)
{
procedh();
block();
if (sym.code == SEM) {
procsuff();
}
else
error(14);
}// 无else表示可以为空
}
void procedh() {
if (sym.code == PROCEDURE) {
getsym();
if (sym.code == ID) {
getsym();
argument();
if (sym.code == SEM)
getsym();
else
error(16);
}
else
error(15);
}
}
void argument() {
if (sym.code == LBR) {
getsym();
if (sym.code == ID) {
getsym();
if (sym.code == COL) {
getsym();
if (sym.code == RBR)
getsym();
else
error(19);
}
else
error(18);
}
error(17);
}
}
void procsuff() {
if (sym.code == PROCEDURE) {
procedh();
block();
if (sym.code == SEM) {
getsym();
procsuff();
}
else
error(20);
}
}
void assipro() {
if (sym.code == ID) {
getsym();
suffix();
}
else
error(21);
}
void sentence() {
if (sym.code == ID) {
assipro();
}
else if (sym.code == IF) {
ifsent();
}
else if (sym.code == WHILE)
whilsent();
else if (sym.code == READ)
read();
else if (sym.code == WRITE)
write();
else if (sym.code == BEGIN)
compsent();
}
void suffix() {
if (sym.code == ASS) {
getsym();
express();
}
else if (sym.code == LBR) {
getsym();
express();
if (sym.code == RBR)
getsym();
else error(22);
}
}
void ifsent() {
if (sym.code == IF) {
getsym();
conditio();
if (sym.code == THEN) {
getsym();
sentence();
}
else
error(24);
}
else
error(23);
}
void whilsent() {
if (sym.code == WHILE) {
getsym();
conditio();
if (sym.code == DO) {
getsym();
sentence();
}
else
error(26);
}
else
error(25);
}
void read() {
if (sym.code == READ) {
getsym();
if (sym.code == LBR) {
getsym();
if (sym.code == ID) {
getsym();
idsuff();
if (sym.code == RBR)
getsym();
else error(27);
}
else
error(30);
}
else error(29);
}
else error(28);
}
void idsuff() {
if (sym.code == COM) {
getsym();
if (sym.code == ID) {
getsym();
idsuff();
}
else
error(30);
} // 无else表示可以为空
}
void write() {
if (sym.code == WRITE) {
getsym();
if (sym.code == LBR) {
getsym();
express();
exprsuff();
if (sym.code == RBR)
getsym();
else error(34);
}
else error(33);
}
else error(32);
}
void compsent() {
if (sym.code == BEGIN) {
getsym();
sentence();
sentsuff();
if (sym.code == END)
getsym();
else error(36);
}
else error(35);
}
void exprsuff() {
if (sym.code == COM) {
getsym();
express();
exprsuff();
}
}
void sentsuff() {
if (sym.code == SEM) {
getsym();
sentence();
sentsuff();
}
}
void conditio() {
if (sym.code == ODD) {
getsym();
express();
}
else {
express();
respoper();
express();
}
}
void express() {
if (sym.code == ADD || sym.code == SUB)
getsym();
term();
termsuff();
}
void term() {
factor();
factsuff();
}
void termsuff() {
if (sym.code == ADD || sym.code == SUB) {
getsym();
factor();
factsuff();
}
}
void factsuff() {
if (sym.code == MUL || sym.code == DIV) {
getsym();
factor();
factsuff();
}
}
void factor() {
if (sym.code == ID) {
getsym();
// factsuff();
}
else if (sym.code == INT) {
getsym();
}
else if (sym.code == LBR) {
getsym();
express();
if (sym.code == RBR)
getsym();
else error(38);
}
else error(37);
}
void addoper() {
if (sym.code == ADD || sym.code == SUB)
getsym();
else
error(39);
}
void muloper() {
if (sym.code == MUL || sym.code == DIV)
getsym();
else
error(40);
}
void respoper() {
if (sym.code >= EQU && sym.code <= GEQ)
getsym();
else
error(41);
}
实验结果
待分析代码
program main;
const x = 1, y=2,z=444;
var z,x:long;xx:long;
a:long;
begin
z := z*3/2;
read(xx,dsaf);
write(dsaf,xx);
if x > y
then
x := x+1;
begin
x := x+1;
y:= xx -12;
x := +123;
x := (1+2);
x:= 213 * 3 + 21/x;
y := y/2 +2;
begin
while x<=10
do
y:=y+1;
end
end
end.
以上代码只是单纯为了检测是否能够通过语法分析,并没有什么实际含义(o゜▽゜)o
语法分析检测通过!