我想让用户能够编写简单的脚本,这些脚本通常会在后台执行。
最简单的解决方案可能只是eval(),但它确实非常危险并且使用了太多资源。是的,我知道eval不是解决办法。
因此,下一个解决方案 - 在沙盒模式下使用不同的解释器。此外,代码应在1秒内执行或应该被杀死。太多的工作和头痛,你不这么认为吗?
但实际上,我不需要太多:我需要能够使用条件并在不同条件下返回不同数字(甚至是字符串)的计算器。例如:
10 if a > 40
50 + c if (a + c) == 100
upgrade if 1/b > 40
42
或类似的。所以,我认为这是一个从头开始编写简单语言的好机会!但是,不是从头开始,应该有适合这种情况的工具。第一个是 pyparsing ,看起来真的很棒!但使用它有点古老而奇怪。例如,simple rules with simple code在7秒内解析!
我有点筋疲力尽,你能在类似情况下提出任何建议或讲述你的成功故事吗?
答案 0 :(得分:0)
考虑使用pypy的沙盒功能:http://pypy.readthedocs.org/en/latest/sandbox.html
答案 1 :(得分:0)
除了我关于添加packrat解析的评论,
from pyparsing import *
ParserElement.enablePackrat()
以下是您的代码的其他一些建议:
尽管我喜欢从较低级别的对象构造解析器作为pyparsing的核心功能,但像十进制数字这样的东西是如此之低,所以所有的pyparsing对象都会让事情变慢。要解析实数,在创建描述模式的正则表达式时,最好在性能方面做得更好。 (这也比你现在的Word(nums +' .-')稍微紧凑,它会接受任何字符组的数字,'。' s和' ; - ' S):
number = Regex(r'-?\d+(\.\d*)?').setParseAction(lambda s, l, t: float(t[0]))
如果你将number
作为定义的一部分重用,那么你的百分比表达式更有意义(因为数字已经从字符串转换为浮点数,与Percent的初始化程序兼容):
percent = (number + Suppress('%')).setParseAction(lambda s, l, t: Percent(t[0]))
您对操作优先级的定义有一些错误 - 在比较操作中没有优先权'<' '>'等等,尽管你在中缀符号的参数中有多个优先级。您还会显示a > b > c
类似Python的不等式,我认为这可能是最好的三元运算支持。请参阅以下更改:
operand = percent | number
inequalities = oneOf("< > >= <=")
expr = infixNotation(operand, [
(oneOf('* /'), 2, opAssoc.LEFT),
(oneOf('+ -'), 2, opAssoc.LEFT),
((inequalities,inequalities), 3, opAssoc.LEFT),
(inequalities, 2, opAssoc.LEFT),
(oneOf('AND and && &'), 2, opAssoc.LEFT),
(oneOf('OR or || |'), 2, opAssoc.LEFT),
])