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

some refactoring

parent dfe2db6f
......@@ -33,7 +33,7 @@ from DHParser.ebnf import EBNFCompiler, grammar_changed, DHPARSER_IMPORTS, \
get_ebnf_preprocessor, get_ebnf_grammar, get_ebnf_transformer, get_ebnf_compiler, \
PreprocessorFactoryFunc, ParserFactoryFunc, TransformerFactoryFunc, CompilerFactoryFunc
from DHParser.error import Error, is_error, has_errors, only_errors, \
CANNOT_VERIFY_TRANSTABLE_WARNING
CANNOT_VERIFY_TRANSTABLE_WARNING, ErrorCode, ERROR
from DHParser.log import suspend_logging, resume_logging, is_logging, log_dir, append_log
from DHParser.parse import Grammar
from DHParser.preprocess import nil_preprocessor, PreprocessorFunc
......@@ -128,6 +128,9 @@ class CompilationError(DSLException):
self.AST = AST
self.result = result
def __str__(self):
return '\n'.join(str(error) for error in self.errors)
def error_str(messages: Iterable[Error]) -> str:
"""
......@@ -181,7 +184,8 @@ def compileDSL(text_or_file: str,
preprocessor: Optional[PreprocessorFunc],
dsl_grammar: Union[str, Grammar],
ast_transformation: TransformationFunc,
compiler: Compiler) -> Any:
compiler: Compiler,
fail_when: ErrorCode = ERROR) -> Any:
"""
Compiles a text in a domain specific language (DSL) with an
EBNF-specified grammar. Returns the compiled text or raises a
......@@ -196,13 +200,13 @@ def compileDSL(text_or_file: str,
parser, grammar_src = grammar_instance(dsl_grammar)
result, messages, AST = compile_source(text_or_file, preprocessor, parser,
ast_transformation, compiler)
if has_errors(messages):
if has_errors(messages, fail_when):
src = load_if_file(text_or_file)
raise CompilationError(only_errors(messages), src, grammar_src, AST, result)
raise CompilationError(only_errors(messages, fail_when), src, grammar_src, AST, result)
return result
def raw_compileEBNF(ebnf_src: str, branding="DSL") -> EBNFCompiler:
def raw_compileEBNF(ebnf_src: str, branding="DSL", fail_when: ErrorCode = ERROR) -> EBNFCompiler:
"""
Compiles an EBNF grammar file and returns the compiler object
that was used and which can now be queried for the result as well
......@@ -221,7 +225,7 @@ def raw_compileEBNF(ebnf_src: str, branding="DSL") -> EBNFCompiler:
grammar = get_ebnf_grammar()
compiler = get_ebnf_compiler(branding, ebnf_src)
transformer = get_ebnf_transformer()
compileDSL(ebnf_src, nil_preprocessor, grammar, transformer, compiler)
compileDSL(ebnf_src, nil_preprocessor, grammar, transformer, compiler, fail_when)
return compiler
......@@ -259,7 +263,10 @@ def compileEBNF(ebnf_src: str, branding="DSL") -> str:
@functools.lru_cache()
def grammar_provider(ebnf_src: str, branding="DSL", additional_code: str = '') -> ParserFactoryFunc:
def grammar_provider(ebnf_src: str,
branding="DSL",
additional_code: str = '',
fail_when: ErrorCode = ERROR) -> ParserFactoryFunc:
"""
Compiles an EBNF-grammar and returns a grammar-parser provider
function for that grammar.
......@@ -277,8 +284,9 @@ def grammar_provider(ebnf_src: str, branding="DSL", additional_code: str = '') -
A provider function for a grammar object for texts in the
language defined by ``ebnf_src``.
"""
grammar_src = compileDSL(ebnf_src, nil_preprocessor, get_ebnf_grammar(),
get_ebnf_transformer(), get_ebnf_compiler(branding, ebnf_src))
grammar_src = compileDSL(
ebnf_src, nil_preprocessor, get_ebnf_grammar(), get_ebnf_transformer(),
get_ebnf_compiler(branding, ebnf_src), fail_when)
log_name = get_config_value('compiled_EBNF_log')
if log_name and is_logging():
append_log(log_name, grammar_src)
......@@ -383,7 +391,7 @@ def is_outdated(compiler_suite: str, grammar_source: str) -> bool:
return True
def run_compiler(text_or_file: str, compiler_suite: str) -> Any:
def run_compiler(text_or_file: str, compiler_suite: str, fail_when: ErrorCode = ERROR) -> Any:
"""Compiles a source with a given compiler suite.
Args:
......@@ -403,7 +411,7 @@ def run_compiler(text_or_file: str, compiler_suite: str) -> Any:
CompilerError
"""
preprocessor, parser, ast, compiler = load_compiler_suite(compiler_suite)
return compileDSL(text_or_file, preprocessor(), parser(), ast(), compiler())
return compileDSL(text_or_file, preprocessor(), parser(), ast(), compiler(), fail_when)
def compile_on_disk(source_file: str, compiler_suite="", extension=".xml") -> Iterable[Error]:
......
......@@ -2826,7 +2826,7 @@ class EBNFCompiler(Compiler):
return value
def gen_search_rule(self, nd: Node) -> ReprType:
def gen_search_rule(self, symbol: str, nd: Node) -> ReprType:
"""Generates a search rule, which can be either a string for simple
string search or a regular expression from the node's content. Returns
an empty string in case the node is neither regexp nor literal.
......@@ -3062,7 +3062,7 @@ class EBNFCompiler(Compiler):
if isinstance(rule, unrepr) and rule.s.isidentifier():
try:
nd = self.rules[rule.s][0].children[1]
refined = self.gen_search_rule(nd)
refined = self.gen_search_rule(symbol, nd)
if not refined: refined = unrepr(rule.s)
except IndexError:
nd = self.tree # TODO: Allow arbitrary parsers, here
......@@ -3094,7 +3094,7 @@ class EBNFCompiler(Compiler):
if isinstance(search, unrepr) and search.s.isidentifier():
try:
nd = self.rules[search.s][0].children[1]
search = self.gen_search_rule(nd)
search = self.gen_search_rule(symbol, nd)
except IndexError:
search = ''
except KeyError:
......@@ -3134,7 +3134,7 @@ class EBNFCompiler(Compiler):
if isinstance(search, unrepr) and search.s.isidentifier():
try:
nd = self.rules[search.s][0].children[1]
search = self.gen_search_rule(nd)
search = self.gen_search_rule(symbol, nd)
except IndexError:
search = ''
except KeyError:
......@@ -3518,7 +3518,7 @@ class EBNFCompiler(Compiler):
if len(node.children) == 2:
error_msgs.append(('', unrepr(node[1].content)))
elif len(node.children) == 3:
rule = self.gen_search_rule(node[1])
rule = self.gen_search_rule(symbol, node[1])
error_msgs.append((rule if rule else unrepr(node[1].content),
unrepr(node[2].content)))
else:
......@@ -3530,11 +3530,11 @@ class EBNFCompiler(Compiler):
# if symbol in self.rules:
# self.tree.new_error(node, 'Skip list for resuming in series for symbol "{}"'
# ' must be defined before the symbol!'.format(symbol))
self.directives.skip[symbol] = [self.gen_search_rule(nd) for nd in node[1:]]
self.directives.skip[symbol] = [self.gen_search_rule(symbol, nd) for nd in node[1:]]
elif key.endswith('_resume'):
symbol = key[:-7]
self.directives.resume[symbol] = [self.gen_search_rule(nd) for nd in node[1:]]
self.directives.resume[symbol] = [self.gen_search_rule(symbol, nd) for nd in node[1:]]
else:
if any(key.startswith(directive) for directive in ('skip', 'error', 'resume')):
......
......@@ -36,7 +36,7 @@ from DHParser.configuration import get_config_value, set_config_value
from DHParser.error import has_errors, MANDATORY_CONTINUATION, PARSER_STOPPED_BEFORE_END, \
REDEFINED_DIRECTIVE, UNUSED_ERROR_HANDLING_WARNING, AMBIGUOUS_ERROR_HANDLING, \
REORDERING_OF_ALTERNATIVES_REQUIRED, BAD_ORDER_OF_ALTERNATIVES, UNCONNECTED_SYMBOL_WARNING, \
ERROR
ERROR, WARNING
from DHParser.syntaxtree import WHITESPACE_PTYPE
from DHParser.ebnf import get_ebnf_grammar, get_ebnf_transformer, EBNFTransform, \
EBNFDirectives, get_ebnf_compiler, compile_ebnf, DHPARSER_IMPORTS, parse_ebnf, transform_ebnf
......@@ -835,7 +835,7 @@ class TestCustomizedResumeParsing:
"""
def test_several_resume_rules_innermost_rule_matching(self):
gr = grammar_provider(self.lang)()
gr = grammar_provider(self.lang, fail_when=WARNING)()
content = 'ALPHA abc BETA bad GAMMA cab .'
cst = gr(content)
assert cst.error_flag
......@@ -906,7 +906,7 @@ class TestCustomizedResumeParsing_with_Parsers:
"""
def test_several_resume_rules_innermost_rule_matching(self):
gr = grammar_provider(self.lang)()
gr = grammar_provider(self.lang, fail_when=WARNING)()
content = 'ALPHA abc BETA bad GAMMA cab .'
cst = gr(content)
assert cst.error_flag
......
Supports Markdown
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