/*
用预测分析法(即LL(1)分析法)构造文法G[E]:
E->E + T / T
T->T * F / F
F->(E) / i / x / y
的预测分析程序(即语法分析器)。
by wzt <[email protected]>
date : 2007.1.14
*/
#include <stdio.h>
#include <string.h>
#define MAXSIZE 200
#define MAX 20
//#define DEBUG
char c[MAX]; /* 要判断的符号串 */
char *str[]={"TD","+TD","","FS","*FS","","(E)","i","x","y"}; /* 所有产生式 */
char Symbol_VT[MAX] = "+*()ixy#"; /* 所有终结符号 */
char Symbol_VN[MAX] = "EDTSF"; /* 所有非终结符号 */
char stack[MAX] = {'#','E'}; /* 分析栈 */
int top = 1;
char temp[MAX];
FILE *s_fp,*t_fp;
int M[][8] = { /* 存放str的下标,-1表示不存在 */
{-1,-1,0,-1,0,0,0,-1},
{1,-1,-1,2,-1,-1,-1,2},
{-1,-1,3,-1,3,3,3,-1},
{5,4,-1,5,-1,-1,-1,5},
{-1,-1,6,-1,7,8,9,-1}
};
void usage(char *pro); /* 程序帮助信息 */
void do_analyses(); /* 分析符号串 */
int VN_to_lin(char X); /* 判断非终结符所在的下标 */
int VT_to_col(char X); /* 判断终结符所在的下标 */
int is_VN(char X); /* 判断字符是否是非终结符 */
int is_VT(char X); /* 判断字符是否是终结符 */
void print_symbols(int i); /* 打印余留符号串 */
void print_stack(); /* 打印分析栈 */
int main(int argc,char **argv)
{
char temp_str[MAXSIZE];
char temp_code,temp_val[MAX];
int j = 0;
if( argc < 3 )
usage(argv[0]);
if( (s_fp = fopen(argv[1],"r")) == NULL ){
printf("Can not open %s.\n",argv[1]);
exit(1);
}
if( (t_fp = fopen(argv[2],"w+")) == NULL ){
printf("Can not open %s.\n",argv[1]);
exit(1);
}
while( fgets(temp_str,MAXSIZE,s_fp) != NULL ){ /* 从文件读取单词二元式 */
sscanf(temp_str,"%c %s",&temp_code,temp_val);
c[j++] = temp_code;
#ifdef DEBUG
printf("%c %s\n",temp_code,temp_val);
#endif
}
c[j] = '\0';
#ifdef DEBUG
printf("%s\n",c);
#endif
do_analyses();
fclose(s_fp);
fclose(t_fp);
return 0;
}
void usage(char *pro) /* 程序帮助信息 */
{
printf("usage : %s <file_int> <file_out>\n",pro);
exit(0);
}
void do_analyses() /* 分析符号串 */
{
char temp_str[MAXSIZE];
char temp_str1[MAXSIZE];
char X;
int i,j = 0,m,n,k;
printf("Step Stack Symbols Syntax\n");
for( i = 0 ; i < strlen(c) ; i++ ){
X = stack[top--]; /*弹出栈顶元素 */
print_symbols(i);
stack[top + 2 ] = '\0';
sprintf(temp_str,"%2d %-8s %-13s",j++,stack,temp);
printf("%s",temp_str);
fputs(temp_str,t_fp);
if( X == '#' ){ /* 符号串匹配成功 */
if( X == c[i] ){
printf("Acc.\n");
}
else{
printf("Symbols Error.\n");
}
exit(0);
}
if( is_VT(X) ){ /* X是终结符号且与要判断的字符相等,就继续循环 */
printf("\n");
fputs("\n",t_fp);
if( X == c[i] )
continue;
else{
printf("Error at %d.\n",i);
}
}
if( is_VN(X) ){ /* X是非终结符号 */
m = VN_to_lin(X); /* 求X在M数组中的纵坐标 */
n = VT_to_col(c[i]); /* 求要判断的字符在M数组中的横坐标 */
for( k = strlen(str[M[m][n]]) - 1 ; k >= 0 ; k-- )
stack[++top] = *(str[M[m][n]] + k ); /* 取得产生式并反向压栈 */
i --; /* !!! i减1,符号串要重新开始判断 */
sprintf(temp_str1,"%c->%s\n",X,str[M[m][n]]);
printf("%s",temp_str1);
fputs(temp_str1,t_fp);
}
}
}
int VN_to_lin(char X) /* 求X在M数组中的纵坐标 */
{
int i;
for( i = 0 ; i < strlen(Symbol_VN) ; i++ ){
if( X == Symbol_VN[i] )
return i;
}
printf("Error. X is not in Symbol_VN \n");
exit(0);
}
int VT_to_col(char X) /* 求要判断的字符在M数组中的横坐标 */
{
int i;
for( i = 0 ; i < strlen(Symbol_VT) ; i++ ){
if( X == Symbol_VT[i] )
return i;
}
printf("Error. %c is not in Symbol_VT \n",X);
exit(0);
}
int is_VN(char X) /* X是非终结符号 */
{
int i;
for( i = 0 ; i < strlen(Symbol_VN) ; i++ ){
if( X == Symbol_VN[i] )
return 1;
}
return 0;
}
int is_VT(char X) /* X是终结符号 */
{
int i;
for( i = 0 ; i < strlen(Symbol_VT) ; i++ ){
if( X == Symbol_VT[i] )
return 1;
}
return 0;
}
void print_symbols(int i) /* 打印余留符号串 */
{
int j,k=0;
for( j = i ; j < strlen(c) ; j++ )
temp[k++] = c[j];
temp[k] = '\0';
}
void print_stack() /* 打印分析栈 */
{
int i;
printf(" ");
for( i = 0 ; i <= top ; i++ )
printf("%c",stack[i]);
}
|