需求
采用递归下降分析法对n!的pascal程序进行语法分析,生成四个结果文件
文法
原始文法
ps: <>代表非终结符
<程序>→<分程序>
<分程序>→begin <说明语句表>;<执行语句表> end
<说明语句表>→<说明语句>│<说明语句表> ;<说明语句>
<说明语句>→<变量说明>│<函数说明>
<变量说明>→integer <变量>
<变量>→<标识符>
<函数说明>→integer function <标识符>(<参数>);<函数体>
<参数>→<变量>
<函数体>→begin <说明语句表>;<执行语句表> end
<执行语句表>→<执行语句>│<执行语句表>;<执行语句>
<执行语句>→<读语句>│<写语句>│<赋值语句>│<条件语句>
<读语句>→read(<变量>)
<写语句>→write(<变量>)
<赋值语句>→<变量>:=<算术表达式>
<算术表达式>→<算术表达式>-<项>│<项>
<项>→<项>*<因子>│<因子>
<因子>→<变量>│<常数>│<函数调用>
<常数>→<无符号整数>
<无符号整数>→<数字>│<无符号整数><数字>
<条件语句>→if<条件表达式>then<执行语句>else <执行语句>
<条件表达式>→<算术表达式><关系运算符><算术表达式>
<关系运算符> →<│<=│>│>=│=│<>
<标识符>→<字母>│<标识符><字母>│ <标识符><数字>
<字母>→a│b│c│d│e│f│g│h│i│j│k│l│m│n│o │p│q │r│s│t│u│v│w│x│y│z|A|…|Z
<数字>→0│1│2│3│4│5│6│7│8│9
经过英语化、消除直接与间接左递归、提取直接与间接公共左因子的文法
ps:
- x()指x为非终结符
- e表示空
- 引入A(),B(),C()为了提取公共左因子
- 引入AA(),BB(),CC(),DD()为了消除直接左递归
variousAndFunctionCall()→e|( agloSen() )
program()→subprogram()
subprogram ()→begin stateTable()exertTable() end
stateTable()→stateSen()AA()
AA()→;stateSen()AA()|e
stateSen()→integer state()
state→variousState()│functionState()
variousState()→various()
functionState()→function various() (arg() ); functionBody()
arg()→various()
functionBody()→begin stateTable();exertTable() end;
exertTable()→exertSen()BB()
BB()→;exertSen()BB()|e
exertSen()→readSen()│writeSen()│assignSen()| ifSen()
readSen()→read(various())
writeSen()→write(various())
assignSen()→various() := agloSen()
agloSen()→xiang()CC()
CC()→- xiang()CC()|e
xiang()→yinzi()DD()
DD()→*yinzi()DD()|e
yinzi()→constt()│various() variousAndFunctionCall()
constt()→digit()A()
A()→e|constt()
variousAndFunctionCall()→e|( agloSen() )
ifSen()→if conditionSen() then exertSen() else exertSen()
conditionSen()→agloSen()relationSymbol()agloSen()
relationSymbol()→<B()│>C()|=
B()→e|=|>
C()→e|=
various()→letter()D()
D→e| letter()|digit()
letter()→a│…│z|A|…|Z
digit()→0│1│2│3│4│5│6│7│8│9
目录文件
文件格式
##注意事项
实验代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERR "x.err"
#define PRO "x.pro"
#define VAR "x.var"
#define DYS "x.dys"
#define LINEMAX 20
int line=1,status,varPosition=0,vkind=0;
char proName[16];
int proLevel=0;;
char tmpWord[35];
char word[25];
FILE* source= fopen("source.dyd", "r+");
int advance();
void writeErr(const char * message);
void writeVar(const char * message);
void writePro(const char * message);
void writeDys(char * message);
void program();
void subprogram ();
void state();
void stateTable();
void AA();
void stateSen();
void variousState();
void functionState();
void arg();
void functionBody();
void exertTable();
void BB();
void exertSen();
void readSen();
void writeSen();
void assignSen();
void agloSen();
void CC();
void xiang();
void DD();
void yinzi();
void constt();
void A();
void variousAndFunctionCall();
void ifSen();
void conditionSen();
void relationSymbol();
void B();
void C();
void various();
void D();
void letter();
void digit();
int latter();
void program(){
writePro("main");
subprogram();
}
void subprogram (){
if (!strcmp(word, "begin"))
{
advance();
stateTable();
vkind--;
exertTable();
if(!strcmp(word,"end")){
int state=advance();
if (state==-1)return;
}else writeErr("no matched end");
}else writeErr("no begin");
}
void stateTable(){
stateSen();
AA();
}
void stateSen(){
if(!strcmp(word, "integer")){
advance();
state();
}else writeErr("no correct integer");
}
void AA(){
if(*word==';')
{
advance();
// if(!strcmp(word, "integer"))
stateSen();
AA();
}
else return;
}
void state(){
if(!strcmp(word, "function"))
functionState();
else
variousState();
}
void variousState(){
writeVar(word);
various();
}
void functionState(){
if(!strcmp(word, "function")){
advance();
writePro(word);
various();
if(*word=='('){
advance();
arg();
if(*word==')'){
advance();
if(*word==';')
{advance();functionBody();
}
else writeErr("7qwe");
}else writeErr("8qwe");
}else writeErr("9qwe");
}else writeErr("10qwe");
}
void arg(){
various();
}
void functionBody(){
if(!strcmp(word, "begin")){
advance();
stateTable();
exertTable();
if(!strcmp(word, "end")){
advance();
if(*word==';')advance();else {writeErr("qwe");};
}else writeErr("qwe");
}
}
void exertTable(){
exertSen();
BB();
}
void BB(){
if(*word==';')
{
advance();exertSen();BB();
}
else return;
}
void exertSen(){
if(!strcmp(word, "read"))
readSen();
else if(!strcmp(word, "write"))
writeSen();
else if(!strcmp(word, "if"))
ifSen();
else assignSen();
}
void readSen(){
if(!strcmp(word, "read")){
advance();
if(*word=='('){
advance();
various();
if(*word==')'){
advance();
}else writeErr("qwe");
}else writeErr("no correct symbol match to read");
}else writeErr("qwe");
}
void writeSen(){
if(!strcmp(word, "write")){
advance();
if(*word=='('){
advance();
various();
if(*word==')'){
advance();
}else writeErr("qwe");
}else writeErr("qwe");
}else writeErr("qwe");
}
void assignSen(){
various();
if(!strcmp(word, ":="))
{
advance();agloSen();
}
else writeErr("err");
}
void agloSen(){
xiang();CC();
}
void CC(){
if(*word=='-')
{
advance();xiang();CC();
}
else return;
}
void xiang(){
yinzi();DD();
}
void DD(){
if(*word=='*')
{
advance();yinzi();DD();
}
else return;
}
void yinzi(){
if((*word)*1>47&&(*word)*1<58)
constt();
else {various();variousAndFunctionCall();}
}
void constt(){
digit();A();
}
void A(){
if((*word)*1>47&&(*word)*1<58)
constt();
else return;
}
void variousAndFunctionCall(){
if(*word=='('){
advance();
agloSen();
if(*word==')'){
advance();
}else writeErr("qwe");
}else return;
}
void ifSen(){
if(!strcmp(word, "if")){
advance();
conditionSen();
if(!strcmp(word, "then")){
advance();
exertSen();
if(!strcmp(word, "else")){
advance();
exertSen();
}else writeErr("qwe");
}else writeErr("qwe");
}else writeErr("qwe");
}
void conditionSen(){
agloSen();relationSymbol();agloSen();
}
void relationSymbol(){
switch(*word){
case '<':advance();B();break;
case '>':advance();C();break;
case '=':advance();
default:writeErr("qwe");
}
}
void B(){
switch (*word){
case '=':advance();break;
case '>':advance();break;
default:return;
}
}
void C(){
if(*word=='=')
advance();
else return;
}
void various(){
letter();D();
}
void D(){
if((*word>='a'&&*word<='z')||(*word>='A'&&*word<='Z'))
letter();
else if((*word)*1>47&&(*word)*1<58) digit();
else return;
}
void letter(){
if((*word>='a'&&*word<='z')||(*word>='A'&&*word<='Z'))
advance();
else {writeErr("is not correct expression");}
}
void digit(){
if((*word)*1>47&&(*word)*1<58)
advance();
else writeErr("errd");
}
void writeErr(const char * message){
FILE *result=fopen(ERR,"a+");
char linec[4];
itoa(line,linec,10);//fputs不能接受int,只能字符串,所以要类型转换
fputs("Line ",result);
fputs(linec,result);
fputs(": ",result);
fputs(message,result);
fputs("\n",result);
fclose(result);
// advance();
}
void writeVar(const char * message){
FILE *var=fopen(VAR,"a+");
char varPositionc[4],proLevelc[4],vkindc[4];
itoa(varPosition,varPositionc,10);
itoa(proLevel,proLevelc,10);
itoa(vkind,vkindc,10);
fputs(message,var);//name
fputs("--",var);
fputs(proName,var);//belong Func
fputs("--",var);
fputs(vkindc,var);
fputs("--ints--",var);
fputs(proLevelc,var);//fun level
fputs("--",var);
fputs(varPositionc,var);//var position
fputs("\n",var);
varPosition++;
vkind++;
fclose(var);
}
void writePro(const char * message){
FILE *result=fopen(PRO,"a+");
char proLevelc[4];
itoa(proLevel,proLevelc,10);//fputs不能接受int,只能字符串,所以要类型转换
fputs(message,result);//name
fputs("--",result);
fputs("ints--",result);
fputs(proLevelc,result);//level
fputs("\n",result);
strcpy(proName,message);
proLevel++;
fclose(result);
}
void writeDys(char * message){
FILE *result=fopen(DYS,"a+");
fputs(message,result);
// fputs("\n",result);
fclose(result);
}
int latter(){
char *tmpWord=(char *)malloc(sizeof(char)*50);
if(fgets(tmpWord, 30, source)!=NULL){
writeDys(tmpWord);
int position=0;
while(*tmpWord==' ')
tmpWord++;
strcpy(word,tmpWord);
while(*tmpWord!=' ')
{
tmpWord++;
position++;
}
word[position]='\0';
tmpWord-=16;
if(!strcmp(word, "EOLN")){
line++;
latter();
}
if(!strcmp(word, "EOF"))return -1;
return 1;
}
free(tmpWord);
return -1;
}
int advance(){
int x=latter();
// printf("%s\n",word);
return x;
}
int main(){
status=advance();
if(status==-1)return 0;
program();
return 0;
}
测试代码
测试程序:
begin
integer k;
integer function F(n);
begin
integer n;
if n<=0 then F:=1
else F:=n*F(n-1)
end;
read(m);
k:=F(m);
write(k)
end
语法分析中必须处理的几种情况:
- 第二行改为:intger m;
- 第三行改为:integer funtion F(n);
- 第九行改为:readm)
4.begin
integer k;
integer function F(n);
begin
integer n;
if n<=0 then F:=1
else F:=n*F(n-1)
end;
read(m);
integer m;
k:=F(m);
write(k)
第九行后加一行 integer m;
注意:第二种修改可能导致重大语法错误,同学们可以自己再另选一种重大语法错误进行测试。
结果
ps:本人原创,抄袭后果自负