def test_non_halting_left_recursive(): h1 = fwd() h1.define(x + h1) ok_(not non_halting(h1)) h2 = fwd() h2.define(x + (h2 | x)) ok_(not non_halting(h2)) nh1 = fwd() nh1.define(nh1 + x) ok_(non_halting(nh1)) nh2 = fwd() nh2.define(x | nh2) ok_(non_halting(nh2)) nh3_fwd = fwd() nh3_fwd.define(nh3_fwd) nh3 = x + nh3_fwd + x ok_(non_halting(nh3)) nh4 = fwd() nh4.define(maybe(x) + nh4 + x) ok_(non_halting(nh4)) nh5 = fwd() nh5.define(many(x) + maybe(x) + nh5 + x) ok_(non_halting(nh5)) h3 = fwd() h3.define(maybe(x) + many(x) + x + h3) ok_(not non_halting(h3))
return unichr(int(m.group('unicode'), 16)) return re_esc.sub(sub, s) def make_string(n): return unescape(n[1:-1]) # JSON Grammar null = n('null') >> const(None) true = n('true') >> const(True) false = n('false') >> const(False) number = sometok('number') >> make_number string = sometok('string') >> make_string value = fwd() member = string + op_(':') + value >> tuple object = (op_('{') + maybe(member + many(op_(',') + member)) + op_('}') >> make_object) array = ( op_('[') + maybe(value + many(op_(',') + value)) + op_(']') >> make_array) value.define(null | true | false | object | array | number | string) json_text = object | array json_file = json_text + skip(eof) name_parser_vars(locals()) def parse(seq): 'Sequence(Token) -> object' return json_file.parse(seq)
string = sometok('string') >> make_string func = sometok('func') >> make_func value = number | name | string makeop = lambda s, f: op(s) >> const(f) add = makeop('+', (ets.add, operator.add)) sub = makeop('-', (ets.sub, operator.sub)) mul = makeop('*', (ets.mul, operator.mul)) div = makeop('/', (ets.div, operator.div)) mul_op = mul | div add_op = add | sub args = fwd() factor = fwd() primary = value call = func + op_('(') + args + op_(')') >> exec_func term = factor + many(mul_op + factor ) >> eval expr = term + many(add_op + term ) >> eval top = expr + skip(eof) args.define( expr + many( op_(',') + expr ) ) factor.define( call | primary | op_('(') + expr + op_(')') ) name_parser_vars(locals())
def make_object(n): return PLObject(n) def make_name(n): assert len(n) == 2 return PLName(n[0], n[1]) def make_array(n): return PLArray(n) number = sometok('number') >> make_number string = sometok('string') >> make_string comment = sometok('comment') >> make_comment name = (sometok('name') | sometok('string')) + maybe(comment) >> make_name value = fwd() member = name + op_('=') + value >> make_member section = maybe(comment) + oneplus(member + op_(';')) + maybe(comment) >> make_section object = ( op_('{') + many(section) + op_('}')) >> make_object array = ( op_('(') + many(value + op_(',')) + op_(')')) >> make_array value.define( object | number | name | array)
id + maybe(op_('=') + id) + skip(maybe(op(','))) >> unarg(Attr)) attr_list = ( many(op_('[') + many(a_list) + op_(']')) >> flatten) attr_stmt = ( (n('graph') | n('node') | n('edge')) + attr_list >> unarg(DefAttrs)) graph_attr = id + op_('=') + id >> make_graph_attr node_stmt = node_id + attr_list >> unarg(Node) # We use a fwd() because of circular definitions like (stmt_list -> stmt -> # subgraph -> stmt_list) subgraph = fwd() edge_rhs = skip(op('->') | op('--')) + (subgraph | node_id) edge_stmt = ( (subgraph | node_id) + oneplus(edge_rhs) + attr_list >> unarg(make_edge)) stmt = ( attr_stmt | edge_stmt | subgraph | graph_attr | node_stmt ) stmt_list = many(stmt + skip(maybe(op(';')))) subgraph.define(memoize(
'str -> Sequence(Token)' specs = [ ('space', (r'[ \t\r\n]+',)), ('int', (r'-?[1-9][0-9]*|0',)), ('true', (r'#t',)), ('false', (r'#f',)), ('char', (r'#\\[A-Za-z_0-9]',)), ('op', (r'[\[\]\(\)\']', re.VERBOSE)), ('name', (r'[A-Za-z_0-9\&\*\+\-\~!\=<>\^/,\?:;.]*',)), ] useless = ['space'] t = make_tokenizer(specs) return [x for x in t(str) if x.type not in useless] sexpr = fwd() integer = sometok('int') >> int symbol = sometok('name') >> Symbol true = sometok('true') >> const(True) false = sometok('false') >> const(False) boolean = true | false char = sometok('char') >> (lambda x: x[2]) dotlist = op_('(') + many(sexpr) + op_(')') >> (lambda x: x or None) quote = op_('\'') + sexpr >> (lambda x: [Symbol('quote'), sexpr]) sexpr.define( integer | symbol | boolean | char | dotlist )
else: s = n.decode("string-escape") return runtime.find("String" if prefix == "u" else "Bytes").clone(s) def make_terminator(n): return Message(n.value) operator = sometok("operator") identifier = sometok("identifier") string = sometok("string") >> make_string number = sometok("number") >> make_number expression = fwd() arguments = fwd() message = fwd() symbol = fwd() terminator = (op(";") | op("\r") | op("\n")) >> make_terminator expression.define(( many(message | terminator)) >> make_expression) message.define(((symbol + maybe(arguments)) | arguments) >> make_message) paren_arguments = op( "(") + maybe(expression) + many(skip(op_(",")) + expression) + op(")") bracket_arguments = op( "[") + maybe(expression) + many(skip(op_(",")) + expression) + op("]")