Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """
- Trying funcparserlib parser combinator library. I skip lexing step and
- use funcparserlib in pyparsing style (I had to define some one-line helpers to
- do so).
- Number parsers:
- Read sign of the number
- >>> [ sign.parse(c) for c in ["+42","42", "-42"] ]
- [1, 1, -1]
- Parse integer
- >>> int_num.parse("-42")
- -42
- Parse fractional number (float)
- >>> [ frac_num.parse(c) for c in ["-1.25", "1.25", "42"] ]
- [-1.25, 1.25, 42.0]
- Helpers:
- >>> to_int(['4','2'])
- 42
- >>> powers(['4','2'])
- [('4', 1), ('2', 0)]
- >>> add_digit(1,(2,3))
- 2001
- Custom format parser:
- Using `ws` to skip whitespaces
- >>> ws.parse(" ")
- _Ignored([' ', ' ', ' '])
- Using `literal` to build literal parsers (to avoid explicit lexing)
- >>> literal("abc").parse("abc def")
- 'abc'
- Packing a list of characters as a string
- >>> pack(['a','b','c'])
- 'abc'
- Read a string of characters which satisfy given predicate
- >>> word(lambda c: c.isalpha() and c.isupper()).parse("ABCdef")
- 'ABC'
- Read the rest of the input as a string
- >>> whatever.parse("abcdef")
- 'abcdef'
- Finally,
- >>> raw = 'Inspection\\n# 2 SHOULD Ref. Sys 1\\n' + \
- 'X 28.75 \\nY 78.500 \\nZ -1.25 \\n\\n'
- >>> custom_format.parse(raw)
- (2, 1, [('X', 28.75), ('Y', 78.5), ('Z', -1.25)])
- """
- import sys
- from funcparserlib.parser import *
- ### helpers
- powers = lambda digs: zip(digs,xrange(len(digs)-1,-1,-1))
- add_digit = lambda acc, dp: acc+int(dp[0])*10**dp[1]
- to_int = lambda digs: reduce(add_digit, powers(digs), 0)
- mk_int = lambda (s,i): s*i
- to_frac = lambda digs: to_int(digs)*1.0/10**len(digs)
- mk_frac = lambda (s,i,f): s*(i+f)
- pack = lambda cs: ''.join(cs)
- ### parsers
- sign = maybe(a("-")|a("+")) >> (lambda c: c == "-" and -1 or +1)
- digits = many(some(lambda c: c.isdigit()))
- int_num = sign + (digits >> to_int) >> mk_int
- frac_num = sign + (digits >> to_int) + (skip(maybe(a("."))) + (digits >> to_frac)) >> mk_frac
- ws = skip(many(some(lambda c: c.isspace())))
- literal = lambda s: reduce(lambda a,b: a+b, map(a,s)) >> pack
- word = lambda p: oneplus(some(p)) >> pack
- whatever = word(lambda x:True)
- ### custom format parser
- varname = word(lambda c: c.isalpha())
- var = (ws + varname + ws + frac_num + ws)
- custom_format = skip(literal("Inspection")) + \
- ws + skip(literal("#")) + \
- ws + int_num + \
- ws + skip(literal("SHOULD")) + \
- ws + skip(literal("Ref. Sys")) + \
- ws + int_num + \
- many(var)
- if __name__ == '__main__':
- if "--test" in sys.argv:
- import doctest
- doctest.testmod()
- else:
- raw = sys.stdin.read()
- print custom_format.parse(raw)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement