Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 56729685 authored by di68kap's avatar di68kap
Browse files

- parser.py, syntax.py: bug concerning collection of errors fixed

parent f117b6de
......@@ -66,8 +66,8 @@ class Error:
return prefix + "%s: %s" % (self.level_str, self.message)
def __repr__(self):
return 'Error("%s", %i, %s, %i, %i, %i)' \
% (self.message, self.level, repr(self.code), self.pos, self.line, self.column)
return 'Error("%s", %s, %i, %i, %i)' \
% (self.message, repr(self.code), self.pos, self.line, self.column)
@property
def level_str(self):
......
......@@ -2039,7 +2039,7 @@ class Compiler:
else:
self._dirty_flag = True
result = self.compile(node)
self.propagate_error_flags(node)
self.propagate_error_flags(node, lazy=True)
return result
def set_grammar_name(self, grammar_name="", grammar_source=""):
......@@ -2058,12 +2058,13 @@ class Compiler:
self.grammar_source = load_if_file(grammar_source)
@staticmethod
def propagate_error_flags(node: Node) -> None:
if node.error_flag < Error.HIGHEST:
def propagate_error_flags(node: Node, lazy: bool = True) -> None:
# See test_parser.TestCompilerClass.test_propagate_error()..
if not lazy or node.error_flag < Error.HIGHEST:
for child in node.children:
Compiler.propagate_error_flags(child)
node.error_flag = max(node.error_flag, child.error_flag)
if node.error_flag >= Error.HIGHEST:
if lazy and node.error_flag >= Error.HIGHEST:
return
@staticmethod
......@@ -2164,6 +2165,7 @@ def compile_source(source: str,
syntax_tree.log(log_file_name + '.ast')
if not is_error(syntax_tree.error_flag):
result = compiler(syntax_tree)
# print(syntax_tree.as_sxpr())
messages.extend(syntax_tree.collect_errors(source_text))
syntax_tree.error_flag = max(syntax_tree.error_flag, efl)
return result, messages, syntax_tree
......@@ -398,21 +398,25 @@ class Node(collections.abc.Sized):
return []
def _collect_errors(self, lbreaks: List[int] = [], clear_errors=False) -> List[Error]:
if self.error_flag:
errors = self.errors
if lbreaks:
for err in errors:
err.pos = self.pos
err.line, err.column = line_col(lbreaks, err.pos)
if clear_errors:
self._errors = []
self.error_flag = 0
if self.children:
for child in self.children:
errors.extend(child._collect_errors(lbreaks, clear_errors))
return errors
errors = self.errors
if errors and lbreaks:
for err in errors:
err.pos = self.pos
err.line, err.column = line_col(lbreaks, err.pos)
if self.children:
for child in self.children:
errors.extend(child._collect_errors(lbreaks, clear_errors))
if clear_errors:
self._errors = []
self.error_flag = 0
else:
return []
if self._errors:
self.error_flag = max(err.code for err in self.errors)
if self.children:
max_child_error = max(child.error_flag for child in self.children)
self.error_flag = max(self.error_flag, max_child_error)
return errors
def _tree_repr(self, tab, open_fn, close_fn, data_fn=identity, density=0) -> str:
......@@ -482,6 +486,8 @@ class Node(collections.abc.Sized):
# s += " '(pos %i)" % node.pos
if src:
txt += " '(pos %i " % node.pos # + " %i %i)" % line_col(src, node.pos)
if node.error_flag:
txt += " HAS ERRORS"
if node.errors:
txt += " '(err '(%s))" % ' '.join(str(err).replace('"', r'\"')
for err in node.errors)
......
python.exe setup.py build_ext --inplace
python3.exe setup.py sdist bdist
\ No newline at end of file
......@@ -12,12 +12,15 @@ SCHREIBWEISE
ym-: Chart. Sangall. A 194.
impir-: v. ibi.
form. sing.:
gen.:
-ri : v. ibi. adde Annal. Plac. a. 1266 p. 516,21.
-iae : Chron. Fred. 2,33. p. 56,22. 2,35.
abl.:
-um : Chron. Fred. 2,15. 2,35sqq. capit. p. 43. confunditur c. imperitus : v. ibi.
form. sing.:
gen.:
-ri: v. ibi. adde Annal. Plac. a. 1266 p. 516,21.
-iae: Chron. Fred. 2,33. p. 56,22. 2,35.
abl.:
-um: Chron. Fred. 2,15. 2,35sqq. capit. p. 43.
confunditur c.:
imperitus: v. ibi.
BEDEUTUNG
......
......@@ -17,7 +17,7 @@ Artikel = [LZ]
[ArtikelKopf]
BedeutungsPosition
[VerweisPosition]
{ SubArtikel }
{ UnterArtikel }
ArtikelVerfasser
[LZ] DATEI_ENDE
......@@ -41,9 +41,9 @@ LemmaVariante = LAT_WORT_TEIL { "-" LAT_WORT_TEIL }
## GRAMMATIK-POSITION ##
GrammatikPosition = "GRAMMATIK" [LZ] Grammatik §ABS { GrammatikVariante §ABS }
GrammatikPosition = "GRAMMATIK" [LZ] §Grammatik ABS { GrammatikVariante §ABS }
Grammatik = §wortart ABS flexion [genus]
Grammatik = wortart §ABS flexion [genus]
wortart = "nomen" | "n."
| "verb" | "v."
......@@ -51,14 +51,16 @@ wortart = "nomen" | "n."
| "adjektiv" | "adj."
| "praeposition" | "praep."
flexion = FLEX { "," §FLEX }
flexion = deklination | konjugation
deklination = FLEX §"," FLEX
konjugation = FLEX
FLEX = /-?[a-z]+/~
genus = "maskulinum" | "m."
| "femininum" | "f."
| "neutrum" | "n."
GrammatikVariante = [wortart ABS] flexion [genus] DPP { Beleg }+
GrammatikVariante = [wortart ABS] flexion [genus] DPP { Beleg }+
......@@ -73,14 +75,32 @@ Etymologie = FREITEXT
#### ARTIKEL-KOPF ############################################################
ArtikelKopf = { SchreibweisenPosition | StrukturPosition
| GebrauchPosition | MetrikPosition | VerwechselungPosition }+
ArtikelKopf = < SchreibweisenPosition | StrukturPosition | GebrauchPosition
| MetrikPosition | VerwechselungPosition >
SchreibweisenPosition = "SCHREIBWEISE" [LZ] §SWTyp DPP [LZ]
SWVariante { ABS SWVariante} [LZ]
SWTyp = "script. fat-" | "script."
SWVariante = Schreibweise DPP Beleg
Schreibweise = ZEICHENFOLGE
## Schreibweisen-Position ##
# TODO: Ggf. noch zu ergänzen um: Zusatz, Mehrere Tyen innerhalb der Schreibweisen-Position.
SchreibweisenPosition = "SCHREIBWEISE" [LZ] { SWKategorie }+
SWKategorie = SWTyp DPP [LZ] §{SWUnterkategorie | SWVariante { ABS SWVariante }}+ [LZ]
SWUnterkategorie = SWUnterTyp DPP [LZ] §SWVariante { ABS SWVariante }+ [LZ]
SWTyp = scriptfat | scriptform | script | form | OFFEN
SWVariante = !KATEGORIENZEILE Schreibweise DPP Beleg
Schreibweise = ZEICHENFOLGE
scriptfat = "script." "fat-"
scriptform = "script. " "form"
script = "srcipt."
form = "form"
#### STRUKTUR-POSITION #######################################################
StrukturPosition = "STRUKTUR" [LZ] { STVariante }+
STVariante = "TODO"
......@@ -96,7 +116,16 @@ DeutscheBedeutung = SW_DEU /(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+/~
Belege = "BELEGE" [LZ] (EinBeleg | { "*" EinBeleg }) ABS
EinBeleg = { !([LZ] "*" | SCHLUESSELWORT) /\s*[^\n]*/~ [ZW] }+ [Zusatz]
Zusatz = "ZUSATZ" /\s*.*/
#### VERWEIS-POSITION #####################################################
VerweisPosition = "VERWEISE"
#### UNTER-ARTIKEL ########################################################
UnterArtikel = "UNTER-ARTIKEL"
#### AUTOR/AUTORIN ###########################################################
......@@ -171,6 +200,7 @@ RZS = /\s*?\n|$/ # Rückwärtiger Zeilensprung oder T
ZEILENSPRUNG = /[ \t]*\n/~
KOMMENTARZEILEN = { /[ \t]*\n?[ \t]*/ COMMENT__ } # echte Kommentarzeilen
KATEGORIENZEILE = /[^:\n]+[:][ \t]*\n/ # Kategorienzeilen enthalten genau einen Doppelpunkt am Ende der Zeile
DATEI_ENDE = !/./
NIEMALS = /(?!.)/
......
Warning: Rule "SW_GRIECH" is not connected to parser root "Artikel" !
Warning: Rule "VerweisZiel" is not connected to parser root "Artikel" !
Warning: Rule "DEU_WORT" is not connected to parser root "Artikel" !
Warning: Rule "DEU_GROSS" is not connected to parser root "Artikel" !
Warning: Rule "DEU_KLEIN" is not connected to parser root "Artikel" !
Warning: Rule "LAT_WORT" is not connected to parser root "Artikel" !
Warning: Rule "GROSSSCHRIFT" is not connected to parser root "Artikel" !
Warning: Rule "ZW" is not connected to parser root "Artikel" !
Warning: Rule "LÜCKE" is not connected to parser root "Artikel" !
Warning: Rule "LEERZEILE" is not connected to parser root "Artikel" !
Warning: Rule "RZS" is not connected to parser root "Artikel" !
Warning: Rule "KOMMENTARZEILEN" is not connected to parser root "Artikel" !
Warning: Rule "NIEMALS" is not connected to parser root "Artikel" !
line: 31, column: 49, Error: Missing definition for symbol 'LemmaWort'
line: 70, column: 22, Error: Missing definition for symbol 'LAT'
line: 70, column: 28, Error: Missing definition for symbol 'GRI'
line: 78, column: 66, Error: Missing definition for symbol 'GebrauchPosition'
line: 79, column: 23, Error: Missing definition for symbol 'MetrikPosition'
line: 79, column: 40, Error: Missing definition for symbol 'VerwechselungPosition'
line: 88, column: 20, Error: Missing definition for symbol 'SWUnterTyp'
line: 89, column: 61, Error: Missing definition for symbol 'OFFEN'
line: 142, column: 1, Warning: Rule "SW_GRIECH" is not connected to parser root "Artikel" !
line: 158, column: 20, Error: Missing definition for symbol 'Autor'
line: 158, column: 30, Error: Missing definition for symbol 'Werk'
line: 158, column: 39, Error: Missing definition for symbol 'Stelle'
line: 158, column: 51, Error: Missing definition for symbol 'Datierung'
line: 158, column: 67, Error: Missing definition for symbol 'Edition'
line: 162, column: 1, Warning: Rule "VerweisZiel" is not connected to parser root "Artikel" !
line: 173, column: 1, Warning: Rule "DEU_GROSS" is not connected to parser root "Artikel" !
line: 174, column: 1, Warning: Rule "DEU_KLEIN" is not connected to parser root "Artikel" !
line: 175, column: 1, Warning: Rule "LAT_WORT" is not connected to parser root "Artikel" !
line: 177, column: 1, Warning: Rule "GROSSSCHRIFT" is not connected to parser root "Artikel" !
line: 199, column: 1, Warning: Rule "RZS" is not connected to parser root "Artikel" !
line: 206, column: 1, Warning: Rule "NIEMALS" is not connected to parser root "Artikel" !
line: 208, column: 1, Warning: Rule "DUMMY" is not connected to parser root "Artikel" !
......@@ -27,8 +27,9 @@ sys.path.extend(['../', './'])
from DHParser.toolkit import is_logging, logging, compile_python_object
from DHParser.stringview import StringView
from DHParser.error import Error
from DHParser.syntaxtree import mock_syntax_tree
from DHParser.parser import compile_source, Retrieve, Grammar, Forward, Token, ZeroOrMore, RE, \
RegExp, Lookbehind, NegativeLookahead, OneOrMore, Series, Alternative, AllOf, SomeOf
RegExp, Lookbehind, NegativeLookahead, OneOrMore, Series, Alternative, AllOf, SomeOf, Compiler
from DHParser.ebnf import get_ebnf_grammar, get_ebnf_transformer, get_ebnf_compiler
from DHParser.dsl import grammar_provider, DHPARSER_IMPORTS
......@@ -542,6 +543,22 @@ class TestBorderlineCases:
assert not cst.error_flag
class TestCompilerClass:
def test_error_propagations(self):
tree = mock_syntax_tree('(A (B 1) (C (D (E 2) (F 3))))')
A = tree
B = next(tree.find(lambda node: str(node) == "1"))
D = next(tree.find(lambda node: node.parser.name == "D"))
F = next(tree.find(lambda node: str(node) == "3"))
B.add_error("Error in child node")
F.add_error("Error in child's child node")
Compiler.propagate_error_flags(tree, lazy=True)
assert A.error_flag
assert not D.error_flag
Compiler.propagate_error_flags(tree, lazy=False)
assert D.error_flag
if __name__ == "__main__":
from DHParser.testing import runner
with logging(False):
......
......@@ -23,6 +23,7 @@ import copy
import sys
sys.path.extend(['../', './'])
from DHParser.error import Error
from DHParser.syntaxtree import Node, mock_syntax_tree, TOKEN_PTYPE
from DHParser.transform import traverse, reduce_single_child, \
replace_by_single_child, flatten, remove_expendables
......@@ -124,6 +125,23 @@ class TestNode:
assert nd1.pos == 0, "Expected Node.pos == 0, got %i" % nd1.pos
assert nd2.pos == 3, "Expected Node.pos == 3, got %i" % nd2.pos
def test_collect_errors(self):
tree = mock_syntax_tree('(A (B 1) (C (D (E 2) (F 3))))')
A = tree
B = next(tree.find(lambda node: str(node) == "1"))
D = next(tree.find(lambda node: node.parser.name == "D"))
F = next(tree.find(lambda node: str(node) == "3"))
B.add_error("Error in child node")
F.add_error("Error in child's child node")
tree.error_flag = Error.ERROR
errors = tree.collect_errors()
assert len(errors) == 2, str(errors)
assert A.error_flag
assert D.error_flag
errors = tree.collect_errors(clear_errors=True)
assert len(errors) == 2
assert not D.error_flag
class TestErrorHandling:
def test_error_flag_propagation(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