编译原理---语法分析

语法分析

词法分析程序的报告因为提前上交的原因导致没有报告,这次倒是留了报告。

思路:

  • 语法分析程序就是在词法分析程序的基础上进行语法分析,查看是否合理
  • 词法分析的结果应该是将 标识符、数字、关键字、逐一分开
  • 到了词法分析程序里面 即使将这些存储起来 ,在逐一分析是否合理
  • 这个程序里面有个小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 ;
}

这个程序中,每一个函数都设置了一个输出,可自行删减。
这个程序中用到的递归比较多,用输出方便查看到哪一步
附加报告 : 语法分析报告

这个代码是接着我的另一篇文章 词法分析 而来的,建议先看懂代码.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python小叮当

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值