pyparsing

  • Thread starter =?iso-8859-2?q?Bo=B9tjan_Jerko?=
  • Start date
?

=?iso-8859-2?q?Bo=B9tjan_Jerko?=

Hello !

I am trying to understand pyparsing. Here is a little test program
to check Optional subclass:

from pyparsing import Word,nums,Literal,Optional

lbrack=Literal("[").suppress()
rbrack=Literal("]").suppress()
ddot=Literal(":").suppress()
start = Word(nums+".")
step = Word(nums+".")
end = Word(nums+".")

sequence=lbrack+start+Optional(ddot+step)+ddot+end+rbrack

tokens = sequence.parseString("[0:0.1:1]")
print tokens

tokens1 = sequence.parseString("[1:2]")
print tokens1

It works on tokens, but the error message is showed on
the second string ("[1:2]"). I don't get it. I did use
Optional for ddot and step so I guess they are optional.

Any hints what I am doing wrong?

The versions are pyparsing 1.1.2 and Python 2.3.3.

Thanks,

B.
 
D

Daniel 'Dang' Griffith

Hello !

I am trying to understand pyparsing. Here is a little test program
to check Optional subclass:

from pyparsing import Word,nums,Literal,Optional

lbrack=Literal("[").suppress()
rbrack=Literal("]").suppress()
ddot=Literal(":").suppress()
start = Word(nums+".")
step = Word(nums+".")
end = Word(nums+".")

sequence=lbrack+start+Optional(ddot+step)+ddot+end+rbrack

tokens = sequence.parseString("[0:0.1:1]")
print tokens

tokens1 = sequence.parseString("[1:2]")
print tokens1

It works on tokens, but the error message is showed on
the second string ("[1:2]"). I don't get it. I did use
Optional for ddot and step so I guess they are optional.

Any hints what I am doing wrong?

The versions are pyparsing 1.1.2 and Python 2.3.3.

Thanks,

B.
I don't see anything "obviously" wrong to me, but changing it thusly
seems to resolve the problem (I added a few intermediate rules to
make it more obvious):

pref = lbrack + start
midf = ddot + step
suff = ddot + end + rbrack
sequence = pref + midf + suff | pref + suff

I've run into "this kind of thing" now and again, and have always
been able to resolve it by reorganizing my rules.

--dang
 
P

Paul McGuire

Bo¹tjan Jerko said:
Hello !

I am trying to understand pyparsing. Here is a little test program
to check Optional subclass:

from pyparsing import Word,nums,Literal,Optional

lbrack=Literal("[").suppress()
rbrack=Literal("]").suppress()
ddot=Literal(":").suppress()
start = Word(nums+".")
step = Word(nums+".")
end = Word(nums+".")

sequence=lbrack+start+Optional(ddot+step)+ddot+end+rbrack

tokens = sequence.parseString("[0:0.1:1]")
print tokens

tokens1 = sequence.parseString("[1:2]")
print tokens1

It works on tokens, but the error message is showed on
the second string ("[1:2]"). I don't get it. I did use
Optional for ddot and step so I guess they are optional.

Any hints what I am doing wrong?

The versions are pyparsing 1.1.2 and Python 2.3.3.

Thanks,

B.
Bostjan -

Here's how pyparsing is processing your input strings:

[0:0.1:1]
[ = lbrack
0 = start
:0.1 = ddot + step (Optional match)
: = ddot
1 = end
] = rbrack

[1:2]
[ = lbrack
1 = start
:2 = ddot + step (Optional match)
] = oops! expected ddot -> failure


Dang Griffith proposed one alternative construct, here's another, perhaps
more explicit:
lbrack + ( ( ddot + step + ddot + end ) | (ddot + end) ) + rbrack

Note that the order of the inner construct is important, so as to not match
ddot+end before trying ddot+step+ddot+end; '|' is a greedy matching
operator, creating a MatchFirst object from pyparsing's class library. You
could avoid this confusion by using '^', which generates an Or object:
lbrack + ( (ddot + end) ^ ( ddot + step + ddot + end ) ) + rbrack
This will evaluate both subconstructs, and choose the longer of the two.

Or you can use another pyparsing helper, the delimited list
lbrack + delimitedlist( Word(nums+"."), delim=":") + rbrack
This implicitly suppresses delimiters, so that all you will get back are
["1","0.1","1"] in the first case and ["1","2"] in the second.

Happy pyparsing!
-- Paul
 
P

Paul McGuire

Dang Griffith proposed one alternative construct, here's another, perhaps
more explicit:
lbrack + ( ( ddot + step + ddot + end ) | (ddot + end) ) + rbrack

should be:
lbrack + start + ( ( ddot + step + ddot + end ) | (ddot + end) ) +
rbrack
Note that the order of the inner construct is important, so as to not match
ddot+end before trying ddot+step+ddot+end; '|' is a greedy matching
operator, creating a MatchFirst object from pyparsing's class library. You
could avoid this confusion by using '^', which generates an Or object:
lbrack + ( (ddot + end) ^ ( ddot + step + ddot + end ) ) + rbrack

should be:
lbrack + start + ( (ddot + end) ^ ( ddot + step + ddot + end ) ) +
rbrack
This will evaluate both subconstructs, and choose the longer of the two.

Or you can use another pyparsing helper, the delimited list
lbrack + delimitedlist( Word(nums+"."), delim=":") + rbrack

at least this one is correct! No, wait, I mis-cased delimitedList!
should be:
lbrack + delimitedList( Word(nums+"."), delim=":") + rbrack
This implicitly suppresses delimiters, so that all you will get back are
["1","0.1","1"] in the first case and ["1","2"] in the second.

Happy pyparsing!
-- Paul
Sorry for the sloppiness,
-- Paul
 
?

=?iso-8859-2?q?Bo=B9tjan_Jerko?=

Paul,

thanks for the explanation.

Bo¹tjan

Dang Griffith proposed one alternative construct, here's another, perhaps
more explicit:
lbrack + ( ( ddot + step + ddot + end ) | (ddot + end) ) +
rbrack

should be:
lbrack + start + ( ( ddot + step + ddot + end ) | (ddot + end)
) +
rbrack
Note that the order of the inner construct is important, so as to
not match
ddot+end before trying ddot+step+ddot+end; '|' is a greedy matching
operator, creating a MatchFirst object from pyparsing's class
library. You
could avoid this confusion by using '^', which generates an Or
object: lbrack + ( (ddot + end) ^ ( ddot + step + ddot + end )
) + rbrack

should be:
lbrack + start + ( (ddot + end) ^ ( ddot + step + ddot + end )
) +
rbrack
This will evaluate both subconstructs, and choose the longer of the
two.

Or you can use another pyparsing helper, the delimited list
lbrack + delimitedlist( Word(nums+"."), delim=":") + rbrack

at least this one is correct! No, wait, I mis-cased delimitedList!
should be:
lbrack + delimitedList( Word(nums+"."), delim=":") + rbrack
This implicitly suppresses delimiters, so that all you will get
back are ["1","0.1","1"] in the first case and ["1","2"] in the
second.

Happy pyparsing!
-- Paul
Sorry for the sloppiness,
-- Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top