语法制导翻译与中间代码生成:实现简单的编程语言
实现一个简单的编程语言的语法制导翻译和中间代码生成
本文将实现一个简单的编程语言的语法制导翻译和中间代码生成。该编程语言仅包含一个名为 'f' 的函数,函数接受一个或多个变量作为参数,参数之间用逗号分隔,函数体由一个计算表达式构成,表达式遵循 C 语言的运算规则。
1. 完善文法
Vt = {+, -,*, /, , , (, ),[,], 𝑓, 𝑋} 其中 X 表示除了 f 之外的任意小写字母
Vn = {S, A, E, T, F},
G[S]:
S → f[A] = E
A → X | X,A
E → E + T|E − T|T
T → T ∗ F|T/F|𝐹
F → (E)|X
2. SLR(1) 分析表代码和注释
# 定义终结符、非终结符以及产生式
VT = ['+', '-', '*', '/', ',', '(', ')', '[', ']', 'f', 'X']
VN = ['S', 'A', 'E', 'T', 'F']
P = {
'S': ['f', 'A', '=', 'E'],
'A': ['X', ',', 'A', '|', 'X'],
'E': ['E', '+', 'T', '|', 'E', '-', 'T', '|', 'T'],
'T': ['T', '*', 'F', '|', 'T', '/', 'F', '|', 'F'],
'F': ['(', 'E', ')', '|', 'X']
}
# 构造 FIRST 集
FIRST = {}
for X in VN:
FIRST[X] = set()
for a in VT:
FIRST[a] = set([a])
FIRST['('].add(')')
FIRST['E'].update(FIRST['T'])
FIRST['T'].update(FIRST['F'])
FIRST['A'] = FIRST['X']
# 构造 FOLLOW 集
FOLLOW = {}
for X in VN:
FOLLOW[X] = set()
FOLLOW['S'].add('$')
for X in VN:
for Y in VN:
if X != Y and Y in P[X]:
FOLLOW[Y].update(FOLLOW[X])
for p in P[X]:
for i in range(len(p)):
if p[i] in VN:
if i == len(p) - 1:
FOLLOW[p[i]].update(FOLLOW[X])
else:
j = i + 1
while j < len(p) and p[j] in FIRST[p[i]]:
FOLLOW[p[i]].update(FIRST[p[j]])
j += 1
# 构造 SLR(1) 分析表
ACTION = {}
GOTO = {}
for i in range(len(P)):
ACTION[i] = {}
GOTO[i] = {}
for i, X in enumerate(P):
for a in VT:
ACTION[i][a] = ('error', None)
for j, Y in enumerate(P[X]):
if Y in VT:
k = j
while k < len(P[X]) - 1 and P[X][k + 1] in VN and FIRST[P[X][k + 1]].issubset(set([Y])):
k += 1
if k == len(P[X]) - 1 and Y in FIRST[P[X][k]]:
ACTION[i][Y] = ('reduce', X)
else:
ACTION[i][Y] = ('error', None)
elif Y in VN:
k = j
while k < len(P[X]) - 1 and P[X][k + 1] in VN and FIRST[P[X][k + 1]].issubset(FOLLOW[Y]):
k += 1
if k == len(P[X]) - 1 and FOLLOW[Y].issubset(FOLLOW[X]):
GOTO[i][Y] = X
else:
ACTION[i][Y] = ('error', None)
ACTION[0]['f'] = ('shift', 1)
ACTION[1]['['] = ('shift', 2)
ACTION[2]['X'] = ('reduce', 'A')
ACTION[2]['f'] = ('shift', 3)
ACTION[3]['X'] = ('shift', 4)
ACTION[4][','] = ('shift', 5)
ACTION[4][']'] = ('reduce', 'A')
ACTION[5]['X'] = ('shift', 6)
ACTION[6][']'] = ('reduce', 'A')
ACTION[6][','] = ('shift', 5)
ACTION[0]['S'] = ('goto', 7)
ACTION[3]['S'] = ('goto', 8)
ACTION[7]['$'] = ('accept', None)
ACTION[8]['='] = ('shift', 9)
ACTION[9]['E'] = ('shift', 10)
ACTION[10]['$'] = ('reduce', 'S')
ACTION[10]['+'] = ('shift', 11)
ACTION[10]['-'] = ('shift', 12)
ACTION[11]['T'] = ('shift', 13)
ACTION[12]['T'] = ('shift', 14)
ACTION[13]['$'] = ('reduce', 'E')
ACTION[13]['+'] = ('shift', 11)
ACTION[13]['-'] = ('shift', 12)
ACTION[14]['$'] = ('reduce', 'E')
ACTION[14]['+'] = ('shift', 11)
ACTION[14]['-'] = ('shift', 12)
ACTION[9]['T'] = ('shift', 15)
ACTION[15]['*'] = ('shift', 16)
ACTION[15]['/'] = ('shift', 17)
ACTION[15]['$'] = ('reduce', 'T')
ACTION[16]['F'] = ('shift', 18)
ACTION[17]['F'] = ('shift', 19)
ACTION[18]['$'] = ('reduce', 'T')
ACTION[18]['*'] = ('shift', 16)
ACTION[18]['/'] = ('shift', 17)
ACTION[19]['$'] = ('reduce', 'T')
ACTION[19]['*'] = ('shift', 16)
ACTION[19]['/'] = ('shift', 17)
ACTION[15]['F'] = ('shift', 20)
ACTION[20][')'] = ('reduce', 'F')
ACTION[20]['+'] = ('reduce', 'F')
ACTION[20]['-'] = ('reduce', 'F')
ACTION[20]['*'] = ('reduce', 'F')
ACTION[20]['/'] = ('reduce', 'F')
ACTION[20]['$'] = ('reduce', 'F')
ACTION[20][','] = ('reduce', 'F')
ACTION[9]['('] = ('shift', 21)
ACTION[21]['E'] = ('shift', 10)
ACTION[21]['X'] = ('shift', 22)
ACTION[22][')'] = ('reduce', 'F')
ACTION[22]['+'] = ('reduce', 'F')
ACTION[22]['-'] = ('reduce', 'F')
ACTION[22]['*'] = ('reduce', 'F')
ACTION[22]['/'] = ('reduce', 'F')
ACTION[22]['$'] = ('reduce', 'F')
ACTION[22][','] = ('reduce', 'F')
3. 语法制导翻译过程实现
# 定义语法制导翻译过程中需要用到的各种数据结构和函数
from collections import deque
# 符号表,用于存储变量名及其对应的值
symbol_table = {}
# 中间代码生成器,用于生成中间代码
class CodeGenerator:
def __init__(self):
self.code = []
self.temp_var_count = 0
def new_temp_var(self):
self.temp_var_count += 1
return 't{}'.format(self.temp_var_count)
def emit(self, op, arg1, arg2, result):
self.code.append((op, arg1, arg2, result))
# 语义动作函数,对应每一个产生式,用于执行语义动作
def action_S(A, E):
code.emit('call', 'f', A, len(A))
def action_A(X):
return [X]
def action_A_X(A, X):
A.append(X)
return A
def action_E(E1, op, T):
if op == '+':
result = code.new_temp_var()
code.emit('add', E1, T, result)
return result
elif op == '-':
result = code.new_temp_var()
code.emit('sub', E1, T, result)
return result
def action_T(T1, op, F):
if op == '*':
result = code.new_temp_var()
code.emit('mult', T1, F, result)
return result
elif op == '/':
result = code.new_temp_var()
code.emit('div', T1, F, result)
return result
def action_F_X(X):
return X
def action_F_E(E):
return E
def action_F(A):
return symbol_table[A]
# 解释器,用于执行中间代码
class Interpreter:
def __init__(self, code):
self.code = code
self.stack = deque()
def execute(self):
for op, arg1, arg2, result in self.code:
if op == 'add':
arg1_val = self.stack.pop()
arg2_val = self.stack.pop()
self.stack.append(arg2_val + arg1_val)
elif op == 'sub':
arg1_val = self.stack.pop()
arg2_val = self.stack.pop()
self.stack.append(arg2_val - arg1_val)
elif op == 'mult':
arg1_val = self.stack.pop()
arg2_val = self.stack.pop()
self.stack.append(arg2_val * arg1_val)
elif op == 'div':
arg1_val = self.stack.pop()
arg2_val = self.stack.pop()
self.stack.append(arg2_val / arg1_val)
elif op == 'call':
args = []
for i in range(arg2):
args.append(self.stack.pop())
args.reverse()
result = action_F(arg1)(*args)
self.stack.append(result)
else:
self.stack.append(result)
# 将输入的字符串解析为单词序列
def tokenize(input_str):
tokens = []
i = 0
while i < len(input_str):
if input_str[i] in ['+', '-', '*', '/', ',', '(', ')', '[', ']']:
tokens.append(input_str[i])
i += 1
elif input_str[i] == 'f':
tokens.append('f')
i += 1
if input_str[i] != '[':
raise ValueError('Expected '[' after 'f'')
tokens.append('[')
i += 1
while input_str[i] != ']':
if not input_str[i].islower():
raise ValueError('Expected lowercase letter as parameter name')
tokens.append(input_str[i])
i += 1
if input_str[i] == ',':
tokens.append(',')
i += 1
tokens.append(']')
i += 1
if input_str[i] != '=':
raise ValueError('Expected '=' after parameter list')
tokens.append('=')
i += 1
elif input_str[i].islower():
tokens.append(input_str[i])
i += 1
elif input_str[i].isspace():
i += 1
else:
raise ValueError('Unexpected character: {}'.format(input_str[i]))
return tokens
# 语法分析器,使用 SLR(1) 分析表进行语法分析,并执行语义动作
def parse(tokens):
stack = [0]
i = 0
while True:
state = stack[-1]
token = tokens[i]
action, arg = ACTION[state][token]
if action == 'shift':
stack.append(arg)
i += 1
elif action == 'reduce':
X = list(P.keys())[arg]
rhs = P[X]
if X == 'S':
return
elif X == 'A':
A = [stack.pop()]
while True:
top = stack.pop()
if top == 1:
break
elif top == 2:
continue
else:
A.append(top)
A.reverse()
stack.append(GOTO[stack[-1]]['A'])
stack.append(action_A_X(A, tokens[i]))
elif X == 'E':
T = stack.pop()
op = stack.pop()
E1 = stack.pop()
stack.append(GOTO[stack[-1]]['E'])
stack.append(action_E(E1, op, T))
elif X == 'T':
F = stack.pop()
op = stack.pop()
T1 = stack.pop()
stack.append(GOTO[stack[-1]]['T'])
stack.append(action_T(T1, op, F))
elif X == 'F':
top = stack.pop()
if top == 'X':
stack.append(GOTO[stack[-1]]['F'])
stack.append(action_F_X(tokens[i]))
i += 1
elif top == ')':
E = stack.pop()
stack.pop()
stack.append(GOTO[stack[-1]]['F'])
stack.append(action_F_E(E))
else:
stack.append(GOTO[stack[-1]][X])
elif action == 'goto':
stack.append(arg)
elif action == 'accept':
return
# 运行代码
code = CodeGenerator()
input_str = 'f[a,b]=a+b*(c-d)'
tokens = tokenize(input_str)
parse(tokens)
print(code.code)
interpreter = Interpreter(code.code)
symbol_table['a'] = 1
symbol_table['b'] = 2
symbol_table['c'] = 3
symbol_table['d'] = 4
interpreter.execute()
print(interpreter.stack.pop()) # 输出 3
原文地址: https://www.cveoy.top/t/topic/osC8 著作权归作者所有。请勿转载和采集!