Skip to content

Instantly share code, notes, and snippets.

@simonesestito
Last active April 7, 2023 08:53
Show Gist options
  • Save simonesestito/0f3f67fd7990f2f42f2281a5606010bf to your computer and use it in GitHub Desktop.
Save simonesestito/0f3f67fd7990f2f42f2281a5606010bf to your computer and use it in GitHub Desktop.
Recursion remover for CFG
X XaZ|YWc|W
Y Yd|WbZ|ZWc|X
W WXa|ZZd|YYe|c
Z XX|Zc
import sys
all_prods = []
line = None
while line != '':
line = input(
'Production as A bc|d (or ""): '
if sys.stdin.isatty()
else ''
)
if not line:
break
letter = line[0]
line = line[2:]
letter_prods = [ [*prod] for prod in line.split('|') ]
all_prods.append([letter, letter_prods])
def print_prods():
for i, [letter, prods] in enumerate(all_prods):
print(f'{letter:<2} -> ', end='')
for ip, prod in enumerate(prods):
for prod_l in prod:
print(f'{prod_l:<2}', end=' ')
if not prod:
print('ε', end='')
print()
if ip < len(prods) - 1:
print(' | ', end='')
print()
print('-'*15)
print()
print('INIZIO')
print_prods()
for i, [curr_l, curr_p] in enumerate(all_prods):
if curr_l.endswith("'"): continue
# Prev letters
for prev_l, prev_p in all_prods[:i]:
if prev_l.endswith("'"): continue
all_prods[i][1] = curr_p = [
p
for p in curr_p
if p[0] != prev_l
] + [
prev_pp + p[1:]
for prev_pp in prev_p
for p in curr_p
if p[0] == prev_l
]
print(f'POST SUBS {prev_l} IN {curr_l}')
print_prods()
# Current recursion
all_prods[i][1] = [ # curr_p assigned
p + [curr_l + "'"]
for p in curr_p
if p[0] != curr_l
]
# New variable X'
all_prods.append([curr_l + "'", [
p[1:] + [curr_l + "'"]
for p in curr_p
if p[0] == curr_l
] + [[
# Epsilon
]]
])
print(f'POST IMMEDIATE {curr_l}')
print_prods()
# Sort by letter
all_prods.sort(key=lambda prod: prod[0])
print('FINALE')
print_prods()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment