def sdf_bond(): fst = yield P.string('\n') >> P.times(P.one_of(' 0123456789'), 3) fst = int(''.join(fst)) snd = yield P.times(P.one_of(' 0123456789'), 3) snd = int(''.join(snd)) bond_type = yield seperator >> num_i yield P.times(seperator >> num_i, 3) return SdfBond(fst, snd, bond_type)
def sdf_atom(): yield P.times(seperator >> num_f, 3) # coordinates atom_symb = yield seperator >> P.many(P.letter()) atom_symb = ''.join(atom_symb) dd = yield seperator >> num_i # mass delta ccc = yield seperator >> num_i # charge delta yield P.times(seperator >> num_i, 4) return SdfAtom(atom_symb, dd, ccc)
def sdf_molecule(): header = yield sdf_header atoms = yield P.times(sdf_atom, header.atom_num) bonds = yield P.times(sdf_bond, header.bond_num) yield seperator >> P.string('M') >> seperator >> P.string( 'END') >> seperator >> P.string('> <value>') value = yield seperator >> num_f yield seperator >> P.string('$$$$') return SdfMolecule(header, atoms, bonds, value)
def sdf_header(): mol_num = yield transparent >> num_i atom_num = yield P.string('\n\n\n') >> P.times(P.one_of(' 0123456789'), 3) atom_num = int(''.join(atom_num)) bond_num = yield P.times(P.one_of(' 0123456789'), 3) bond_num = int(''.join(bond_num)) yield P.times(seperator >> num_i, 5) yield seperator >> P.string("V2000") return SdfHeader(mol_num, atom_num, bond_num)
def FunCall(): fname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) found_args = yield ps.times(ActArgs, 0, 1) found_args = found_args[0] if len(found_args) > 0 else [] yield ps.token(TOKEN.PAR_CLOSE) return AST.FUNCALL(id=fname, kind=FunKind.FUNC, args=found_args)
def InfixOpDecl(): side = yield (ps.token(TOKEN.INFIXL) ^ ps.token(TOKEN.INFIXR)) if side.typ is TOKEN.INFIXL: found_kind = FunKind.INFIXL elif side.typ is TOKEN.INFIXR: found_kind = FunKind.INFIXR else: raise Exception("Should never happen") found_fixity = yield ps.token(TOKEN.INT) operator = yield ps.token(TOKEN.OP_IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) a = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.COMMA) b = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(InfFunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=found_kind, fixity=found_fixity, id=operator, params=[a, b], type=typesig, vardecls=decls, stmts=found_stmts)
def StmtFor(): yield ps.token(TOKEN.FOR) yield ps.token(TOKEN.PAR_OPEN) initial = yield ps.times(ActStmt, 0, 1) initial = initial[0] if len(initial) > 0 else None yield ps.token(TOKEN.SEMICOLON) condition = yield ps.times(Exp, 0, 1) condition = condition[0] if len(condition) > 0 else None yield ps.token(TOKEN.SEMICOLON) update = yield ps.times(ActStmt, 0, 1) update = update[0] if len(update) > 0 else None yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.LOOP(init=initial, cond=condition, update=update, stmts=contents)
def FunDecl(): fname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) args = yield ps.times(FArgs, 0, 1) args = args[0] if len(args) > 0 else args yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(FunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=FunKind.FUNC, fixity=None, id=fname, params=args, type=typesig, vardecls=decls, stmts=found_stmts)
def StmtIfElse(): yield ps.token(TOKEN.IF) yield ps.token(TOKEN.PAR_OPEN) condition = yield Exp yield ps.token(TOKEN.PAR_CLOSE) yield ps.token(TOKEN.CURL_OPEN) if_contents = yield ps.many(Stmt) yield ps.token(TOKEN.CURL_CLOSE) first_cond = AST.CONDBRANCH(expr=condition, stmts=if_contents) elifs = yield ps.many(StmtElif) elses = yield ps.times(StmtElse, 0, 1) return AST.IFELSE(condbranches=[first_cond, *elifs, *elses])
def PrefixOpDecl(): yield ps.token(TOKEN.PREFIX) operator = yield ps.token(TOKEN.OP_IDENTIFIER) yield ps.token(TOKEN.PAR_OPEN) varname = yield ps.token(TOKEN.IDENTIFIER) yield ps.token(TOKEN.PAR_CLOSE) typesig = yield ps.times(PreFunTypeSig, 0, 1) typesig = typesig[0] if len(typesig) > 0 else None yield ps.token(TOKEN.CURL_OPEN) decls = yield ps.many(VarDecl) found_stmts = yield ps.many1(Stmt) yield ps.token(TOKEN.CURL_CLOSE) return AST.FUNDECL(kind=FunKind.PREFIX, fixity=None, id=operator, params=[varname], type=typesig, vardecls=decls, stmts=found_stmts)
VERSION = b"\x00" ######################################## ## Reader ######################################## header = string(HEADER) version = string(VERSION) everything = regex(b"(?s).*") # don't forget newlines byte = regex(b"(?s).") char = byte.parsecmap(lambda x: unpack("b", x)[0]) short = regex(b"(?s).{2}").parsecmap(lambda x: unpack(">h", x)[0]) intp = regex(b"(?s).{4}").parsecmap(lambda x: unpack(">i", x)[0]) nbytes = lambda x: times(byte, x).parsecmap(lambda x: b"".join(x)) @generate def utf8_bytes(): """ Parses utf8 string, prefixed with length. """ length = yield short name = yield nbytes(length) return name.decode("utf8") @generate def kv_bytes(): """ Parses list of key values. """ kv = {} n = yield char
def ImportName(): found_name = yield AnyId found_alias = yield ps.times(ps.token(TOKEN.AS) >> AnyId, 0, 1) found_alias = found_alias[0] if len(found_alias) > 0 else None return AST.IMPORTNAME(name=found_name, alias=found_alias)
def StmtRet(): yield ps.token(TOKEN.RETURN) found_expr = yield ps.times(Exp, 0, 1) found_expr = found_expr[0] if len(found_expr) > 0 else None yield ps.token(TOKEN.SEMICOLON) return AST.RETURN(expr=found_expr)
vi_line = (number + typminmax) << ignore @generate("ratio") def ratio(): [num, den] = yield (separated(number, string("/"), 2, maxt=2, end=False) | na.result([0, 0])) if den: return num / den else: return None ramp_line = string("dV/dt_") >> ( (string("r").result("rising") | string("f").result("falling")) << ignore) + times(ratio, 1, 3) ex_line = word(string("Executable")) \ >> ((((string("L") | string("l")) >> string("inux")).result("linux") | \ ((string("W") | string("w")) >> string("indows")).result("windows")) \ << string("_") << many(none_of("_")) << string("_")) \ + lexeme(string("32") | string("64")) \ + count(name, 2) << ignore def manyTrue(p): "Run a parser multiple times, filtering ``False`` results." @generate("manyTrue") def fn(): "many(p) >> filter(True)" nodes = yield many(p)