def Node(margin): return P.seclude(P.match(r'( {%d,})' % margin) + swallow(lambda indent: (line + Node(len(indent)+1).star()) >> P.hug))
a_literal = one_of(builder.literals) a_keyword = one_of(builder.keywords) lex_grammar_source = r""" token* :end. token : whitespace | :keyword :Token | :punct :Token | ident | integer. whitespace : /\s+/ | comment. comment : '(*' in_comment* '*)'. in_comment : comment | !'*)' :anyone. # XXX are comments nested in Oberon-0? ident : /([A-Za-z][A-Za-z0-9]*)/ :'#IDENT' :Token. integer : /(\d+)/ :'#INTEGER' :Token. """ lex_grammar = Grammar(lex_grammar_source)(Token = lambda s, kind=None: Token(kind or s, s), keyword = match(r'(%s)\b' % a_keyword), punct = match(r'(%s)' % a_literal)) ## import sys; sys.setrecursionlimit(5000) ## import glob ## from parson import exceptionally ## for filename in sorted(glob.glob('ob-bad/*.ob')): print exceptionally(lambda: test(filename)) #. testing ob-bad/badassign.ob #. (top, ('MODULE', 'badassign', ';', 'BEGIN'), ('1', ':=', '2', 'END', 'badassign', '.')) #. testing ob-bad/commentnoend.ob #. ((literal('') ((token)* end)), "MODULE commentnoend;\n (* started off well,\n but didn't finish\nEND commentnoend.\n", '') #. testing ob-bad/keywordasname.ob #. (top, ('MODULE',), ('END', ';', 'END', 'END', '.')) #. testing ob-bad/repeatsection.ob #. (top, ('MODULE', 'repeatsection', ';', 'CONST', 'aconst', '=', '10', ';'), ('CONST', 'aconst', '=', '20', ';', 'END', 'repeatsection', '.'))
Parse an outline using indentation. After Higher Order Perl, section 8.6. """ import parson as P def swallow(fn): return P._Peg('swallow', lambda s, far, (i, vals): fn(*vals).run(s, far, (i, ()))) def Node(margin): return P.seclude(P.match(r'( {%d,})' % margin) + swallow(lambda indent: (line + Node(len(indent)+1).star()) >> P.hug)) line = '* ' + P.match(r'(.*)\n?') outline = Node(0).star() + ~P.anyone eg = """\ * Hello * Aloha * Bonjour * Adieu * also * Whatever * yay?""" ## from pprint import pprint; pprint(outline(eg)) #. (('Hello', ('Aloha', ('Bonjour',), ('Adieu',)), ('also',)),
""" Word-count function. """ from parson import match, feed blanks = match(r'\s*') marks = match(r'\S+') zero = feed(lambda: 0) add1 = feed(lambda n: n+1) wc = zero + blanks + (add1 + marks + blanks).star() ## wc(' ') #. (0,) ## wc('a b c ') #. (3,) ## wc(example_input) #. (10,) example_input = r""" hi there hey how are you? fine. thanks. ok then."""