预测分析法进行语法分析(编译原理)
2015-03-23 19:26
183 查看
预测分析法是一种表驱动的方法,它由下推栈,预测分析表和控制程序组成。实际上是一种下推自动机的实现模型。预测分析法的关键为预测分析表的构建,即文法中各非终结符first集和follow集的求得。预测分析法从开始符号开始,根据当前句型的最左边的非终结符和分析串中的当前符号,查预测分析表确定下一步推导所要选择的产生式,最终得到输入串的最左推导,完成输入串的语法检查。
其中主要建立first集,follow集合用来消除左递归(较难)
输入文本:
E T F
+ * ( ) i
E->E+T|T
T->T*F|F
F->(E)|i
(i)*i
(i)*iii
源码(C语言版)
运行结果:
其中主要建立first集,follow集合用来消除左递归(较难)
输入文本:
E T F
+ * ( ) i
E->E+T|T
T->T*F|F
F->(E)|i
(i)*i
(i)*iii
源码(C语言版)
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #ifndef success #define success 1 #endif #define MAX_AMOUNT 20 /*定义非终结符*/ typedef struct NOterminal { char character; int first_number;/*FIRST集的判定,初始为0*/ int follow_number;/*FOLLOW集的判定,初始为0*/ char * FIRST;/*FIRST 集合*/ char * FOLLOW;/*FOLLOW集合*/ struct NOterminal *next; } noterminal; /*定义终结符*/ typedef struct Terminal { char character;/*当前的字符*/ struct Terminal *next; } terminal; /*定义产生式*/ typedef struct PRODUCTION { char source;/*产生的开始*/ char * result;/*产生的结果*/ struct PRODUCTION *next;/*指向下一条`*/ } production; int amount=0; char TEST_STACK[20]; char* TEST_LIST[10]; char terminal_all[10]= {0}; terminal TERMINAL_HEAD, *current_terminal=&TERMINAL_HEAD; noterminal NOTERMINAL_HEAD, *current_noterminal=&NOTERMINAL_HEAD; production PRODUCTION_HEAD, *current_production=&PRODUCTION_HEAD; /*函数申明*/ size_t read(void); size_t test(void); size_t write(void); void Test_read(void); size_t STACK_FULL(); void STACK_POP(void); size_t STACK_EMPTY(); void init_stack(void); void prediction(void); void test_follow(void); void emergency(int model); void prediction_table(void); void STACK_PUSH(char source); void insert_to_terminal(char get); void insert_to_noterminal(char get); void eliminate_left_recursion(void); void combine(char* destinction,char* source); size_t is_appeared(char tobejudged,char*source); void insert_to_production(char source , char* result); size_t find_first(noterminal* this_noterminal,production *this_production); size_t find_follow(noterminal* this_noterminal,production *this_production); int main(void) { TERMINAL_HEAD.next=NULL; NOTERMINAL_HEAD.next=NULL; PRODUCTION_HEAD.next=NULL; read(); Test_read(); printf("\n消除左递归\n\n"); eliminate_left_recursion(); Test_read(); printf("\n求FIRST集\n\n"); prediction(); printf("\n求FOLLOW集\n\n"); test_follow(); prediction_table(); emergency(0); return 0; } /*读文件*/ size_t read(void) { int line=0,model=0,old_line=0; int number=0; char current_get=0,read_temp[10]= {0}; FILE * read_stream=fopen("test1.txt","r"); if(!read_stream) { printf("error in open file ,can`t open file\n"); exit(EXIT_FAILURE); } insert_to_terminal('#');/*插入栈底元素,以#表示栈底*/ insert_to_terminal('^');/*插入空串元素,以^表示栈底*/ while(!feof(read_stream)) { current_get=fgetc(read_stream); while(current_get==' ') current_get=fgetc(read_stream);/*忽略空格*/ while(current_get=='\n') { current_get=fgetc(read_stream); line++;/*跳过换行*/ } switch(line) { case 0: insert_to_noterminal(current_get); break; case 1: insert_to_terminal(current_get); break; case 3: ungetc(current_get,read_stream); old_line=1; break; default: perror("error in format of program \n"); emergency(0); break; } if(old_line) break; } while(!feof(read_stream)) { memset(read_temp,0,sizeof(read_temp)); old_line=line; current_get=fgetc(read_stream); while(current_get==' ') current_get=fgetc(read_stream);/*忽略空格*/ while(current_get=='\n') { current_get=fgetc(read_stream); line++;/*跳过换行*/ } model=((line-old_line)>model)? (line-old_line): model; switch(model) { case 0: case 1: fscanf(read_stream,"%s",read_temp); insert_to_production(current_get,read_temp); break; case 2: ungetc(current_get,read_stream); TEST_LIST[number]=(char*)malloc(20); memset(TEST_LIST[number],0,20); fscanf(read_stream,"%s",TEST_LIST[number++]); break; default: perror("error in format of program \n"); emergency(1); break; } } fclose(read_stream); return success; } /*测试*/ size_t test(void) { noterminal *TEMP_NOTERMINAL=NOTERMINAL_HEAD.next; for(; TEMP_NOTERMINAL!=NULL; TEMP_NOTERMINAL=TEMP_NOTERMINAL->next) { printf("%c\tfirst number=%d\tfirst=%s\n", TEMP_NOTERMINAL->character, TEMP_NOTERMINAL->first_number, TEMP_NOTERMINAL->FIRST); } printf("\n"); return success; } /*求FIRST集合*/ size_t find_first(noterminal* this_noterminal,production *this_production) { noterminal* this_noterminal_temp; char temp[2]= {0}; char *TEMP2,*help; while(this_production->source!=this_noterminal->character) this_production=this_production->next;/*移向下一个产生式*/ /*查看是否是第一次,如果是,分配空间*/ if(this_noterminal->first_number==0) { this_noterminal->FIRST=(char*)malloc(MAX_AMOUNT+1); memset(this_noterminal->FIRST,0,MAX_AMOUNT+1); } while(this_production&&this_production->source==this_noterminal->character) { TEMP2=this_production->result; while(*TEMP2) { if(is_appeared(*TEMP2,terminal_all)) { temp[0]=this_production->result[0]; combine(this_noterminal->FIRST,temp); break; } else { this_noterminal_temp=NOTERMINAL_HEAD.next; while(this_noterminal_temp->character!=*TEMP2) this_noterminal_temp=this_noterminal_temp->next; if(this_noterminal_temp->first_number==0)/*没求first集*/ find_first(this_noterminal_temp,PRODUCTION_HEAD.next); combine(this_noterminal->FIRST,this_noterminal_temp->FIRST); help=this_noterminal->FIRST; while(*help&&*help!='^') help++; if(*help&&*(TEMP2+1))/*包含'^'*/ { while(*help) { *help=*(help+1); help++; } } else break; TEMP2++; } } this_production=this_production->next; } this_noterminal->first_number=strlen(this_noterminal->FIRST); return success; } /*求FOLLOW集合*/ size_t find_follow(noterminal* this_noterminal,production *this_production) { char* help=NULL; char* temp_result; int symbol=0; char terminal_array[2]= {0}; noterminal* FOLLOW_TEMP,*FOLLOW_HELP; if(this_noterminal->follow_number==0) { this_noterminal->FOLLOW=(char* )malloc(MAX_AMOUNT+1); memset(this_noterminal->FOLLOW,0,MAX_AMOUNT+1); } /*第一个非终结符包含有#*/ if(this_noterminal==NOTERMINAL_HEAD.next) *this_noterminal->FOLLOW='#'; while(this_production) { temp_result=this_production->result; /*一个产生式未结尾*/ while(*temp_result) { if(*temp_result!=this_noterminal->character) { temp_result++; continue; } temp_result++; if(!*temp_result) symbol=1; while(*temp_result) { if(is_appeared(*temp_result,terminal_all)) { terminal_array[0]=*temp_result; combine(this_noterminal->FOLLOW,terminal_array); } else { FOLLOW_TEMP=NOTERMINAL_HEAD.next; while(FOLLOW_TEMP->character!=*temp_result) FOLLOW_TEMP=FOLLOW_TEMP->next; combine(this_noterminal->FOLLOW,FOLLOW_TEMP->FIRST); help=this_noterminal->FOLLOW; while(*help&&*help!='^') help++; if(*help)/*包含'^'*/ { while(*help) { *help=*(help+1); help++; } symbol=1; } else { symbol=0; break; } } temp_result++; } if(symbol&&this_production->source!=this_noterminal->character) { FOLLOW_HELP=NOTERMINAL_HEAD.next; while(FOLLOW_HELP->character!=this_production->source) FOLLOW_HELP=FOLLOW_HELP->next; if(FOLLOW_HELP->follow_number==0) find_follow(FOLLOW_HELP,PRODUCTION_HEAD.next); combine(this_noterminal->FOLLOW,FOLLOW_HELP->FOLLOW); symbol=0; } } this_production=this_production->next; } this_noterminal->follow_number=strlen(this_noterminal->FOLLOW); return success; } /*紧急退出*/ void emergency(int model) { current_noterminal=NOTERMINAL_HEAD.next; current_terminal=TERMINAL_HEAD.next; current_production=PRODUCTION_HEAD.next; while(current_noterminal) { NOTERMINAL_HEAD.next=current_noterminal->next; free(current_noterminal->FIRST); free(current_noterminal->FOLLOW); free(current_noterminal); current_noterminal=NOTERMINAL_HEAD.next; } while(current_terminal) { TERMINAL_HEAD.next=current_terminal->next; free(current_terminal); current_terminal=TERMINAL_HEAD.next; } while(current_production) { PRODUCTION_HEAD.next=current_production->next; free(current_production->result); free(current_production); current_production=PRODUCTION_HEAD.next; } printf("退出成功\n"); exit(0); } /*插入到终结符*/ void insert_to_terminal(char get) { terminal *Temp_terminal=(terminal*)malloc(sizeof(terminal)); if(!Temp_terminal) { perror("can`t malloc for this program\n"); emergency(0); } Temp_terminal->character=get; Temp_terminal->next=NULL; current_terminal->next=Temp_terminal; current_terminal=Temp_terminal;/*移向下一个节点*/ return ; } /*插入到非终结符*/ void insert_to_noterminal(char get) { noterminal *Temp_noterminal=(noterminal*)malloc(sizeof(noterminal)); if(!Temp_noterminal) { perror("can`t malloc for this program\n"); emergency(0); } Temp_noterminal->character=get; Temp_noterminal->next=NULL; Temp_noterminal->FIRST=NULL; Temp_noterminal->FOLLOW=NULL; Temp_noterminal->first_number=0; Temp_noterminal->follow_number=0; current_noterminal->next=Temp_noterminal; current_noterminal=Temp_noterminal;/*移向下一个节点*/ return ; } /*插入到产生式*/ void insert_to_production(char source , char* result) { char TEMP[20]= {0}; int COUNT=0,number=0,length=0,exit_condition=strlen(result); production *Temp_production; for (COUNT=0; COUNT!=exit_condition+1; COUNT++) { if(*result=='-'&&*(result+1)=='>') { result+=2; COUNT+=2; } if((*result!='|')&&(*result)) TEMP[number++]=*result; else { Temp_production=(production*)malloc(sizeof(production)); length=strlen(TEMP)+1; Temp_production->result=(char* )malloc(length); memset(Temp_production->result,0,length); strncpy(Temp_production->result,TEMP,length-1); memset(TEMP,0,sizeof(TEMP)); Temp_production->source=source; Temp_production->next=NULL; current_production->next=Temp_production; current_production=Temp_production; number=0; } result++; } return ; } /*消除左递归*/ void eliminate_left_recursion(void) { int number=0; char new_char[3]= {0},TEMP_RESULT[20],temp_empty[3]= {'^',0,0}; production *Temp_production=PRODUCTION_HEAD.next; production *Temp_FREE; terminal *temp=TERMINAL_HEAD.next; while(Temp_production) { if(Temp_production->source==Temp_production->result[0]) { memset(TEMP_RESULT,0,sizeof(TEMP_RESULT)); new_char[0]=Temp_production->source-'A'+'a'; /*复制到新的产生式*/ strcat(TEMP_RESULT,Temp_production->result+1); strcat(TEMP_RESULT,new_char); insert_to_noterminal(new_char[0]); insert_to_production(new_char[0],TEMP_RESULT); insert_to_production(new_char[0],temp_empty); /*修改当前的产生式*/ memset(TEMP_RESULT,0,sizeof(TEMP_RESULT)); strcat(TEMP_RESULT,Temp_production->next->result); strcat(TEMP_RESULT,new_char); memset(Temp_production->result,0,strlen(Temp_production->result)); strncpy(Temp_production->result,TEMP_RESULT,strlen(TEMP_RESULT)); Temp_FREE= Temp_production->next; Temp_production->next=Temp_production->next->next; free(Temp_FREE); continue; } Temp_production=Temp_production->next; } while(temp) { terminal_all[number++]=temp->character; temp=temp->next; } return ; } void Test_read(void) { int number=1; production *TEMP_PRODUCTION=PRODUCTION_HEAD.next; terminal *TEMP_TERMINAL=TERMINAL_HEAD.next; noterminal *TEMP_NOTERMINAL=NOTERMINAL_HEAD.next; printf("\n产生式\n"); for(number=1; TEMP_PRODUCTION!=NULL; TEMP_PRODUCTION=TEMP_PRODUCTION->next,number++) { printf("%d\t%c\t%s\n",number,TEMP_PRODUCTION->source,TEMP_PRODUCTION->result); } printf("\n终结符\n"); for(; TEMP_TERMINAL!=NULL; TEMP_TERMINAL=TEMP_TERMINAL->next) { printf("%c\t",TEMP_TERMINAL->character); } printf("\n"); printf("\n非终结符\n"); for(; TEMP_NOTERMINAL!=NULL; TEMP_NOTERMINAL=TEMP_NOTERMINAL->next) { printf("%c\t",TEMP_NOTERMINAL->character); } printf("\n读取测试\n%s\n%s\n",TEST_LIST[0],TEST_LIST[1]); printf("\n"); return ; } size_t is_appeared(char tobejudged,char*source) { size_t length=strlen(source),counts=0; while((counts!=length)&&(*source!=tobejudged)) { counts++; source++; } return counts==length?!success: success; } void combine(char* destinction,char* source) { char temp[2]= {0}; while(*source) { if(!is_appeared(*source,destinction)) { temp[0]=*source; strcat(destinction,temp); } source++; } return ; } void prediction(void) { noterminal* TEMP_NOTERMINAL=NOTERMINAL_HEAD.next; while(TEMP_NOTERMINAL!=NULL) { find_first(TEMP_NOTERMINAL,PRODUCTION_HEAD.next); TEMP_NOTERMINAL=TEMP_NOTERMINAL->next; } test(); TEMP_NOTERMINAL=NOTERMINAL_HEAD.next; while(TEMP_NOTERMINAL!=NULL) { find_follow(TEMP_NOTERMINAL,PRODUCTION_HEAD.next); TEMP_NOTERMINAL=TEMP_NOTERMINAL->next; } return ; } void test_follow(void) { noterminal *TEMP_NOTERMINAL=NOTERMINAL_HEAD.next; for(; TEMP_NOTERMINAL!=NULL; TEMP_NOTERMINAL=TEMP_NOTERMINAL->next) { printf("%c\tfollow number=%d\tfollow=%s\n", TEMP_NOTERMINAL->character, TEMP_NOTERMINAL->follow_number, TEMP_NOTERMINAL->FOLLOW); } printf("\n"); return ; } void prediction_table(void) { int line=0,row=0,current_character=0,number=0; char* FIRST_CLUM,*test_exper; noterminal* temp_noterminal=NOTERMINAL_HEAD.next,*temp_noterminal21; terminal* temp_terminal=TERMINAL_HEAD.next; production* temp_production=PRODUCTION_HEAD.next; char hah[5][7]; memset(hah,0,sizeof(hah)); for(line=0; line<5; line++) { for(row=0; row<7; row++) hah[line][row]=0; } line=0; while(temp_production) { row=0; if(is_appeared(*temp_production->result,terminal_all)&&(*temp_production->result!='^')) { while(terminal_all[row]!=*temp_production->result) row++; hah[current_character][row]=line+1; } else { temp_noterminal=NOTERMINAL_HEAD.next; if(*temp_production->result=='^') { while(temp_noterminal->character!=temp_production->source) temp_noterminal=temp_noterminal->next; FIRST_CLUM=temp_noterminal->FOLLOW; if(is_appeared('#',FIRST_CLUM)) { row=0; while(terminal_all[row] != '#') row++; hah[current_character][row]=line+1; } while(*FIRST_CLUM) { row=0; while(terminal_all[row]!=*FIRST_CLUM) row++; hah[current_character][row]=line+1; FIRST_CLUM++; } if(temp_production->next&&temp_production->source!=temp_production->next->source) current_character++; temp_production=temp_production->next; line++; continue; } /*是非终结符*/ while(temp_noterminal->character!=*temp_production->result) temp_noterminal=temp_noterminal->next; FIRST_CLUM=temp_noterminal->FIRST; while(*FIRST_CLUM) { row=0; while(terminal_all[row]!=*FIRST_CLUM) row++; hah[current_character][row]=line+1; FIRST_CLUM++; } temp_noterminal21=NOTERMINAL_HEAD.next; while(temp_noterminal21->character!=temp_production->source) temp_noterminal21=temp_noterminal21->next; if(is_appeared('^',temp_noterminal->FIRST)&&is_appeared('#',temp_noterminal21->FOLLOW)) { row=0; while(terminal_all[row]!=*FIRST_CLUM) row++; hah[line][row]=line+1; FIRST_CLUM++; } } if(temp_production->next&&temp_production->source!=temp_production->next->source) current_character++; temp_production=temp_production->next; line++; } printf("\n预测分析表\n\n"); printf(" \t"); for(temp_terminal=TERMINAL_HEAD.next; temp_terminal; temp_terminal=temp_terminal->next) printf("%c\t",temp_terminal->character); temp_noterminal=NOTERMINAL_HEAD.next; for(line=0; line<5; line++) { printf("\n%c\t",temp_noterminal->character); for(row=0; row<7; row++) printf("%c\t",hah[line][row]==0?' ':(hah[line][row]-0+'0')); temp_noterminal=temp_noterminal->next; } printf("\n\n"); system("pause"); printf("\n\n"); memset(TEST_STACK,0,sizeof(TEST_STACK)); init_stack(); test_exper=TEST_LIST[0]; test_exper[strlen(test_exper)]='#'; STACK_PUSH(NOTERMINAL_HEAD.next->character); while(!STACK_EMPTY()) { printf("分析栈\t"); for(number=0; number<=amount; number++) printf("%c",TEST_STACK[number]); printf("\t剩余字符串\t%s\n",test_exper); if(TEST_STACK[amount]==*test_exper) { STACK_POP(); test_exper++; } else { line=0; row=0; temp_noterminal=NOTERMINAL_HEAD.next; while(temp_noterminal->character!=TEST_STACK[amount]) { temp_noterminal=temp_noterminal->next; line++; } while(terminal_all[row]!=*test_exper) row++; row=hah[line][row]; if(!row) break; temp_production=PRODUCTION_HEAD.next; while(--row) temp_production=temp_production->next; FIRST_CLUM=temp_production->result; current_character=strlen(FIRST_CLUM); FIRST_CLUM=FIRST_CLUM+current_character-1; STACK_POP(); while(current_character) { if(*FIRST_CLUM!='^') STACK_PUSH(*FIRST_CLUM); FIRST_CLUM--; current_character--; } } } printf("分析栈\t"); for(number=0; number<=amount; number++) printf("%c",TEST_STACK[number]); printf("\t剩余字符串\t%s\n",test_exper); if(STACK_EMPTY()&&*test_exper=='#') printf("\n合法输入\n"); else printf("\n不合法输入\n"); return ; } void STACK_POP(void) { if(STACK_EMPTY()) { printf("栈空\n"); emergency(2); } amount--; return ; } size_t STACK_EMPTY() { return amount==0? success:!success; } size_t STACK_FULL() { return amount==19? success:!success; } void STACK_PUSH(char source) { if(STACK_FULL()) { printf("栈满\n"); emergency(2); } TEST_STACK[++amount]=source; return ; } void init_stack(void) { amount=0; TEST_STACK[amount]='#'; return ; }
运行结果:
相关文章推荐
- 编译原理实验二——语法分析(预测分析)
- 编译原理(预测分析法)
- 编译原理语法分析
- 编译原理 - 递归向下法语法分析(Java版)
- 利用编译原理中的语法分析进行表达式求值
- [编译原理代码][NFA转DFA并最小化DFA并使用DFA进行词法分析]
- 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集
- 编译原理实验——预测分析法
- 编译原理实习(应用预测分析法LL(1)实现语法分析)
- [编译原理初探(一)]语法分析[1]
- 编译原理实现预测分析法(LL(1))
- 【编译原理】语法分析
- 编译原理实验三——语法分析(递归下降法)
- 编译原理程序设计实践(五) 语法分析的相关函数
- 【编译原理】语法分析(二)
- 【编译原理】语法分析(四)
- 哈工大编译原理实验2——语法分析
- 编译原理实习(应用预测分析法LL(1)实现语法分析)
- 在Windows平台使用flex和tcc进行编译原理-词法分析的实验环境搭建
- 编译原理课程设计_C--编译器_语法分析&代码生成