Files
Django_kube/Webcal-python/venv/lib/python3.11/site-packages/tatsu/semantics.py
T

96 lines
2.8 KiB
Python

from __future__ import annotations
import builtins
from .exceptions import SemanticError
from .objectmodel import BASE_CLASS_TOKEN, Node
from .synth import synthesize
from .util import simplify_list
class ASTSemantics:
def group(self, ast, *args):
return simplify_list(ast)
def element(self, ast, *args):
return simplify_list(ast)
def sequence(self, ast, *args):
return simplify_list(ast)
def choice(self, ast, *args):
if len(ast) == 1:
return simplify_list(ast[0])
return ast
class ModelBuilderSemantics:
"""Intended as a semantic action for parsing, a ModelBuilderSemantics creates
nodes using the class name given as first parameter to a grammar
rule, and synthesizes the class/type if it's not known.
"""
def __init__(self, context=None, base_type=Node, types=None):
self.ctx = context
self.base_type = base_type
self.constructors = {}
for t in types or ():
self._register_constructor(t)
def _register_constructor(self, constructor):
self.constructors[constructor.__name__] = constructor
return constructor
def _find_existing_constructor(self, typename):
constructor = builtins
for name in typename.split('.'):
try:
context = vars(constructor)
except Exception as e:
raise SemanticError(
f'Could not find constructor for {typename} ({type(constructor).__name__}): {e!s}',
) from e
if name in context:
constructor = context[name]
else:
constructor = None
break
return constructor
def _get_constructor(self, typename, base):
typename = str(typename)
if typename in self.constructors:
return self.constructors[typename]
constructor = self._find_existing_constructor(typename)
if not constructor:
constructor = synthesize(typename, base)
return self._register_constructor(constructor)
def _default(self, ast, *args, **kwargs):
if not args:
return ast
typespec = args[0].split(BASE_CLASS_TOKEN)
typename = typespec[0]
bases = typespec[-1:0:-1]
base = self.base_type
for base_ in bases:
base = self._get_constructor(base_, base)
constructor = self._get_constructor(typename, base)
try:
if isinstance(constructor, type) and issubclass(constructor, Node):
return constructor(ast=ast, ctx=self.ctx, **kwargs)
else:
return constructor(ast, *args[1:], **kwargs)
except Exception as e:
raise SemanticError(
f'Could not call constructor for {typename}: {e!s}',
) from e