2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 93ed340e authored by Eckhart Arnold's avatar Eckhart Arnold
Browse files

- made ptype parameter implicit (again)

parent 08eef33e
...@@ -205,17 +205,19 @@ class ParserMetaClass(type): ...@@ -205,17 +205,19 @@ class ParserMetaClass(type):
class Parser(metaclass=ParserMetaClass): class Parser(metaclass=ParserMetaClass):
def __init__(self, name='', ptype=''): def __init__(self, name=''):
assert isinstance(name, str), str(name) assert isinstance(name, str), str(name)
assert not ptype or ptype[0] == ':'
self.name = name self.name = name
self.ptype = ptype or ':' + self.__class__.__name__
# self.pbases = {cls.__name__ for cls in inspect.getmro(self.__class__)} # self.pbases = {cls.__name__ for cls in inspect.getmro(self.__class__)}
self._grammar = None # center for global variables etc. self._grammar = None # center for global variables etc.
self.reset() self.reset()
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
return self.__class__(self.name, self.ptype) return self.__class__(self.name)
@property
def ptype(self):
return ':' + self.__class__.__name__
def reset(self): def reset(self):
self.visited = dict() self.visited = dict()
...@@ -474,11 +476,11 @@ class ScannerToken(Parser): ...@@ -474,11 +476,11 @@ class ScannerToken(Parser):
indented block. Otherwise indented block are difficult to handle indented block. Otherwise indented block are difficult to handle
with parsing expression grammars. with parsing expression grammars.
""" """
def __init__(self, scanner_token, ptype=''): def __init__(self, scanner_token):
assert isinstance(scanner_token, str) and scanner_token and \ assert isinstance(scanner_token, str) and scanner_token and \
scanner_token.isupper() scanner_token.isupper()
assert RX_SCANNER_TOKEN.match(scanner_token) assert RX_SCANNER_TOKEN.match(scanner_token)
super(ScannerToken, self).__init__(scanner_token, ptype) super(ScannerToken, self).__init__(scanner_token)
def __call__(self, text): def __call__(self, text):
if text[0:1] == BEGIN_SCANNER_TOKEN: if text[0:1] == BEGIN_SCANNER_TOKEN:
...@@ -515,8 +517,8 @@ class RegExp(Parser): ...@@ -515,8 +517,8 @@ class RegExp(Parser):
other parsers delegate part of the parsing job to other parsers, other parsers delegate part of the parsing job to other parsers,
but do not match text directly. but do not match text directly.
""" """
def __init__(self, regexp, name='', ptype=''): def __init__(self, regexp, name=''):
super(RegExp, self).__init__(name, ptype) super(RegExp, self).__init__(name)
self.regexp = re.compile(regexp) if isinstance(regexp, str) else regexp self.regexp = re.compile(regexp) if isinstance(regexp, str) else regexp
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
...@@ -525,7 +527,7 @@ class RegExp(Parser): ...@@ -525,7 +527,7 @@ class RegExp(Parser):
regexp = copy.deepcopy(self.regexp, memo) regexp = copy.deepcopy(self.regexp, memo)
except TypeError: except TypeError:
regexp = self.regexp.pattern regexp = self.regexp.pattern
return RegExp(regexp, self.name, self.ptype) return RegExp(regexp, self.name)
def __call__(self, text): def __call__(self, text):
match = text[0:1] != BEGIN_SCANNER_TOKEN and self.regexp.match(text) # ESC starts a scanner token. match = text[0:1] != BEGIN_SCANNER_TOKEN and self.regexp.match(text) # ESC starts a scanner token.
...@@ -538,10 +540,8 @@ class RegExp(Parser): ...@@ -538,10 +540,8 @@ class RegExp(Parser):
return self.name or self.ptype + ' /%s/' % self.regexp.pattern return self.name or self.ptype + ' /%s/' % self.regexp.pattern
def Whitespace(re_wsp='\s*'): class Whitespace(RegExp):
rx_parser = RegExp(re_wsp) assert WHITESPACE_PTYPE == ":Whitespace"
rx_parser.ptype = WHITESPACE_PTYPE
return rx_parser
class RE(Parser): class RE(Parser):
...@@ -557,7 +557,7 @@ class RE(Parser): ...@@ -557,7 +557,7 @@ class RE(Parser):
respective parameters in the constructor are set to ``None`` the respective parameters in the constructor are set to ``None`` the
default whitespace expression from the Grammar object will be used. default whitespace expression from the Grammar object will be used.
""" """
def __init__(self, regexp, wL=None, wR=None, name='', ptype=''): def __init__(self, regexp, wL=None, wR=None, name=''):
"""Constructor for class RE. """Constructor for class RE.
Args: Args:
...@@ -573,7 +573,7 @@ class RE(Parser): ...@@ -573,7 +573,7 @@ class RE(Parser):
See above. See above.
name: The optional name of the parser. name: The optional name of the parser.
""" """
super(RE, self).__init__(name, ptype) super(RE, self).__init__(name)
self.wL = wL self.wL = wL
self.wR = wR self.wR = wR
self.wspLeft = Whitespace(wL) if wL else ZOMBIE_PARSER self.wspLeft = Whitespace(wL) if wL else ZOMBIE_PARSER
...@@ -585,7 +585,7 @@ class RE(Parser): ...@@ -585,7 +585,7 @@ class RE(Parser):
regexp = copy.deepcopy(self.main.regexp, memo) regexp = copy.deepcopy(self.main.regexp, memo)
except TypeError: except TypeError:
regexp = self.main.regexp.pattern regexp = self.main.regexp.pattern
return self.__class__(regexp, self.wL, self.wR, self.name, self.ptype) return self.__class__(regexp, self.wL, self.wR, self.name)
def __call__(self, text): def __call__(self, text):
# assert self.main.regexp.pattern != "@" # assert self.main.regexp.pattern != "@"
...@@ -622,15 +622,15 @@ class RE(Parser): ...@@ -622,15 +622,15 @@ class RE(Parser):
self.main.apply(func) self.main.apply(func)
def Token(token, wL=None, wR=None, name=''): class Token(RE):
"""Returns an RE-parser that matches plain strings that are assert TOKEN_PTYPE == ":Token"
considered as 'tokens'.
def __init__(self, token, wL=None, wR=None, name=''):
The parser's name will be set to the TOKEN_PTYPE, making it easy to self.token = token
identify tokens in the abstract syntax tree transformation and super(Token, self).__init__(escape_re(token), wL, wR, name)
compilation stage.
""" def __deepcopy__(self, memo={}):
return RE(escape_re(token), wL, wR, name, TOKEN_PTYPE) return self.__class__(self.token, self.wL, self.wR, self.name)
def mixin_comment(whitespace, comment): def mixin_comment(whitespace, comment):
...@@ -654,14 +654,14 @@ def mixin_comment(whitespace, comment): ...@@ -654,14 +654,14 @@ def mixin_comment(whitespace, comment):
class UnaryOperator(Parser): class UnaryOperator(Parser):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(UnaryOperator, self).__init__(name, ptype) super(UnaryOperator, self).__init__(name)
assert isinstance(parser, Parser) assert isinstance(parser, Parser)
self.parser = parser self.parser = parser
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
parser = copy.deepcopy(self.parser, memo) parser = copy.deepcopy(self.parser, memo)
return self.__class__(parser, self.name, self.ptype) return self.__class__(parser, self.name)
def apply(self, func): def apply(self, func):
if super(UnaryOperator, self).apply(func): if super(UnaryOperator, self).apply(func):
...@@ -669,14 +669,14 @@ class UnaryOperator(Parser): ...@@ -669,14 +669,14 @@ class UnaryOperator(Parser):
class NaryOperator(Parser): class NaryOperator(Parser):
def __init__(self, *parsers, name='', ptype=''): def __init__(self, *parsers, name=''):
super(NaryOperator, self).__init__(name, ptype) super(NaryOperator, self).__init__(name)
assert all([isinstance(parser, Parser) for parser in parsers]), str(parsers) assert all([isinstance(parser, Parser) for parser in parsers]), str(parsers)
self.parsers = parsers self.parsers = parsers
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
parsers = copy.deepcopy(self.parsers, memo) parsers = copy.deepcopy(self.parsers, memo)
return self.__class__(*parsers, name=self.name, ptype=self.ptype) return self.__class__(*parsers, name=self.name)
def apply(self, func): def apply(self, func):
if super(NaryOperator, self).apply(func): if super(NaryOperator, self).apply(func):
...@@ -685,8 +685,8 @@ class NaryOperator(Parser): ...@@ -685,8 +685,8 @@ class NaryOperator(Parser):
class Optional(UnaryOperator): class Optional(UnaryOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(Optional, self).__init__(parser, name, ptype) super(Optional, self).__init__(parser, name)
assert isinstance(parser, Parser) assert isinstance(parser, Parser)
assert not isinstance(parser, Optional), \ assert not isinstance(parser, Optional), \
"Nesting options would be redundant: %s(%s)" % \ "Nesting options would be redundant: %s(%s)" % \
...@@ -718,8 +718,8 @@ class ZeroOrMore(Optional): ...@@ -718,8 +718,8 @@ class ZeroOrMore(Optional):
class OneOrMore(UnaryOperator): class OneOrMore(UnaryOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(OneOrMore, self).__init__(parser, name, ptype) super(OneOrMore, self).__init__(parser, name)
assert not isinstance(parser, Optional), \ assert not isinstance(parser, Optional), \
"Use ZeroOrMore instead of nesting OneOrMore and Optional: " \ "Use ZeroOrMore instead of nesting OneOrMore and Optional: " \
"%s(%s)" % (str(name), str(parser.name)) "%s(%s)" % (str(name), str(parser.name))
...@@ -742,8 +742,8 @@ class OneOrMore(UnaryOperator): ...@@ -742,8 +742,8 @@ class OneOrMore(UnaryOperator):
class Sequence(NaryOperator): class Sequence(NaryOperator):
def __init__(self, *parsers, name='', ptype=''): def __init__(self, *parsers, name=''):
super(Sequence, self).__init__(*parsers, name=name, ptype=ptype) super(Sequence, self).__init__(*parsers, name=name)
assert len(self.parsers) >= 1 assert len(self.parsers) >= 1
def __call__(self, text): def __call__(self, text):
...@@ -762,8 +762,8 @@ class Sequence(NaryOperator): ...@@ -762,8 +762,8 @@ class Sequence(NaryOperator):
class Alternative(NaryOperator): class Alternative(NaryOperator):
def __init__(self, *parsers, name='', ptype=''): def __init__(self, *parsers, name=''):
super(Alternative, self).__init__(*parsers, name=name, ptype=ptype) super(Alternative, self).__init__(*parsers, name=name)
assert len(self.parsers) >= 1 assert len(self.parsers) >= 1
assert all(not isinstance(p, Optional) for p in self.parsers) assert all(not isinstance(p, Optional) for p in self.parsers)
...@@ -783,8 +783,8 @@ class Alternative(NaryOperator): ...@@ -783,8 +783,8 @@ class Alternative(NaryOperator):
class FlowOperator(UnaryOperator): class FlowOperator(UnaryOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(FlowOperator, self).__init__(parser, name, ptype) super(FlowOperator, self).__init__(parser, name)
class Required(FlowOperator): class Required(FlowOperator):
...@@ -803,8 +803,8 @@ class Required(FlowOperator): ...@@ -803,8 +803,8 @@ class Required(FlowOperator):
class Lookahead(FlowOperator): class Lookahead(FlowOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(Lookahead, self).__init__(parser, name, ptype) super(Lookahead, self).__init__(parser, name)
def __call__(self, text): def __call__(self, text):
node, text_ = self.parser(text) node, text_ = self.parser(text)
...@@ -835,8 +835,8 @@ def iter_right_branch(node): ...@@ -835,8 +835,8 @@ def iter_right_branch(node):
class Lookbehind(FlowOperator): class Lookbehind(FlowOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(Lookbehind, self).__init__(parser, name, ptype) super(Lookbehind, self).__init__(parser, name)
print("WARNING: Lookbehind Operator is experimental!") print("WARNING: Lookbehind Operator is experimental!")
def __call__(self, text): def __call__(self, text):
...@@ -875,8 +875,8 @@ class NegativeLookbehind(Lookbehind): ...@@ -875,8 +875,8 @@ class NegativeLookbehind(Lookbehind):
class Capture(UnaryOperator): class Capture(UnaryOperator):
def __init__(self, parser, name='', ptype=''): def __init__(self, parser, name=''):
super(Capture, self).__init__(parser, name, ptype) super(Capture, self).__init__(parser, name)
print("WARNING: Capture operator is experimental") print("WARNING: Capture operator is experimental")
def __call__(self, text): def __call__(self, text):
...@@ -890,16 +890,16 @@ class Capture(UnaryOperator): ...@@ -890,16 +890,16 @@ class Capture(UnaryOperator):
class Retrieve(Parser): class Retrieve(Parser):
def __init__(self, symbol, counterpart=None, name='', ptype=''): def __init__(self, symbol, counterpart=None, name=''):
if not name: if not name:
name = symbol.name name = symbol.name
super(Retrieve, self).__init__(name, ptype) super(Retrieve, self).__init__(name)
self.symbol = symbol self.symbol = symbol
self.counterpart = counterpart if counterpart else lambda value: value self.counterpart = counterpart if counterpart else lambda value: value
print("WARNING: Retrieve operator is experimental") print("WARNING: Retrieve operator is experimental")
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
return self.__class__(self.symbol, self.counterpart, self.name, self.ptype) return self.__class__(self.symbol, self.counterpart, self.name)
def __call__(self, text): def __call__(self, text):
stack = self.grammar.variables[self.symbol.name] stack = self.grammar.variables[self.symbol.name]
......
...@@ -330,4 +330,4 @@ class TestBoundaryCases: ...@@ -330,4 +330,4 @@ class TestBoundaryCases:
if __name__ == "__main__": if __name__ == "__main__":
from run import runner from run import runner
runner("TestBoundaryCases", globals()) runner("", globals())
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment