# [Tutor] Parsing problem

Liam Clarke cyresse at gmail.com
Sat Jul 23 16:02:32 CEST 2005

```*sigh* I just read the documentation more carefully and found the difference
between the
| operator and the ^ operator.

Input -

j = { line = { foo = 10 bar = 20 } }

New code

sel = pp.Forward()
values = ((pp.Word(pp.printables) + pp.Suppress("=") + pp.Word(pp.printables))
^ sel)
sel << (pp.Word(pp.printables) + pp.Suppress("=") + pp.Suppress("{") +
pp.OneOrMore(values) + pp.Suppress("}"))

Output -

(['j', 'line', 'foo', '10', 'bar', '20'], {})

My apologies for the deluge.

Regards,

Liam Clarke

On 7/24/05, Liam Clarke <cyresse at gmail.com> wrote:
>
> Hmmm... just a quick update, I've been poking around and I'm obviously
> making some error of logic.
>
> Given a line -
>
> f = "j = { line = { foo = 10 bar = 20 } }"
>
> And given the following code -
>
> select = pp.Forward()
> select <<
> pp.Word(pp.printables) + pp.Suppress("=") + pp.Suppress("{") +
> pp.OneOrMore( (pp.Word(pp.printables) + pp.Suppress("=") +
> pp.Word(pp.printables) ) | select ) + pp.Suppress("}")
>
> sel.parseString(f) gives -
>
> (['j', 'line', '{', 'foo', '10', 'bar', '20'], {})
>
> So I've got a bracket sneaking through there. Argh. My brain hurts.
>
> Is the | operator an exclusive or?
>
> Befuddled,
>
> Liam Clarke
>
> On 7/23/05, Liam Clarke <cyresse at gmail.com> wrote:
> >
> > Howdy,
> >
> > could just copy and paste your solution (which works pretty well), but I
> > want to understand what I'm doing *grin*
> >
> > However, I've been hitting a couple of ruts in the path to
> > enlightenment. Is there a way to tell pyparsing that to treat specific
> > escaped characters as just a slash followed by a letter? For the time being
> > I've converted all backslashes to forwardslashes, as it was choking on \a in
> > a file path.
> >
> > But my latest hitch, takes this form (apologies for large traceback)
> >
> > Traceback (most recent call last):
> > File "<interactive input>", line 1, in ?
> > File "parse.py", line 336, in parse
> > parsedEntries = dicts.parseString(test_data)
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 616, in
> > parseString
> > loc, tokens = self.parse( instring.expandtabs(), 0 )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 558, in parse
> > loc,tokens = self.parseImpl( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 1518, in
> > parseImpl
> > return self.expr.parse( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 558, in parse
> > loc,tokens = self.parseImpl( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 1367, in
> > parseImpl
> > loc, exprtokens = e.parse( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 558, in parse
> > loc,tokens = self.parseImpl( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 1518, in
> > parseImpl
> > return self.expr.parse( instring, loc, doActions )
> > File "c:\python24\Lib\site-packages\pyparsing.py", line 560, in parse
> > raise ParseException, ( instring, len(instring), self.errmsg, self )
> >
> > ParseException: Expected "}" (at char 9909), (line:325, col:5)
> >
> > The offending code can be found here (includes the data) - http://www.rafb.net/paste/results/L560wx80.html
> >
> >
> > It's like pyparsing isn't recognising a lot of my "}"'s, as if I add
> > another one, it throws the same error, same for adding another two...
> >
> > No doubt I've done something silly, but any help in finding the tragic
> > flaw would be much appreciated. I need to get a parsingResults object out so
> > I can learn how to work with the basic structure!
> >
> > Much regards,
> >
> > Liam Clarke
> >
> > On 7/21/05, Paul McGuire < paul at alanweberassociates.com> wrote:
> > >
> > > Liam, Kent, and Danny -
> > >
> > > It sure looks like pyparsing is taking on a life of its own! I can see
> > > I no
> > > longer am the only one pitching pyparsing at some of these
> > > applications!
> > >
> > > Yes, Liam, it is possible to create dictionary-like objects, that is,
> > > ParseResults objects that have named values in them. I looked into
> > > your
> > > application, and the nested assignments seem very similar to a
> > > ConfigParse
> > > type of structure. Here is a pyparsing version that handles the test
> > > data
> > > in your original post (I kept Danny Yoo's recursive list values, and
> > > recursive dictionary entries):
> > >
> > > --------------------------
> > > import pyparsing as pp
> > >
> > > listValue = pp.Forward()
> > > listSeq = pp.Suppress ('{') + pp.Group(pp.ZeroOrMore(listValue)) +
> > > pp.Suppress('}')
> > > listValue << ( pp.dblQuotedString.setParseAction(pp.removeQuotes) |
> > > pp.Word(pp.alphanums) | listSeq )
> > >
> > > keyName = pp.Word( pp.alphas )
> > >
> > > entries = pp.Forward()
> > > entrySeq = pp.Suppress('{') + pp.Group(pp.OneOrMore(entries)) +
> > > pp.Suppress('}')
> > > entries << pp.Dict(
> > > pp.OneOrMore (
> > > pp.Group( keyName + pp.Suppress('=') + (entrySeq |
> > > listValue) ) ) )
> > > --------------------------
> > >
> > >
> > > Dict is one of the most confusing classes to use, and there are some
> > > examples in the examples directory that comes with pyparsing (see
> > > dictExample2.py), but it is still tricky. Here is some code to access
> > > your
> > > input test data, repeated here for easy reference:
> > >
> > > --------------------------
> > > testdata = """\
> > > country = {
> > > tag = ENG
> > > ai = {
> > > flags = { }
> > > combat = { DAU FRA ORL PRO }
> > > continent = { }
> > > area = { }
> > > region = { "British Isles" "NorthSeaSea" "ECAtlanticSea"
> > > "NAtlanticSea"
> > > "TagoSea" "WCAtlanticSea" }
> > > war = 60
> > > ferocity = no
> > > }
> > > }
> > > """
> > > parsedEntries = entries.parseString(testdata)
> > >
> > > def dumpEntries(dct,depth=0):
> > > keys = dct.keys()
> > > keys.sort()
> > > for k in keys:
> > > print (' '*depth) + '- ' + k + ':',
> > > if isinstance(dct[k],pp.ParseResults):
> > > if dct[k][0].keys():
> > > print
> > > dumpEntries(dct[k][0],depth+1)
> > > else:
> > > print dct[k][0]
> > > else:
> > > print dct[k]
> > >
> > > dumpEntries( parsedEntries )
> > >
> > > print
> > > print parsedEntries.country[0].tag
> > > print parsedEntries.country[0].ai[0].war
> > > print parsedEntries.country[0].ai[0].ferocity
> > > --------------------------
> > >
> > > This will print out:
> > >
> > > --------------------------
> > > - country:
> > > - ai:
> > > - area: []
> > > - combat: ['DAU', 'FRA', 'ORL', 'PRO']
> > > - continent: []
> > > - ferocity: no
> > > - flags: []
> > > - region: ['British Isles', 'NorthSeaSea', 'ECAtlanticSea',
> > > 'NAtlanticSea', 'TagoSea', 'WCAtlanticSea']
> > > - war: 60
> > > - tag: ENG
> > >
> > > ENG
> > > 60
> > > No
> > > --------------------------
> > >
> > > But I really dislike having to dereference those nested values using
> > > the
> > > 0'th element. So I'm going to fix pyparsing so that in the next
> > > release,
> > > you'll be able to reference the sub-elements as:
> > >
> > > print parsedEntries.country.tag
> > > print parsedEntries.country.ai.war
> > > print parsedEntries.country.ai.ferocity
> > >
> > > This *may* break some existing code, but Dict is not heavily used,
> > > based on
> > > feedback from users, and this may make it more useful in general,
> > > especially
> > > when data parses into nested Dict's.
> > >
> > > Hope this sheds more light than confusion!
> > > -- Paul McGuire
> > >
> > > _______________________________________________
> > > Tutor maillist - Tutor at python.org
> > > http://mail.python.org/mailman/listinfo/tutor
> > >
> >
> >
> >
> > --
> > 'There is only one basic human right, and that is to do as you damn well
> > And with it comes the only basic human duty, to take the consequences.'
>
>
>
>
> --
> 'There is only one basic human right, and that is to do as you damn well
> And with it comes the only basic human duty, to take the consequences.'
>

--
'There is only one basic human right, and that is to do as you damn well