Commit d43a732c authored by Eckhart Arnold's avatar Eckhart Arnold

- processing does not stop on normal errors, any more,...

- processing does not stop on normal errors, any more, but only on fatal errors (EXPERIMENTAL)
parent 3f45d04f
......@@ -41,7 +41,7 @@ from DHParser.preprocess import with_source_mapping, PreprocessorFunc, SourceMap
from DHParser.syntaxtree import Node, RootNode, ZOMBIE_TAG, StrictResultType
from DHParser.transform import TransformationFunc
from DHParser.parse import Grammar
from DHParser.error import adjust_error_locations, is_error, Error
from DHParser.error import adjust_error_locations, is_error, is_fatal, Error
from DHParser.log import log_parsing_history, log_ST, is_logging, logfile_basename
from DHParser.toolkit import load_if_file
......@@ -195,8 +195,9 @@ def compile_source(source: str,
3. AST-transformation
4. Compiling.
The compilations stage is only invoked if no errors occurred in
either of the two previous stages.
The later stages AST-transformation, compilation will only be invoked if
no fatal errors occurred in any of the earlier stages of the processing
source (str): The input text for compilation or a the name of a
......@@ -222,11 +223,17 @@ def compile_source(source: str,
ast = None # type: Optional[Node]
original_text = load_if_file(source) # type: str
log_file_name = logfile_basename(source, compiler) # type: str
# preprocessing
if preprocessor is None:
source_text = original_text # type: str
source_mapping = lambda i: i # type: SourceMapFunc
source_text, source_mapping = with_source_mapping(preprocessor(original_text))
# parsing
syntax_tree = parser(source_text) # type: RootNode
if is_logging():
log_ST(syntax_tree, log_file_name + '.cst')
......@@ -235,24 +242,48 @@ def compile_source(source: str,
# assert is_error(syntax_tree.error_flag) or str(syntax_tree) == strip_tokens(source_text), \
# str(syntax_tree) # Ony valid if neither tokens or whitespace are dropped early
# only compile if there were no syntax errors, for otherwise it is
# likely that error list gets littered with compile error messages
result = None
# efl = syntax_tree.error_flag
# messages = syntax_tree.errors(clear_errors=True)
if not is_error(syntax_tree.error_flag):
# efl = max(efl, syntax_tree.error_flag)
# messages.extend(syntax_tree.errors(clear_errors=True))
if not is_fatal(syntax_tree.error_flag):
# AST-transformation
if is_error(syntax_tree.error_flag):
# catch Python exception, because if an error has occured
# earlier, the syntax tree might not look like expected,
# which could (fatally) break AST transformations.
except Excpetion as e:
"AST-Transformation failed due to earlier parser errors. "
"Crash Message: " + str(e), Error.AST_TRANSFORM_CRASH)
if is_logging():
log_ST(syntax_tree, log_file_name + '.ast')
if not is_error(syntax_tree.error_flag):
if not is_fatal(syntax_tree.error_flag):
if preserve_ast:
ast = copy.deepcopy(syntax_tree)
result = compiler(syntax_tree, original_text)
# print(syntax_tree.as_sxpr())
# messages.extend(syntax_tree.errors())
# syntax_tree.error_flag = max(syntax_tree.error_flag, efl)
# Compilation
if is_error(syntax_tree.error_flag):
# assume Python crashes are merely a consequence of earlier
# errors, so let's catch them
result = compiler(syntax_tree, original_text)
except Exception as e:
node = compiler.context[-1] if compiler.context else syntax_tree
node, "Compilation failed, most likely, due to errors earlier "
"in the processing pipeline. Crash Message: " + str(e),
# assume Python crashes are programming mistakes, so let
# the exceptions through
result = compiler(syntax_tree, original_text)
messages = syntax_tree.errors_sorted # type: List[Error]
adjust_error_locations(messages, original_text, source_mapping)
......@@ -260,3 +291,4 @@ def compile_source(source: str,
# TODO: Verify compiler against grammar, i.e. make sure that for all on_X()-methods, `X` is the name of a parser
# TODO: AST validation against an ASDSL-Specification
\ No newline at end of file
......@@ -45,6 +45,7 @@ from DHParser.stringview import StringView
__all__ = ('ErrorCode',
......@@ -63,11 +64,12 @@ class Error:
# error levels
NO_ERROR = ErrorCode(0)
MESSAGE = ErrorCode(1)
WARNING = ErrorCode(100)
ERROR = ErrorCode(1000)
NO_ERROR = ErrorCode(0)
MESSAGE = ErrorCode(1)
WARNING = ErrorCode(100)
ERROR = ErrorCode(1000)
FATAL = ErrorCode(10000)
# warning codes
......@@ -89,6 +91,11 @@ class Error:
# fatal errors
AST_TRANSFORM_CRASH = ErrorCode(10010)
COMPILER_CRASH = ErrorCode(10020)
def __init__(self, message: str, pos, code: ErrorCode = ERROR,
orig_pos: int = -1, line: int = -1, column: int = -1) -> None:
assert isinstance(code, ErrorCode)
......@@ -135,15 +142,22 @@ class Error:
def is_warning(code: int) -> bool:
"""Returns True, if error is merely a warning."""
"""Returns True, if error is merely a warning or a message."""
return code < Error.ERROR
def is_error(code: int) -> bool:
"""Returns True, if error is an error, not just a warning."""
"""Returns True, if error is a (fatal) error, not just a warning."""
return code >= Error.ERROR
def is_fatal(code: int) -> bool:
"""Returns True, ir error is fatal. Fatal errors are typically raised
when a crash (i.e. Python exception) occurs at later stages of the
processing pipline (e.g. ast transformation, compiling). """
return code >= Error.FATAL
# def Warning(message: str, pos, code: ErrorCode = Error.WARNING,
# orig_pos: int = -1, line: int = -1, column: int = -1) -> Error:
# """
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