/*
待分析的簡單語言的語法
用擴充的BNF表示如下:
⑴<程序>::=begin<語句串>end
⑵<語句串>::=<語句>{;<語句>}
⑶<語句>::=<賦值語句>
⑷<賦值語句>::=ID:=<表達式>
⑸<表達式>::=<項>{+<項> | -<項>}
⑹<項>::=<因子>{*<因子> | /<因子>
⑺<因子>::=ID | NUM | (<表達式>)
*/
#include "stdio.h"
#include "string.h"
char prog[100],token[8],ch;//prog[100],用來存儲要處理的對象,token用來與關鍵字比較,ch用來存儲一個字符
char *rwtab[6]={"begin","if","then","while","do","end"};//關鍵字表
int syn,p,m,n,sum;
/*syn是種別碼,p為prog數組的指針,m為token數組的指針,n為rwtab數組的指針,sum為詞法分析器里的數字數值大小*/
int flag;//flag與判斷是否end有關
void factor(void);//因式 factor
void expression(void);//表達式 expression
void yucu(void);
void term(void);//項 term
void statement(void);// 語句 statement
void parser(void);
void scaner(void);//掃描器
int main(void)
{
p=flag=0;
printf("\nplease input a string (end with '#'): \n");
/*從命令行讀取要處理的對象,並存儲在prog[]數組中*/
do
{
scanf("%c",&ch);
//printf("\n input %c now\n",ch);
prog[p++]=ch;
}while(ch!='#');
p=0;
scaner();//主要完成賦值種別碼等詞法分析功能
parser();//調用各種遞歸子程序,完成語法分析的過程
//getch();
}
/*調用各種遞歸子程序,完成語法分析的過程*/
void parser(void)
{
if(syn==1)//begin
{
scaner(); /*讀下一個單詞符號*/
yucu(); /*調用yucu()函數;*/
if(syn==6)//end
{
scaner();
if((syn==0)&&(flag==0))//出現#且flag=0
printf("success!\n");
}
else
{
if(flag!=1) printf("the string haven't got a 'end'!\n");//flag來判斷是否end
flag=1;
}
}
else
{
printf("haven't got a 'begin'!\n");
flag=1;
}
return;
}
void yucu(void)
{
statement(); /*調用函數statement();*/
while(syn==26)//分號
{
scaner(); /*讀下一個單詞符號*/
if(syn!=6)
statement(); /*調用函數statement();*/
}
return;
}
void statement(void)
{
if(syn==10)
{
scaner(); /*讀下一個單詞符號*/
if(syn==18)
{
scaner(); /*讀下一個單詞符號*/
expression(); /*調用函數expression();*/
}
else
{
printf("the sing ':=' is wrong!\n");
flag=1;
}
}
else
{
printf("wrong sentence!\n");
flag=1;
}
return;
}
void expression(void)
{
term();
while((syn==13)||(syn==14))
{
scaner(); /*讀下一個單詞符號*/
term(); /*調用函數term();*/
}
return;
}
void term(void)
{
factor();
while((syn==15)||(syn==16))
{
scaner(); /*讀下一個單詞符號*/
factor(); /*調用函數factor(); */
}
return;
}
void factor(void)//因式處理函數
{
if((syn==10)||(syn==11))//標識符,數字
{
scaner();
}
else if(syn==27)//開頭是左括號(
{
scaner(); /*讀下一個單詞符號*/
expression(); /*調用函數statement();*/
if(syn==28)//出現右括號)
{
scaner(); /*讀下一個單詞符號*/
}
else
{
printf("the error on '('\n");
flag=1;
}
}
else
{
printf("the expression error!\n");
flag=1;
}
return;
}
/*主要完成賦值種別碼等詞法分析功能*/
void scaner(void)//掃描器,詞法分析器內容
{
sum=0;//數字初始化為0
for(m=0;m<8;m++)//初始化token
token[m++]=NULL;
m=0;//m為token的指針
ch=prog[p++];//數組指針+1
while(ch==' ')//遇到空格+1
ch=prog[p++];
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))//遇到字母
{
while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;
ch=prog[p++];//p+1,下次循環使用
}
p--;//循環跳出,要-1
syn=10;//10,字母開頭
token[m++]='\0';//\0為字符串結束符
/*判別是否為關鍵字*/
for(n=0;n<6;n++)//n為rwtab的指針
if(strcmp(token,rwtab[n])==0)//strcmp返回值為0,則兩個參數大小相同
{
syn=n+1;
break;
}
}
else if((ch>='0')&&(ch<='9'))//遇到數字
{
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;//回溯
syn=11;//11為數字
}
/*除數字和字母開頭以外的其他符號*/
else
switch(ch)
{
case '<':
m=0;
ch=prog[p++];
if(ch=='>')
{
syn=21;
}
else if(ch=='=')
{
syn=22;
}
else
{
syn=20;
p--;//回溯
}
break;
case '>':
m=0;
ch=prog[p++];
if(ch=='=')
{
syn=24;
}
else
{
syn=23;
p--;
}
break;
case ':':
m=0;
ch=prog[p++];
if(ch=='=')
{
syn=18;
}
else
{
syn=17;
p--;
}
break;
case '+':
syn=13;
break;
case '-':
syn=14;
break;
case '*':
syn=15;
break;
case '/':
syn=16;
break;
case '(':
syn=27;
break;
case ')':
syn=28;
break;
case '=':
syn=25;
break;
case ';':
syn=26;
break;
case '#':
syn=0;
break;
default:
syn=-1;
break;
}
}