c++ - 通过 std::regex 从数学表达式制作树

标签 c++ regex

程序获取如下字符串: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.

我需要使用 one 正则表达式将它变成树(仅在内存中)。 我怎样才能做到这一点? 提出方法:

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

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

最佳答案

如 n.m. 所述,正则表达式无法处理嵌套的括号。然而,有一些简单的替代方法可以解析嵌套的括号,例如 recursive descent parsers .

例子:

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;
}

关于c++ - 通过 std::regex 从数学表达式制作树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27010147/

相关文章:

regex - 我该如何处理这个正则表达式问题?

regex - 验证字符串的前半部分与后半部分相同

ruby - 如何在 ruby​​ 1.8 中用 ascii 替换 unicode 引号?

c++ - 库包 pcre-8.37 中的文件 pcre.h 在哪里

c++ - 从文本文件中查找和提取数据

c++ - std::make_pair 与 C++11 统一初始值设定项

c++ - 如何从指向 GDB 中基类的指针确定对象是否是某个派生 C++ 类的实例?

MySQL REGEXP 不匹配一个以上的单词

c++ - 两个线程使用相同的 websocket 句柄——这会导致任何问题吗?

c++ - 扩展Visual Studio(2010+)项类型处理程序