1from .utils import Serialize
2
3###{standalone
4
5class Symbol(Serialize):
6    __slots__ = ('name',)
7
8    is_term = NotImplemented
9
10    def __init__(self, name):
11        self.name = name
12
13    def __eq__(self, other):
14        assert isinstance(other, Symbol), other
15        return self.is_term == other.is_term and self.name == other.name
16
17    def __ne__(self, other):
18        return not (self == other)
19
20    def __hash__(self):
21        return hash(self.name)
22
23    def __repr__(self):
24        return '%s(%r)' % (type(self).__name__, self.name)
25
26    fullrepr = property(__repr__)
27
28
29class Terminal(Symbol):
30    __serialize_fields__ = 'name', 'filter_out'
31
32    is_term = True
33
34    def __init__(self, name, filter_out=False):
35        self.name = name
36        self.filter_out = filter_out
37
38    @property
39    def fullrepr(self):
40        return '%s(%r, %r)' % (type(self).__name__, self.name, self.filter_out)
41
42
43class NonTerminal(Symbol):
44    __serialize_fields__ = 'name',
45
46    is_term = False
47
48
49class RuleOptions(Serialize):
50    __serialize_fields__ = 'keep_all_tokens', 'expand1', 'priority', 'template_source', 'empty_indices'
51
52    def __init__(self, keep_all_tokens=False, expand1=False, priority=None, template_source=None, empty_indices=()):
53        self.keep_all_tokens = keep_all_tokens
54        self.expand1 = expand1
55        self.priority = priority
56        self.template_source = template_source
57        self.empty_indices = empty_indices
58
59    def __repr__(self):
60        return 'RuleOptions(%r, %r, %r, %r)' % (
61            self.keep_all_tokens,
62            self.expand1,
63            self.priority,
64            self.template_source
65        )
66
67
68class Rule(Serialize):
69    """
70        origin : a symbol
71        expansion : a list of symbols
72        order : index of this expansion amongst all rules of the same name
73    """
74    __slots__ = ('origin', 'expansion', 'alias', 'options', 'order', '_hash')
75
76    __serialize_fields__ = 'origin', 'expansion', 'order', 'alias', 'options'
77    __serialize_namespace__ = Terminal, NonTerminal, RuleOptions
78
79    def __init__(self, origin, expansion, order=0, alias=None, options=None):
80        self.origin = origin
81        self.expansion = expansion
82        self.alias = alias
83        self.order = order
84        self.options = options or RuleOptions()
85        self._hash = hash((self.origin, tuple(self.expansion)))
86
87    def _deserialize(self):
88        self._hash = hash((self.origin, tuple(self.expansion)))
89
90    def __str__(self):
91        return '<%s : %s>' % (self.origin.name, ' '.join(x.name for x in self.expansion))
92
93    def __repr__(self):
94        return 'Rule(%r, %r, %r, %r)' % (self.origin, self.expansion, self.alias, self.options)
95
96    def __hash__(self):
97        return self._hash
98
99    def __eq__(self, other):
100        if not isinstance(other, Rule):
101            return False
102        return self.origin == other.origin and self.expansion == other.expansion
103
104
105###}
106