In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit 0500646e authored by Eckhart Arnold's avatar Eckhart Arnold

- syntaxtree.py: full json serialization

parent aceb5bda
...@@ -88,15 +88,20 @@ CONFIG_PRESET['max_parser_dropouts'] = 3 ...@@ -88,15 +88,20 @@ CONFIG_PRESET['max_parser_dropouts'] = 3
# 'json' - output in JSON-format. This is probably the least # 'json' - output in JSON-format. This is probably the least
# readable representation, but useful for serialization, for # readable representation, but useful for serialization, for
# example, to return syntax trees from remote procedure calls. # example, to return syntax trees from remote procedure calls.
# 'simple-json' - a more readable JSON-format
# Default values: "compact" for concrete syntax trees and "XML" for abstract # Default values: "compact" for concrete syntax trees and "XML" for abstract
# syntax trees and "S-expression" for any other kind of tree. # syntax trees and "S-expression" for any other kind of tree.
XML_SERIALIZATION = "XML" XML_SERIALIZATION = "XML"
SXPRESSION_SERIALIZATION = "S-expression" SXPRESSION_SERIALIZATION = "S-expression"
COMPACT_SERIALIZATION = "compact" COMPACT_SERIALIZATION = "compact"
JSON_SERIALIZATION = "json" JSON_SERIALIZATION = "json"
SIMPLE_JSON_SERIALIZATION = "simple-json"
SERIALIZATIONS = frozenset({XML_SERIALIZATION, SXPRESSION_SERIALIZATION, SERIALIZATIONS = frozenset({XML_SERIALIZATION,
COMPACT_SERIALIZATION, JSON_SERIALIZATION}) SXPRESSION_SERIALIZATION,
COMPACT_SERIALIZATION,
JSON_SERIALIZATION,
SIMPLE_JSON_SERIALIZATION})
CONFIG_PRESET['cst_serialization'] = COMPACT_SERIALIZATION CONFIG_PRESET['cst_serialization'] = COMPACT_SERIALIZATION
CONFIG_PRESET['ast_serialization'] = XML_SERIALIZATION CONFIG_PRESET['ast_serialization'] = XML_SERIALIZATION
......
...@@ -26,7 +26,8 @@ parser classes are defined in the ``parse`` module. ...@@ -26,7 +26,8 @@ parser classes are defined in the ``parse`` module.
from collections import OrderedDict from collections import OrderedDict
import copy import copy
import json import json
from typing import Callable, cast, Iterator, List, AbstractSet, Set, Union, Tuple, Optional, Dict from typing import Callable, cast, Iterator, Sequence, List, AbstractSet, Set, Union, Tuple, \
Optional, Dict
from DHParser.configuration import SERIALIZATIONS, XML_SERIALIZATION, SXPRESSION_SERIALIZATION, \ from DHParser.configuration import SERIALIZATIONS, XML_SERIALIZATION, SXPRESSION_SERIALIZATION, \
COMPACT_SERIALIZATION, JSON_SERIALIZATION COMPACT_SERIALIZATION, JSON_SERIALIZATION
...@@ -292,7 +293,6 @@ class Node(JSONSerializable): # (collections.abc.Sized): Base class omitted for ...@@ -292,7 +293,6 @@ class Node(JSONSerializable): # (collections.abc.Sized): Base class omitted for
self._id = gen_id() self._id = gen_id()
return self._id return self._id
def equals(self, other: 'Node') -> bool: def equals(self, other: 'Node') -> bool:
""" """
Equality of value: Two nodes are considered as having the same value, Equality of value: Two nodes are considered as having the same value,
...@@ -771,45 +771,62 @@ class Node(JSONSerializable): # (collections.abc.Sized): Base class omitted for ...@@ -771,45 +771,62 @@ class Node(JSONSerializable): # (collections.abc.Sized): Base class omitted for
## JSON reading and writing ## JSON reading and writing
def to_json_obj(self) -> Dict: def to_json_obj(self) -> Dict:
"""Serialize a node or tree as json-object""" """Serialize a node or tree as JSON-object."""
json_obj = {'__class__': 'DHParser.Node', 'tag_name': self.tag_name } json_obj = {'__class__': 'DHParser.Node', 'tag_name': self.tag_name }
if self.children: if self.children:
json_obj['result'] = [child.to_json_obj() for child in self.children] json_obj['result'] = [child.to_json_obj() for child in self.children]
else: else:
json_obj['result'] = str(self._result) json_obj['result'] = str(self.result)
if self.pos >= 0:
json_obj['pos'] = self.pos
if self.has_attr(): if self.has_attr():
json_obj['attr'] = dict(self._xml_attr) json_obj['attr'] = dict(self.attr)
if self._pos >= 0:
json_obj['pos'] = self._pos
json_obj['id'] = self.id json_obj['id'] = self.id
return json_obj return json_obj
def to_simplified_json_obj(self) -> List:
"""Serialize node or tree as JSON-serializable nested list."""
l = [self.tag_name, list[self.result] if self.children else str(self.result)]
pos = self.pos
if pos >= 0:
l.append(pos)
if self.has_attr():
l.append(dict(self.attr))
return l
@staticmethod @staticmethod
def from_json_obj(json_obj: Dict) -> 'Node': def from_json_obj(json_obj: Union[Dict, Sequence]) -> 'Node':
"""Convert a json object representing a node (or tree) back into a """Convert a JSON-object representing a node (or tree) back into a
Node object. Raises a ValueError, if `json_obj` does not represent Node object. Raises a ValueError, if `json_obj` does not represent
a node.""" a node."""
assert isinstance(json_obj, Dict) if isinstance(json_obj, Dict):
if json_obj.get('__class__', '') not in ('DHParser.Node', 'DHParser.RootNode'): if json_obj.get('__class__', '') not in ('DHParser.Node', 'DHParser.RootNode'):
raise ValueError('JSON object: ' + str(json_obj) + raise ValueError('JSON object: ' + str(json_obj) +
' does not represent a Node object.') ' does not represent a Node object.')
tag_name = json_obj['tag_name'] tag_name = json_obj['tag_name']
result = json_obj['result'] result = json_obj['result']
if isinstance(result, str):
leafhint = True
else:
leafhint = False
result = tuple(Node.from_json_obj(child) for child in result) result = tuple(Node.from_json_obj(child) for child in result)
node = Node(tag_name, result, leafhint) node = Node(tag_name, result)
node._pos = json_obj.get('pos', -1) node._pos = json_obj.get('pos', -1)
attr = json_obj.get('attr', {}) attr = json_obj.get('attr', {})
if attr: if attr:
node.attr.update(attr) node.attr.update(attr)
node._id = json_obj['id'] node._id = json_obj['id']
else:
assert isinstance(json_obj, Sequence)
assert 2 <= len(json_obj) <= 4
node = Node(json_obj[0], json_obj[1])
for extra in json_obj[2:]:
if isinstance(extra, dict):
node.attr.update(extra)
else:
assert isinstance(extra, int)
node._pos = extra
return node return node
def as_json(self, indent: Optional[int] = 2, ensure_ascii=False) -> str: def as_json(self, indent: Optional[int] = 2, ensure_ascii=False, simplified=False) -> str:
return json.dumps(self.to_json_obj(), indent=indent, ensure_ascii=ensure_ascii, return json.dumps(self.to_simplified_json_obj() if simplified else self.to_json_obj(),
indent=indent, ensure_ascii=ensure_ascii,
separators=(', ', ': ') if indent is not None else (',', ':')) separators=(', ', ': ') if indent is not None else (',', ':'))
## generalized serialization methoed ## generalized serialization methoed
......
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