Thanks guys, I daresay I will have a lot of questions regarding this,
but at least I have a point to start digging and a better shovel!<br>
<br>
Cheers, <br>
<br>
Liam Clarke<br><br><div><span class="gmail_quote">On 7/19/05, <b class="gmail_sendername">Danny Yoo</b> &lt;<a href="mailto:dyoo@hkn.eecs.berkeley.edu">dyoo@hkn.eecs.berkeley.edu</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><br>On Mon, 18 Jul 2005, Liam Clarke wrote:<br><br>&gt; country = {<br>&gt; tag = ENG<br>&gt; ai = {<br>&gt; flags = { }<br>&gt; combat = { DAU FRA ORL PRO }<br>&gt; continent = { }<br>&gt; area = { }<br>&gt; region = { &quot;British Isles&quot; &quot;NorthSeaSea&quot; &quot;ECAtlanticSea&quot; &quot;NAtlanticSea&quot;
<br>&gt; &quot;TagoSea&quot; &quot;WCAtlanticSea&quot; }<br>&gt; war = 60<br>&gt; ferocity = no<br>&gt; }<br>&gt; }<br><br>[Long message ahead; skip if you're not interested.]<br><br><br>Kent mentioned PyParsing,<br><br>&nbsp;&nbsp;&nbsp;&nbsp;
<a href="http://pyparsing.sourceforge.net/">http://pyparsing.sourceforge.net/</a><br><br>which is a really excellent system.&nbsp;&nbsp;Here's a demo of what it can do, just<br>so you have a better idea what pyparsing is capable of.
<br><br>(For the purposes of this demo, I'm doing 'import pyparsing', but in real<br>usage, I'd probably use 'from pyparsing import ...' just to make things<br>less verbose.)<br><br><br>Let's say that we want to recognize a simpler subset of the data that you
<br>have there, something like:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;{ fee fie foo fum }<br><br>And let's imagine that we have a function parse() that can take a string<br>like:<br><br>######<br>&gt;&gt;&gt; testString = &quot;&quot;&quot;<br>... { fee fie foo fum }
<br>... &quot;&quot;&quot;<br>######<br><br><br>This imaginary parse() function could turn that into something that looks<br>like a Python value, like this:<br><br>######<br>&gt;&gt;&gt; parse(testString)<br>([&quot;fee&quot;, &quot;fie&quot;, &quot;foo&quot;, &quot;fum&quot;])
<br>######<br><br>That's our goal; does this make sense so far?&nbsp;&nbsp;So how do we start?<br><br><br><br>Instead of going at the big goal of doing:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;country = { fee fie foo fum }<br><br>let's start small by teaching our system how to recognize the innermost
<br>parts, the small things like fee or foo.&nbsp;&nbsp;Let's start there:<br><br>######<br>&gt;&gt;&gt; Symbol = pyparsing.Word(pyparsing.alphas)<br>######<br><br>We want a Symbol to be able to recognize a &quot;Word&quot; made up of alphabetic
<br>letters.&nbsp;&nbsp;Does this work?<br><br>######<br>&gt;&gt;&gt; Symbol.parseString(&quot;fee&quot;)<br>(['fee'], {})<br>#######<br><br>Symbol is now a thing that can parse a string, and return a list of<br>results in a pyparsing.ParseResults
 object.<br><br><br>Ok, if we can recognize Symbols, let's go for the jugular:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;{ fee fie foo fum }<br><br><br>Let's call this a Sequence.<br><br>######<br>&gt;&gt;&gt; Sequence = &quot;{&quot; + pyparsing.ZeroOrMore
(Symbol) + &quot;}&quot;<br>######<br><br><br>A Sequence is made up of zero or more Symbols.<br><br><br>Wait, let's change that, for a moment, to &quot;A Sequence is made up of zero<br>or more Values.&quot;&nbsp;&nbsp;(You'll see why in a moment.&nbsp;&nbsp;*grin*)
<br><br><br><br>If we turn toward this strange way, then we need a definition for a Value:<br><br>######<br>&gt;&gt;&gt; Value = Symbol<br>######<br><br>and now we can say that a Sequence is a bunch of Values:<br><br>######
<br>&gt;&gt;&gt; Sequence = &quot;{&quot; + pyparsing.ZeroOrMore(Value) + &quot;}&quot;<br>######<br><br><br>Let's try this out:<br><br>######<br>&gt;&gt;&gt; Sequence.parseString('{ fee fie&nbsp;&nbsp;&nbsp;&nbsp;foo fum}')<br>(['{', 'fee', 'fie', 'foo', 'fum', '}'], {})
<br>######<br><br><br>This is close, but it's not quite right: the problem is that we'd like to<br>somehow group the results all together in a list, and without the braces.<br>That is, we actually want to see:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;[['fee', 'fie', 'foo', 'fum']]
<br><br>in some form.&nbsp;&nbsp;(Remember, we want a list of a single result, and that<br>result should be our Sequence.)<br><br><br>How do we get this working?&nbsp;&nbsp;We have to tell pyparsing to &quot;Group&quot; the<br>middle elements together in a collection, and to &quot;suppress&quot; the braces
<br>from the result.<br><br>Here we go:<br><br>######<br>&gt;&gt;&gt; Sequence = (pyparsing.Suppress(&quot;{&quot;) +<br>...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyparsing.Group(pyparsing.ZeroOrMore(Value)) +<br>...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyparsing.Suppress
(&quot;}&quot;))<br>######<br><br>Does this work?<br><br><br>######<br>&gt;&gt;&gt; Sequence.parseString('{ fee fie&nbsp;&nbsp;&nbsp;&nbsp;foo fum}')<br>([(['fee', 'fie', 'foo', 'fum'], {})], {})<br>######<br><br><br>That looks a little messy and more nested than expected.
<br><br><br>Actually, what's happening is that we're looking at that<br>pyparsing.ParseResults object, so there's more nesting in the string<br>representation than what's really there.&nbsp;&nbsp;We can use the ParseResults's<br>asList() method to make it a little easier to see what the real result
<br>value looks like:<br><br>######<br>&gt;&gt;&gt; Sequence.parseString('{ fee fie&nbsp;&nbsp;&nbsp;&nbsp;foo fum}').asList()<br>[['fee', 'fie', 'foo', 'fum']]<br>######<br><br>That's better.<br><br><br><br>Out of curiosity, wouldn't it be neat if we could parse out something like
<br>this?<br><br>&nbsp;&nbsp;&nbsp;&nbsp; { fee fie {foo &quot;fum&quot;} }<br><br>*cough* *cough*<br><br>What we'd like to do is make Sequence itself a possible value.&nbsp;&nbsp;The<br>problem is that then there's a little circularity involved:<br><br>
<br>### Illegal PyParsing pseudocode&nbsp;&nbsp;###<br>Value = Symbol | Sequence<br><br>Sequence = (pyparsing.Suppress(&quot;{&quot;) +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pyparsing.Group(pyparsing.ZeroOrMore(Value)) +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pyparsing.Suppress
(&quot;}&quot;))<br>######<br><br>The problem is that Value can't be defined before Sequence is, and<br>vice-versa.&nbsp;&nbsp;We break this problem by telling PyParsing &quot;ok, the following<br>rules will come up soon&quot; and &quot;forward&quot; define them:
<br><br>######<br>&gt;&gt;&gt; Value = pyparsing.Forward()<br>&gt;&gt;&gt; Sequence = pyparsing.Forward()<br>######<br><br>and once we have these forward declarations, we can then reconnect them to<br>their real definitions by using '&lt;&lt;'.&nbsp;&nbsp;(This looks bizarre, but it applies
<br>just to rules that are Forward()ed.)<br><br>######<br>Value&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt; (Symbol | Sequence)<br>Sequence &lt;&lt; (pyparsing.Suppress(&quot;{&quot;) +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pyparsing.Group(pyparsing.ZeroOrMore(Value)) +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
pyparsing.Suppress(&quot;}&quot;))<br>######<br><br><br>Let's try it:<br><br>######<br>&gt;&gt;&gt; Value.parseString(' { fee fie {foo fum} } ').asList()<br>[['fee', 'fie', ['foo', 'fum']]]<br>######<br><br><br>Cool.<br><br>
<br>Ok, that was a little artificial, but oh well.&nbsp;&nbsp;The idea is we now know<br>how to say:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;A Value is either a Symbol or Sequence<br><br>and<br><br>&nbsp;&nbsp;&nbsp;&nbsp;A Sequence is a bunch of Values<br><br>without getting into trouble with pyparsing, and that's important whenever
<br>we're dealing with things that have recursive structure... like:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;country = {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tag = ENG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ai = {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
flags = { }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
combat = { DAU FRA ORL PRO }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
continent = { }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
area = { }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
region = { &quot;British Isles&quot;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;NorthSeaSea&quot;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;ECAtlanticSea&quot;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;NAtlanticSea&quot;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;TagoSea&quot;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;WCAtlanticSea&quot;
}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
war = 60<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ferocity = no }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>Anyway, this is a really fast whirlwind tour of pyparsing, with some<br>intentional glossing-over of hard stuff, just so you get a better idea of<br>the core of parsing.&nbsp;&nbsp;Sorry if it went fast.&nbsp;&nbsp;*grin*
<br><br><br>If you have questions, please feel free to ask!<br><br></blockquote></div><br><br><br>-- <br>'There is only one basic human right, and that is to do as you damn well please.<br>And with it comes the only basic human duty, to take the consequences.'