topdown - Python module for text parsing (v1.0)

version:
1.0
license:
MIT
published date:
Nov 1 2010
repository:
https://bitbucket.org/ckuwata/topdown

example: simple calculator

from topdown import *
from operator import *

def num(seq):
    e = seq.parse(Regex('-?[0-9]+'))
    return int(e)

def op1(seq):
    e = seq.parse(list('+-'))
    if e == '+':
        o = add
    else:
        o = sub
    return lambda a, b: (o, a, b)

def op2(seq):
    e = seq.parse(list('*/'))
    if e == '*':
        o = mul
    else:
        o = div
    return lambda a, b: (o, a, b)

def factor(seq):
    def _factor(s):
        p1 = s.parse('(')
        e = expr(s)
        p2 = s.parse(')')
        return e
    return seq.parse([num, _factor])

term = chainl(factor, op2)
expr = chainl(term, op1)


def evaluate(tree):
    if isinstance(tree, int):
        return tree
    o = tree[0]
    l = tree[1]
    r = tree[2]
    if not isinstance(l, int):
        l = evaluate(l)
    if not isinstance(r, int):
        r = evaluate(r)
    return o(l, r)

def calc(s):
    t = expr.run(s.strip(), auto_remove_ws=True)
    return evaluate(t)

def main():
    while True:
        try:
            s = raw_input('>>> ')
        except EOFError:
            print
            break
        try:
            c = calc(s)
        except ParseFailed, e:
            print 'Invalid expression: %s' % s
        else:
            print c

if __name__ == '__main__':
    main()

changes

Jun 11 2011
version 1.1
new function `keyword`
chainl can takes optional keyword argument `allow_trailing_operator`
improved exception handling
Nov 1 2010
version 1.0