?? pl0語法分析器遞歸子程序法.c
字號:
//程序名: yufashini.cpp
//作者:小萬(wbaobao)
//郵箱:wbaobao#zj.com
//QQ:421404493
//創建日期:2004.10
//程序功能:PL/0語言語法分析程序,檢測pl/0源程序的語法是否正確
//程序不足之處:語言中對分程序的定義中沒有包含常量的定義說明。錯誤處理能力不是很強。
/*各個符號和產生式說明
對應的函數 產生式 產生式的開始符號集合
void S();程序 S-->F. p,m,e,k,q,g,n,r,f,.,;,
void F();分程序 F-->B(Y|GY)|G(Y|BY)|Y p,m,e,k,q,g,n,r,f,.,;,
void B();變量說明部分 pe(,e)*; p
void G();過程說明部分 CF;|CF;G m
void Y();語句 Y-->eaA|kToY|qToY|ge|n(e(,e)*)|r(e(,e)*)|fY(;Y)*j|<空> e,k,q,g,n,r,f,.,;,
void C();過程首部 C-->me; m
void A();表達式 A-->(+|-|<空>)N|A(+|-)N +,-,e,d,(
void N();項 N-->I|N(*|/)I e,d,(
void I();因子 I-->e|d|(A) e,d,(
void X();關系運算符 X-->#|<|>|b #,<,>,b
void T();//條件 T-->AXA|lA +,-,e,d,(,l
其中終結符的含義均為二元式中的類別碼所代表的單詞
(+,+);(-,-);(*,*);(/,/);((,();(),));(,,,);(;,;);(.,.);(#,#);(=,=);(>,>);(<,<);(:=,a);(>=,b);
(<=,c);(數字,d);(標識符,e);(begin,f);(call,g);(const,h);(do,i);(end,j);(if,k);(odd,l);
(procedure,m);(read,n);(then,o);(var,p);(while,q);(write,r);
*/
/*測試數據:
(PROCEDURE,m)(P,e)(;,;)
(VAR,p)(D,e)(;,;)
(PROCEDURE,m)(Q,e)(;,;)
(VAR,p)(X,e)(;,;)
(BEGIN,f)
(READ,n)((,()(X,e)(),))(;,;)
(D,e)(:=,a)(X,e)(;,;)
(WHILE,q)(X,e)(<,<)(0,d)
(DO,i)(CALL,g)(P,e)(;,;)
(END,j)(;,;)
(BEGIN,f)
(WRITE,r)((,()(D,e)(),))(;,;)
(CALL,g)(Q,e)(;,;)
(END,j)(;,;)
(BEGIN,f)
(CALL,g)(P,e)(;,;)
(END,j)(.,.)
//請將以上數據存為b.c(上面為詞法分析的結果)
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
char token;
char tempword[25];
FILE *op;
int row;
void error(int wnum);
char word();
void S();//程序
void F();//分程序
void B();//變量說明部分
void G();//過程說明部分
void Y();//語句
void C();//過程首部
void A();//表達式
void N();//項
void I();//因子
void X();//關系運算符
void T();//條件
struct infoword
{
char word[25];
char type;
int row;
int error;
infoword *next;
infoword *pre;
};
infoword *head,*cur;
infoword *point;
void filltable(char *str,char t)
{
//infoword newnode;
int i=0;
infoword *newnode=new infoword;
strcpy(newnode->word,str);
newnode->type=t; //putchar('q');
newnode->row=row;
newnode->error=i;
newnode->pre=NULL;
newnode->next=NULL;
if(head==NULL)
{
point=head=newnode;//初始化point和head指針
cur=newnode;//初始化cur指針
}
else
{
newnode->pre=cur;
cur->next=newnode;
cur=newnode;
}
}
char find(char *str)
{
infoword *tempp;//puts(str);
tempp=head;
while(tempp&&strcmp((tempp->word),str))tempp=tempp->next;
if(tempp==NULL)return NULL;
else return tempp->type;
}
int compare(char *str,char t)
{
char a;
a=find(str);
if(a)
if(a==t)
return 1;//類型為要求類型
error(44);//找到但不是要求類型
error(42);//未找到
return 0;
}
char word()//return a char
{
//FILE *op;
//op=fopen("b.c","r");
char tempc;
char tempx;
char tempw[25];
int i=0,j=0;
while(!feof(op))
{
tempc=fgetc(op);
strcpy(tempword,"");
if(tempc==10)
{
row++;
//printf("%d\n",row);
}
if(tempc==',')
{
tempx=fgetc(op);
tempc=fgetc(op);
if(tempc==')')
{
//putchar(tempx);
if(tempx=='e')
{
fseek(op,-4l,1);//putchar(fgetc(op));fseek(op,-1l,1);//去掉逗號
do
{
tempw[i]=fgetc(op);//逆向輸入
i++;
fseek(op,-2l,1);//putchar(fgetc(op));fseek(op,-1l,1);
}while(fgetc(op)!='(');//判斷這個單詞結束的標志
for(j=0;i>0;i--)
{
tempword[j]=tempw[i-1];//再次順序輸入到tempword
j++;
fseek(op,1l,1);
}
tempword[j]='\0';
//puts(tempword);
fseek(op,3l,1);//putchar(fgetc(op));fseek(op,-1l,1);
}
return tempx;
//putchar(tempc);
//putchar('\n');
}
fseek(op,-2l,1);
}
}
return NULL;
}
void error(int wnum)
{
if(wnum==4)printf("錯誤(%d):var,procedure后應為標志符\n",row);
else if(wnum==5)printf("錯誤(%d):漏掉了','或';'\n",row);
else if(wnum==6)printf("錯誤(%d):過程說明后的符號不正確(應是語句的開始符,或過程的定義符)\n",row);
else if(wnum==7)printf("錯誤(%d):應是語句開始符\n",row);
else if(wnum==8)printf("錯誤(%d):程序體內語句部分的后跟符不正確\n",row);
else if(wnum==9)printf("錯誤(%d):程序結尾丟了句號'.'\n",row);
else if(wnum==10)printf("錯誤(%d):語句之間丟了分號';'\n",row);
else if(wnum==11)printf("錯誤(%d):標志符未說明\n",row);
else if(wnum==12)printf("錯誤(%d):賦值語句中,賦值號左部標志符屬性應是變量\n",row);
else if(wnum==13)printf("錯誤(%d):賦值號左部標志符后應是賦值號':='\n",row);
else if(wnum==14)printf("錯誤(%d):call應為標志符\n",row);
else if(wnum==15)printf("錯誤(%d):call后標志符屬性應為過程\n",row);
else if(wnum==16)printf("錯誤(%d):條件語句中丟了'then'\n",row);
else if(wnum==17)printf("錯誤(%d):丟了'end'或';'\n",row);
else if(wnum==18)printf("'錯誤(%d):while'型循環語句中丟了'do'\n",row);
else if(wnum==19)printf("錯誤(%d):語句后的符號不正確\n",row);
else if(wnum==20)printf("錯誤(%d):應為關系運算符\n",row);
else if(wnum==21)printf("錯誤(%d):表達式內標志符屬性不能是過程\n",row);
else if(wnum==22)printf("錯誤(%d):表達式中漏掉右括號')'\n",row);
else if(wnum==23)printf("錯誤(%d):因子后的非法符號\n",row);
else if(wnum==24)printf("錯誤(%d):表達式的開始符號不能是此符號\n",row);
else if(wnum==31)printf("錯誤(%d):數越界\n",row);
else if(wnum==32)printf("錯誤(%d):read語句括號中的標志符不是變量\n",row);
else if(wnum==1)printf("錯誤(%d):wwww\n",row);
else if(wnum==2)printf("錯誤(%d):\n",row);
else if(wnum==33)printf("錯誤(%d):應該為賦值號\n",row);
else if(wnum==34)printf("錯誤(%d):讀語句缺少左括號\n",row);
else if(wnum==35)printf("錯誤(%d):程序的開始符號出錯\n",row);
else if(wnum==36)printf("錯誤(%d):read語句括號中缺少標志符\n",row);
else if(wnum==37)printf("錯誤(%d):read語句漏掉左括號'('\n",row);
else if(wnum==38)printf("錯誤(%d):write語句括號中缺少表達式\n",row);
else if(wnum==39)printf("錯誤(%d):write語句漏掉左括號'('\n",row);
else if(wnum==40)printf("錯誤(%d):關系運算符出錯\n",row);
else if(wnum==41)printf("錯誤(%d):條件開始子集錯誤\n",row);
else if(wnum==42)printf("錯誤(%d):標志符未定義\n",row);
else if(wnum==43)printf("錯誤(%d):標志符已定義\n",row);
else if(wnum==44)printf("錯誤(%d):標志符屬性不復合要求\n",row);
else if(wnum==45)printf("錯誤(%d):分程序后應跟分號\n",row);
else if(wnum==36)printf("錯誤(%d):程序意外結束,無法繼續編譯\n",row);
}
/*約定每一個產生式結束時都得取出下一個字符*/
void S()//程序
{
//輸入符號為結束標志,輸出提示信息,退出程序
if(token=='.')
{
printf("analyse over!\n\n");
exit(0);
}
//當輸入符號不屬于開始符號集時,轉到錯誤處理//下面句判斷條件有錯誤
if(token!='p'&&token!='m'&&token!='e'&&token!='k'&&token!='q'&&token!='g'&&token!='n'&&token!='r'&&token!='f'&&token!='.'&&token!=';'&&token!='j')
{
error(35);int stemprow=0;
stemprow=row;
token=word();/*程序的開始符號出錯,處理方式:判斷后跟符是否為S的開始符,直到取得一個可以是語句或變量說明部分或過程說明部分的開始符*/
while(stemprow==row)
{
token=word();
}
//token=word();putchar(token);
S();
}
else
{
F();
if(token=='.')
{
printf("analyse over!\n");
}
else
{
error(9);//putchar('m');//缺少程序的結束符
//fputchar(token);
}
}
}
void F()//分程序
{
int ftemprow=0;
ftemprow=row;
if(token=='m')
{
G();
//token=word();
if(token=='p')
{
B();//putchar('y');
Y();
}
else
{
Y();
}
}
else if(token=='p')
{
B();
//token=word();
if(token=='m')
{
G();
Y();
}
else
{//putchar('y');
Y();
}
}
else if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
{
Y();
}
else
{
error(1);//putchar('y');
while(ftemprow==row)
token=word();
F();
}
}
void B()//變量說明部分
{
int temprow=0;
temprow=row;
if(token!='p') //當輸入符號不等于p時,轉到錯誤處理
{ //putchar(token);
error(1);//變量說明部分的關鍵字應該是‘var’
while(temprow==row)
token=word();
}
else
{
token=word();
if(token!='e')//判斷是否在同行
{
error(4);
while(temprow==row)
token=word();
}
else
{
if(find(tempword))
{
error(43);//標志符已定義
//putchar('b');
}
else
{
filltable(tempword,'p');//putchar('t');
}
token=word();
if(token!=';'&&token!=',')
{
error(5);//putchar('x');//變量結束符應該是分號//檢查該行是否結束是則缺少分號不是則缺少逗號
while(temprow==row)//行未結束則繼續取詞
token=word();
}
else
{
while(token==',')//當
{
token=word(); //putchar('x');
if(token!='e')
{
error(4);//判斷該行是否結束是則報錯結束符應該是分號,不是報錯應該為標志符
while(temprow==row)
token=word();
}
else
{
if(find(tempword))
{
error(43);//標志符已定義
//putchar('b');
}
else
{
filltable(tempword,'p');//putchar('t');
}
token=word();//繼續取數
}
}
if(token!=';'&&temprow==row)//還要判斷是否同行
{
error(17);//結束符不正確
}
else
{
token=word();
}
}
}
}
}
void G()//過程說明部分
{
//putchar('y');
int gtemprow=0;
gtemprow=row;
if(token!='m')
{
//putchar('y');
error(1);//putchar('y');//過程說明符應該為procedure
while(gtemprow==row)
token=word();
}
else
{
//putchar('y');
//token=word();
C(); //putchar('x');
F(); //putchar('x');
if(token!=';')
{
error(45);//putchar('x');//the end shoud be ';' 只報錯不作處理
}
token=word();//繼續取單詞
if(token=='m')//是'm'就說明是另一個過程的開始
{
//token=word();
G();
}
}
}
void Y()//語句
{
int ytemprow=0;
if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
{
if(token=='e')//賦值語句
{
compare(tempword,'p');
ytemprow=0;
ytemprow=row;
token=word();//putchar('x');
if(token!='a')
{
error(33);//putchar('y');//應該為賦值號
while(ytemprow==row)
token=word();
ytemprow=0;//putchar(token);
}
else
{
token=word();//putchar('w');putchar(token);//continue to get the next alpha
A();//putchar('z');//Call A
//putchar('x');putchar(token);//token=word();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -