通过 std::regex 从数学表达式中制作树

Make tree from mathematical expression by std::regex

本文关键字:表达式 std regex 通过      更新时间:2023-10-16

Programm get string like: VARIABLE=EXPRESSION.

其中VARIABLE是一些字母和数字,起始字母EXPRESSION是数学表达式,可以包括:

1) + or *
2) ( or )
3) numbers (for example, 5; 3.8; 1e+18, 8.41E-10)
4) another names of variables.

我需要使用一个常规的 expassion 将其转换为树(仅在内存中)。我该怎么做?被提出的方法:

  1. 搜索 = 出 ()
  2. 在 () 中搜索 +
  3. 在 () 中搜索 *
  4. 如果有人找到 - 将表达式分成两部分,否则我们得到数字或变量。

看起来很简单,但我无法创建此表达式。我找到了如何将条件运算符放入正则表达式中。大多数情况下,我只需要 =、+ 和 * 的 3 个常规表达式。例:https://i.stack.imgur.com/I8R12.png

如 n.m. 所述,正则表达式不能处理嵌套括号。但是,有一些简单的替代方法可以解析嵌套括号,例如递归下降解析器。

例:

enum TokenType
{
    TTId,
    TTNumber,
    TTPlus,
    TTMinus,
    TTTimes,
    TTDivide,
    TTLParen,
    TTRParen,
    TTEndOfInput
};
TokenType token = TTEndOfInput;
string tokenValue;
int peekChar();
void nextChar();
void error(string msg); // doesn't return
Value *createConstant(string value);
Value *createReadVariable(string name);
Value *createAdd(Value *l, Value *r);
Value *createSubtract(Value *l, Value *r);
Value *createMultiply(Value *l, Value *r);
Value *createDivide(Value *l, Value *r);
Value *createNegate(Value *l, Value *r);
Value *expression();
void getToken()
{
    token = TTEndOfInput;
    tokenValue = "";
    if(peekChar() == EOF)
        return;
    if(isalpha(peekChar()))
    {
        while(isalnum(peekChar()))
        {
            tokenValue += (char)peekChar();
            nextChar();
        }
        token = TTId;
        return;
    }
    if(isdigit(peekChar()) || peekChar() == '.')
    {
        while(isdigit(peekChar()))
        {
            tokenValue += (char)peekChar();
            nextChar();
        }
        if(peekChar() == '.')
        {
            tokenValue += (char)peekChar();
            nextChar();
            while(isdigit(peekChar()))
            {
                tokenValue += (char)peekChar();
                nextChar();
            }
            if(tokenValue == ".")
                error("missing digit");
        }
        if(peekChar() == 'e')
        {
            tokenValue += (char)peekChar();
            nextChar();
            if(peekChar() == '+' || peekChar() == '-')
            {
                tokenValue += (char)peekChar();
                nextChar();
            }
            if(!isdigit(peekChar()))
                error("missing digit");
            while(isdigit(peekChar()))
            {
                tokenValue += (char)peekChar();
                nextChar();
            }
        }
        token = TTNumber;
        return;
    }
    switch(peekChar())
    {
    case '+':
        token = TTPlus;
        nextChar();
        return;
    case '-':
        token = TTMinus;
        nextChar();
        return;
    case '*':
        token = TTTimes;
        nextChar();
        return;
    case '/':
        token = TTDivide;
        nextChar();
        return;
    case '(':
        token = TTLParen;
        nextChar();
        return;
    case ')':
        token = TTRParen;
        nextChar();
        return;
    default:
        error("invalid charater");
    }
}
Value *topLevel()
{
    Value *retval;
    switch(token)
    {
    case TTId:
        retval = createReadVariable(tokenValue);
        getToken();
        return retval;
    case TTNumber:
        retval = createConstant(tokenValue);
        getToken();
        return retval;
    case TTLParen:
        getToken();
        retval = expression();
        if(token != TTRParen)
            error("expected )");
        getToken();
        return retval;
    case TTMinus:
        getToken();
        return createNegate(topLevel());
    default:
        error("unexpected token");
    }
}
Value *mulDiv()
{
    Value *retval = topLevel();
    while(token == TTTimes || token == TTDivide)
    {
        TokenType operation = token;
        getToken();
        Value *rhs = topLevel();
        if(operation == TTTimes)
        {
            retval = createMultiply(retval, rhs);
        }
        else // operation == TTDivide
        {
            retval = createDivide(retval, rhs);
        }
    }
    return retval;
}
Value *addSub()
{
    Value *retval = mulDiv();
    while(token == TTPlus || token == TTMinus)
    {
        TokenType operation = token;
        getToken();
        Value *rhs = mulDiv();
        if(operation == TTPlus)
        {
            retval = createAdd(retval, rhs);
        }
        else // operation == TTMinus
        {
            retval = createSubtract(retval, rhs);
        }
    }
    return retval;
}
Value *expression()
{
    return addSub();
}
void error(string msg)
{
    cerr << "error : " << msg << endl;
    exit(1);
}
int main()
{
    getToken();
    Value *expressionTree = expression();
    // ...
    return 0;
}