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