2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 0e289db1 authored by Eckhart Arnold's avatar Eckhart Arnold
Browse files

small corrections; test for load_compiler_suite

parent c3899a9a
......@@ -28,4 +28,4 @@ from .versionnumber import __version__
__author__ = "Eckhart Arnold <arnold@badw.de>"
__copyright__ = "http://www.apache.org/licenses/LICENSE-2.0"
__all__ = ['toolkit', 'syntaxtree', 'parsers', 'ebnf', 'dsl']
# __all__ = ['toolkit', 'syntaxtree', 'parsers', 'ebnf', 'dsl'] # flat namespace
......@@ -39,7 +39,7 @@ __all__ = ['GrammarError',
'load_compiler_suite',
'compileDSL',
'compileEBNF',
'compile_parser',
'parser_factory',
'compile_on_disk']
......@@ -172,7 +172,7 @@ def compileDSL(text_or_file, scanner, dsl_grammar, ast_transformation, compiler)
compilation error.
Raises:
CompilationError if any errors occured during compilation
CompilationError if any errors occurred during compilation
"""
assert isinstance(text_or_file, str)
assert isinstance(compiler, CompilerBase)
......@@ -194,25 +194,27 @@ def compileEBNF(ebnf_src, branding = "DSL"):
Args:
ebnf_src(str): Either the file name of an EBNF grammar or
the EBNF grammar itself as a string.
branding (str or bool): Branding name for the compiler
suite source code.
branding (str): Branding name for the compiler suite source
code.
Returns:
The complete compiler suite skeleton as Python source code.
Raises:
CompilationError if any errors occurred during compilation
"""
grammar = get_ebnf_grammar()
if branding == True: branding = "DSL"
compiler = get_ebnf_compiler(branding or "DSL", ebnf_src)
compiler = get_ebnf_compiler(branding , ebnf_src)
grammar_src = compileDSL(ebnf_src, nil_scanner, grammar, EBNFTransformer, compiler)
src = [DHPARSER_IMPORTS,
compiler.gen_scanner_skeleton(),
grammar_src,
compiler.gen_transformer_skeleton(),
compiler.gen_compiler_skeleton(),
DHPARSER_MAIN.format(NAME=branding)]
src = ["#/usr/bin/python\n",
SECTION_MARKER.format(marker=SYMBOLS_SECTION), DHPARSER_IMPORTS,
SECTION_MARKER.format(marker=SCANNER_SECTION), compiler.gen_scanner_skeleton(),
SECTION_MARKER.format(marker=PARSER_SECTION), grammar_src,
SECTION_MARKER.format(marker=AST_SECTION), compiler.gen_transformer_skeleton(),
SECTION_MARKER.format(marker=COMPILER_SECTION), compiler.gen_compiler_skeleton(),
SECTION_MARKER.format(marker=SYMBOLS_SECTION), DHPARSER_MAIN.format(NAME=branding)]
return '\n'.join(src)
def compile_parser(ebnf_src, branding="DSL"):
def parser_factory(ebnf_src, branding="DSL"):
"""Compiles an EBNF grammar and returns a grammar-parser factory
function for that grammar.
......@@ -250,19 +252,18 @@ def load_compiler_suite(compiler_suite):
'Please delete or repair file manually.')
# TODO: Compile in one step and pick parts from namespace later ?
scanner = compile_python_object(imports + scanner_py, 'get_\w*_scanner$')
parser = compile_python_object(imports + parser_py, 'get_\w*_grammar$')
ast = compile_python_object(imports + ast_py, 'get_\w*_transformer$')
compiler = compile_python_object(imports + compiler_py, 'get_\w*_compiler$')
else:
# assume source is an ebnf grammar
# assume source is an ebnf grammar. Is there really any reasonable application case for this?
with logging(False):
parser_py, errors, AST = compile_source(source, None,
compile_py, errors, AST = compile_source(source, None,
get_ebnf_grammar(), get_ebnf_transformer(), get_ebnf_compiler())
if errors:
raise GrammarError('\n\n'.join(errors), source)
scanner = get_ebnf_scanner
ast = get_ebnf_transformer
compiler = get_ebnf_compiler
parser = compile_python_object(DHPARSER_IMPORTS + parser_py, 'get_\w*_grammar$')
compiler = compile_python_object(imports + compiler_py, 'get_\w*_compiler$')
return scanner, parser, ast, compiler
......
......@@ -20,11 +20,15 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import inspect
import os
import sys
sys.path.extend(['../', './'])
from DHParser.dsl import compile_on_disk, run_compiler, compileDSL, compileEBNF, compile_parser
from DHParser.parsers import GrammarBase, CompilerBase
from DHParser.ebnf import get_ebnf_compiler, get_ebnf_scanner, get_ebnf_transformer
from DHParser.dsl import compile_on_disk, run_compiler, compileDSL, compileEBNF, parser_factory, \
load_compiler_suite
ARITHMETIC_EBNF = """
......@@ -44,9 +48,9 @@ class TestCompileFunctions:
parser_src = compileEBNF(ARITHMETIC_EBNF, branding="CustomDSL")
assert isinstance(parser_src, str), str(type(parser_src))
assert parser_src.find('get_CustomDSL') >= 0
parser_factory = compile_parser(ARITHMETIC_EBNF, branding="TestDSL")
assert callable(parser_factory)
parser = parser_factory()
factory = parser_factory(ARITHMETIC_EBNF, branding="TestDSL")
assert callable(factory)
parser = factory()
result = parser("5 + 3 * 4")
assert not result.error_flag
result = parser("5A + 4B ** 4C")
......@@ -78,6 +82,18 @@ class TestCompilerGeneration:
os.remove(name)
pass
def test_load_compiler_suite(self):
src = compileEBNF(self.trivial_lang, "Trivial")
scanner, parser, transformer, compiler = load_compiler_suite(src)
scanner = scanner()
parser = parser()
transformer = transformer()
compiler = compiler()
assert callable(scanner)
assert isinstance(parser, GrammarBase)
assert callable(transformer)
assert isinstance(compiler, CompilerBase)
def test_compiling_functions(self):
# test if cutting and reassembling of compiler suite works:
errors = compile_on_disk(self.grammar_name)
......
......@@ -28,7 +28,7 @@ sys.path.extend(['../', './'])
from DHParser.toolkit import is_logging
from DHParser.parsers import compile_source, Retrieve, WHITESPACE_KEYWORD, nil_scanner
from DHParser.ebnf import get_ebnf_grammar, get_ebnf_transformer, EBNFTransformer, get_ebnf_compiler
from DHParser.dsl import compileEBNF, compileDSL, compile_parser
from DHParser.dsl import compileEBNF, compileDSL, parser_factory
class TestDirectives:
......@@ -42,7 +42,7 @@ class TestDirectives:
def test_whitespace_linefeed(self):
lang = "@ whitespace = linefeed\n" + self.mini_language
MinilangParser = compile_parser(lang)
MinilangParser = parser_factory(lang)
parser = MinilangParser()
assert parser
syntax_tree = parser("3 + 4 * 12")
......@@ -58,7 +58,7 @@ class TestDirectives:
def test_whitespace_vertical(self):
lang = "@ whitespace = vertical\n" + self.mini_language
parser = compile_parser(lang)()
parser = parser_factory(lang)()
assert parser
syntax_tree = parser("3 + 4 * 12")
assert not syntax_tree.collect_errors()
......@@ -71,7 +71,7 @@ class TestDirectives:
def test_whitespace_horizontal(self):
lang = "@ whitespace = horizontal\n" + self.mini_language
parser = compile_parser(lang)()
parser = parser_factory(lang)()
assert parser
syntax_tree = parser("3 + 4 * 12")
assert not syntax_tree.collect_errors()
......@@ -131,8 +131,8 @@ class TestPopRetrieve:
"""
def setup(self):
self.minilang_parser = compile_parser(self.mini_language)()
self.minilang_parser2 = compile_parser(self.mini_lang2)()
self.minilang_parser = parser_factory(self.mini_language)()
self.minilang_parser2 = parser_factory(self.mini_lang2)()
@staticmethod
def opening_delimiter(node, name):
......
......@@ -28,7 +28,7 @@ from DHParser.syntaxtree import no_operation, traverse, remove_expendables, \
replace_by_single_child, reduce_single_child, flatten
from DHParser.parsers import compile_source
from DHParser.ebnf import get_ebnf_grammar, get_ebnf_transformer, get_ebnf_compiler
from DHParser.dsl import compile_parser, DHPARSER_IMPORTS
from DHParser.dsl import parser_factory, DHPARSER_IMPORTS
ARITHMETIC_EBNF = """
......@@ -72,7 +72,7 @@ class TestInfiLoopsAndRecursion:
def test_direct_left_recursion(self):
minilang = ARITHMETIC_EBNF
snippet = "5 + 3 * 4"
parser = compile_parser(minilang)()
parser = parser_factory(minilang)()
assert parser
syntax_tree = parser(snippet)
assert not syntax_tree.collect_errors()
......@@ -87,7 +87,7 @@ class TestInfiLoopsAndRecursion:
def test_inifinite_loops(self):
minilang = """not_forever = { // } \n"""
snippet = " "
parser = compile_parser(minilang)()
parser = parser_factory(minilang)()
syntax_tree = parser(snippet)
assert syntax_tree.error_flag
# print(syntax_tree.collect_errors())
......
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