Search code examples
pythonpyparsing

How to get values of a pyparsing parser from parseAction


I have this pyparsing variable in a class:

def takeval(type, name, value):
     #do stuff with args
    
self.variable = pp.Optional(self.let_ | self.const_ | self.var_).set_results_name('vartype') ^ self.varname ^ self.set_ ^ self.object
#I want to set the function

self.variable = self.variable.setParseAction(takeval(vartype, varname, object))

How would I get the values of vartype, varname and object from a parse action?

  • I want vartype to be the value of one of: self.let_, self.const_ or self.var_
  • I want varname to be the value of self.varname
  • I wan object to be the value of self.object

Example of goal output:

I parse the string: 'const hi = "hello"'

I want 'const', 'hi', 'hello' to be sent to the target function.

Any help appreciated!


Solution

  • I have even three versions for you.

    • Version 1 needs for each of you parser actions a separate call parser action.
    • Verison 2 needs only one such function.
    • Version 3 needs nothing of such but the caller code is not so nice any more.

    Normally I use the result names a lot. But for simplification I did not do this in this example.

    from pyparsing import *
    
    class Parser:
        
      def takeval(self, type, name, value):
        print("Type is " + type)
        print("Name is " + name)
        print("Value is "+ value)
      
      # For version 1
      def call_takeval(self, s, loc, toks):
        self.takeval(toks[0], toks[1], toks[2])
      
      # For version 2
      def as_parse_action(self, parse_action):
        def call_parse_action(s, loc, toks):
          parse_action(toks[0], toks[1], toks[2])
        return call_parse_action
      
      
      def __init__(self):
      
        self.let_ = Literal("let")
        self.const_ = Literal("const")
        self.var_ = Literal("var")
        self.varname = Word(alphas)
        self.set_ = Literal("=")
        self.obj = Literal('"').suppress() + Word(alphas) + Literal('"').suppress()
        
        self.variable_version_1 = Optional(self.let_ | self.const_ | self.var_).setResultsName('vartype') \
            + self.varname.setResultsName('varname') + self.set_.suppress() + self.obj.setResultsName('varobj')
        
        self.variable_version_2 = Optional(self.let_ | self.const_ | self.var_).setResultsName('vartype') \
            + self.varname.setResultsName('varname') + self.set_.suppress() + self.obj.setResultsName('varobj')
        
        self.variable_version_3 = Optional(self.let_ | self.const_ | self.var_).setResultsName('vartype') \
            + self.varname.setResultsName('varname') + self.set_.suppress() + self.obj.setResultsName('varobj')
    
        self.variable_version_1 = self.variable_version_1.setParseAction(self.call_takeval)
        
        self.variable_version_2 = self.variable_version_2.setParseAction(self.as_parse_action(self.takeval))
        
        self.variable_version_3 = self.variable_version_2.setParseAction( \
            lambda s, loc, toks : self.takeval(toks[0], toks[1], toks[2]))
        
        
        
      def parse(self, text):
        print("Version 1:")
        self.variable_version_1.parseString(text)
        print("Version 2:")
        self.variable_version_2.parseString(text)
        print("Version 3:")
        self.variable_version_3.parseString(text)
    
    
    
    test_string = 'const hi = "hello"'
    parser = Parser()
    parser.parse(test_string)