-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path04_shift_reduce_parser.py
More file actions
50 lines (42 loc) · 1.69 KB
/
04_shift_reduce_parser.py
File metadata and controls
50 lines (42 loc) · 1.69 KB
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
def shift_reduce_parser(input_string):
grammar = {"T+T": "T", "T-T": "T", "T*T": "T", "id": "T"}
# Initialize stack and input
stack = ["$"]
input_string += "$"
pointer = 0
def try_reduce():
# Try to reduce from largest possible handles
for size in range(3, 0, -1): # Try handles of length 3, 2, 1
if len(stack) >= size + 1: # +1 because of '$' at bottom
handle = "".join(stack[-size:])
if handle in grammar:
for _ in range(size):
stack.pop()
stack.append(grammar[handle])
return f"Reduce {handle} → {grammar[handle]}"
return None
# Print header
print(f"{'Stack':<30} {'Input':<30} Action")
print(f"{''.join(stack):<30} {input_string[pointer:]:<30} Initial State")
while True:
# Try reducing if possible
reduction = try_reduce()
if reduction:
print(f"{''.join(stack):<30} {input_string[pointer:]:<30} {reduction}")
continue
# Check for accept condition
if input_string[pointer] == "$" and stack == ["$", "T"]:
print(f"{''.join(stack):<30} {input_string[pointer:]:<30} Accept")
break
# Shift next symbol
if input_string[pointer : pointer + 2] == "id":
stack.append("id")
pointer += 2
print(f"{''.join(stack):<30} {input_string[pointer:]:<30} Shift")
else:
stack.append(input_string[pointer])
pointer += 1
print(f"{''.join(stack):<30} {input_string[pointer:]:<30} Shift")
# Example usage
input_string = "id+id*id"
shift_reduce_parser(input_string)