Thread: [Pyparsing] RuntimeError: maximum recursion depth exceeded
Brought to you by:
ptmcg
From: elekis <el...@gm...> - 2010-03-27 17:30:36
|
hi, I have a error that I can't find the solution. I have the following recursive rule decimal_digits = Forward() decimal_digits << (nums | (decimal_digits + nums)) p = decimal_digits.parseString("876875.878") but I have a runtimeerro maximum recursion depth exceeded. dunno why . any idea ? thanks a++ -- http://twoji.deviantart.com/ http://www.flickr.com/elekis |
From: Paul M. <pt...@au...> - 2010-03-28 06:41:56
|
I can see that you are just getting started with pyparsing. First of all, nums is not intended to be used as a parsing expression as you have used it. nums is a string defined in pyparsing to make it easy to create Word's made up of digits and other charaters. Pyparsing allows you to mix strings and expressions so that you can easily build up parsers using the '+' and '|' operators. For instance, to match a Python comment that starts with a '#' character and goes to the end of the line, you can use: comment = "#" + restOfLine The '+' operator in pyparsing will automatically promote strings to a pyparsing Literal, so this is synonymous with: comment = Literal("#") + restOfLine but I think that the first version is a little easier to read. You are use the string 'nums' that is defined by pyparsing, but I don't think the results are as you intended. Your statement: decimal_digits << (nums | (decimal_digits + nums)) is like saying: decimal_digits << ("0123456789" | (decimal_digits + "0123456789")) which will get expanded to: decimal_digits << (Literal("0123456789") | (decimal_digits + Literal("0123456789"))) Now your input string "876875.878" *does* contain numeric digits, it does not contain the exact sequence "0123456789", so that Literal will never match. So then pyparsing proceeds to the second alternative, which is (decimal_digits + Literal("0123456789")) So pyparsing recursively tries to match decimal_digits, which takes us back to the original expression, which fails, and so we recurse again,... and again and again until we hit the recursion limit. Let's start by correcting your implementation of a repetition of digits, to match the leading part of your test string. You can't just match the string defined by nums, since that will only match the literal sequence "0123456789". So you want to match *any one of* these characters, one at a time. Conveniently, pyparsing includes a helper method named oneOf that will take a list of strings, or a single string of space-separated strings. I suspect you are trying to follow a BNF definition for a real number, something like: decimal_digits ::= digit | decimal_digits digit This is a recursive definition that will recursively match a sequence of digits. To directly translate this to pyparsing would be similar to your attempt, but we'll correct it to use oneOf: decimal_digits = Forward() digit = oneOf(list(nums)) decimal_digits << (digit + decimal_digits | digit) This is a common experience when trying to take a classical BNF definition and convert it directly to pyparsing. Your definition uses recursion to successively match the leading digits of your input string. BNF does not have syntax for repetition, so to define something like a list of elements, one must use: list_of_items ::= item list_of_items | item In pyparsing, you can simply define list_of_items = OneOrMore(item) So we could replace our complicated decimal_digits definition above with just: digit = oneOf(list(nums)) decimal_digits = OneOrMore(digit) But even better would be to use pyparsing's Word class, for which nums was intended in the first place. decimal_digits = Word(nums) Word takes one or two strings to specify a sequence of characters. If just one string of possible characters is given, then Word will match as many characters in that set as possible, like decimal_digits. If two strings are given, the first will be used as the set of valid *initial* characters, and the second will be used as the set of valid *body* characters. So you could see something like: uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lowers = "abcdefghijklmnopqrstuvwxyz" capitalized_word = Word(uppers, lowers) To match your full string, you would need something like this: real_number = Combine(Optional("-") + Word(nums) + "." + Word(nums)) Please read some of the pyparsing documentation, and check out the examples on the pyparsing wiki. Welcome to pyparsing! -- Paul > -----Original Message----- > From: elekis [mailto:el...@gm...] > Sent: Saturday, March 27, 2010 12:30 PM > To: pyp...@li... > Subject: [Pyparsing] RuntimeError: maximum recursion depth exceeded > > hi, > > I have a error that I can't find the solution. > > I have the following recursive rule > > decimal_digits = Forward() > decimal_digits << (nums | (decimal_digits + nums)) > p = decimal_digits.parseString("876875.878") > > but I have a runtimeerro maximum recursion depth exceeded. > > dunno why . > > any idea ? > > thanks > > a++ > > -- > http://twoji.deviantart.com/ > http://www.flickr.com/elekis > |