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

Commit a8103ec5 authored by Eckhart Arnold's avatar Eckhart Arnold

tuned Parser deepcopy

parent 318987ab
......@@ -352,13 +352,13 @@ class EBNFCompiler(CompilerBase):
if key in {'comment', 'whitespace'}:
if node.result[1].parser.name == "list_":
if len(node.result[1].result) != 1:
node.add_error("Directive %s must have one, but not %i values" %
node.add_error('Directive "%s" must have one, but not %i values.' %
(key, len(node.result[1])))
value = self.compile__(node.result[1]).pop()
if value in {'linefeed', 'standard'} and key == 'whitespace':
value = '\s*' if value == "linefeed" else self.DEFAULT_WHITESPACE
else:
node.add_error('Value "%" not allowed for directive %s' % (value, key))
node.add_error('Value "%" not allowed for directive "%s".' % (value, key))
else:
value = node.result[1].result.strip("~")
if value != node.result[1].result:
......
......@@ -212,6 +212,9 @@ class Parser(metaclass=ParserMetaClass):
self._grammar = None # center for global variables etc.
self.reset()
def __deepcopy__(self, memo):
return self.__class__(self.name)
def reset(self):
self.visited = dict()
self.recursion_counter = dict()
......@@ -462,19 +465,12 @@ class RegExp(Parser):
self.regexp = re.compile(regexp) if isinstance(regexp, str) else regexp
def __deepcopy__(self, memo):
# This method is obsolete with the new `regex` module! It's
# being kept for compatibility with Python's standard library
# `regex` supports deep copies, but not `re`
try:
regexp = copy.deepcopy(self.regexp)
regexp = copy.deepcopy(self.regexp, memo)
except TypeError:
regexp = self.regexp.pattern
duplicate = RegExp(regexp, self.name)
duplicate.name = self.name # this ist needed!!!!
# duplicate.regexp = self.regexp
duplicate.grammar = self.grammar
duplicate.visited = copy.deepcopy(self.visited, memo)
duplicate.recursion_counter = copy.deepcopy(self.recursion_counter, memo)
return duplicate
return RegExp(regexp, self.name)
def __call__(self, text):
match = text[0:1] != BEGIN_SCANNER_TOKEN and self.regexp.match(text) # ESC starts a scanner token.
......@@ -497,6 +493,13 @@ class RE(Parser):
self.wspRight = RegExp(wR, WHITESPACE_KEYWORD) if wR else ZOMBIE_PARSER
self.main = RegExp(regexp)
def __deepcopy__(self, memo={}):
try:
regexp = copy.deepcopy(self.main.regexp, memo)
except TypeError:
regexp = self.main.regexp.pattern
return self.__class__(regexp, self.wL, self.wR, self.name)
def __call__(self, text):
# assert self.main.regexp.pattern != "@"
t = text
......@@ -555,6 +558,10 @@ class UnaryOperator(Parser):
assert isinstance(parser, Parser)
self.parser = parser
def __deepcopy__(self, memo):
parser = copy.deepcopy(self.parser, memo)
return self.__class__(parser, self.name)
def apply(self, func):
if super(UnaryOperator, self).apply(func):
self.parser.apply(func)
......@@ -566,6 +573,10 @@ class NaryOperator(Parser):
assert all([isinstance(parser, Parser) for parser in parsers]), str(parsers)
self.parsers = parsers
def __deepcopy__(self, memo):
parsers = copy.deepcopy(self.parsers, memo)
return self.__class__(*parsers, name=self.name)
def apply(self, func):
if super(NaryOperator, self).apply(func):
for parser in self.parsers:
......@@ -771,6 +782,9 @@ class Retrieve(Parser):
super(Retrieve, self).__init__(name)
self.symbol = symbol # if isinstance(symbol, str) else symbol.name
def __deepcopy__(self, memo):
return self.__class__(self.symbol, self.name)
def __call__(self, text):
symbol = self.symbol if isinstance(self.symbol, str) \
else self.symbol.name
......@@ -801,8 +815,17 @@ class Forward(Parser):
def __init__(self):
Parser.__init__(self)
self.parser = None
self.name = ''
self.cycle_reached = False
def __deepcopy__(self, memo):
assert id(self) not in memo
duplicate = self.__class__()
memo[id(self)] = duplicate
parser = copy.deepcopy(self.parser, memo)
duplicate.set(parser)
return duplicate
def __call__(self, text):
return self.parser(text)
......
......@@ -71,6 +71,12 @@ class ZombieParser:
self.name = "ZOMBIE"
self.__class__.alive = True
def __copy__(self):
return self
def __deepcopy__(self, memo):
return self
def __str__(self):
return self.name
......
......@@ -44,8 +44,10 @@ class TestDirectives:
parser = MinilangParser()
assert parser
syntax_tree = parser.parse("3 + 4 * 12")
parser.log_parsing_history("WSP")
assert not syntax_tree.collect_errors()
syntax_tree = parser.parse("3 + 4 \n * 12")
parser.log_parsing_history("WSPLF")
assert not syntax_tree.collect_errors()
def test_whitespace_standard(self):
......
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