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

Commit 465f90f6 authored by eckhart's avatar eckhart
Browse files

- added syntaxtree.Node.__deepcopy__

parent ad1709b9
...@@ -34,6 +34,7 @@ See module ``ebnf`` for a sample of the implementation of a ...@@ -34,6 +34,7 @@ See module ``ebnf`` for a sample of the implementation of a
compiler object. compiler object.
""" """
import copy
import os import os
import re import re
...@@ -216,8 +217,9 @@ class Compiler: ...@@ -216,8 +217,9 @@ class Compiler:
def compile_source(source: str, def compile_source(source: str,
preprocessor: Optional[PreprocessorFunc], # str -> str preprocessor: Optional[PreprocessorFunc], # str -> str
parser: Grammar, # str -> Node (concrete syntax tree (CST)) parser: Grammar, # str -> Node (concrete syntax tree (CST))
transformer: TransformationFunc, # Node -> Node (abstract syntax tree (AST)) transformer: TransformationFunc, # Node (CST) -> Node (abstract syntax tree (AST))
compiler: Compiler) -> Tuple[Any, List[Error], Node]: # Node (AST) -> Any compiler: Compiler, # Node (AST) -> Any
preserve_ast: bool = False) -> Tuple[Any, List[Error], Node]:
""" """
Compiles a source in four stages: Compiles a source in four stages:
1. Pre-Processing (if needed) 1. Pre-Processing (if needed)
...@@ -239,13 +241,15 @@ def compile_source(source: str, ...@@ -239,13 +241,15 @@ def compile_source(source: str,
transforms it (in place) into an abstract syntax tree. transforms it (in place) into an abstract syntax tree.
compiler (function): A compiler function or compiler class compiler (function): A compiler function or compiler class
instance instance
preserve_ast (bool): Preserves the AST-tree.
Returns (tuple): Returns (tuple):
The result of the compilation as a 3-tuple The result of the compilation as a 3-tuple
(result, errors, abstract syntax tree). In detail: (result, errors, abstract syntax tree). In detail:
1. The result as returned by the compiler or ``None`` in case of failure 1. The result as returned by the compiler or ``None`` in case of failure
2. A list of error or warning messages 2. A list of error or warning messages
3. The root-node of the abstract syntax tree 3. The root-node of the abstract syntax tree if `preserve_ast` is True
or `None` otherwise.
""" """
original_text = load_if_file(source) original_text = load_if_file(source)
log_file_name = logfile_basename(source, compiler) log_file_name = logfile_basename(source, compiler)
...@@ -272,6 +276,8 @@ def compile_source(source: str, ...@@ -272,6 +276,8 @@ def compile_source(source: str,
if is_logging(): if is_logging():
log_ST(syntax_tree, log_file_name + '.ast') log_ST(syntax_tree, log_file_name + '.ast')
if not is_error(syntax_tree.error_flag): if not is_error(syntax_tree.error_flag):
if preserve_ast:
ast = copy.deepcopy(syntax_tree)
result = compiler(syntax_tree) result = compiler(syntax_tree)
# print(syntax_tree.as_sxpr()) # print(syntax_tree.as_sxpr())
# messages.extend(syntax_tree.collect_errors()) # messages.extend(syntax_tree.collect_errors())
...@@ -279,4 +285,4 @@ def compile_source(source: str, ...@@ -279,4 +285,4 @@ def compile_source(source: str,
messages = syntax_tree.collect_errors() messages = syntax_tree.collect_errors()
adjust_error_locations(messages, original_text, source_mapping) adjust_error_locations(messages, original_text, source_mapping)
return result, messages, syntax_tree return result, messages, (ast if preserve_ast else None)
...@@ -540,10 +540,6 @@ class EBNFCompiler(Compiler): ...@@ -540,10 +540,6 @@ class EBNFCompiler(Compiler):
definitions.append((self.WHITESPACE_PARSER_KEYWORD, definitions.append((self.WHITESPACE_PARSER_KEYWORD,
'Whitespace(%s)' % self.WHITESPACE_KEYWORD)) 'Whitespace(%s)' % self.WHITESPACE_KEYWORD))
# definitions.append(('wspR__', self.WHITESPACE_KEYWORD
# if 'right' in self.directives['literalws'] else "''"))
# definitions.append(('wspL__', self.WHITESPACE_KEYWORD
# if 'left' in self.directives['literalws'] else "''"))
definitions.append((self.WHITESPACE_KEYWORD, definitions.append((self.WHITESPACE_KEYWORD,
("mixin_comment(whitespace=" + self.RAW_WS_KEYWORD + ("mixin_comment(whitespace=" + self.RAW_WS_KEYWORD +
", comment=" + self.COMMENT_KEYWORD + ")"))) ", comment=" + self.COMMENT_KEYWORD + ")")))
......
...@@ -53,8 +53,8 @@ __all__ = ('Parser', ...@@ -53,8 +53,8 @@ __all__ = ('Parser',
'TKN', 'TKN',
'Whitespace', 'Whitespace',
'mixin_comment', 'mixin_comment',
# 'UnaryOperator', 'UnaryOperator',
# 'NaryOperator', 'NaryOperator',
'Synonym', 'Synonym',
'Option', 'Option',
'ZeroOrMore', 'ZeroOrMore',
......
...@@ -26,6 +26,7 @@ parser classes are defined in the ``parse`` module. ...@@ -26,6 +26,7 @@ parser classes are defined in the ``parse`` module.
import collections.abc import collections.abc
from collections import OrderedDict from collections import OrderedDict
import copy
from DHParser.error import Error, linebreaks, line_col from DHParser.error import Error, linebreaks, line_col
from DHParser.stringview import StringView from DHParser.stringview import StringView
...@@ -278,6 +279,17 @@ class Node(collections.abc.Sized): ...@@ -278,6 +279,17 @@ class Node(collections.abc.Sized):
self.result = result self.result = result
self.parser = parser or ZOMBIE_PARSER self.parser = parser or ZOMBIE_PARSER
def __deepcopy__(self, memo):
if self.children:
duplicate = self.__class__(self.parser, copy.deepcopy(self.children), False)
else:
duplicate = self.__class__(self.parser, self.result, True)
duplicate.errors = copy.deepcopy(self.errors) if self.errors else []
duplicate._pos = self._pos
duplicate._len = self._len
if hasattr(self, '_xml_attr'):
duplicate._xml_attr = copy.deepcopy(self._xml_attr)
return duplicate
def __str__(self): def __str__(self):
s = "".join(str(child) for child in self.children) if self.children else self.content s = "".join(str(child) for child in self.children) if self.children else self.content
......
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