Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit c1b3846f authored by Eckhart Arnold's avatar Eckhart Arnold
Browse files

- parser.py errors now also appear in the history logs

parent f1605c5c
......@@ -123,13 +123,17 @@ class HistoryRecord:
self.node = node
self.remaining = remaining
def err_msg(self):
return self.ERROR + ": " + "; ".join(self.node._errors).replace('\n', '\\')
@property
def stack(self):
return "->".join(str(parser) for parser in self.call_stack)
@property
def status(self):
return self.FAIL if self.node is None else self.ERROR if self.node._errors else self.MATCH
return self.FAIL if self.node is None else \
self.err_msg() if self.node._errors else self.MATCH
@property
def extent(self):
......@@ -160,7 +164,7 @@ def add_parser_guard(parser_func):
node, rest = parser_func(parser, text)
if grammar.history_tracking:
if grammar.moving_forward: # and result[0] == None
if grammar.moving_forward or (node and node._errors): # and result[0] == None
grammar.moving_forward = False
record = HistoryRecord(grammar.call_stack.copy(), node, len(rest))
grammar.history.append(record)
......@@ -378,11 +382,17 @@ class Grammar:
else:
stitches.append(result)
error_msg = "Parser stopped before end" + \
("! trying to recover..."
(("! trying to recover" +
(" but stopping history recording at this point."
if self.history_tracking else "..."))
if len(stitches) < MAX_DROPOUTS
else " too often! Terminating parser.")
stitches.append(Node(None, skip))
stitches[-1].add_error(error_msg)
if self.history_tracking:
record = HistoryRecord(self.call_stack.copy(), stitches[-1], len(rest))
self.history.append(record)
self.history_tracking = False
if stitches:
if rest:
stitches.append(Node(None, rest))
......
gedicht = bibliographisches {LZ}+ [serie] §titel §text
gedicht = bibliographisches { LEERZEILE }+ [serie] §titel §text §ENDE
bibliographisches = autor §"," [ZSP] werk §"," [ZSP] ort §"," [ZSP] jahr §"."
bibliographisches = autor §"," [NZ] werk §"," [NZ] ort §"," [NZ] jahr §"."
autor = namenfolge [verknüpfung]
werk = wortfolge ["." §untertitel] [verknüpfung]
untertitel = wortfolge [verknüpfung]
ort = wortfolge [verknüpfung]
jahr = JAHRESZAHL
serie = !(titel vers ZSP vers) { [ZSP] zeile }+ {LZ}+
titel = zeile
zeile = [LEER] { ZEICHENFOLGE }+
serie = !(titel vers NZ vers) { NZ zeile }+ { LEERZEILE }+
titel = NZ zeile { LEERZEILE }+
zeile = { ZEICHENFOLGE }+
text = { strophe }+
strophe = {LZ+} { [ZSP] vers }+
vers = [LEER] { ZEICHENFOLGE }+
text = { strophe {LEERZEILE}+ }+
strophe = { NZ vers }+
vers = { ZEICHENFOLGE }+
wortfolge = { WORT }+
namenfolge = { NAME }+
......@@ -24,7 +24,7 @@ WORT = /\w+/~
NAME = /\w+\.?/~
ZEICHENFOLGE = /[^ \n<>]+/~
LEER = /[ \t]+/
ZSP = /\n/~
LZ = /\n[ \t]*\n/~
NZ = /\n/~
LEERZEILE = /\n[ \t]*(?=\n)/~
JAHRESZAHL = /\d\d\d\d/~
ENDE = !/./
#!/usr/bin/python
#######################################################################
#
# SYMBOLS SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
import os
import sys
from functools import partial
try:
import regex as re
except ImportError:
import re
from DHParser.toolkit import logging, is_filename
from DHParser.parsers import Grammar, CompilerBase, Required, Token, \
Optional, OneOrMore, Sequence, RE, NegativeLookahead, mixin_comment, compile_source
from DHParser.syntaxtree import traverse, no_operation
#######################################################################
#
# SCANNER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
def LyrikScanner(text):
return text
def get_scanner():
return LyrikScanner
#######################################################################
#
# PARSER SECTION - Don't edit! CHANGES WILL BE OVERWRITTEN!
#
#######################################################################
class LyrikGrammar(Grammar):
r"""Parser for a Lyrik source file, with this grammar:
gedicht = bibliographisches { LEERZEILE }+ [serie] §titel §text
bibliographisches = autor §"," [NZ] werk §"," [NZ] ort §"," [NZ] jahr §"."
autor = namenfolge [verknüpfung]
werk = wortfolge ["." §untertitel] [verknüpfung]
untertitel = wortfolge [verknüpfung]
ort = wortfolge [verknüpfung]
jahr = JAHRESZAHL
serie = !(titel vers NZ vers) { NZ zeile }+ { LEERZEILE }+
titel = NZ zeile
zeile = { ZEICHENFOLGE }+
text = { strophe {LEERZEILE}+ }+
strophe = { NZ vers }+
vers = { ZEICHENFOLGE }+
wortfolge = { WORT }+
namenfolge = { NAME }+
verknüpfung = "<" ziel ">"
ziel = ZEICHENFOLGE
WORT = /\w+/~
NAME = /\w+\.?/~
ZEICHENFOLGE = /[^ \n<>]+/~
LEER = /[ \t]+/
NZ = /\n/~
LEERZEILE = /\n[ \t]*(?=\n)/~
JAHRESZAHL = /\d\d\d\d/~
ENDE = !/./
"""
source_hash__ = "6718329094e23c5285d3bed5b2861c10"
parser_initialization__ = "upon instatiation"
COMMENT__ = r''
WSP__ = mixin_comment(whitespace=r'[\t ]*', comment=r'')
wspL__ = ''
wspR__ = WSP__
ENDE = NegativeLookahead(RE('.', wR=''))
JAHRESZAHL = RE('\\d\\d\\d\\d')
LEERZEILE = RE('\\n[ \\t]*(?=\\n)')
NZ = RE('\\n')
LEER = RE('[ \\t]+', wR='')
ZEICHENFOLGE = RE('[^ \\n<>]+')
NAME = RE('\\w+\\.?')
WORT = RE('\\w+')
ziel = ZEICHENFOLGE
verknüpfung = Sequence(Token("<"), ziel, Token(">"))
namenfolge = OneOrMore(NAME)
wortfolge = OneOrMore(WORT)
vers = OneOrMore(ZEICHENFOLGE)
strophe = OneOrMore(Sequence(NZ, vers))
text = OneOrMore(Sequence(strophe, OneOrMore(LEERZEILE)))
zeile = OneOrMore(ZEICHENFOLGE)
titel = Sequence(NZ, zeile)
serie = Sequence(NegativeLookahead(Sequence(titel, vers, NZ, vers)), OneOrMore(Sequence(NZ, zeile)),
OneOrMore(LEERZEILE))
jahr = JAHRESZAHL
ort = Sequence(wortfolge, Optional(verknüpfung))
untertitel = Sequence(wortfolge, Optional(verknüpfung))
werk = Sequence(wortfolge, Optional(Sequence(Token("."), Required(untertitel))), Optional(verknüpfung))
autor = Sequence(namenfolge, Optional(verknüpfung))
bibliographisches = Sequence(autor, Required(Token(",")), Optional(NZ), werk, Required(Token(",")), Optional(NZ),
ort, Required(Token(",")), Optional(NZ), jahr, Required(Token(".")))
gedicht = Sequence(bibliographisches, OneOrMore(LEERZEILE), Optional(serie), Required(titel), Required(text))
root__ = gedicht
def get_grammar():
global thread_local_Lyrik_grammar_singleton
try:
grammar = thread_local_Lyrik_grammar_singleton
return grammar
except NameError:
thread_local_Lyrik_grammar_singleton = LyrikGrammar()
return thread_local_Lyrik_grammar_singleton
#######################################################################
#
# AST SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
Lyrik_AST_transformation_table = {
# AST Transformations for the Lyrik-grammar
"gedicht": no_operation,
"bibliographisches": no_operation,
"autor": no_operation,
"werk": no_operation,
"untertitel": no_operation,
"ort": no_operation,
"jahr": no_operation,
"serie": no_operation,
"titel": no_operation,
"zeile": no_operation,
"text": no_operation,
"strophe": no_operation,
"vers": no_operation,
"wortfolge": no_operation,
"namenfolge": no_operation,
"verknüpfung": no_operation,
"ziel": no_operation,
"WORT": no_operation,
"NAME": no_operation,
"ZEICHENFOLGE": no_operation,
"LEER": no_operation,
"NZ": no_operation,
"LEERZEILE": no_operation,
"JAHRESZAHL": no_operation,
"ENDE": no_operation,
"*": no_operation
}
LyrikTransform = partial(traverse, processing_table=Lyrik_AST_transformation_table)
def get_transformer():
return LyrikTransform
#######################################################################
#
# COMPILER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
class LyrikCompiler(CompilerBase):
"""Compiler for the abstract-syntax-tree of a Lyrik source file.
"""
def __init__(self, grammar_name="Lyrik", grammar_source=""):
super(LyrikCompiler, self).__init__(grammar_name, grammar_source)
assert re.match('\w+\Z', grammar_name)
def on_gedicht(self, node):
return node
def on_bibliographisches(self, node):
pass
def on_autor(self, node):
pass
def on_werk(self, node):
pass
def on_untertitel(self, node):
pass
def on_ort(self, node):
pass
def on_jahr(self, node):
pass
def on_serie(self, node):
pass
def on_titel(self, node):
pass
def on_zeile(self, node):
pass
def on_text(self, node):
pass
def on_strophe(self, node):
pass
def on_vers(self, node):
pass
def on_wortfolge(self, node):
pass
def on_namenfolge(self, node):
pass
def on_verknüpfung(self, node):
pass
def on_ziel(self, node):
pass
def on_WORT(self, node):
pass
def on_NAME(self, node):
pass
def on_ZEICHENFOLGE(self, node):
pass
def on_LEER(self, node):
pass
def on_NZ(self, node):
pass
def on_LEERZEILE(self, node):
pass
def on_JAHRESZAHL(self, node):
pass
def on_ENDE(self, node):
pass
def get_compiler(grammar_name="Lyrik", grammar_source=""):
global thread_local_Lyrik_compiler_singleton
try:
compiler = thread_local_Lyrik_compiler_singleton
compiler.set_grammar_name(grammar_name, grammar_source)
return compiler
except NameError:
thread_local_Lyrik_compiler_singleton = \
LyrikCompiler(grammar_name, grammar_source)
return thread_local_Lyrik_compiler_singleton
#######################################################################
#
# END OF DHPARSER-SECTIONS
#
#######################################################################
def compile_src(source):
"""Compiles ``source`` and returns (result, errors, ast).
"""
with logging("LOGS"):
compiler = get_compiler()
cname = compiler.__class__.__name__
log_file_name = os.path.basename(os.path.splitext(source)[0]) \
if is_filename(source) < 0 else cname[:cname.find('.')] + '_out'
result = compile_source(source, get_scanner(),
get_grammar(),
get_transformer(), compiler)
return result
if __name__ == "__main__":
if len(sys.argv) == 1:
sys.argv.append("Lyrisches_Intermezzo_IV.txt")
if len(sys.argv) > 1:
result, errors, ast = compile_src(sys.argv[1])
if errors:
for error in errors:
print(error)
sys.exit(1)
else:
print(result)
else:
print("Usage: LyrikCompiler.py [FILENAME]")
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