Discussion:
[Pyparsing] Recursive Grammar
Will McGugan
2014-06-27 17:13:25 UTC
Permalink
Hi,

I have a moderately complex grammar that is throws a recursion error when
parsing the expression "(1,2,3,(4,5,6,(7,8,9)))" (a nested data structure).
I've pasted the grammar definition below, can you give me some guidance on
where I've made the grammar recursive?

Thanks in advance!

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(('(') + expr + Suppress(')'))
index = Group(('[') + expr + Suppress(']'))

braceop = callop | index

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),

(braceop, 1, opAssoc.LEFT, EvalBraceOp),

(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),

(logicopOR, 2, opAssoc.LEFT, EvalLogicOpOR),
(logicopAND, 2, opAssoc.LEFT, EvalLogicOpAND),

(ternaryop, 3, opAssoc.LEFT, EvalTernaryOp),
])

expr.validate()
--
Will McGugan
http://www.willmcgugan.com
Loading...