Recent Changes

Friday, November 17

  1. 8:42 am

Sunday, October 1

  1. 3:00 pm

Sunday, September 3

  1. msg += operator and user function for math equation message posted += operator and user function for math equation ah, i did not notice the tokens become a list if i use Group function. After removing the Group and…
    += operator and user function for math equation
    ah, i did not notice the tokens become a list if i use Group function. After removing the Group and use code like this, i got
    def assignVar(t):
        global vars_
        vars_=defaultdict(float)
        print('t0 is {}'.format(t[0]))
        vars_[t[0]]=t[-1]
    The var on lhs is updated with rhs value. If there is any better way, please let me know.
    Another question is on the funccall. I would need to map many user function to python function. In the excelExpr.py example the funcCall is actually an aggregation using MatchFirst of various functions. This seems a bit tedious as we need to a new line each time we have a new function and then append the new function name in the funcCall line. Is there easier way such as just using a dictionary?
    Sorry for all these many questions but i am glad to be able to make some progress little by little.
    6:12 am
  2. msg += operator and user function for math equation message posted += operator and user function for math equation Thanks for the clarification. Would you mind to give a simple example on how to assign the token va…
    += operator and user function for math equation
    Thanks for the clarification. Would you mind to give a simple example on how to assign the token value on rhs to variable on lhs? I tried something like this:
    assignmentExpr = Group(varname('lhs') + EQ('operator') + expr('rhs'))('assignment').addParseAction(lambda t: t[0] = t[-1])
    but i got an error
    SyntaxError: lambda cannot contain assignment

    Also, what is the difference between addParseAction and setParseAction?
    4:59 am

Saturday, September 2

  1. msg += operator and user function for math equation message posted += operator and user function for math equation The parsed data returned by pyparsing implements all the methods of a list so that it can be treate…
    += operator and user function for math equation
    The parsed data returned by pyparsing implements all the methods of a list so that it can be treated as a list (len, for i in result, result[0], etc.). If you *must* have a list (for JSON serialization, for example), you can use result.asList() and the parsed data will be converted to a nested list. Note that this will strip any defined results names, like" fname" or "argslist".

    augAssignOp won't really fit into into the infixNotation model because '+=' isn't really an operator. You can't write "x * (a += 14)". The '+=' can only occur as part of an enhanced assignment statement. So you should really implement '+=' as another form of assignment:

    EQ = Literal('=')
    PLUS_EQ = Literal('+=')
    assignmentExpr = varname('lhs') + EQ('operator') + arithExpr('rhs')
    augmentedAssignmentExpr = varname('lhs') + PLUS_EQ('operator') + arithExpr('rhs')

    and then have your overall parser match for "assignment | augmentedAssignment".

    statement_parser = assignmentExpr | augmentedAssignemtExpr

    You could attach a parse action to statement_parser that would look at the variable name in "lhs", the value in "rhs", and the assignment or augmented assignment based on whether "operator" was "=" or "+=".
    8:47 am
  2. msg += operator and user function for math equation message posted += operator and user function for math equation For my work, there is no exponential operation, and this makes things easier. But on the other hand…
    += operator and user function for math equation
    For my work, there is no exponential operation, and this makes things easier. But on the other hand, the user defined function is exactly like a python function and can take argument such as list or keyword argument (name = value). i plan to directly write those functions in python, so i just need to call those functions with parsed argument list.
    I have read more examples such as arith.py and excelExpr.py and discussion in this forum. And it seems infixNotation helps to simplify the definition of operators. But i am puzzled whether i should treat the brackets as an operator and if so how to do that.
    I have tried a bit with new style of code like below by making list a kind of parseelement instead of an operator
    from pyparsing import *
     
    compOp = oneOf("< > >= <=")
    multOp = oneOf("* /")
    addOp = oneOf("+ -")
    augassignOp = Literal('+=')
     
    EQ,LPAR,RPAR,LBRA,RBRA = map(Suppress, '=()[]')
     
    varname = Regex(r'[a-zA-Z_][a-zA-Z0-9_]*')
    fname = Regex(r'[a-zA-Z][a-zA-Z0-9_]*')
    decimalnumber = Regex(r'[+-]?\d+(\.\d*)?')
     
    expr = Forward()
    listmaker = Group(LBRA + delimitedList(expr) + RBRA)('list')
    funccall = Group(fname('fname') + LPAR + Group(delimitedList(expr))("arglist") + RPAR)
    operand = decimalnumber | listmaker | funccall | varname
    expr <<= infixNotation(operand,
        [
        (multOp, 2, opAssoc.LEFT),
        (addOp, 2, opAssoc.LEFT),
        (compOp, 2, opAssoc.LEFT),
    #    (augassignOp, 2, opAssoc.LEFT),
        ])
     
    l = ['cond(1,select(4,[2, 3]))']
     
    for item in l:
        source = item
        expr.runTests(source)

    The parsing seems to work as I got below result:
    cond(1,select(4,[2, 3]))
    [['cond', ['1', ['select', ['4', ['2', '3']]]]]]
    [0]:
      ['cond', ['1', ['select', ['4', ['2', '3']]]]]
      - arglist: ['1', ['select', ['4', ['2', '3']]]]
        [0]:
          1
        [1]:
          ['select', ['4', ['2', '3']]]
          - arglist: ['4', ['2', '3']]
            - list: ['2', '3']
          - fname: 'select'
      - fname: 'cond'

    But i am puzzled how to pass the argument back to the function as a list. Also i have not figured out how to handle the keyword argument.

    Also, i am still stuck at the augassignOp because i cannot use a lambda expression like l"ambda a, b: a = a + b" as shown in the airth.py example.

    Would appreciate any feedback. Thanks.
    6:28 am

Tuesday, August 29

  1. msg Odd .copy() behaviour message posted Odd .copy() behaviour Haven't forgotten you - I looked back through history to see what the impetus was for this change, …
    Odd .copy() behaviour
    Haven't forgotten you - I looked back through history to see what the impetus was for this change, but did not see the specific bug or case that inspired it. I did make your change and reran my unit tests, and all appears to be okay, but I still want to revisit my history dive.

    Thanks for your patience,
    -- Paul
    5:07 am

Sunday, August 27

  1. msg += operator and user function for math equation message posted += operator and user function for math equation I am new to parsing and have just come accross this tool which looks great. For my work, I need …
    += operator and user function for math equation
    I am new to parsing and have just come accross this tool which looks great.

    For my work, I need to parse multiple lines of math equations with variables and user defined functions inside. For example, with 3 lines of string:
    x = 1
    y = Max(1,2)
    x += y
    I want to be able to get x = 3 and y = 2 at the end.

    Below is my attempt on this. I am just trying to make a slight modification to the fourFn.py and SimpleCalc.py examples in the wiki page.
    import operator
    from pyparsing import Literal,Word,Combine,Optional,ZeroOrMore,Forward,nums,\
        alphas
    from collections import defaultdict
     
    def main():
        global exprStack
        exprStack = []
        global varStack
        varStack  = []
        global variables
        variables = defaultdict(float)
        l = ['x=1','y=abs(2)', 'x+=y']
        for item in l:
            source = item
            L = BNF().parseString( source )
            print(L)
            result = evaluateStack( exprStack[:] )
            print(varStack)
            print(result)
            variables[varStack.pop()]=result
            print(variables)
     
    def Scalar(x):
        return x
     
    def pushFirst( strg, loc, toks ):
        exprStack.append( toks[0] )
     
    def assignVar( strg, loc, toks ):
        varStack.append( toks[0] )
     
    bnf = None
    def BNF():
        """
        expop   :: '^'
        multop  :: '*' | '/'
        addop   :: '+' | '-'
        integer :: ['+' | '-'] '0'..'9'+
        atom    :: real | fn '(' expr ')' | '(' expr ')'
        factor  :: atom [ expop factor ]*
        term    :: factor [ multop factor ]*
        expr    :: term [ addop term ]*
        iaddop  :: '+='
        assign  :: '='
        """
        global bnf
        if not bnf:
            point = Literal( "." )
            fnumber = Combine( Word( "+-"+nums, nums ) + 
                               Optional( point + Optional( Word( nums ) ) ))
            ident = Word(alphas+"_", alphas+nums+"_")
     
            plus  = Literal( "+" )
            minus = Literal( "-" )
            mult  = Literal( "*" )
            div   = Literal( "/" )
            lpar  = Literal( "(" ).suppress()
            rpar  = Literal( ")" ).suppress()
            addop  = plus | minus
            multop = mult | div
            expop = Literal( "^" )
            assign = Literal( "=" )
            iaddop = Literal("+=")
     
            expr = Forward()
            atom = ( fnumber | ident + lpar + expr + rpar | ident ).setParseAction(pushFirst) | ( lpar + expr.suppress() + rpar )
     
            # by defining exponentiation as "atom [ ^ factor ]..." instead of "atom [ ^ atom ]...", we get right-to-left exponents, instead of left-to-righ
            # that is, 2^3^2 = 2^(3^2), not (2^3)^2.
            factor = Forward()
            factor << atom + ZeroOrMore( ( expop + factor ).setParseAction( pushFirst ) )
     
            term = factor + ZeroOrMore( ( multop + factor ).setParseAction( pushFirst ) )
            expr << term + ZeroOrMore( ( addop + term ).setParseAction( pushFirst ) )
            bnf =  ident.setParseAction(assignVar) + (assign | iaddop.setParseAction( pushFirst )) + expr
        return bnf
     
    # map operator symbols to corresponding arithmetic operations
    opn = { "+" : operator.add,
            "-" : operator.sub,
            "*" : operator.mul,
            "/" : operator.truediv,
            "^" : operator.pow,
            "+=" : operator.iadd}
    fn  = { "Max" : max,
            "Min" : min,
            "abs" : abs,
           "Scalar" : Scalar}
     
    def evaluateStack( s ):
        op = s.pop() 
        if op in "+-*/^" or op in '+=':
            op2 = evaluateStack( s )
            op1 = evaluateStack( s )
            return opn[op]( op1, op2 )
        elif op in fn:
            return fn[op]( evaluateStack( s ) )
        elif op in variables:
            return variables[op]        
        else:
            return float( op )
     
    if __name__ == '__main__':
        main()

    But I have faced two issues.
    1. The += operator is not working as expected. With input string as ['x=1','y=2', 'x+=y'], I still get x= 1 in the end. <-- defaultdict(<class 'float'>, {'x': 1.0, 'y': 2.0})
    2. My user defined funciton name will have the same name convention as the variable name convention. The only difference is that the function will have parentheses followed. I tried to modify the atom definition but it is not working as expected. With input string as ['x=1','y=abs(2)', 'x+=y'], I got a ValueError: could not convert string to float: 'y'.

    Would you help to shred some lights on how to fix the problem? Thanks.
    7:25 pm

Monday, August 21

  1. user_add ckot71 ckot71 joined pyparsing
    6:36 am

Friday, August 18

  1. msg schemaSQL.parseFile(f) fails if parseAll=True attemted message posted schemaSQL.parseFile(f) fails if parseAll=True attemted Thanks for your help again!!! Haven't yet mastered virtualenv (I installed virtualenvwrapper-win …
    schemaSQL.parseFile(f) fails if parseAll=True attemted
    Thanks for your help again!!!
    Haven't yet mastered virtualenv (I installed virtualenvwrapper-win on windows), but tracked down and deleted all the pyparsing.pyc-s windows could find, and checked the version in every pyparsing.py source windows could find.
    To my great embarrassment the ONLY 1.4.11 was the one I downloaded from somewhere during internet search and put it right next to my source in the eclipse workspace.
    The others ranged from 2.0.1.10 - 2.2.0 (I recently installed with pip).
    After clearing that and restarting eclips the version is 2.2.0 (Yayyyy!)
    No if only I could fix the tcl/tk so mathplotlip could work :)
    10:42 am

More