actions at parsing time

42 views
Skip to first unread message

zunbeltz

unread,
Jan 7, 2012, 12:49:04 PM1/7/12
to modgrammar
Dear all,ion at parsing time

I have learnt that pyparsing has the feature of being possible to
apply a function at parsing time. For a grammar it is possible to
define a function that is called when the grammar is found. I know
that modgrammar has de elem_innit function that should do the same
job.
My problem is the following: I would like to change every "@@" by a
single "@".
Because "@@" can be surrounded by any text, i think it could be nice
to do it at parsing time, so the postprocessing of the parsing result
is easier.

i tried to do
class DoubleAt(Grammar):
grammar = "@@"
def elem_init(self, sesiondata):
self[0] = L("@")

But i get the error
TypeError: 'DoubleAt' object does not support item assignment

Has any sense to do what I am trying? Or the only way is to define a
function to be called when the total parsing result is processed?

Best regards,

Zunbeltz

Alex Stewart

unread,
Jan 7, 2012, 5:50:39 PM1/7/12
to modgr...@googlegroups.com
elem_init is the method you're looking for, but there are a couple of problems with the way you're trying to use it..

First of all, as the error you experienced indicates, parse result objects don't support assignment using the obj[index] = value syntax.  If you really need to, the way to get around this would be to modify the object's "elements" attribute instead (obj[index] is really just a shortcut for saying obj.elements[index] anyway).

The other problem with your code, however, is that L('@') is a grammar definition (class), not a parse result (object), and the 'elements' list should contain parse results, not grammar classes.  You would instead need to create a result object that looks like the result you would get from matching L('@') to some text, and then use that.  Faking match objects is possible to do, but not really documented well, because it's generally the wrong way to go about things anyway.

I think part of the problem is that you're trying to make Modgrammar behave like pyparsing, when Modgrammar is actually quite a bit more sophisticated, and has better ways to do most things.  If you really want .tokens() to return something else for a DoubleAt match, instead of trying to fake a parse result by replacing elements with other ones in the parse tree, the more modgrammar-ish way to do things would be something like the following:

class DoubleAt(Grammar):
   grammar = ("@@")
   grammar_terminal = True

   def elem_init(self, sesiondata):
       self.string = "@"

('grammar_terminal = True' tells .tokens() to treat this object as the terminal instead of the (L('@@')) sub-match, and then we just set the DoubleAt result's 'string' attribute to "@" instead, so that's what ends up in the .tokens() output)

Even this is a bit of a hack, though.  The better way is to actually have your application get its information from the full result objects instead of just the matched text strings (for example, by using .terminals() instead of .tokens()), so that instead of doing 'if token == "@":' somewhere, you could do 'if isinstance(elem, AtSign):' instead.  Then, for example, you could make AtSign match '@' or '@@' (or make subclasses of AtSign, etc), and your code would still do the right thing (and you wouldn't need any 'elem_init' hacks).

-alex

Zunbeltz Izaola

unread,
Jan 7, 2012, 7:16:40 PM1/7/12
to modgr...@googlegroups.com
Dear Alex,

Thanks for your fast and comprehensive answer!
I will follow your suggestion to use the full result object and not
hacking the string field.

Given that I started to compare modgrammar to pyparsing, is there any
way to refer to the elements in a matching grammar with a string
instead of a index number? Pyparsing has a function called
setResultName, that allow to set a name for different parts of the
grammar, and them it is possible to refer to them by name. For
example, I parse
@i myfile
with the grammar L('@i), L(' '), FilenameGrammar)
I would like to refer to the filename as
element['filename'] instead of elemnt[2].
The closest thing I found is the dynamic tagging shown in the tutorial
but I can not replicate this functionality.

Best regards,

Zunbeltz

--
Zunbeltz Izaola

Alex Stewart

unread,
Jan 8, 2012, 3:47:23 PM1/8/12
to modgrammar
I believe tags are what you're looking for, yes. If you add a
'grammar_tags = ("filename")' to FilenameGrammar, then you should be
able to use 'element.find_tag("filename')" to refer to it in the
results..

I actually hadn't thought about it before, but I suppose there's
really no reason that this functionality couldn't be added to the
element[...] syntax as well.. I may see about adding that as a
feature in the future..

-alex

Alex Stewart

unread,
Jan 8, 2012, 4:05:46 PM1/8/12
to modgrammar
Actually, I should also mention that even without using tags, you can
also look up result objects based on their grammar class, so even
without adding tags to it, you could instead do:

element.get(FilenameGrammar)

as well..

-alex

Zunbeltz Izaola

unread,
Jan 9, 2012, 3:02:19 AM1/9/12
to modgr...@googlegroups.com
Tnanks Alex,

I think it is true that I can use tags or .get method.

Zunbeltz

ig., 2012.eko urtren 08a 22:05(e)an, Alex Stewart(e)k idatzi zuen:


--
Zunbeltz Izaola

Reply all
Reply to author
Forward
0 new messages