【问题标题】:Parsing mathematical expressions in C#在 C# 中解析数学表达式
【发布时间】:2016-03-17 09:32:51
【问题描述】:

作为一个项目,我想为 C# 中的数学表达式编写一个解析器。我知道有这方面的库,但想创建自己的库来了解这个主题。

举个例子,我有这样的表达方式

min(3,4) + 2 - abs(-4.6)

然后,我通过指定正则表达式并检查用户试图匹配其中一个正则表达式的表达式,从此字符串创建令牌。这是从前到后完成的:

    private static List<string> Tokenize(string expression)
    {
        List<string> result = new List<string>();
        List<string> tokens = new List<string>();

        tokens.Add("^\\(");// matches opening bracket
        tokens.Add("^([\\d.\\d]+)"); // matches floating point numbers
        tokens.Add("^[&|<=>!]+"); // matches operators and other special characters
        tokens.Add("^[\\w]+"); // matches words and integers
        tokens.Add("^[,]"); // matches ,
        tokens.Add("^[\\)]"); // matches closing bracket

        while (0 != expression.Length)
        {
            bool foundMatch = false;

            foreach (string token in tokens)
            {
                Match match = Regex.Match(expression, token);
                if (false == match.Success)
                {
                    continue;
                }

                result.Add(match.Value);
                expression = Regex.Replace(expression, token, "");
                foundMatch = true;

                break;
            }

            if (false == foundMatch)
            {
                break;
            }
        }

        return result;
    }

这很好用。现在我希望用户能够在表达式中输入字符串。我在Regex tokenize issue 找到了一个问题,但是答案提供了匹配表达式中任何地方的文本的正则表达式。但是我需要它来匹配表达式前面的第一次出现,这样我就可以保持令牌的顺序。 作为示例,请参见:

5 + " is smaller than " + 10

应该给我代币 5+" is greater than "+10

如果可能的话,我还希望能够输入转义字符,以便用户能够在字符串中使用字符 ",例如 "This is an apostrophe \" " 给了我令牌 "This is an apostrophe " "

Wiktor Stribiżew 对那个问题的回答看起来非常好,但我无法修改它,所以它只匹配开头并且只有一个单词。感谢您的帮助!

【问题讨论】:

  • 你尝试了什么?不是事件"(.*?)"? (恭喜 Wiktor 现在成为参考;))
  • 会推荐类似SpracheNitra 的东西。用正则表达式解析复杂的表达式是一个杯子游戏。

标签: c# regex parsing


【解决方案1】:

你提到这个问题很有趣。我实际上采用了(又一次)我的答案在这里为你工作;)

Here's a fiddle 显示解决方案。

正则表达式是

(?!\+)(?:"((?:\\"|[^"])*)"?)

我更改了代码以使用捕获组,以便能够以简单的方式添加周围的引号。该循环还删除了分隔 tokens+ 符号。

问候

【讨论】:

  • 谢谢!现在我可以继续了:)
猜你喜欢
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多