Re: [Pyparsing] RuntimeError: maximum recursion depth exceeded
Brought to you by:
ptmcg
|
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
>
|