Commit b37c25d7 authored by di68kap's avatar di68kap
Browse files

- Weitere Fehlerkorrekturen; Elimination des "component"-Parameters zugunst...

- Weitere Fehlerkorrekturen; Elimination des "component"-Parameters zugunst der initialisierung des component-Feldes durch die ParserHQ-Klasse vorbereitet -> dient größerer Übersichtlichkeit der
  generierten Parser
parent 0c033d66
......@@ -322,9 +322,6 @@ def left_recursion_guard(callfunc):
parser.recursion_counter[location] += 1
# # call preprocess hook
# if parser.preprocess is not None:
# text = parser.preprocess(parser, text)
parser.headquarter.call_stack.append(parser)
parser.headquarter.moving_forward = True
......@@ -353,10 +350,6 @@ def left_recursion_guard(callfunc):
# left recursion and use the saved result
result = parser.visited[location]
# # call postprocess hook
# if parser.postprocess is not None:
# text, result = parser.postprocess(parser, text, result)
parser.recursion_counter[location] -= 1
except RecursionError:
......@@ -381,16 +374,22 @@ class ParserMetaClass(type):
super(ParserMetaClass, C).__init__(name, bases, attrs)
def sane_parser_name(name):
""""Checks whether given name is an acceptable parser name. Parser names
must not be preceeded or succeeded by a double underscore '__'!
"""
return name and name[:2] != '__' and name[-2:] != '__'
class Parser(metaclass=ParserMetaClass):
def __init__(self, component=None):
assert component is None or isinstance(component, str)
self.component = component or ''
self.component = '' #component or ''
self.headquarter = None # head quater for global variables etc.
self.visited = dict()
self.recursion_counter = dict()
self.cycle_detection = set()
# self.preprocess = None # f(str) -> str
# self.postprocess = None # f(str, Node or str) -> (str, Node or str)
def __call__(self, text):
raise NotImplementedError
......@@ -413,10 +412,22 @@ class Parser(metaclass=ParserMetaClass):
class ParserHeadquarter:
def __init__(self, root=None):
self.root__ = root if root else copy.deepcopy(self.__class__.root__)
def __init__(self):
# initialize parser components
C = self.__class__
Cdict = C.__dict__
for entry in Cdict:
if sane_parser_name(entry):
parser = Cdict[entry]
if isinstance(parser, Parser):
print(type(parser), parser.component, entry)
if isinstance(parser, Forward):
parser.parser.component = entry
else:
parser.component = entry
self.root__ = copy.deepcopy(self.__class__.root__)
self.root__.apply(self._add_parser)
self.variables = dict()
self.variables = dict() # support for Pop and Retrieve operators
self.last_node = None
self.call_stack = []
self.moving_forward = True
......@@ -425,8 +436,9 @@ class ParserHeadquarter:
def _add_parser(self, parser):
"""Adds the copy of the parser object to this instance of ParserHeadquarter.
"""
if parser.component: # overwrite class variable with instance variable
self.__setattr__(parser.component, parser)
print(parser.component)
if sane_parser_name(parser.component): # overwrite class variable with instance variable
setattr(self, parser.component, parser)
parser.headquarter = self
def parse(self, document):
......@@ -443,7 +455,7 @@ class ParserHeadquarter:
"instance of the ParserHeadquarter class!")
self.unused = False
parser = self.root__
stitches = [];
stitches = []
rest = document
while rest and len(stitches) < MAX_DROPOUTS:
result, rest = parser(rest)
......@@ -517,6 +529,7 @@ class ScannerToken(Parser):
class RegExp(Parser):
def __init__(self, component, regexp, orig_re = ''):
super(RegExp, self).__init__(component)
self.component = component
self.regexp = re.compile(regexp) if isinstance(regexp, str) else regexp
self.orig_re = orig_re
......@@ -527,12 +540,13 @@ class RegExp(Parser):
except TypeError:
regexp = self.regexp.pattern
duplicate = RegExp(self.component, regexp, self.orig_re)
duplicate.component = self.component # this ist needed!!!!
duplicate.regexp = self.regexp
duplicate.orig_re = self.orig_re
duplicate.headquarter = self.headquarter
duplicate.visited = copy.deepcopy(self.visited, memo)
duplicate.recursion_counter = copy.deepcopy(self.recursion_counter,
memo)
# duplicate.preprocess = self.preprocess
# duplicate.postprocess = self.postprocess
return duplicate
def __call__(self, text):
......@@ -554,8 +568,7 @@ class RegExp(Parser):
def __str__(self):
pattern = self.orig_re or self.regexp.pattern # for readability of error messages !
return Parser.__str__(self).replace(TOKEN_KEYWORD, "RE") \
+ "/" + pattern + "/"
return Parser.__str__(self) + "/" + pattern + "/"
def escape_re(s):
......@@ -826,10 +839,12 @@ class Capture(UnaryOperator):
class Retrieve(Parser):
def __init__(self, component, symbol):
super(Retrieve, self).__init__(component)
self.symbol = symbol if isinstance(symbol, str) else symbol.component
self.symbol = symbol # if isinstance(symbol, str) else symbol.component
def __call__(self, text):
stack = self.headquarter.variables[self.symbol]
symbol = self.symbol if isinstance(self.symbol, str) \
else self.symbol.component
stack = self.headquarter.variables[symbol]
value = self.pick_value(stack)
if text.startswith(value):
return Node(self, value), text[len(value):]
......@@ -874,7 +889,7 @@ class Forward(Parser):
def set(self, parser):
assert isinstance(parser, Parser)
self.component = parser.component
# self.component = parser.component # this is now assigned by the constructor of ParserHeadquarter
self.parser = parser
def apply(self, func):
......@@ -1076,7 +1091,7 @@ class CompilerBase:
def compile__(self, node):
comp, cls = node.parser.component, node.parser.__class__.__name__
elem = comp or cls
if elem == 'compile__' or elem[:2] == '__' or elem[-2:] == '__':
if not sane_parser_name(elem):
node.add_error("Must not use reserved name '%s' as parser "
"component! " % elem + "(Any name starting with "
"'_' or '__' or ending with '__' is reserved.)")
......@@ -1182,7 +1197,7 @@ class EBNFGrammar(ParserHeadquarter):
EOF = !/./
"""
expression = Forward()
source_hash__ = "b1291fa35ac696654838fc94cabf439b"
source_hash__ = "c8e9cee1d0218a6c4a9c5cbc781c215a"
wspc__ = mixin_comment(whitespace=r'\s*', comment=r'#.*(?:\n|$)')
EOF = NegativeLookahead("EOF", RE('.'))
list_ = RE('\\w+\\s*(?:,\\s*\\w+\\s*)*', "list_", wspcR=wspc__)
......@@ -1506,7 +1521,7 @@ class EBNFCompiler(CompilerBase):
return self.non_terminal(node, 'Sequence')
def factor(self, node):
assert isinstance(node.parser, Sequence) # these assert statements can be removed
assert isinstance(node.parser, Sequence), node.as_sexpr() # these assert statements can be removed
assert node.children
assert len(node.result) >= 2, node.as_sexpr()
prefix = node.result[0].result
......@@ -1851,7 +1866,7 @@ if (os.path.exists('examples/EBNF/EBNF.ebnf')
and has_source_changed('examples/EBNF/EBNF.ebnf', EBNFGrammar)):
assert False, "WARNING: Grammar source has changed. The parser may not " \
"represent the actual grammar any more!!!"
pass
if __name__ == "__main__":
print(sys.argv)
......
This diff is collapsed.
......@@ -10,7 +10,7 @@ directive = "@" §symbol §"=" ( regexp | literal | list_ )
expression = term { "|" term }
term = factor { factor }
factor = [flowmarker] [retrieveop] symbol !"=" # negative lookahead to be sure it's not a definition
factor = [flowmarker] [retrieveop] symbol !"=" # negative lookahead to be sure it's not a definition
| [flowmarker] literal
| [flowmarker] regexp
| [flowmarker] group
......
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