实验要求
根据给出的简单语言的语法构成规则(见下面),编制LL(1)语法分析器,要在词法分析输出的单词基础上进行语法分析,输出相应的语法分析结果和错误信息。
E->E+T|E-T|T
T->T*F|T/F|F
F->(E)|i
上式中, i 为整数或标识符,对于整数和标识符的识别可以借助实验1。
关于错误信息:不要求错误种类,只需给出出错位置。
代码中的函数
open_inputf():打开input.txt
● void inf_nextc(): 读入文件的内容-若是空,返回0
int is_number(char number):判断是否为整常量,是的话返回1
int is_oper(char letter): //暂时猜测:判断是不是±/()这几个符号,是的话返回1
//cq猜测:判断当前列有无对应的文法,如果有则返回当前第几列
int is_endc()://是不是±/() i 这几个符号–终结符,是的话返回1
● int str_put_stack() :入栈(字符栈),如果是整常量,i入栈。同时把我们输入的2+33转为i+i3(即转为一般化)
char get_str_stack_top():获取栈顶元素
char out_str_stack():出栈(字符栈)
char out_analy_stack() :出栈(分析栈)
void put_analy_stack(char letter):入栈(分析栈)
● get_product_form(): 有横纵坐标,返回预测表对应的产生式
open_LL1analyf():将input.txt内容读入分析器
● LL1_analy():预测分析过程,先把#E压入栈中,导序入栈—如果抽到我们的话,我觉得主要回报的就是栈的弹出和进入
-
如果分析栈-字符栈一样的话,这可以是字符栈输出,
-
分析栈-字符栈都为#作为栈顶—>分析正确
-
如果得到的分析栈顶不是终结符的话,则查二维表(横坐标是自己,纵坐标是字符栈顶),strcmp(相等才是0),只有二者(product_form与“1”即无产生式)相等时候才会提示分析储出错。当既不是1也不是0时,将其逆序压入分析栈。
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define analy_stack_cap 30
#define str_stack_cap 30
#define row_num 5
#define col_num 8
char ch;
char analy_stack_top;
const char* product_form;
int str_stack_content_num, str_stack_current_num;
char str_stack[str_stack_cap];
int analy_stack_current_num=2;
char analy_stack[analy_stack_cap]={'#', 'E'};
const char fat_row[]={'E', 'A', 'T', 'B', 'F'};
const char fat_col[]={'i', '+', '-', '*', '/', '(', ')', '#'};
const char* const forecast_analy_table[row_num][col_num]={
{"TA", "1", "1", "1", "1", "TA", "1", "1"},
{"1", "+TA", "-TA", "1", "1", "1", "0", "0"},
{"FB", "1", "1", "1", "1", "FB", "1", "1"},
{"1", "0", "0", "*FB", "/FB", "1", "0", "0"},
{"i", "1", "1", "1", "1", "(E)", "1", "1"}
};
int error_location=1;
FILE *inputf, *LL1f;
void open_inputf(){
if((inputf=fopen("input.txt", "r"))==NULL){
printf("打开input失败\n");
exit(0);
}
}
void inf_nextc(){
if((ch=fgetc(inputf))==EOF){
ch=0;
}
}
int is_number(char number){
if(ch>=48 && ch<=57)
return 1;
return 0;
}
int is_oper(char letter){
int col=0;
for(int i=1; i<col_num-1; i++){
if(fat_col[i]==letter){
col=1;
break;
}
}
return col;
}
int is_endc(char letter){
int endc_mark=0;
for(int i=0; i<col_num-1; i++){
if(fat_col[i]==letter){
endc_mark=1;
break;
}
}
return endc_mark;
}
int str_put_stack(){
int i=0, result=0;
inf_nextc();
began:
if(ch==' '){
inf_nextc();
goto began;
}else if(is_number(ch)){
if(ch!='0'){
do{
inf_nextc();
}while(is_number(ch));
}else{
inf_nextc();
if(is_number(ch)){
printf("扫描至 %d 行\n", error_location);
return result;
}
}
if(ch=='.'){
inf_nextc();
if(is_number(ch))
do{
inf_nextc();
}while(is_number(ch));
else{
printf("扫描至 %d 行\n", error_location);
return result;
}
}
str_stack[i++]='i';
goto began;
}else if(is_oper(ch) ){
str_stack[i++]=ch;
inf_nextc();
goto began;
}else if(ch=='#'){
str_stack[i++]=ch;
do{
inf_nextc();
}while(ch==' ');
if(ch=='\n'){
error_location++;
}
str_stack_current_num=str_stack_content_num=i;
printf("第 %d 行扫描完成\n", error_location-1);
result=1;
}else{
printf("全文扫描至 %d 行\n", error_location);
}
return result;
}
char get_str_stack_top(){
return str_stack[str_stack_content_num-str_stack_current_num];
}
char out_str_stack(){
char letter=str_stack[str_stack_content_num-str_stack_current_num--];
str_stack[str_stack_content_num-str_stack_current_num-1]=' ';
return letter;
}
char out_analy_stack(){
char letter=analy_stack[--analy_stack_current_num];
analy_stack[analy_stack_current_num]=0;
return letter;
}
void put_analy_stack(char letter){
analy_stack[analy_stack_current_num++]=letter;
}
const char* get_product_form(char rowc, char colc){
int row=0, col=0;
for(; row<row_num; row++)
if(fat_row[row]==rowc)
break;
for(; col<col_num;col++)
if(fat_col[col]==colc)
break;
return forecast_analy_table[row][col];
}
void open_LL1analyf(){
if((LL1f=fopen("LL1.txt", "w"))==NULL){
printf("打开LL1.txt失败");
exit(0);
}
}
int LL1_analy(){
int i=1;
fprintf(LL1f, " %4s %14s %15s %13s\n", "步骤", "分析栈", "剩余输入串", "所用产生式");
began:
ch=get_str_stack_top();
abegan:
analy_stack_top=out_analy_stack();
if(is_endc(analy_stack_top)){
if(analy_stack_top==ch){
fprintf(LL1f, " %-4d %13s%c %15s %c %-5s\n", i, analy_stack, analy_stack_top, str_stack, ch, "匹配");
out_str_stack();
i++;
goto began;
}else{
fprintf(LL1f, " %-4d %13s%c %15s %s\n", i, analy_stack, analy_stack_top, str_stack, "出错,终止");
printf("语法错误,程序终止\n");
}
}else{
if(analy_stack_top=='#'){
if(analy_stack_top==ch){
fprintf(LL1f, " %-4d %13s%c %15s %s\n", i, analy_stack, analy_stack_top, str_stack, "接受");
analy_stack[0]='#';
analy_stack[1]='E';
analy_stack_current_num=2;
memset(str_stack, 0, sizeof(str_stack));
printf("语法正确\n");
return 1;
}else{
fprintf(LL1f, " %-4d %13s%c %15s %s\n", i, analy_stack, analy_stack_top, str_stack, "出错,终止");
printf("语法错误,程序终止\n");
}
}else{
product_form=get_product_form(analy_stack_top, ch);
if(strcmp(product_form, "1")){
fprintf(LL1f, " %-4d %13s%c %15s %c%s%s\n", i, analy_stack, analy_stack_top, str_stack, analy_stack_top, "->", product_form);
i++;
if(strcmp(product_form, "0")){
int num=strlen(product_form);
while(num--){
put_analy_stack(product_form[num]);
}
}
goto abegan;
}else{
fprintf(LL1f, " %-4d %13s%c %15s %s\n", i, analy_stack, analy_stack_top, str_stack, "出错,终止");
printf("语法错误,程序终止\n");
}
}
}
return 0;
}
int main(){
open_inputf();
open_LL1analyf();
while(str_put_stack()){
if(LL1_analy()){
}else{
getchar();
break;
}
}
fclose(LL1f);
fclose(inputf);
return 1;
}
修改下路径即可