infixNotation
的实施速度比使用enablePackrat
时的运行速度慢,这大大提高了性能。
解析需要识别和解析以下类型的字符串:
prefix::dotted.alphanum.string -> [prefix::dotted.alphanum.string]
pow(some::var + 2.3, 5) -> [pow, [[some::var, +, 2.3], 5]]
我使用的代码:
def parse_expression(expr_str):
fraction = Combine("." + Word(nums))
number = Combine(Word(nums) + Optional(fraction)).setParseAction(str_to_num)
event_id_expr = Word(alphanums + "_") + "::"
dotted_columns = Combine(Word(alphanums + "_") + Optional("."))
column_expr = Combine(event_id_expr + OneOrMore(dotted_columns))
arith_expr = infixNotation(column_expr | number, [
(Word(alphanums + "_"), 1, opAssoc.RIGHT),
("-", 1, opAssoc.RIGHT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
(Literal(","), 2, opAssoc.LEFT)
])
parsed_expr = arith_expr.parseString(expr_str).asList()[0]
return parsed_expr
def str_to_num(t):
num_str = t[0]
try:
return int(num_str)
except ValueError:
return float(num_str)
我能做出哪些改变会导致显着的性能提升?我解析的结构相当简单,但它们分批进行。平均每个字符串大约需要5.3毫秒。
答案 0 :(得分:2)
看起来你是"捏造"函数好像是运算符,我认为你最好将函数调用移动到infixNotation
的操作数表达式中:
def parse_expression(expr_str):
number = pyparsing_common.number()
event_id_expr = Word(alphas+"_", alphanums + "_") + "::"
dotted_columns = Combine(Word(alphas+"_", alphanums + "_") + Optional("."))
column_expr = Combine(event_id_expr + OneOrMore(dotted_columns))
func_name = Word(alphas+"_", alphanums+'_')
LPAR, RPAR = map(Suppress, "()")
arith_expr = Forward()
func_call = Group(func_name('name')
+ LPAR
+ Group(Optional(delimitedList(arith_expr)))("args")
+ RPAR)
arith_expr <<= infixNotation(number | func_call | column_expr, [
("-", 1, opAssoc.RIGHT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
])
parsed_expr = arith_expr.parseString(expr_str)[0]
return parsed_expr
我还修改了大部分标识符以使用Word的双参数形式 - 只需使用Word(alphanums+"_")
也可以匹配普通整数,我不会认为是你的意图。如果我弄错了,那就把它们放回原处。