-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathambiguate.py
executable file
·64 lines (49 loc) · 1.62 KB
/
ambiguate.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env python3
import sys
def parse_grammar(fn):
grammar = {}
with open(fn, 'r') as grammar_file:
for line in grammar_file:
line = line.strip() # Strip trailing whitespace
line = line.split('#')[0] # Stop reading after comment starts
if len(line) == 0: continue
# Split into component parts
line = line.split()
lhs = line[0]
rhs = line[1:]
# Add to grammar
if lhs not in grammar:
grammar[lhs] = []
grammar[lhs].append(rhs)
return grammar
def print_grammar(grammar):
for (lhs, rhs) in grammar.items():
for rule in rhs:
print('%s\t%s' % (lhs, ' '.join(rule)))
def symbols(g):
res = set([])
for (lhs, rhs) in g.iteritems():
res.add(lhs)
for syms in rhs:
res |= set(syms)
return res
def nonterminals(g):
return set(g.keys())
def terminals(g):
return symbols(g) - nonterminals(g)
def main(grammar_fn, n):
grammar = parse_grammar(grammar_fn)
for i in range(n-1):
mapping = { sym : '%s_%d' % (sym, i) for sym in nonterminals(grammar) }
for (lhs, rhs) in list(grammar.items()):
new_lhs = mapping[lhs]
new_rhs = [[mapping.get(sym, sym) for sym in rule] for rule in rhs]
grammar[new_lhs] = new_rhs
for (s1, s2) in mapping.items():
grammar[s1].append([s2])
print_grammar(grammar)
if __name__ == '__main__':
if len(sys.argv) != 3:
print('Usage: ambiguate.py GRAMMAR N')
exit(1)
main(sys.argv[1], int(sys.argv[2]))