语法分析实验报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
while((syn==15)||(syn==16))//如果出现'*'和'/'
{
scaner();
factor(); //调用函数factor()
}
return;
}
void factor()//判断'*'和'/'是否出现'('
{
if((syn==10)||(syn==11))//'*'和'/'后面出现变量或数字
words[]用来存放读入的字符串,最大值为100
m用来指示token数组下标
*/
char words[100],token[8],ch;
char *retab[6]={"begin","if","then","while","do","end"};//关键字
int syn,p,m,n,sum;
int kk;//用来记录是否出错,0正确,1错误
p--;
syn=10;//种别码初始值设为10,标识为变量名
for(n=0;n<6;n++)//将识别出来的字符和已定义的标示符作比较,
{
if(strcmp(token,rwtab[n])==0)//若和关键字匹配则将种别码换成对应关键字的种别码
{
syn=n+1;
}
}
}
else if((ch>='0'&&ch<='9'))
break;
//case'\n':
//syn=-2;
//break;
default:
syn=-1;break;
}
}
int main()
{
printf("请输入一串字符串,以#结尾:\n");
p=0;//p置为0,往数组中读入的字符串
do//将字符串读入words数组中,直到出现#结束
{
scanf("%c",&ch);
words[p++] = ch;
}while(ch!='#');
p=0;//重新置为0,为下面扫描整个数组做准备
do
{
scanner();//调用scanner()方法扫描整个数组
switch(syn)
{
case 11:
printf("(%-10d%5d)\n",sum,syn);
break;
case -1:
m=0;token[m++]=ch;
ch=words[p++];
if(ch=='>')
{
syn=21;
token[m+1]=ch;
}
else if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case '>' :
m=0;token[m++]=ch;
//声明各个方法
void factor();
void expression();
void yucu();
void term();
void statement();
void lrparser();
void scaner();
int main()
{
p=0;//p置为0,往数组中读入的字符串
printf("请输入一段包含在'begin'和'end'之间字符串(以'#'结尾): \n");
2
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1
用扩充的BNF表示如下:
(1)<程序>::=begin <语句串> end
(2)<语句串>::=<语句>{:语句}
(3)<语句>::=<赋值语句>
(4)<赋值语句>::=ID := <表达式>
(5)<表达死>::=<项>{+<项>|-<项>}
case'=':
syn=25;token[0]=ch;
break;
case';':
syn=26;token[0]=ch;
break;
case'(':
syn=27;token[0]=ch;
break;
case')':
syn=28;token[0]=ch;
break;
case'#':
syn=0;token[0]=ch;
while(syn==26)//如果是';',判断下一个是否是'end'
{
scaner(); //读下一个单词符号
if(syn!=6)//不是'end'继续进行下一步
statement();//调用函数statement()
}
return;
}
void statement()
{
if(syn==10)//字符串的种别码为10时,表明为变量名
(6)<项>::=<因子>{*<因子>|/<因子>}
(7)<因子>::=ID | NUM | ( <表达式> )
3
算法的基本任务是从字符串中表示的源程序中识别出具有独立意义的单词符号,并通过其基本文法,正确规约到开始符号。
1)全局变量的设置
在此程序中,需要设置两个个全局变量:关键字表retab[6]、当前识别的种别号syn。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
*/
#include<stdio.h>
#include<string.h>
/*
*关键字作为特殊标识符处理,把它们预先安排在一个字符串数组中(称为rwtab),
*当扫描程序识别出标识符时,查rwtab。如能查到匹配的单词,则该单词为关键字,
⑴<程序>::=begin<语句串>end
⑵<语句串>::=<语句>{;<语句>}
⑶<语句>::=<赋值语句>
⑷<赋值语句>::=ID:=<表达式>
⑸<表达式>::=<项>{+<项> | -<项>}
⑹<项>::=<因子>{*<因子> | /<因子>
⑺<因子>::=ID | NUM |(<表达式>)
*/
{
syn=17;
p--;
}
break;
case'*':
syn=13;token[0]=ch;
break;
case'/':
syn=14;token[0]=ch;
break;
case '+':
syn=15;token[0]=ch;
break;
case'-':
syn=16;token[0]=ch;
break;
{
m=0;//token数组从下标0开始存入读入字符
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<'z')||(ch>='A'&&ch<='Z'))//将字母后是数字或字母的字符存入token数组中
{
token[m++]=ch;
ch=words[p++];
}
token[m++]='\0';//token数组末尾置为'\0'
printf("you input a wrong string !");
break;
default:
printf("(%-10s%5d)\n",token,syn);
}
} while (syn!=0);
printf("解析完成");
}
4
语法分析代码:
/*
待分析的简单语言的语法
用扩充的BNF表示如下:
ch=words[p++];
if(ch=='=')
{
syn=24;
token[m+1]=ch;
}
else
{
syn=20;
p--;
}
break;
case ':':
m=0;token[m++]=ch;
ch=words[p++];
if(ch=='=')
{
syn=18;
token[m+1]=ch;
}
else
scaner();
else if(syn==27)//判断'*'和'/'后面出现'('
{
scaner(); //进行'('里面表达式的判断
expression(); //调用函数expression()
if(syn==28)// '('后匹配到')'
scaner(); //继续读下一个单词符号
else{// '('后没有匹配到')'
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum = sum*10+ch-'0';//转换为数字输出
ch=words[p++];
}
p--;
syn=11;//全为数字则种别码为11
if(sum>32767)
syn=-1;
}
else switch(ch)//其余字符
{
case '<' :
printf("解析成功!\n");
}
else
{
if(kk!=1)
printf("字符串没有以'end'结尾!\n");
kk=1;
}
}
else
{ห้องสมุดไป่ตู้
printf("字符串没有以'begin'开头!\n");
kk=1;
}
return ;
}
void yucu()
{
statement(); //调用函数statement()
{
scaner();
if(syn==18)//变量名后面种别码为18时,表明为赋值符号
{
scaner();
expression(); //调用函数expression()函数
}
else
{
printf("句子的赋值符号':='不正确!\n");
kk=1;
}
}
else//句子不是以变量名开头,出错
{
printf("错误的句子!\n");
#include <stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
/*
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
p为记号,用来对应存放数组下标。出ch用来读入每次输入的字符
*否则为一般标识符。其描述如下:
*/
const char *rwtab[6]={"begin","if","then","while","do","end"};
/*
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
p为记号,用来对应存放数组下标。出ch用来读入每次输入的字符
课程实验报告
课程名称:编译原理(语法分析)
专业班级:软件工程(2)班
学号:20121344073
姓名:张伟
指导教师:顾彬
报告日期:2015.6.18
计算机科学与技术学院
1
1)设计并编制一个语法分析程序,加深对语法分析程序中递归下降分析方法的理解;
2)巩固对代码生成及报错处理等理论的认识;
3)培养对完整系统独立分析和设计的能力;
do//将字符串读入words数组中,直到出现#结束
{
scanf("%c",&ch);
words[p++] = ch;
}while(ch!='#');
p=0;//重新置为0,为下面扫描整个数组做准备
scaner();//调用scanner()方法扫描整个数组
lrparser();//调用lrparser()方法分析程序
{
for(n=0;n<8;n++) token[n] = NULL;//初始化token数组
ch=words[p++];//ch用来读入字符数组存储的字符
while(ch==' ')//字符为空时
{
ch=words[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//读入字符为字母,则可能是变量名或者标识符
kk=1;
}
return;
}
void expression()//判断表达式是否正确
{
term();
while((syn==13)||(syn==14))
{
scaner();
term(); //调用函数term()
}
return;
}
void term()//判断是否出现'*'和‘/’
{
factor();
printf("'('与后面表达式没有匹配成功\n");
kk=1;
}
}
else
{
printf("表达式出错!\n");//表达式出错
kk=1;
}
return;
}
void scaner()
{
sum=0;
for(m=0;m<8;m++)//初始化token数组
其中retab中元素为“begin”“if”“then”“while”“do”“end”,在程序会扫描出标识符时,首先查关键字表。如果能找到匹配的单词,则该单词为关键字,否则为一般标识符。
syn用于每一步扫描中scanner的返回值。在整个语法分析程序中均需要使用该全局变量。
词法分析代码:
/*输入:所给文法的源程序字符串。
words[]用来存放读入的字符串,最大值为100
m用来指示token数组下标
*/
int sum=0,syn,p,n,m=0;
char words[80],token[8];//char token[10],words[100];
char ch;
void scanner()//定义扫描方法,用于扫描整个字符串存放的数组words
getchar();
}
void lrparser()//分析程序
{
if(syn==1)//判断输入字符串是否以'begin'结尾
{
scaner(); //读下一个单词符号
yucu();//调用yucu()函数
if (syn==6)//判断输入字符串是否以'end'结尾
{
scaner();
if ((syn==0)&&(kk==0))
{
scaner();
factor(); //调用函数factor()
}
return;
}
void factor()//判断'*'和'/'是否出现'('
{
if((syn==10)||(syn==11))//'*'和'/'后面出现变量或数字
words[]用来存放读入的字符串,最大值为100
m用来指示token数组下标
*/
char words[100],token[8],ch;
char *retab[6]={"begin","if","then","while","do","end"};//关键字
int syn,p,m,n,sum;
int kk;//用来记录是否出错,0正确,1错误
p--;
syn=10;//种别码初始值设为10,标识为变量名
for(n=0;n<6;n++)//将识别出来的字符和已定义的标示符作比较,
{
if(strcmp(token,rwtab[n])==0)//若和关键字匹配则将种别码换成对应关键字的种别码
{
syn=n+1;
}
}
}
else if((ch>='0'&&ch<='9'))
break;
//case'\n':
//syn=-2;
//break;
default:
syn=-1;break;
}
}
int main()
{
printf("请输入一串字符串,以#结尾:\n");
p=0;//p置为0,往数组中读入的字符串
do//将字符串读入words数组中,直到出现#结束
{
scanf("%c",&ch);
words[p++] = ch;
}while(ch!='#');
p=0;//重新置为0,为下面扫描整个数组做准备
do
{
scanner();//调用scanner()方法扫描整个数组
switch(syn)
{
case 11:
printf("(%-10d%5d)\n",sum,syn);
break;
case -1:
m=0;token[m++]=ch;
ch=words[p++];
if(ch=='>')
{
syn=21;
token[m+1]=ch;
}
else if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case '>' :
m=0;token[m++]=ch;
//声明各个方法
void factor();
void expression();
void yucu();
void term();
void statement();
void lrparser();
void scaner();
int main()
{
p=0;//p置为0,往数组中读入的字符串
printf("请输入一段包含在'begin'和'end'之间字符串(以'#'结尾): \n");
2
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1
用扩充的BNF表示如下:
(1)<程序>::=begin <语句串> end
(2)<语句串>::=<语句>{:语句}
(3)<语句>::=<赋值语句>
(4)<赋值语句>::=ID := <表达式>
(5)<表达死>::=<项>{+<项>|-<项>}
case'=':
syn=25;token[0]=ch;
break;
case';':
syn=26;token[0]=ch;
break;
case'(':
syn=27;token[0]=ch;
break;
case')':
syn=28;token[0]=ch;
break;
case'#':
syn=0;token[0]=ch;
while(syn==26)//如果是';',判断下一个是否是'end'
{
scaner(); //读下一个单词符号
if(syn!=6)//不是'end'继续进行下一步
statement();//调用函数statement()
}
return;
}
void statement()
{
if(syn==10)//字符串的种别码为10时,表明为变量名
(6)<项>::=<因子>{*<因子>|/<因子>}
(7)<因子>::=ID | NUM | ( <表达式> )
3
算法的基本任务是从字符串中表示的源程序中识别出具有独立意义的单词符号,并通过其基本文法,正确规约到开始符号。
1)全局变量的设置
在此程序中,需要设置两个个全局变量:关键字表retab[6]、当前识别的种别号syn。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
*/
#include<stdio.h>
#include<string.h>
/*
*关键字作为特殊标识符处理,把它们预先安排在一个字符串数组中(称为rwtab),
*当扫描程序识别出标识符时,查rwtab。如能查到匹配的单词,则该单词为关键字,
⑴<程序>::=begin<语句串>end
⑵<语句串>::=<语句>{;<语句>}
⑶<语句>::=<赋值语句>
⑷<赋值语句>::=ID:=<表达式>
⑸<表达式>::=<项>{+<项> | -<项>}
⑹<项>::=<因子>{*<因子> | /<因子>
⑺<因子>::=ID | NUM |(<表达式>)
*/
{
syn=17;
p--;
}
break;
case'*':
syn=13;token[0]=ch;
break;
case'/':
syn=14;token[0]=ch;
break;
case '+':
syn=15;token[0]=ch;
break;
case'-':
syn=16;token[0]=ch;
break;
{
m=0;//token数组从下标0开始存入读入字符
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<'z')||(ch>='A'&&ch<='Z'))//将字母后是数字或字母的字符存入token数组中
{
token[m++]=ch;
ch=words[p++];
}
token[m++]='\0';//token数组末尾置为'\0'
printf("you input a wrong string !");
break;
default:
printf("(%-10s%5d)\n",token,syn);
}
} while (syn!=0);
printf("解析完成");
}
4
语法分析代码:
/*
待分析的简单语言的语法
用扩充的BNF表示如下:
ch=words[p++];
if(ch=='=')
{
syn=24;
token[m+1]=ch;
}
else
{
syn=20;
p--;
}
break;
case ':':
m=0;token[m++]=ch;
ch=words[p++];
if(ch=='=')
{
syn=18;
token[m+1]=ch;
}
else
scaner();
else if(syn==27)//判断'*'和'/'后面出现'('
{
scaner(); //进行'('里面表达式的判断
expression(); //调用函数expression()
if(syn==28)// '('后匹配到')'
scaner(); //继续读下一个单词符号
else{// '('后没有匹配到')'
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum = sum*10+ch-'0';//转换为数字输出
ch=words[p++];
}
p--;
syn=11;//全为数字则种别码为11
if(sum>32767)
syn=-1;
}
else switch(ch)//其余字符
{
case '<' :
printf("解析成功!\n");
}
else
{
if(kk!=1)
printf("字符串没有以'end'结尾!\n");
kk=1;
}
}
else
{ห้องสมุดไป่ตู้
printf("字符串没有以'begin'开头!\n");
kk=1;
}
return ;
}
void yucu()
{
statement(); //调用函数statement()
{
scaner();
if(syn==18)//变量名后面种别码为18时,表明为赋值符号
{
scaner();
expression(); //调用函数expression()函数
}
else
{
printf("句子的赋值符号':='不正确!\n");
kk=1;
}
}
else//句子不是以变量名开头,出错
{
printf("错误的句子!\n");
#include <stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
/*
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
p为记号,用来对应存放数组下标。出ch用来读入每次输入的字符
*否则为一般标识符。其描述如下:
*/
const char *rwtab[6]={"begin","if","then","while","do","end"};
/*
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
p为记号,用来对应存放数组下标。出ch用来读入每次输入的字符
课程实验报告
课程名称:编译原理(语法分析)
专业班级:软件工程(2)班
学号:20121344073
姓名:张伟
指导教师:顾彬
报告日期:2015.6.18
计算机科学与技术学院
1
1)设计并编制一个语法分析程序,加深对语法分析程序中递归下降分析方法的理解;
2)巩固对代码生成及报错处理等理论的认识;
3)培养对完整系统独立分析和设计的能力;
do//将字符串读入words数组中,直到出现#结束
{
scanf("%c",&ch);
words[p++] = ch;
}while(ch!='#');
p=0;//重新置为0,为下面扫描整个数组做准备
scaner();//调用scanner()方法扫描整个数组
lrparser();//调用lrparser()方法分析程序
{
for(n=0;n<8;n++) token[n] = NULL;//初始化token数组
ch=words[p++];//ch用来读入字符数组存储的字符
while(ch==' ')//字符为空时
{
ch=words[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//读入字符为字母,则可能是变量名或者标识符
kk=1;
}
return;
}
void expression()//判断表达式是否正确
{
term();
while((syn==13)||(syn==14))
{
scaner();
term(); //调用函数term()
}
return;
}
void term()//判断是否出现'*'和‘/’
{
factor();
printf("'('与后面表达式没有匹配成功\n");
kk=1;
}
}
else
{
printf("表达式出错!\n");//表达式出错
kk=1;
}
return;
}
void scaner()
{
sum=0;
for(m=0;m<8;m++)//初始化token数组
其中retab中元素为“begin”“if”“then”“while”“do”“end”,在程序会扫描出标识符时,首先查关键字表。如果能找到匹配的单词,则该单词为关键字,否则为一般标识符。
syn用于每一步扫描中scanner的返回值。在整个语法分析程序中均需要使用该全局变量。
词法分析代码:
/*输入:所给文法的源程序字符串。
words[]用来存放读入的字符串,最大值为100
m用来指示token数组下标
*/
int sum=0,syn,p,n,m=0;
char words[80],token[8];//char token[10],words[100];
char ch;
void scanner()//定义扫描方法,用于扫描整个字符串存放的数组words
getchar();
}
void lrparser()//分析程序
{
if(syn==1)//判断输入字符串是否以'begin'结尾
{
scaner(); //读下一个单词符号
yucu();//调用yucu()函数
if (syn==6)//判断输入字符串是否以'end'结尾
{
scaner();
if ((syn==0)&&(kk==0))