-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrammer.py
37 lines (27 loc) · 1.33 KB
/
grammer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Grammar:
def __init__(self, grammar_str):
self.grammar_str = '\n'.join(filter(None, grammar_str.splitlines()))
self.grammar = {}
self.start = None
self.terminals = set()
self.nonterminals = set()
for production in list(filter(None, grammar_str.splitlines())):
head, _, bodies = production.partition(' -> ')
if not head.isupper():
raise ValueError(
f'\'{head} -> {bodies}\': Head \'{head}\' is not capitalized to be treated as a nonterminal.')
if not self.start:
self.start = head
self.grammar.setdefault(head, [])
self.nonterminals.add(head)
bodies = {tuple(body.split()) for body in ' '.join(bodies.split()).split('|')}
for body in bodies:
if '^' in body and body != ('^',):
raise ValueError(f'\'{head} -> {" ".join(body)}\': Null symbol \'^\' is not allowed here.')
self.grammar[head].append(body)
for symbol in body:
if not symbol.isupper() and symbol != '^':
self.terminals.add(symbol)
elif symbol.isupper():
self.nonterminals.add(symbol)
self.symbols = self.terminals | self.nonterminals