some bits flipped
some bits flipped

Reputation: 3092

StringEnd() raises exception when match fails - PyParsing

The following prints 'pass':

pattern = Word(alphanums) + StringEnd()
str=" bar "
results = pattern.parseString(str)
if 1 == len(results) && "bar" == results[0] :
    print("pass")
else:
    print("fail")

but this throws and exception in parseImpl of class StringEnd (when the char following 'r' in 'bar' is not a string end):

pattern = Word(alphanums) + StringEnd()
str=" bar foo "
results = pattern.parseString(str)  # <-- exception raised

as does this:

pattern = Word(alphanums)
str = " bar foo"
results = pattern.parseString(str,parseAll=True)

I would expect the 2nd/3rd parseString calls to just return an empty array, as it would obviously not satisfy the grammer.

Can anyone help me understand why?

(should be obvious, but to run you'll need 'from pyparsing import *'; also I'm on python3.2 and pyparsing 1.5.6)

Upvotes: 1

Views: 1221

Answers (2)

PaulMcG
PaulMcG

Reputation: 63739

Returning an empty list on a failed match is ambiguous - did the grammar match and just return an empty match, or did it not match at all?

>>> from pyparsing import *
>>> integer = Word(nums)
>>> expr = Suppress("data:") + ZeroOrMore(integer) + StringEnd()

Parse some data:

>>> expr.parseString("data: 1 2 3").asList()
['1', '2', '3']

Successful parse, there just weren't any numbers here:

>>> expr.parseString("data:").asList()
[]

Exception tells you this match failed:

>>> expr.parseString("data: 4 Z 6 7").asList()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python26\lib\site-packages\pyparsing-1.5.6-py2.6.egg\pyparsing.py", line 1032, in parseString
    raise exc
pyparsing.ParseException: Expected end of text (at char 12), (line:1, col:13)

Upvotes: 0

BrenBarn
BrenBarn

Reputation: 251398

When you call parseString on a grammar, you are telling it "parse this string using this grammar, starting at the beginning". It has to match something, or it will raise an exception. This is doubly true when you use parseAll=True. You are saying "match this entire string against this grammar". If it doesn't all match, it's an error. parseString is not an "optional" sort of match where it will just silently fail if you try to match the wrong grammar. If something "obviously does not match the grammar", that's.exactly when it's supposed to raise an error.

You might want to try searchString instead. This will just look for all matches within the string, wherever they are:

>>> pattern = pyp.Word(pyp.alphanums)
>>> pattern.searchString(" bar foo ")
([([u'bar'], {}), ([u'foo'], {})], {})

Upvotes: 2

Related Questions