I'm trying to parse a simple key = value query language. I've actually accomplished it with a huge monstrosity parser that I then make a second pass through to clean up the parse tree. What I'd like to do is make a clean parse from the bottom up, which includes things like using sets for the (key,val) pairs so redundant pairs are eliminated etc. While I got it working before, I don't feel like I fully understood why pyparsing was acting the way it was, so I did a lot of work arounds etc, sort of fighting against the grain.
Currently, here is the beginning of my "simplified" parser:
from pyparsing import *
bool_act = lambda t: bool(t[0])
int_act = lambda t: int(t[0])
def keyval_act(instring, loc, tokens):
return set([(tokens.k, tokens.v)])
def keyin_act(instring, loc, tokens):
return set([(tokens.k, set(tokens.vs))])
string = (
Word(alphas + '_', alphanums + '_')
| quotedString.setParseAction( removeQuotes )
)
boolean = (
CaselessLiteral('true')
| CaselessLiteral('false')
)
integer = Word(nums).setParseAction( int_act )
value = (
boolean.setParseAction(bool_act)
| integer
| string
)
keyval = (string('k') + Suppress('=') + value('v')
).setParseAction(keyval_act)
keyin = (
string('k') + Suppress(CaselessLiteral('in')) +
nestedExpr('{','}', content = delimitedList(value)('vs'))
).setParseAction(keyin_act)
grammar = keyin + stringEnd | keyval + stringEnd
Currently, the "grammar" nonterminal is just a stub, I will eventually add nestable conjunctions and disjunctions to the keys so that searches like this can be parsed:
a = 1, b = 2 , c in {1,2,3} | d = 4, ( e = 5 | e = 2, (f = 3, f = 4))
For now though, I am having trouble understanding how pyparsing calls my setParseAction functions. I know there is some magic in terms of how many arguments are passed, but I am getting an error where no arguments are being passed to the function at all. So currently, if I do:
grammar.parseString('hi in {1,2,3}')
I get this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 1021, in parseString
loc, tokens = self._parse( instring, 0 )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 894, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 2478, in parseImpl
ret = e._parse( instring, loc, doActions )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 894, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 2351, in parseImpl
loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 921, in _parseNoCache
tokens = fn( instring, tokensStart, retTokens )
File "/usr/lib/python2.6/site-packages/pyparsing.py", line 675, in wrapper
return func(*args[limit[0]:])
TypeError: keyin_act() takes exactly 3 arguments (0 given)
As you can see from the traceback, I'm using python2.6, and pyparsing 1.5.6
Can anyone give me some insight into why the function isn't getting the right number of arguments?