Source code for sexpr.grammar
from .matcher import Matcher
from .sexpr import Sexpr
_str_format = '''
(grammar
path:
{}
root:
{}
rules:
{}
)'''
[docs]class Grammar(Matcher):
registered_tags = {}
[docs] @classmethod
def register(cls, tag, tag_class):
cls.registered_tags[tag] = tag_class
def __init__(self, source, options = None):
self.options = options or {}
self.yaml = source.get('rules', {})
self.path = self.options.get('path', None)
self.rules = self.compile_rules(self.yaml)
try:
self.root = self.options.get('root', None)
self.root = self.root or list(self.yaml.items())[0][0]
self.top_tags = self.yaml.get(self.root, [])
except IndexError:
raise ValueError('Cannot load root node. Grammar is ill-formed.')
[docs] def sexpr(self, sexpr):
if isinstance(sexpr, list) and sexpr and sexpr[0] in self.rules:
sexpr = [sexpr[0]] + [self.sexpr(n) for n in sexpr[1:]]
return self.tag_node(sexpr)
return sexpr
[docs] def tag_node(self, sexpr):
if isinstance(sexpr, Sexpr):
return sexpr
elif sexpr and sexpr[0] in self.registered_tags:
return self.registered_tags[sexpr[0]](sexpr, self)
return Sexpr(sexpr, self)
def __repr__(self):
print_rule = lambda r: '{} = {}'.format(r.name, r.body)
return _str_format.format(
self.path or '-',
self.root,
'\n '.join(print_rule(r) for r in self.rules.values())
)