[Pyparsing] Call operator
Brought to you by:
ptmcg
From: Will M. <wil...@gm...> - 2014-04-04 17:15:28
|
Hi, I have an expression parser that is working nicely, and I'd like to add a 'call' syntax. Basically something like this: <operand>(<operand>) Which should be simple to implement, I have an index operator <operand>[<operand>] which works, but when I use round brackets the parser gets stuck in an infinite loop. I think this may be because operatorPrecendance already uses brackets for parenthesis. Any idea how I would implement this? Here's my grammar definition: integer = Word(nums) real = Combine(Word(nums) + "." + Word(nums)) constant = oneOf('True False None yes no') + WordEnd() variable = Regex(r'([a-zA-Z0-9\._]+)') explicit_variable = '$' + Regex(r'([a-zA-Z0-9\._]+)') string = QuotedString('"', escChar="\\") | QuotedString('\'', escChar="\\") regexp = QuotedString('/', escChar=None) timespan = Combine(Word(nums) + oneOf('ms s m h d')) variable_operand = variable explicit_variable_operand = explicit_variable integer_operand = integer real_operand = real number_operand = real | integer string_operand = string operand = variable | real | integer | string assignop = Literal('=') groupop = Literal(',') signop = oneOf('+ -') multop = oneOf('* / // %') filterop = oneOf('|') plusop = oneOf('+ -') notop = Literal('not') rangeop = Literal('..') exclusiverangeop = Literal('...') ternaryop = ('?', ':') variable_operand.setParseAction(EvalVariable) explicit_variable_operand.setParseAction(EvalExplicitVariable) integer_operand.setParseAction(EvalInteger) real_operand.setParseAction(EvalReal) string_operand.setParseAction(EvalString) constant.setParseAction(EvalConstant) regexp.setParseAction(EvalRegExp) timespan.setParseAction(EvalTimespan) expr = Forward() modifier = Combine(Word(alphas + nums) + ':') callop = Group(Suppress('(') + expr + Suppress(')')) operand = (timespan | real_operand | integer_operand | string_operand | regexp | constant | explicit_variable_operand | variable_operand ) comparisonop = (oneOf("< <= > >= != == ~= ^= $=") | (Literal('is not') + WordEnd()) | (oneOf("is in instr lt lte gt gte matches fnmatches") + WordEnd()) | (Literal('not in') + WordEnd()) | (Literal('not instr') + WordEnd())) logicop = oneOf("and or") + WordEnd() logicopOR = Literal('or') + WordEnd() logicopAND = Literal('and') + WordEnd() formatop = Literal('::') expr << operatorPrecedence(operand, [ (signop, 1, opAssoc.RIGHT, EvalSignOp), (exclusiverangeop, 2, opAssoc.LEFT, EvalExclusiveRangeOp), (rangeop, 2, opAssoc.LEFT, EvalRangeOp), (callop, 2, opAssoc.LEFT, EvalCallOp), (index, 1, opAssoc.LEFT, EvalIndexOp), (modifier, 1, opAssoc.RIGHT, EvalModifierOp), (formatop, 2, opAssoc.LEFT, EvalFormatOp), (multop, 2, opAssoc.LEFT, EvalMultOp), (plusop, 2, opAssoc.LEFT, EvalAddOp), (assignop, 2, opAssoc.LEFT, EvalAssignOp), (groupop, 2, opAssoc.LEFT, EvalGroupOp), (filterop, 2, opAssoc.LEFT, EvalFilterOp), (comparisonop, 2, opAssoc.LEFT, EvalComparisonOp), (notop, 1, opAssoc.RIGHT, EvalNotOp), #(logicop, 2, opAssoc.LEFT, EvalLogicOp), (logicopOR, 2, opAssoc.LEFT, EvalLogicOpOR), (logicopAND, 2, opAssoc.LEFT, EvalLogicOpAND), (ternaryop, 3, opAssoc.LEFT, EvalTernaryOp), ]) Thanks, Will -- Will McGugan http://www.willmcgugan.com |