使用正则表达式在Swift中解析Infix数学表达式

时间:2019-03-05 05:20:38

标签: swift regex

我想使用正则表达式将格式化为前缀数学形式的字符串转换为令牌数组。我对正则表达式非常陌生,因此如果对这个问题的回答太琐碎了,请原谅我

例如:

"31+2--3*43.8/1%(1*2)"-> ["31", "+", "2", "-", "-3", "*", "43.8", "/", "1", "%", "(", "*", "2", ")"]

我已经实现了一种可以完成此任务的方法,但是,它由许多行代码和一些嵌套循环组成。我发现当我定义更多甚至可能由多个字符组成的运算符/函数时,例如logcos,编辑正则表达式字符串比向其中添加更多行代码要容易得多。我的工作职能。正则表达式是否适合此工作?如果是,我在哪里出错?还是我最好添加到工作解析器中?

我已经提到了以下SO帖子:

How to split a string, but also keep the delimiters?

这个非常有帮助,但是我不相信我在正确地使用'lookahead'。

Validate mathematical expressions using regular expression?

上述问题的解决方案不会将字符串转换为令牌数组。而是检查给定的字符串是否是有效的数学表达式。

我的代码如下:

func convertToInfixTokens(expression: String) -> [String]?
{
    do
    {
        let pattern = "^(((?=[+-/*]))(-)?\\d+(\\.\\d+)?)*"

        let regex = try NSRegularExpression(pattern: pattern)

        let results = regex.matches(in: expression, range: NSRange(expression.startIndex..., in: expression))

        return results.map
        {
            String(expression[Range($0.range, in: expression)!])
        }
    }
    catch
    {
        return nil
    }
}

当我确实向该函数传递有效的中缀表达式时,它返回nil。我的正则表达式字符串在哪里出问题?

注意:我什至没有试图将括号解析为单独的标记。我仍在弄清楚为什么它不适用于此表达式:

"-99+44+2+-3/3.2-6"

感谢任何反馈,谢谢!

1 个答案:

答案 0 :(得分:1)

您的模式不起作用,因为它仅匹配字符串开头的文本(请参见^锚点),然后(?=[+-/*])正向搜索要求第一个字符是指定集合中的运算符但是您使用的唯一运算符是可选的-。因此,当*第二次尝试与-99+44+2+-3/3.2-6匹配封闭的模式序列时,它会看到+44-?\d无法对其进行匹配(因为它不知道如何匹配将+-?匹配)。

这是您的正则表达式与字符串匹配的方式:

enter image description here

您可以使用

对表达式进行标记
let pattern = "(?<!\\d)-?\\d+(?:\\.\\d+)?|[-+*/%()]"

请参见regex demo

详细信息

  • (?<!\d)-当前位置的左边不应有数字
  • -?-可选的-
  • \d+-1个或更多数字
  • (?:\.\d+)?-.和1个以上的数字的可选序列
  • |-或
  • \D-除数字以外的任何字符。

使用您的函数输出:

Optional(["31", "+", "2", "-", "-3", "*", "43.8", "/", "1", "%", "(", "1", "*", "2", ")"])