语法分析器

#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
#define #      -1
#define ERROR   -2
#define variable       1
#define integer  2
#define decimal  3
#define plus     4
#define minus    5
#define multiply  6
#define divide      7
#define LP       8
#define RP       9
struct Tree
{
	int type = 0;
	string detail;
	Tree *lchild = nullptr;
	Tree *rchild = nullptr;
};


#include "data.h"
FILE * file;
string curtoken;
int curtokenType;
string nexttoken;
int nexttokenType;
bool right=true;
void getToken();
Tree* getExpression();
Tree* getTerm();
Tree* getFactor();
void traversal(Tree *root,int &i,int &j)//只能后序
{
	if (root)
	{
		if (!root->lchild&&!root->rchild)//如果该结点是叶子结点
		{
			cout << root->detail;
		}
		//如果左孩子是叶子,右孩子不是
		else if (!root->lchild->lchild&&!root->lchild->rchild&&root->rchild->lchild&&root->rchild->rchild)
		{
			
			traversal(root->rchild, i,j);
			traversal(root->lchild, i,j);
			cout << ' ';
			cout << '(' << ++i << ')';
			cout << ' ';
			cout << root->detail;
			cout << "\t---->(" << ++j << ")"<<endl;
		}
		else
		{
			traversal(root->lchild,i,j);
			cout << ' ';
			traversal(root->rchild, i,j);
			if (root->lchild->type == 4 || root->lchild->type == 5 || root->lchild->type == 6 || root->lchild->type == 7)
			{
				cout << '(' << ++i << ')';
			}
			cout << ' ';
			if (root->rchild->type == 4 || root->rchild->type == 5 || root->rchild->type == 6 || root->rchild->type == 7)
			{
				cout << '(' << ++i << ')'<<' ';
			}
			cout << ' ';
			cout << root->detail;
			cout << "\t---->(" << ++j << ")" << endl;
		}
	}
}
int main()
{
    char buffer[256]="C:\\Users\\Administrator\\Desktop\\parser\\parser\\input.txt";
	//scanf_s("%s", buffer,255);
	int errno_terr;
	if (errno_terr = fopen_s(&file, buffer, "r"))
	{
		printf("n打开源程序文件出错!n");
		return -1;
	}
	getToken();
	auto root=getExpression();
	int i=0,j=0;
	if (right)
	{
		traversal(root, i, j);
	}
	else
	{
		cout << "四则运算式有错" << endl;
	}
	fclose(file);
	getchar();
	return 0;
}

#include "data.h"

extern FILE * file;
extern string curtoken;
extern int curtokenType;
extern string nexttoken;
extern int nexttokenType;
void getToken()//词法分析函数:每次调用,可以得到下一个非字符型单词的具体内容以及类型
{
	
	curtoken = nexttoken;
	curtokenType = nexttokenType;
	//初始化单词类型以及容器
	nexttoken.clear();
	nexttokenType = #;

	char ch = getc(file);

	if (ch != EOF)
	{
		while (ch == ' ' || ch == '\n' || ch == '\t') ch = getc(file);  //跳过所有的分隔符

		if (ch == EOF) return;  //文件结束

		if (isalpha(ch))   //如果是字母,则进行标识符处理
		{
			nexttoken += ch;
			ch = getc(file);
			while (isalnum(ch))  //如果是字母或数字组合继续;如果不是则标识符组合结束
			{
				nexttoken += ch; //组合的标识符保存在token中
				ch = getc(file);  //读下一个字符
			}
			nexttokenType = variable;
			if (ch != EOF) fseek(file, -1, 1);   //回退一个字符 
		}
		else if (isdigit(ch))//数字处理
		{
			nexttoken += ch;
			ch = getc(file);  //读下一个字符
			while (isdigit(ch))  //如果是数字则组合整数;如果不是则整数组合结束
			{
				nexttoken += ch;  //组合整数保存在token中
				ch = getc(file);  //读下一个字符
			}
			if (ch != '.')
			{
				nexttokenType = integer;
			}
			else
			{
				nexttokenType = decimal;
				nexttoken += '.';
				ch = getc(file);
				while (isdigit(ch))
				{
					nexttoken += ch;
					ch = getc(file);
				}
			}
			if (ch != EOF) fseek(file, -1, 1);   //回退一个字符 
		}
		else if (ch == '+')
		{
			nexttoken = "+";
			nexttokenType = plus;
		}
		else if (ch == '-')
		{
			nexttoken = "-";
			nexttokenType = minus;
		}
		else if (ch == '*')
		{
			nexttoken = "*";
			nexttokenType = multiply;
		}
		else if (ch == '/')
		{
			nexttoken = "/";
			nexttokenType = divide;
		}
		else if (ch == '(')
		{
			nexttoken = "(";
			nexttokenType = LP;
		}
		else if (ch == ')')
		{
			nexttoken = ")";
			nexttokenType = RP;
		}
		else
		{
			nexttokenType = ERROR;
		}
	}
}

#include "data.h"

extern string curtoken;
extern int curtokenType;
extern string nexttoken;
extern int nexttokenType;
extern bool right;
extern void getToken();
extern Tree* getExpression();
extern Tree* getTerm();
extern Tree* getFactor();

Tree *getExpression()
{
	auto lchild=getTerm();
	while (nexttokenType == plus || nexttokenType == minus)
	{
		Tree *parent = new Tree;
		if (nexttokenType == plus)
		{
			parent->type = plus;
			parent->detail = "+";
		}
		else
		{
			parent->type = minus;
			parent->detail = "-";
		}
		getToken();
		auto rchild=getTerm();
		parent->lchild = lchild;
		parent->rchild = rchild;
		lchild = parent;
	}
	if (nexttokenType == variable || nexttokenType == integer || nexttokenType == decimal)
	{
		cout << curtoken << "和" << nexttoken << "之前没有操作符" << endl;
		getchar();
		exit(0);
	}
	return lchild;
}

Tree* getTerm()
{
 	auto lchild = getFactor();
	while (nexttokenType == multiply || nexttokenType == divide)
	{
		Tree *parent = new Tree;
		if (nexttokenType == multiply)
		{
			parent->type = multiply;
			parent->detail = "*";
		}
		else
		{
			parent->type = divide;
			parent->detail = "/";
		}
		getToken();
		auto rchild = getTerm();
		parent->lchild = lchild;
		parent->rchild = rchild;
		lchild = parent;	
	}
	if (nexttokenType == variable || nexttokenType == integer || nexttokenType == decimal)
	{
		cout << curtoken << "和" << nexttoken << "之前没有操作符" << endl;
		getchar();
		exit(0);
	}
	return lchild;
}

Tree* getFactor()
{
	Tree *leaf = new Tree;
	getToken();
	if (curtokenType == variable)
	{
		leaf->type = variable;
		leaf->detail = curtoken;
	}
	else if (curtokenType == integer)
	{
		leaf->type = integer;
		leaf->detail = curtoken;
	}
	else if (curtokenType ==decimal)
	{
		leaf->type = decimal;
		leaf->detail = curtoken;
	}
	else if (curtokenType == LP)
	{
		leaf = getExpression();
		getToken();
		if (curtokenType != RP)
		{
			cout << "没有匹配的左括号" << endl;
			getchar();
			exit(0);
		}
	}
	else
	{
		cout << curtoken << "出错" << endl;
		right = false;
	}
	return leaf;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值