自制编程语言(3)---语法分析---赋值语句

0.简介

本次实现赋值语句。

1.赋值语句

a = a + b
a = 9

以上语句均为赋值语句,这里引入了许多表达式分析。

2.一元表达式

先从一元表达式开始。

std::shared_ptr<Expression> Parser::parseUnaryExpr()
{
	//什么情况下是一元表达式
	Token token = getToken();
	//有符号前缀的情况下
	if (token == TK_MINUS || token == TK_LOGNOT || token == TK_BITNOT)
	{
		//创建结点
		auto result = std::make_shared<BinaryExpression>(line, column);
		//左表达式是空
		result->left_expression = nullptr;
		//获取运算符
		result->opt = token;
		//吃掉运算符
		pushNextToken();
		//右分支还是一元表达式,例如---1,!!!!x等,一元表达式运算符可以叠加
		result->right_expression = parseUnaryExpr();
		return result;
	}

	//一些不带符号的基础表达式也列为无符号一元表达式
	else if (token == TK_INT || token == TK_DOUBLE || token == TK_STR || token == TK_CHAR
		|| token == TK_IDENT || token == KW_FALSE || token == KW_TRUE || token == TK_LPAREN || token == TK_LBRACE)
	{
		//返回基础表达式
		return parsePrimaryExpr();
	}
	return nullptr;
}

这里认为一元表达式如下

a
9
9.9
true
-9
!a
~a

分析器先分析出一元表达式后,如果是一元运算,则构造好后直接返回。

如果得到的表达式是单纯的变量和数字,则将其提取出来,保存成单独的表达式

std::shared_ptr<Expression> Parser::parsePrimaryExpr()
{
	//如果是标识符
	if (getToken() == TK_IDENT)
	{
		//保留当前标识符名字
		std::string identName = getLexeme();
		//吃掉标识符
		pushNextToken();
		return std::make_shared<IdentifierExpression>(identName, line, column);
	}
	//如果是布尔
	else if (getToken() == KW_TRUE || getToken() == KW_FALSE)
	{
		//auto tVal = getCurrentLexeme();
		bool val = getLexeme() == "true" ? true : false;
		auto result = std::make_shared<BoolExpression>(val, line, column);
		pushNextToken();
		return result;
	}
	else if (getToken() == TK_INT)
	{
		//获取数字
		int val = atoi(getLexeme().c_str());
		//吃掉数字
		pushNextToken();
		return  std::make_shared<IntExpression>(val,line,column);
	}
	else if (getToken() == TK_STR)
	{
		//获取字符串
		std::string val = getLexeme();
		//吃掉字符串
		pushNextToken();
		return std::make_shared<StringExpression>(val, line, column);
	}
	else if (getToken() == TK_CHAR)
	{
		//获取字符
		char val = getLexeme()[0];
		//吃掉字符
		pushNextToken();
		return std::make_shared<CharExpression>(val, line, column);
	}
	else if (getToken() == TK_DOUBLE)
	{
		std::istringstream in;
		//获取数字
		in.str(getLexeme());
		float val = 0;
		in >> val;
		//吃掉数字
		pushNextToken();
		return std::make_shared<FloatExpression>(val, line, column);
	}
	return nullptr;
}

3.二元表达式

当遇到二元运算符的时候,则解析二元表达式,这个要在一元表达式之后。然后还有赋值表达式。

std::shared_ptr<Expression> Parser::parseExpression()
{
	//检测一元表达式
	auto unary_result = parseUnaryExpr();
	//如果是赋值运算符
	Token token = getToken();
	if (token == TK_ASSIGN)
	{
		//判断左值是不是普通标识符
		if (typeid(*unary_result) != typeid(IdentifierExpression))
		{
			throw("error");
		}
		auto result = std::make_shared<AssignExpression>(line, column);
		//获取赋值符号
		result->opt = getToken();
		//获得左值
		result->left_value = unary_result;
		//吃掉赋值符号
		pushNextToken();
		//获得右值
		result->right_value = parseExpression();
		return result;
	}

	//检测二元运算符
	//如果是以下这些运算符
	while (token == TK_BITOR || token == TK_BITAND || token == TK_LOGAND || token == TK_LOGNOT ||
		token == TK_EQ || token == TK_NE || token == TK_GT || token == TK_GE ||
		token == TK_LT || token == TK_LE || token == TK_PLUS || token == TK_MINUS ||
		token == TK_MOD || token == TK_TIMES || token == TK_DIV || token == TK_LOGOR || token == TK_BITNOT)
	{
		//二元表达式
		auto result = std::make_shared<BinaryExpression>(line, column);
		//这里放之前的一元表达式
		result->left_expression = unary_result;
		//保存预算符
		result->opt = getToken();
		//下一个符号
		pushNextToken();
		//右分支也是表达式
		result->right_expression = parseExpression();
		//这里是为了让二元表达式可以连续连接
		unary_result = result;
		token = getToken();
	}
	return unary_result;
}

4.赋值

有了前面的铺垫之后,就可以写出比较完整的赋值语句了。

int a
int b
b = b + a

5.源码

这里

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值