c语言实现一个简单的语法分析器
来源:互联网 发布:exe软件汉化工具 编辑:程序博客网 时间:2024/05/17 20:10
一、前言
接着上次的词法分析器,这次是语法分析器;
简单来讲,语法分析器要实现的功能就是分析一个程序段是否是合法的,依据就是文法;我们依旧采取词法分析器的littleP文法来分析。大型的语法分析器,都是会提示多处错误,我就只实现了遇到一处错误就报错的策略,这样更加容易一些;
二、源代码以及注释:
/*待分析的简单语言的语法用扩充的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);//因式 factorvoid expression(void);//表达式 expressionvoid yucu(void);void term(void);//项 termvoid statement(void);// 语句 statementvoid 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=0printf("success!\n");}else{if(flag!=1) printf("the string haven't got a 'end'!\n");//flag来判断是否endflag=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;//数字初始化为0for(m=0;m<8;m++)//初始化tokentoken[m++]=NULL;m=0;//m为token的指针ch=prog[p++];//数组指针+1while(ch==' ')//遇到空格+1ch=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--;//循环跳出,要-1syn=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为数字}/*除数字和字母开头以外的其他符号*/elseswitch(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;}}
三、种别码
四、测试程序代码
begin a:=9; x:=2*3; b:=a+x end #
此代码是符合文法的,将会输出success;
x:=a+b*c end #
此代码因缺少begin,所以将会报错!
五、运行效果
0 0
- c语言实现一个简单的语法分析器
- 深入浅出编译原理-5-一个简单语法分析器的C语言实现
- c语言词法分析器的一个简单实现
- 一个简单词法分析器的C语言实现
- C语言实现一个简单的词法分析器
- 语法分析器C语言实现
- 一个简单C语言的词法分析器
- c语言词法分析器的简单实现
- C++写的一个简单的语法分析器(分析C语言)
- 一个简单的C语言词法分析与语法分析器【原】
- 一个语法分析器的实现
- 基于c语言的语法分析器的实现
- C语言的语法分析器——java实现
- java实现C语言子集的语法分析器
- 深入浅出编译原理-4-一个简单词法分析器的C语言实现
- 一个简单的SLR语法分析器
- 用C语言实现简单的词法分析器
- 简单的语法分析器
- java开发环境搭建
- handler机制的原理
- Winform子窗体刷新父窗体
- java得到类信息的代码演示
- Qt学习笔记01
- c语言实现一个简单的语法分析器
- 1、CommonUtils.uuid()和CommonUtils.toBean(map, Person.class)
- 项目起不来解决方案
- 项目-两个成员的类模板将类声明改为类模板声明,使得数据成员data1和data2可以是任何类型
- spring 使用注解获取properties 文件属性值
- 求特征值
- static linked list(静态链表,结合数组实现)
- 项目-数组类模板在数组类的基础上,将之改造为类模板,以使数组中可以存储各种类型的数据
- 项目-两个成员的类模板为该类增默认构造函数、带两个参数分别对应两个数据成员初值的构造函数,以及复制构造函数