import gll @gll.parser("expression") def expression(string): parser = gll.seq(ws, func_call | literal, ws, tag="expression") return parser(string) ws = gll.skipmany(gll.string(" ")) skipped = lambda pat: gll.skip(gll.string(pat), tag="skip_{}".format(pat)) variable = gll.regex("\w+", tag="variable_name") type_decl = gll.regex("\w+", tag="type") comma = gll.skip(gll.regex(r"\s*,\s*")) number = gll.many1(gll.digit(), tag="number") string = gll.seq(skipped("\""), gll.regex(r'[^"\\]+'), skipped("\""), tag="string") lst = gll.seq(skipped("["), gll.sep_by(comma, expression | variable), skipped("]"), tag="list") declaration = gll.seq(skipped("var"), ws, variable, ws, type_decl, tag="declaration") assignment = gll.seq(variable, ws, skipped("="), ws, expression, tag="assignment") return_statement = gll.seq(skipped("return"), ws, expression, tag="return") func_call = gll.seq(variable, skipped("("), gll.sep_by(comma, expression | variable, tag="arguments"), skipped(")"), tag="call") literal = number | string | lst special = gll.seq(ws, return_statement | declaration | assignment, ws) body = gll.seq(skipped("{"), skipped("\n"), gll.sep_by(gll.regex(r"\s*\n+\s*"), expression | special, tag="body"), gll.opt(skipped("\n")), skipped("}")) argument = gll.seq(variable, ws, type_decl, tag="parameter") arguments_list = gll.seq(skipped("("), gll.sep_by(comma, argument), skipped(")"), tag="parameters") function = gll.seq(skipped("func"), ws, gll.regex("\w+", tag="function_name"), ws, arguments_list, ws, type_decl, ws, body, ws, tag="function") package_name = gll.seq(skipped("package"), ws, variable, gll.skipmany(gll.string(" ")), skipped("\n"), tag="package_name") package = gll.seq(package_name, gll.sep_by(gll.string("\n"), function, tag="package_body"), gll.many(skipped("\n")), tag="package") parser = gll.all(package)