您可以使用pyparsing 来解析这种类型的表达式:
from pyparsing import *
expr = Forward()
double = Word(nums + ".").setParseAction(lambda t:float(t[0]))
integer = Word(nums).setParseAction(lambda t:int(t[0]))
variable = Word(alphas)
string = dblQuotedString
funccall = Group(variable + "(" + Group(Optional(delimitedList(expr))) + ")")
array_func = Group(funccall + "[" + Group(delimitedList(expr, "][")) + "]")
array_var = Group(variable + "[" + Group(delimitedList(expr, "][")) + "]")
operand = double | string | array_func | funccall | array_var | variable
expop = Literal('^')
signop = oneOf('+ -')
multop = oneOf('* /')
plusop = oneOf('+ -')
expr << operatorPrecedence( operand,
[("^", 2, opAssoc.RIGHT),
(signop, 1, opAssoc.RIGHT),
(multop, 2, opAssoc.LEFT),
(plusop, 2, opAssoc.LEFT),]
)
result = expr.parseString('sin( 1 + 2 * x ) + tan( 2.123 * x )')
print result
打印:
[[['sin', '(', [[1.0, '+', [2.0, '*', 'x']]], ')'], '+', ['tan', '(', [[2.123, '*', 'x']], ')']]]
这是一个嵌套列表,允许尊重运算符优先级。要获得您想要的扁平化列表,只需扁平化列表:
import collections
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
for sub in flatten(el):
yield sub
else:
yield el
print list(flatten(result))
打印:
['sin', '(', 1.0, '+', 2.0, '*', 'x', ')', '+', 'tan', '(', 2.123, '*', 'x', ')']
或者,如果您只想在不考虑运算符优先级或结构的情况下进行标记,您可以在一行中完成:
>>> from pyparsing import *
>>> OneOrMore(Word(alphas+"_", alphanums+"_") | Word(printables)).parseString("sin( 1 + 2 * x ) + tan( 2.123 * x )").asList()
['sin', '(', '1', '+', '2', '*', 'x', ')', '+', 'tan', '(', '2.123', '*', 'x', ')']