系列入口:编程实战:类C语法的编译型脚本解释器(九)编译语句
本文介绍表达式的编译。
一、代码概览
表达式的编译就是不断获取下一个标识符,直到遇到不属于表达式的东西。
完整代码如下:
Expression* GetExpression(CTokens& tokens, T_VARIABLE_S& vars, Expression* pExpression, size_t& pos, char const* endch, bool half = false)
{
size_t start_pos = pos;
size_t op_pos = 0;
Token* pToken;
Expression* pOperand = NULL;//下一个操作数
Token* pOperator = NULL;//指向下一个操作符
while (true)
{
if (NULL == pOperand && NULL == pOperator)
{
tokens.MoveCurrentToken(pToken, pos);
if (tokens.IsPosNotToken(pos))
{
return pExpression;
}
if (isExpressionEnd(tokens, pos, endch))
{//空语句
if (NULL == pExpression)
{
pExpression = NewExpression();
pExpression->source_start = tokens.TokenStart(pos);
pExpression->source_end = tokens.TokenStart(pos);
if (NULL == pExpression)throw "内存不足";
}
return pExpression;
}
//取下一个操作数,可能没有(当下一个标记是操作符)
if (NULL != pOperator)cout << pOperator->text << endl;
GetOperand(tokens, vars, pOperand, pos);
//取下一个操作符
if (GetOperator(tokens, pOperator, pos))op_pos = pos - 1;
}
if (NULL == pOperand && NULL == pOperator)
{//什么都没取到,结束
return pExpression;
}
if (NULL == pExpression)
{//新建表达式
if (NULL == pOperator || isExpressionEnd(tokens, pos - 1, endch))
{
if (isExpressionEnd(tokens, pos - 1, endch))--pos;
else
{
string str;
if (!isExpressionEnd(tokens, pos, endch))
{
cout << tokens.m_tokens[pos - 1].text << " " << endch << endl;
cout << pOperand->ToString(m_source, vars) << endl;
CException::Throw(__FILE__, __LINE__, m_source, tokens.TokenStart(pos), "期待操作符");
}
}
pExpression = pOperand;
return pExpression;
}
else
{
pExpression = NewExpression();
if (NULL == pExpression)throw "内存不足";
pExpression->source_start = tokens.TokenStart(start_pos);
pExpression->source_end = tokens.TokenStart(op_pos);
pExpression->type = Expression::OPERATION;
pExpression->op = pOperator->text;
if (NULL != pOperand)pExpression->AddLeftOperand(*pOperand);
}
pOperand = NULL;
pOperator = NULL;
}
else
{//追加表达式
if (NULL == pOperator || isExpressionEnd(tokens, pos - 1, endch))
{//操作符为空
if (isExpressionEnd(tokens, pos - 1, endch))--pos;
pExpression->AddRightOperand(*pOperand);
pExpression->source_end = tokens.TokenStart(pos);
pOperand = NULL;
return pExpression;
}
else
{
long level1, level2;
if (NULL == pExpression->pLeftOperand())level1 = 2;//单目算符
else if (!tokens.GetOperatorLevel(pExpression->op.c_str(), level1))Throw(__FILE__, __LINE__, pExpression->op + " 操作符优先级未知或此处不应该出现此操作符");
if (NULL == pOperand)level2 = 2;//单目算符
else if (!tokens.GetOperatorLevel(pOperator->text.c_str(), level2))Throw(__FILE__, __LINE__, pOperator->text + " 操作符优先级未知或此处不应该出现此操作符");
if (level1 < level2 || level1 == level2 && tokens.IsOperatorLeftFirst(level1))
{
pExpression->AddRightOperand(*pOperand);
pExpression->source_end = tokens.TokenStart(pos - 1);
if (half)
{
--pos;//退回最后一个操作符
return pExpression;
}
Expression* tmp = NewExpression();
if (NULL == tmp)throw "内存不足";
tmp->type = Expression::OPERATION;
tmp->source_start = pExpression->source_start;
tmp->source_end = op_pos;
tmp->op = pOperator->text;
tmp->AddLeftOperand(*pExpression);
pExpression = tmp;
pOperand = NULL;
pOperator = NULL;
}
else
{
Expression* tmp = NewExpression();
if (NULL == tmp)throw "内存不足";
tmp->type = Expression::OPERATION;
if (NULL == pOperand)tmp->source_start = tokens.TokenStart(op_pos);
else tmp->source_start = pOperand->source_start;
tmp->source_end = tokens.TokenStart(op_pos);
tmp->op = pOperator->text;
tmp->AddLeftOperand(*pOperand);
pOperand = NULL;
pOperator = NULL;
pOperand = GetExpression(tokens, vars, tmp, pos, endch, true);
if (GetOperator(tokens, pOperator, pos))op_pos = pos - 1;
}
}
}
}
//return pExpression;
}
参数char const* endch指出期待什么样的结尾,分为“}”和“)”两种情况。
(我还没写完)