我使用AST构建了一个表达式求值程序,现在想将它连接到解析器。我想使用正则表达式自己构建解析,而不依赖于Pyparser或tokenize库等工具。
有效符号:实数,+, - ,*,/,(,) 数字格式:带或不带小数的任何有效实数,前面带有可选的正/负号。
num_pattern = r"[-+]?[0-9]*\.?[0-9]+"
symbol_pattern = "[/+-/*()]"
输入是一个包含数字或符号的表达式,后跟可选空格,后跟数字或符号并重复。
我想找到每个标记,剥离任何空格,添加一个空格,然后重新组合输出(然后我将变成一个以空格分隔的列表)。
我最大的两个问题是负号( - )既可以作为数字的一部分也可以作为运算符出现。我不确定如何分开这两个案例。我也很难将结果分组在一起,让我可以替换它们。我可以找到字符串中的所有数字,我可以找到所有的符号,但我不知道如何创建一个单一的regEx,它将每个多位数字和每个符号分成一组,我这可以替换/添加空间。我知道这与使用贪婪的比赛有关,但我已经迷失了。
示例:
(-23 + 8) * 5 --> ( -23 + 8 ) * 5
-23--23 --> -23 - -23
.3 * (-3+ 9) --> .3 * ( -3 + 9 )
答案 0 :(得分:1)
考虑到-23
和.3
等数字,我提出了以下解决方案,该问题在三种情况下使用alteration
。
正则表达式: ((-?(?:\d+(?:\.\d+)?))|([-+\/*()])|(-?\.\d+))
<强>解释强>
((-?(?:\d+(?:\.\d+)?))
匹配带小数部分的任何带符号的负数或正数。
([-+\/*()])
匹配任何令牌。
(-?\.\d+))
匹配带有仅小数部分的带符号数字。与.3
一样。
替换为:替换为 \1
,即
First captured group
space
。
<强> Regex101 Demo 强>
答案 1 :(得分:1)
虽然你可能会对正则表达式走得很远,但你会遇到不可避免的障碍。正则表达式代码只能解析Chomsky类型2语法(也称为正则表达式或无上下文语法),而数学公式是类型3,它是超集。特别是嵌套的表达式会带来麻烦。
所以你可以使用正则表达式进行扫描,但之后你需要一个具有一种堆栈机制的解析器。
答案 2 :(得分:0)
我更喜欢命名组:
((?P<brackets>[()])|(?P<number>\-?\d*\.?\d+)|(?P<operator>[+\-\*\/]))
参见示例https://regex101.com/r/dW4hP0/2
然后在匹配时使用re.finditer和groupdict。
答案 3 :(得分:0)
noob想出了这个表达的很大一部分。但它并不是按照我想要的方式工作。我做了一系列小调整来实现这个目标:
带有替换((((^|\s)-)?(\d*\.\d+|\d+))|([-+\/*()]))
的 \1
(注意空格)
主要有两个部分。第一个是数字部分。它将匹配隐式正数和显式负数。它还会处理a.b
或.b
(0.b
的缩写)形式的十进制数字,但会拒绝右侧没有数字的.
。
(((^|\s)-)?(\d*\.\d+|\d+))
((^|\s)-)?
部分处理可选的负号。为了使否定与减法分开,有一个约束,即负数要么以空格为前缀,要么是在字符串的开头。
第二部分([-+\/*()]))
只匹配列表中的单个运算符。
示例:
-3 --> -3
-3+3 --> -3 + 3
3-3 --> 3 - 3
3--3 --> 3 - - 3 (user error)
3- -3 --> 3 - -3
2+(-3+5) --> 2 + ( - 3 + 5 ) (user error)
2 + ( -3 + 5) --> 2 + ( -3 + 5 )
-0.3 --> -0.3
0.3+.5 --> 0.3 + .5
-.3 --> -.3
-.3-0.5 --> -.3 - 0.5
答案 4 :(得分:-1)
目前还不清楚你想做什么。
如果您尝试使用正则表达式解析数学表达式,那么您运气不好,正则表达式不够强大(实际上,您甚至不能将括号与正则表达式匹配:见here)
如果您尝试将运算符-
与数学-
区分开来,那么您也运气不好:要做到这一点,您需要在大多数情况下进行语义分析而您不能这样做&#39;直列&#39;用正则表达式。
最后,您的数字模式中存在错误(最终?
必须包含数字部分,否则它将无法按预期工作):
num_pattern = r"[-+]?[0-9]*(\.[0-9]+)?"