语法分析
词法分析程序的报告因为提前上交的原因导致没有报告,这次倒是留了报告。
思路:
- 语法分析程序就是在词法分析程序的基础上进行语法分析,查看是否合理
- 词法分析的结果应该是将 标识符、数字、关键字、逐一分开
- 到了词法分析程序里面 即使将这些存储起来 ,在逐一分析是否合理
- 这个程序里面有个小bug–没有设置数字的范围
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define _KEY_WORD_END "waiting for your expanding" /*定义结束关键字*/
#define MAX_SIZE 225
typedef struct {
int typenum;
char *word;
}WORD;
typedef struct{
int num;
char arr[MAX_SIZE];
}res_word;
res_word Word[MAX_SIZE]; //存放词法分析结果
int len = 0; //作为遍历word[]的长度标记
WORD *scanner(); //词法扫描函数,获得一个单词
char m_getch(); //从输入缓存区读取一个字符到ch中
void getbc(); //去掉空白部分
void concat(); //拼接单词
int letter(); //判断是字母
int digit(); //判断是数字
int reserve(); //检索关键字表格
void retract(); //回退一个字符
char *dtb(); //数字转换成二进制(暂时没有任何的功能)
void lrparser(); //单词分析主函数
void yucu(); //语句串分析函数
void statement(); //标识符和复制语句分析函数
void expression(); //表达式分析函数
void term(); //乘除号分析函数
void factor(); // 标识符 或者 数字 以及 左右括号分析函数
void main_L(); //给syn赋初值 且 调用语法分析主函数 lrparser();
void backgetword(); //回退一个单词
char input[MAX_SIZE]; //输入缓冲区
char token[MAX_SIZE]=""; //单词缓冲区
int p_input; //输入缓冲区指针
int p_token; //单词缓冲区指针
int kk = 0;
int syn;
/*
单词符号 种别码 单词符号 种别码 单词符号 种别码
bengin 1 if 2 then 3
while 4 do 5 end 6
main 7 int 8 float 9
for 10 else 11 double 12
char 13 break 14 continue 15
标识符 16 整数 17 + 18
- 19 * 20 # 21
% 22 != 23 < 24
<> 25 <= 26 > 27
>= 28 = 29 == 30
; 31 ( 32 ) 33
! 34 / 35 " 36
{ 37 } 38 := 39
: 40
程序能识别注释,且将其过滤掉
*/
char ch; //当前读入字符
char * rwtab[] = {"begin","if","then","while","do","end","main","int","float","for","else","double","char","break","continue","printf"} ;
int main(){
int i = 0;
int over = 1;
WORD * oneword = new WORD;//已经测试可以使用 new(。cpp)
printf("Enter your words(end with $):\n");
// freopen("in.txt","r",stdin);
scanf("%[^$]s",input);
p_input = 0;
while(over < 2000&& over != -1){
oneword = scanner(); //获得一个单词
if(oneword->typenum < 1000){
// printf("% d % s\n",oneword->typenum,oneword->word);//打印种别码和自生的值
strcpy(Word[i].arr,oneword->word);
Word[i].num = oneword->typenum;
i++;
}
over = oneword->typenum;
}
main_L();
printf("\n press $ to exit:");
scanf("%[^$]s",input);
return 0;
}
char m_getch(){ //从输入缓存区读取一个字符到ch中
ch = input[p_input];
p_input = p_input + 1;
return (ch);
}
void getbc(){ //去掉空白部分
while(ch==' '||ch == 10){
ch = input[p_input];
p_input += 1;
}
}
void concat(){ //拼接单词
token[p_token] = ch;
p_token += 1;
token[p_token] = '\0';
}
int letter(){ //判断是字母
if(ch >= 'a'&&ch <= 'z'||ch >= 'A'&&ch <= 'Z') return 1;
return 0;
}
int digit(){ //判断是数字
if(ch >= '0'&&ch <= '9')return 1;
else return 0;
}
int reserve(){ //检索关键字表格
int i = 0;
while(strcmp(rwtab[i],_KEY_WORD_END)){
if(!strcmp(rwtab[i],token)){
return (i + 1);
}
if(i>strlen(*rwtab)) break;
i = i + 1;
}
return 16;
}
void retract(){ //回退一个字符
p_input = p_input - 1;
}
char *dbt(){ //数字转换成二进制
return NULL;
}
WORD *scanner(){
WORD *myword = new WORD;
myword->typenum = 10;
myword->word = "";
p_token = 0;
m_getch();
getbc();
if(letter()){
while(letter()||digit()){
concat(); //拼接单词
m_getch(); //从输入缓存区读取一个字符到ch中
}
retract(); //回退一个字符
myword->typenum = reserve();
myword->word = token;
return (myword);
}
else if(digit()){
while(digit()){
concat();
m_getch();
}
retract();
myword->typenum = 17;
myword->word = token;
return (myword);
}
else switch(ch){
case '+': myword->typenum = 18;
myword->word = "+";
return (myword);
break;
case '-': myword->typenum = 19;
myword->word = "-";
return (myword);
break;
case '*': myword->typenum = 20;
myword->word = "*";
return (myword);
break;
case '#': myword->typenum = 21;
myword->word = "#";
return (myword);
break;
case '%': myword->typenum = 22;
myword->word = "%";
return (myword);
break;
case ';': myword->typenum = 31;
myword->word = ";";
return (myword);
break;
case '(': myword->typenum = 32;
myword->word = "(";
return (myword);
break;
case ')': myword->typenum = 33;
myword->word = ")";
return (myword);
break;
case '!': m_getch();
if(ch == '='){
myword->typenum = 23;
myword->word = "!=";
return (myword);
}
retract();
myword->typenum = 34;
myword->word = "!";
return (myword);
break;
case '<': m_getch();
if(ch == '='){
myword->typenum = 26;
myword->word = "<=";
return (myword);
}
if(ch == '>'){
myword->typenum = 25;
myword->word = "<>";
return (myword);
}
retract();
myword->typenum = 24;
myword->word = "<";
return (myword);
break;
case '>': m_getch();
if(ch == '='){
myword->typenum = 28;
myword->word = ">=";
return (myword);
}
retract();
myword->typenum = 27;
myword->word = ">";
return (myword);
break;
case ':': m_getch();
if(ch=='='){
myword->typenum = 39;
myword->word = ":=";
return myword;
}
retract();
myword->typenum = 40;
myword->word = ":";
return myword;
case '=': m_getch();
if(ch == '='){
myword->typenum = 30;
myword->word = "==";
return (myword);
}
retract();
myword->typenum = 29;
myword->word = "=";
return (myword);
break;
case '{': myword->typenum = 37;
myword->word = "{";
return myword;
break;
case '}': myword->typenum = 38;
myword->word = "}";
return myword;
break;
case'\0': myword->typenum=2001; //当读取到最后一个字符串的时候 ,为 \0 ,程序会当成无法辨别的程序,故而需要一个case来处理
myword->word="OVER";
return(myword);
break;
case '/': m_getch();
if(ch == '*'){
while(1){
m_getch();
if(ch == '*'){
m_getch();
if(ch == '/')
break;
}
}
myword->typenum = 1001;
myword->word = NULL;
return (myword);
}
else if(ch == '/'){
while(1){
m_getch();
if(ch == '\n')
break;
}
myword->typenum = 1000;
myword->word = NULL;
return (myword);
}
retract();
myword->typenum = 35;
myword->word = "/";
return (myword);
break;
case '"': myword->typenum = 36;
myword->word = " “";
return (myword);
break;
default: myword->typenum = -1;
myword->word = "ERROR";
return (myword);
}
}
void main_L(){ //给syn赋初值 且 调用语法分析主函数 lrparser();
syn = Word[len].num;
lrparser();
}
void getword(){ //从数组中拿到一个单词或符号
len++;
syn = Word[len].num;
}
void backgetword(){ //回退一个单词
len--;
}
void lrparser(){ //单词分析主函数
if(syn == 1){ //判断是否为begin
printf("\nbegin判断成功!种别码:%d 单词:%s\n",syn,Word[len].arr);
getword();
yucu();
if(syn == 6){ //判断是否为end
printf("\nend判断成功!种别码:%d 单词:%s\n",syn,Word[len].arr);
if(syn == 6)
printf("succcess\n");
}
else{
printf("error: 缺end\n");
}
}
else printf("error: 缺失begin\n");
return ;
}
void yucu(){ //语句串分析函数
statement();
while(syn == 31){ //判断是否为分号
getword();
printf("分号判断正确!种别码:%d 单词:%s\n",syn,Word[len].arr);
statement();
}
return ;
}
void statement(){ //标识符和复制语句分析函数
if(syn == 16){ //标识符
printf("标识符判断成功!种别码:%d 单词:%s\n",syn,Word[len].arr);
getword();
if(syn == 39){ // :=
printf("赋值号判断成功!种别码:%d 单词:%s\n",syn,Word[len].arr);
getword();
printf("获得了什么》》种别码:%d 单词:%s\n",syn,Word[len].arr);
expression();
}
else{
printf("复制号错误\n");
}
}
else {
printf("输出语句错误\n");
backgetword();
}
return ;
}
void expression(){ //表达式分析函数
term();
while(syn == 18 || syn == 19){ // + -
getword(); //读取下一个单词
term();
}
return ;
}
void term(){ //乘除号分析函数
factor();
while(syn == 20||syn == 35){ // * /
printf("乘除号判断正确!种别码:%d 单词:%s\n",syn,Word[len].arr);
getword();
factor();
}
return ;
}
void factor(){ // 标识符 或者 数字 以及 左右括号分析函数
if(syn == 16 || syn == 17){ //标识符 或者 数字
printf("标识符 或者 数字 判断正确!种别码:%d 单词:%s\n",syn,Word[len].arr);
getword();
printf("factor获得了什么->种别码:%d 单词:%s\n",syn,Word[len].arr);
}
else if(syn == 32){ // (
printf("左括号判断正确!种别码:%d %s\n",syn,Word[len].arr);
getword();
expression();
if(syn == 33){ // )
getword();
}
else {printf("输出 ‘)’错误\n"); kk = 1;}
}
else {printf("输出表达式错误\n"); kk = 1;}
return ;
}
这个程序中,每一个函数都设置了一个输出,可自行删减。
这个程序中用到的递归比较多,用输出方便查看到哪一步
附加报告 : 语法分析报告
这个代码是接着我的另一篇文章 词法分析 而来的,建议先看懂代码.