用Python编写的数学语法检查器

10 投票
5 回答
4101 浏览
提问于 2025-04-16 11:09

我只需要用Python检查一个字符串是否是有效的数学表达式。

为了简单起见,假设我只需要使用 + - * / 这些运算符(+ - 也可以作为一元运算符),还有数字和嵌套的括号。为了完整性,我还加上了一些简单的变量名。

所以我可以这样测试:

test("-3 * (2 + 1)") #valid
test("-3 * ")        #NOT valid

test("v1 + v2")      #valid
test("v2 - 2v")      #NOT valid ("2v" not a valid variable name)

我试过 pyparsing,但是在尝试示例时:“简单的代数表达式解析器,可以执行 +,-,*,/^ 的算术运算”,我发现它能通过一些无效的代码,而且在尝试修复时,总是解析出错误的语法,但没有抛出异常。

试试这个

>>>test('9', 9)
9 qwerty = 9.0 ['9'] => ['9']
>>>test('9 qwerty', 9)
9 qwerty = 9.0 ['9'] => ['9']

两个测试都通过了... o_O

有什么建议吗?

5 个回答

1

你可以尝试自己写一个简单的解析器,来把算术表达式的字符串分解成一个个小部分,然后构建一个表达式树。如果这个树是有效的(也就是说,树的叶子节点都是操作数,内部节点都是运算符),那么你就可以说这个表达式是有效的。

基本的思路是创建一些辅助函数来帮助你构建解析器。

def extract() 这个函数会从表达式中获取下一个字符。
def peek() 这个函数和extract类似,但它用来检查下一个字符,如果没有空格的话。
get_expression()
get_next_token()

另外,如果你能保证字符之间有空格的话,可以使用 split() 来完成所有的分解工作。

然后你就可以构建你的树,并检查它的结构是否正确。

想了解更多信息,可以试试这个链接: http://effbot.org/zone/simple-top-down-parsing.htm

2

在调用 parseString 时,如果加上 parseAll=True,那么这个解析器就会变成一个验证器。

3

这是因为pyparsing的代码允许使用函数。(顺便说一下,它的功能比你需要的要多很多,比如创建一个栈并进行计算。)

首先,你可以从代码中去掉piident(可能还有其他我现在想不起来的东西),这样就不允许使用这些字符了。

原因其实不同:PyParsing的解析器默认不会尝试处理整个输入。你需要在expr的末尾添加+ StringEnd()(当然也要导入它),这样如果它不能解析整个输入就会失败。在这种情况下,会抛出pyparsing.ParseException的错误。(来源:http://pyparsing-public.wikispaces.com/FAQs

如果你想了解一些解析的知识,使用任何一个不错的解析库,你需要的功能可能不到三十行代码就能实现(我个人喜欢LEPL)。

撰写回答