编译原理实验 —— 语法分析器

/*
待分析的简单语言的语法
用扩充的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);//因式 factor
void expression(void);//表达式 expression
void yucu(void);
void term(void);//项 term
void statement(void);// 语句 statement
void 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=0
			printf("success!\n");
		}
		else
		{
			if(flag!=1) printf("the string haven‘t got a ‘end‘!\n");//flag来判断是否end
			flag=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;//数字初始化为0

	for(m=0;m<8;m++)//初始化token
		token[m++]=NULL;

	m=0;//m为token的指针
	ch=prog[p++];//数组指针+1

	while(ch==‘ ‘)//遇到空格+1
		ch=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--;//循环跳出,要-1
		syn=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为数字
	}

	/*除数字和字母开头以外的其他符号*/
	else
	switch(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;
	}
}

  

原文地址:https://www.cnblogs.com/zili/p/9900389.html

时间: 2024-11-08 21:29:45

编译原理实验 —— 语法分析器的相关文章

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

编译原理 - 实验三 - 递归下降语法分析器的调试及扩展

一. 语法分析介绍 语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备.执行语法分析任务的程序叫语法分析程序或语法分析器. 二. 所实现的语义分析和代码生成程序能处理什么语句 (1)简单变量的声明语句 (2)表达式语句 (3)if语句. (4)while语句 (5)for语句 (6)write语句 (7)read语句 (8)do语句. (9)处理过程调用和返回 三.实验过程 ①用VC

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

必要的软件架构师——编译原理&amp;#183;语法

最近软测试.我观看进程的视频! 发现里面有很多内容已经在自我不错的接触过程.而占80%比例! 但其中的一部分.我很奇怪的一部分.研究,在这里,将我研究的内容整理分享给大家! 编译原理: 首先,我第一眼看到他的时候.认为这是个特神奇的科学知识! 里面应该有非常多难点.可是.我的愿望达到了,前两次看书都有点云里雾里的感觉.可是随着接触的深入,视频,书籍,网络三方面的共同攻击下,这个神奇的东西,变得不神奇了. 编程语言的发展.我们只是多介绍.想了解的,能够去看这个站点"编程语言发展历史".我

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

编译原理实验:java实现语法分析器

实验方法:递归下降分析法基本思想是,对文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分.因此需要分别构造 E,E’,T,T’,F 函数来执行自己的识别功能,根据文法的内容顺序决定函数的识别功能. java程序实现: import java.util.Scanner; public class GrammarAnalysis { static char[] s = new char[100]; static int sing; static int i; //用来

编译原理 实验2 DFA的运行

DFA的运行 一. 实验目的 1.理解有穷自动机的作用: 2.利用状态图和状态表表示有穷自动机: 3.以程序实现有穷自动机的运行过程; 4.利用状态表和有穷自动机的运行原理编制程序,使得程序能够识别一个输入串是否为一个有效的符号串.具体可以选择下面之一:无符号定点实数,无符号正偶数,自然数,整数,十六进制数,或其他自己定义的符号串. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 1.简单介绍你所设计的有穷自动机.(要求必须完成无符