diff --git a/examples/golike.py b/examples/golike.py index 2db6fb6..3199557 100644 --- a/examples/golike.py +++ b/examples/golike.py @@ -1,11 +1,20 @@ import gll -ws = gll.many(gll.whitespace) +ws = gll.skipmany(gll.whitespace()) +skipped = lambda pat: gll.skip(gll.string(pat)) -function = function +body = gll.seq(skipped("{"), skipped("}")) -package_name = gll.seq(gll.skip(gll.string("package")), gl.skip(ws), - gll.regex(".*$"), tag="package_name") +argument = gll.seq(gll.regex("\w+", tag="argument"), ws, + gll.regex("\w+", tag="type"), gll.skip(gll.regex("[\s,]*"))) +arguments_list = gll.seq(skipped("("), gll.many(argument), skipped(")"), tag="arguments") + +function = gll.seq(skipped("func"), ws, gll.regex("\w+", tag="function_name"), + ws, arguments_list, ws, body, ws, tag="function") + +package_name = gll.seq(skipped("package"), ws, gll.regex("\w+", tag="name"), + gll.skipmany(gll.string(" ")), skipped("\n"), + tag="package_name") package = gll.seq(package_name, gll.many(function, tag="package_body"), tag="package") diff --git a/gll/parser.py b/gll/parser.py index 5059886..2e5cf89 100644 --- a/gll/parser.py +++ b/gll/parser.py @@ -1,5 +1,6 @@ import re +from gll.util import rename from gll.result import Success, Failure class Parser: @@ -11,6 +12,7 @@ class Parser: return self.fun(string) def __or__(self, other): + @rename("{}_alt_{}".format(self.tag, other.tag)) def internal(string): res = self(string) @@ -20,6 +22,7 @@ class Parser: return Parser(internal) def __rshift__(self, into): + @rename("{}_into_{}".format(self.tag, self.into)) def internal(string): res = self(string) return Success(into(res.value), res.rest, self.tag) @@ -27,6 +30,7 @@ class Parser: def string(match, tag=None): + @rename("string_{}".format(match)) def internal(string): ln = len(match) if len(string) < ln: @@ -43,16 +47,20 @@ def string(match, tag=None): def regex(match, tag=None, reopts=None): if not reopts: reopts = [] - rx = regex.compile(match, *reopts) + rx = re.compile(match, *reopts) + + @rename("regex_{}".format(match)) def internal(string): res = rx.match(string) if res: - return Success(res.group(0), string[endpos+1:], tag) + group = res.group(0) + return Success(group, string[res.end():], tag) return Failure(string) return Parser(internal, tag) def digit(tag=None): + @rename("digit") def internal(string): if not string: return Failure(string) @@ -65,6 +73,7 @@ def digit(tag=None): def many(parser, tag=None): + @rename("many_{}".format(parser.tag)) def internal(string): res = parser(string) @@ -81,6 +90,7 @@ def many(parser, tag=None): def many1(parser, tag=None): + @rename("many1_{}".format(parser.tag)) def internal(string): res = parser(string) @@ -97,16 +107,20 @@ def many1(parser, tag=None): def whitespace(tag=None): + @rename("whitespace") def internal(string): + if not string: + return Failure(string) head = string[0] tail = string[1:] - if head.strip == "": + if head.strip() == "": return Success(head, tail, tag) return Failure(string) return Parser(internal, tag) def skip(parser, tag=None): + @rename("skip_{}".format(parser.tag)) def internal(string): res = parser(string) @@ -121,6 +135,7 @@ def skipmany(parser, tag=None): def opt(parser, tag=None): + @rename("opt_{}".format(parser.tag)) def internal(string): res = parser(string) if res.valid: @@ -130,6 +145,7 @@ def opt(parser, tag=None): def seq(*parsers, tag=None): + @rename("seq_{}".format("_".join(str(parser.tag) for parser in parsers))) def internal(string): resl = [] rest = string @@ -143,6 +159,7 @@ def seq(*parsers, tag=None): return Parser(internal, tag) def all(parser, tag=None): + @rename("all_{}".format(parser.tag)) def internal(string): res = parser(string) diff --git a/gll/result.py b/gll/result.py index 2621bd7..e3aafd8 100644 --- a/gll/result.py +++ b/gll/result.py @@ -34,7 +34,7 @@ class Success(Result): def __bool__(self): return bool(self.value) - def tokens(self, purge=False, inner=False): + def tokens(self, purge=True, inner=False): if type(self.value) == list: for val in self.value: if type(val) == Success: @@ -43,6 +43,8 @@ class Success(Result): yield tok else: toks = list(val.tokens(purge, inner=True)) + if not len(toks) and purge: + continue if len(toks) == 1: toks = toks[0] yield Token(toks, tag=val.tag) diff --git a/gll/util.py b/gll/util.py new file mode 100644 index 0000000..7e3413d --- /dev/null +++ b/gll/util.py @@ -0,0 +1,5 @@ +def rename(name): + def wrapped(f): + f.__name__ = name + return f + return wrapped