编译原理之语法分析(自顶向下递归下降法 Pl/0语言文法 打印语法树)

 先调用词法分析程序后将单词保存到一个全局的字符串数组result中,并声明全局int变量ip,指向当前的单词下标,然后调用程序函数,即可完成一步步的递归,最后分析出能否规约为一颗语法树。

 

下面的代码是语法分析部分:

/函数声明
void subProgram();
void conExplain();
void varExplain();
void processExplain();
void constDef();
void statement();
void varExplain();
void id();
void unsInt();
void dig();
void processHead();
void AssignmentStatement();
void expression();
void CompoundStatement();
void conditions();
void AddAndSubtract();
void item();
void factor();
void MULAndDIV();
void ConditionStatement();
void relationship();
void processCall();
void readStatement();
void dowhile();
void writeStatement();

void  program()//程序
{
	ip = 0;
	subProgram();
	
	if (result[ip] == ".")
	{
		ip++;
		cout << "成功";
	}
	else
		exit(0);
}

void subProgram()//分程序
{
	
	//常量说明部分
	if (result[ip] == "const")
	{
		conExplain();
	}
	//变量说明部分
	if (result[ip] == "var")
	{
		varExplain();
	}
	//过程说明部分
	if (result[ip] == "procedure")
	{
		processExplain();
	}
	statement();//语句
}
void conExplain()//常量说明部分
{
	if (result[ip] == "const")
	{
		ip++;
		constDef();
		while (result[ip] == ",")
		{
			ip++;
			constDef();
		}
		if (result[ip] == ";")
		{
			ip++;
		}
		else
			exit(0);
	}
	else
		exit(0);
}
void varExplain()//变量说明语句
{
	if (result[ip] == "var")
	{
		ip++;
		id();
		while (result[ip] == ",")
		{
			ip++;
			id();
		}
	
	   if (result[ip] == ";")
		   ip++;
	   else
		   exit(0);
	}
	else
		exit(0);
}
void processExplain()//过程说明部分
{
	processHead();
	subProgram();
	if (result[ip] == ";")
	{
		ip++;
		while (result[ip]=="procedure")
		{
			
			processExplain();
		}
	}
	    else
			exit(0);
}
void statement()//语句
{
	if (isexists(result[ip]))//赋值语句
		AssignmentStatement();
	else if (result[ip] == "if")//条件语句
		ConditionStatement();
	else if (result[ip] == "while")//当型循环
		dowhile();
	else if (result[ip] == "call")//过程调用
		processCall();
	else if (result[ip] == "read")//读语句
		readStatement();
	else if (result[ip] == "write")//写语句
		writeStatement();
	else if (result[ip] == "begin")//复合语句
		CompoundStatement();
	
}
void constDef()//常量定义
{
	id();
	if (result[ip] == "=")
	{
		ip++;
		unsInt();
	}
	else
		exit(0);
}

void id()//标识符
{
	if (isexists(result[ip]))
		ip++;
	else
		exit(0);
}
void unsInt()//无符号整数
{
	if (isexistc(result[ip]))
		ip++;
	else
		exit(0);
}

void dig()//数字
{
	if (result[ip].at(0) <= 57 && result[ip].at(0) >= 48)
	{
		ip++;
	}
	else
		exit(0);
}
void processHead()//过程首部
{
	if (result[ip] == "procedure")
	{
		ip++;
		id();
		if (result[ip] == ";")
			ip++;
		else
			exit(0);
	}
	else
		exit(0);
}
void AssignmentStatement()//赋值语句
{
	id();
	if (result[ip] == ":=")
	{
		ip++;
		expression();
	}
	else
		exit(0);
}
void expression()//表达式
{
	if (result[ip] == "+" || result[ip] == "-")
	{
		ip++;
	}
	item();
	while (result[ip] == "+" || result[ip] == "-")
	{
		AddAndSubtract();
		item();
	}
	
}
void CompoundStatement()//复合语句
{
	if (result[ip] == "begin")
	{
		ip++;
		statement();
		while (result[ip] == ";")
		{
			ip++;
			statement();

		}
		if (result[ip] == "end")
		{
			ip++;
		}
		else
			exit(0);
	}
	else
		exit(0);

}
void conditions()//条件
{ 
	
	 if (result[ip] == "odd")
	{       
                ip++;
		expression();
	}
	 else 
	{
		expression();
		relationship();
		expression();
	}
}
void item()//项
{
	factor();
	while (result[ip]=="*"|| result[ip] == "/")
	{
		MULAndDIV();
		factor();
	}
}
void factor()//因子
{
	if ((result[ip].at(0) <= 122 && result[ip].at(0) >= 97))
	{
		id();
	}
	else if ((result[ip].at(0) <= 57 && result[ip].at(0) >= 48))
	{

		unsInt();
	}
	else if ((result[ip] == "("))
	{

		expression();
		if (result[ip] == ")")
			ip++;
		else
			exit(0);
 	}
	else
		exit(0);

}
void AddAndSubtract()//加减运算符
{
	if (result[ip] == "+" || result[ip] == "-")
	{
		ip++;
	}
	else
		exit(0);
}
void MULAndDIV()//乘除运算符
{
	if (result[ip] == "*" || result[ip] == "/")
	{
		ip++;
	}
	else
		exit(0);
}
void relationship()//关系运算符
{
	if (result[ip] == "=" || result[ip] == "#"||result[ip]=="<"|| result[ip] == "<="||result[ip] == ">"
		||result[ip] == ">=")
	{
		ip++;
	}
	else
		exit(0);
}
void ConditionStatement()//条件语句
{
	if (result[ip] == "if")
	{
		ip++;
		conditions();
		if (result[ip] == "then")
		{
			ip++;
			statement();
		}
		else
			exit(0);
	}
	else
		exit(0);
}
void processCall()//过程调用语句
{
	if (result[ip] == "call")
	{
		ip++;
		id();
	}
	else
		exit(0);
}
void dowhile()//当型循环
{
	if (result[ip] == "while")
	{
		ip++;
		conditions();
		if (result[ip] == "do")
		{
			ip++;
			statement();
		}
		else
			success = 0;
	}
	else
		exit(0);
}
void readStatement()//读语句
{
	if (result[ip] == "read")
	{
		ip++;
		if (result[ip] == "(")
		{
			ip++;
			id();
			while (result[ip] == ",")
			{
				ip++;
				id();

			}
			if (result[ip] == ")")
				ip++;
			else
				exit(0);

		}
		else
			exit(0);
	}
	else
		exit(0);
}
void writeStatement()//写语句
{

	if (result[ip] == "write")
	{
		ip++;
		if (result[ip] == "(")
		{
			ip++;
			expression();
			while (result[ip] == ",")
			{
				ip++;
				expression();

			}
			if (result[ip] == ")")
				ip++;
			else
				exit(0);

		}
		else
			exit(0);
	}
	else
		exit(0);
}

 

 

这里是完整的词法分析加语法分析:

#pragma once
#include<iostream>
#include<string>
#include <fstream>
#include <sstream>
#include<Windows.h>
bool success = 1;
using namespace std;
char ch;//字符变量,存放最新读进的源程序字符
char strToken[100];//字符数组,存放构成单词符号的字符串
int len = 0;//记录字符串的长度
string klabel[29] = { "+","-","*","/","=","#","<","<=",">",">=",",",";",":=","(",")",".","const","var","procedure","begin","end","odd","if","then","call"
,"while","do","read","write" };
string slabel[100] = {};
string  clabel[100] = {};
string  result[100] = {};
int ip = 0;
int slen = 0;//标识符表的下标
int clen = 0;//常量表的下标
			 //判断是否为数字
const char *input;
int index = 0;
bool isDigit()
{
	if (ch < 58 && ch >= 48)
		return true;
	else
		return false;
}
//判断是否为小写字母
bool issLetter()
{
	if (ch <= 122 && ch >= 97)
		return true;
	else
		return false;
}
bool isDigit(char ch1)
{
	if (ch1 < 58 && ch1 >= 48)
		return true;
	else
		return false;
}

//判断是否为小写字母
bool issLetter(char ch1)
{
	if (ch1 <= 122 && ch1 >= 97)
		return true;
	else
		return false;
}
//判断是否为大写字母
bool islLetter()
{
	if (ch <= 90 && ch >= 65)
		return true;
	else
		return false;
}
//将下一输入字符读到ch中
void GetChar()
{
	ch = input[index];
	index++;

}
//判断ch中是否是空白,若是,则调用GetChar直至读入下一个非空白的字符
void GetBC()
{
	while (ch == 32)
		GetChar();
}
//将ch中的字符连接到strToken之后
void concat()
{
	strToken[len] = ch;
	len++;
}
//对strToken中的字符串查找保留字表,若他是一个保留字则返回则返回他的编码,否则返回0值
int Reserve()
{

	for (int i = 0; i < 29; i++)
	{
		/*const char *p = klabel[i].data();
		if (strcmp(p,strToken)==0)
		{
		return i;
		}*/
		if (klabel[i] == strToken)
			return i;
	}
	return -1;
}
//将搜索指示器回调一个字符位置
void Retract()
{
	index--;
	ch = 32;
}
//将strToken中的标识符插入到符号表
int insertId()
{
	slabel[slen] = strToken;
	slen++;
	return slen - 1;
}
//将strToken中的常数插入到常数表
int insertConst()
{
	clabel[clen] = strToken;
	clen++;
	return clen - 1;
}
string readFileIntoString(char * filename)
{
	ifstream ifile(filename);
	//将文件读入到ostringstream对象buf中
	ostringstream buf;
	char ch;
	while (buf&&ifile.get(ch))
		buf.put(ch);
	//返回与流对象buf关联的字符串
	return buf.str();
}
//检测是否已经存在此标识符
int isexists(string str)
{
	for (int i = 0; i < slen; i++)
		if (str == slabel[i])
			return 1;

	return 0;
}
//检测是否已经存在此常量
int  isexistc(string con)
{
	for (int i = 0; i < clen; i++)
		if (con == clabel[i])
			return 1;
	return -1;
}
int isexists()
{
	for (int i = 0; i < slen; i++)
		if (strToken == slabel[i])
			return i;

	return -1;
}
//检测是否已经存在此常量
int  isexistc()
{
	for (int i = 0; i < clen; i++)
		if (strToken == clabel[i])
			return i;
	return -1;
}
//名字表的结构体
struct symbel
{
	string name;
	string kind;
	int level;
	int addr;
	int value;
}symlabel;
//判断是否退出

//主程序
void lex(string file1)
{
	int code, value, num = 0;
	/*cout << "请输入单词长度"<<endl;
	cin >> num;
	cout << "请输入单词:"<<endl;
	cin >> input;*/
	//char filename[] = "test.txt";
	//const char *file = readFileIntoString(filename).data();
	std::ifstream in(file1);
	std::ostringstream tmp;
	tmp << in.rdbuf();
	std::string str = tmp.str();
	cout << str << endl;
	for (int i = 0; i < str.length(); i++)//如果输入中有大写字母࿰
  • 11
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值