PL\0 컴파일링 원리 실험(남항)5: 실험 코드, PL\0 코드, 중간 코드의 상세한 설명
23879 단어 컴파일링 원리
매일 저녁에 몇 십 분에서 몇 시간씩 쉬지 않고 일했는데, 중간에 잔업으로 며칠 동안 꾸물거렸는데, 이로써 마침내 완성된 셈이다!
PL\0 코드
program id;
const m:=7, n:=85;
var x,y,z,q,r;
procedure multiply;
var a,b;
begin
a:=x; b:=y; z:=0;
while b>0 do
begin
if odd b then z:=z+a;
a:=2*a; b:=b/2
end
end
begin
x:=m; y:=n;
call multiply
end
컴파일 원리 실험 코드
import sys
# ,
def error(line_num, message):
print(' ' + str(line_num) + ' :' + message)
''' token'''
key_word = ['program', 'const', 'var', 'procedure', 'begin', 'end', 'if', 'then', 'while', 'do', 'call', 'read',
'write'] #
symbol = ['+', '-', '*', '/', '(', ')', '=', ',', ';'] #
token_list = []
token_index = 0
# , 、 ,
def deal_word(word, line_num):
length = len(word)
index = 0
while index < length:
token = dict()
value = '' # token
attribute = '' # token
if word[index].isalpha(): #
while index < length and (word[index].isalpha() or word[index].isdigit()):
value += word[index]
index += 1
if value in key_word: #
attribute = 'keyword'
else:
attribute = 'identifier'
elif word[index].isdigit(): #
while index < length and word[index].isdigit():
value += word[index]
index += 1
value = int(value)
attribute = 'number'
elif word[index] == ':': # : :=
value += word[index]
index += 1
if index < length and word[index] == '=':
value += word[index]
index += 1
attribute = value
elif word[index] == '
value += word[index]
index += 1
if index < length and (word[index] == '=' or word[index] == '>'):
value += word[index]
index += 1
attribute = value
elif word[index] == '>': # > > >=
value += word[index]
index += 1
if index < length and word[index] == '=':
value += word[index]
index += 1
attribute = value
elif word[index] in symbol: #
value = word[index]
attribute = word[index]
index += 1
else:
print(' ' + str(line_num) + ': ' + word[index])
sys.exit(0)
# token
token['value'] = value
token['line_num'] = line_num
token['attribute'] = attribute
token_list.append(token)
# token
def get_token():
global token_index
if token_index >= len(token_list):
sys.exit(0)
token = token_list[token_index]
token_index += 1
return token
''' '''
table_list = [] #
mid_code = [] #
level = 0 # , 1
address = 0 # , level
dx = 3 # 3 SL DL RA
# ,
def record_table(name, kind, value=None, level=None, address=None, size=None):
table = dict()
table['name'] = name
table['kind'] = kind
table['value'] = value
table['level'] = level
table['address'] = address
table['size'] = size
table_list.append(table)
#
def emit(f, l, a):
operation = dict()
operation['F'] = f
operation['L'] = l
operation['A'] = a
mid_code.append(operation)
#
def find_table(val):
index = 0
for var in table_list:
if var['name'] == val:
return index
index += 1
return -1
# → program ;
def prog():
token = get_token()
if token['value'] == 'program': # program
token = get_token()
if token['attribute'] == 'identifier': #
token = get_token()
if token['value'] == ';': # block
block()
else:
error(token['line_num'], ' ;')
else:
error(token['line_num'], ' , ')
else:
error(token['line_num'], ' program ')
# → [][][]
# ; , condecl vardecl proc block
def block():
global dx
global level
global mid_code
global token_index
dx = 3 # block SL DL RA
# block
# block , , body , body
# , , cx1 jmp
cx1 = len(mid_code) # cx1 jmp
emit('JMP', 0, 0)
token = get_token()
if token['value'] == 'const': # → const {,};
const()
token = get_token()
while token['value'] == ',':
const()
token = get_token()
if token['value'] == ';':
token = get_token()
else:
error(token['line_num'], ' ;')
if token['value'] == 'var': # → var {,};
token = get_token()
if token['attribute'] == 'identifier': # dx
record_table(token['value'], 'VARIABLE', level=level, address=dx)
dx += 1
token = get_token()
else:
error(token['line_num'], 'var ')
while token['value'] == ',':
token = get_token()
if token['attribute'] == 'identifier':
record_table(token['value'], 'VARIABLE', level=level, address=dx)
dx += 1
token = get_token()
continue
if token['value'] == ';':
token = get_token()
else:
error(token['line_num'], ' ;')
# while
while token['value'] == 'procedure': # → procedure ([{,}]);{;}
token = get_token()
if token['attribute'] == 'identifier':
record_table(token['value'], 'PROCEDURE', level=level, address=len(mid_code))
token = get_token()
else:
error(token['line_num'], ' ')
if token['value'] != ';': #
error(token['line_num'], ' ;')
token_index -= 1
# block block level
level += 1 # +1
cur_dx = dx #
block()
level -= 1 #
dx = cur_dx #
token = get_token()
if token['value'] == ';': # proc
token = get_token()
else:
break
token_index -= 1 #
# body block jmp
ins = dict()
ins['F'] = 'JMP'
ins['L'] = 0
ins['A'] = len(mid_code) # body
mid_code[cx1] = ins
emit('INT', 0, dx) # body SL DL RA
body() # body
emit('OPR', 0, 0) # ,
# → :=
def const():
token = get_token()
variable = token['value']
if token['attribute'] == 'identifier': #
token = get_token()
if token['value'] == ':=':
token = get_token()
if token['attribute'] == 'number':
record_table(variable, 'CONSTANT', value=token['value'], level=level)
else:
error(token['line_num'], ':= ')
else:
error(token['line_num'], ' :=')
else:
error(token['line_num'], ' ')
# → begin {;}end
def body():
global token_index
token = get_token()
if token['value'] != 'begin':
error(token['line_num'], ' begin')
token_index -= 1
statement()
token = get_token()
while token['value'] == ';': # statement
statement()
token = get_token()
if token['value'] != 'end':
error(token['line_num'], ' end')
token_index -= 1
# → :=
# |if then [else ]
# |while do
# |call ([{,}])
# |
# |read ({,})
# |write ({,})
def statement():
global token_index
global level
token = get_token()
if token['value'] == 'end': # ; statement,
error(token['line_num'], '; ')
token_index -= 1
return
if token['attribute'] == 'identifier': # :=
index = find_table(token['value'])
if index == -1:
error(token['line_num'], token['value'] + ' ')
elif table_list[index]['kind'] != 'VARIABLE':
error(token['line_num'], table_list[index]['name'] + ' ')
token = get_token()
if token['value'] != ':=':
error(token['line_num'], ' :=')
token_index -= 1 #
expression()
if index != -1: # sto
emit('STO', level - table_list[index]['level'], table_list[index]['address'])
elif token['value'] == 'if': # if then [else ]
lexp()
token = get_token()
if token['value'] != 'then':
error(token['line_num'], ' then')
token_index -= 1
cx2 = len(mid_code) # cx2 jpc
emit('JPC', 0, 0) # if jpc else
statement()
# if else
ins = dict()
ins['F'] = 'JPC'
ins['L'] = 0
ins['A'] = len(mid_code) # if
mid_code[cx2] = ins
token = get_token()
if token['value'] == 'else': #
cx1 = len(mid_code)
emit('JMP', 0, 0)
statement()
# if
ins = dict()
ins['F'] = 'JMP'
ins['L'] = 0
ins['A'] = len(mid_code) # if
mid_code[cx1] = ins
else:
token_index -= 1 #
# if
elif token['value'] == 'while': # while do
jmp_addr = len(mid_code) # while
lexp()
token = get_token()
#
if token['value'] != 'do':
error(token['line_num'], ' do ')
token_index -= 1
cx2 = len(mid_code) # cx2 jpc
emit('JPC', 0, 0) # if jpc else
statement()
# jmp
emit('JMP', 0, jmp_addr)
# jpc
ins = dict()
ins['F'] = 'JPC'
ins['L'] = 0
ins['A'] = len(mid_code) # while
mid_code[cx2] = ins
elif token['value'] == 'call': # call ([{,}])
token = get_token()
if token['attribute'] != 'identifier':
error(token['line_num'], ' ')
else:
index = find_table(token['value'])
if index == -1:
error(token['line_num'], token['value'] + ' ')
elif table_list[index]['kind'] == 'PROCEDURE':
emit('CAL', level - table_list[index]['level'], table_list[index]['address'])
else:
error(token['line_num'], token['value'] + ' ')
else: # body
token_index -= 1
body()
# → [+|-]{}
def expression():
global token_index
token = get_token()
if token['value'] == '+' or token['value'] == '-':
term()
if token['value'] == '-': # -
emit('OPR', 0, 1)
else:
token_index -= 1 #
term()
token = get_token()
while token['value'] == '+' or token['value'] == '-':
term()
if token['value'] == '+':
emit('OPR', 0, 2)
elif token['value'] == '-':
emit('OPR', 0, 3)
token = get_token()
token_index -= 1
# → {}
def term():
global token_index
factor()
token = get_token() #
while token['value'] == '*' or token['value'] == '/':
factor()
if token['value'] == '*':
emit('OPR', 0, 4)
elif token['value'] == '/':
emit('OPR', 0, 5)
token = get_token()
token_index -= 1 #
# ||()
def factor():
global token_index
token = get_token()
if token['attribute'] == 'identifier': #
index = find_table(token['value'])
if index == -1: #
error(token['line_num'], token['value'] + ' ')
else:
if table_list[index]['kind'] == 'CONSTANT': #
emit('LIT', 0, table_list[index]['value']) #
elif table_list[index]['kind'] == 'VARIABLE':
emit('LOD', level - table_list[index]['level'], table_list[index]['address']) #
elif table_list[index]['kind'] == 'PROCEDURE':
error(token['line_num'], table_list[index]['name'] + ' , ')
elif token['attribute'] == 'number': #
emit('LIT', 0, token['value'])
elif token['attribute'] == '(': #
expression()
token = get_token()
if token['attribute'] != ')': #
error(token['line_num'], ' ')
token_index -= 1 #
# → |odd
def lexp():
global token_index
token = get_token()
if token['value'] == 'odd':
expression()
emit('OPR', 0, 6) #
else:
token_index -= 1 #
expression()
token = get_token()
if token['value'] != '=' and token['value'] != '<>' and token['value'] != '' and token['value'] != '>=':
error(token['line_num'], ' ')
token_index -= 1
expression()
if token['value'] == '=':
emit('OPR', 0, 8)
elif token['value'] == '<>':
emit('OPR', 0, 9)
elif token['value'] == '=':
emit('OPR', 0, 11)
elif token['value'] == '>':
emit('OPR', 0, 12)
elif token['value'] == '<=':
emit('OPR', 0, 13)
#
stack = [0 for i in range(0, 8000)] # 0 SL DL RA
# B level SL
def get_sl(B, level):
global stack
res_B = B
while level > 0:
res_B = stack[res_B]
level -= 1
return res_B
#
def interpreter():
#
global stack
B = 0 #
T = 0 #
I = None #
P = 0 # mid_code
#
I = mid_code[P]
P += 1
while P != 0: # P 0
if I['F'] == 'JMP': #
P = I['A']
elif I['F'] == 'JPC':
if stack[T] == 0: # 0
P = I['A']
T -= 1 #
elif I['F'] == 'INT':
T += I['A'] - 1 #
elif I['F'] == 'LOD':
T += 1
stack[T] = stack[get_sl(B, I['L']) + I['A']]
elif I['F'] == 'STO':
stack[get_sl(B, I['L']) + I['A']] = stack[T]
T -= 1
elif I['F'] == 'LIT':
T += 1
stack[T] = I['A']
elif I['F'] == 'CAL': #
T += 1
stack[T] = get_sl(B, I['L'])
stack[T + 1] = B
stack[T + 2] = P
B = T
P = I['A']
elif I['F'] == 'OPR':
if I['A'] == 0: #
T = B - 1
P = stack[T + 3]
B = stack[T + 2]
elif I['A'] == 1: #
stack[T] = -stack[T]
elif I['A'] == 2: #
T -= 1
stack[T] = stack[T] + stack[T + 1]
elif I['A'] == 3: #
T -= 1
stack[T] = stack[T] - stack[T + 1]
elif I['A'] == 4: #
T -= 1
stack[T] = stack[T] * stack[T + 1]
elif I['A'] == 5: #
T -= 1
stack[T] = int(stack[T] / stack[T + 1])
elif I['A'] == 6: # odd
stack[T] = stack[T] % 2
elif I['A'] == 8: # ==
T -= 1
stack[T] = stack[T] == stack[T + 1]
elif I['A'] == 9: # !=
T -= 1
stack[T] = stack[T] != stack[T + 1]
elif I['A'] == 10: # <
T -= 1
stack[T] = stack[T] < stack[T + 1]
elif I['A'] == 11: # >=
T -= 1
stack[T] = stack[T] >= stack[T + 1]
elif I['A'] == 12: # >
T -= 1
stack[T] = stack[T] > stack[T + 1]
elif I['A'] == 13: # <=
T -= 1
stack[T] = stack[T] <= stack[T + 1]
I = mid_code[P] #
if P == 0:
break
P += 1 # P+1
if __name__ == '__main__':
# , , 、 、
with open('code.txt', 'r') as file:
line_num = 1
for line in file.readlines():
for word in line.strip().split():
deal_word(word, line_num)
line_num += 1
# ,
prog() # prog
#
interpreter()
중간 코드 설명
위의 PL\0 코드에서 생성한 중간 코드
{'F': 'JMP', 'L': 0, 'A': 30} #
{'F': 'JMP', 'L': 0, 'A': 2} # multiply
{'F': 'INT', 'L': 0, 'A': 5} # 5
{'F': 'LOD', 'L': 1, 'A': 3} # x
{'F': 'STO', 'L': 0, 'A': 3} # a
{'F': 'LOD', 'L': 1, 'A': 4} # y
{'F': 'STO', 'L': 0, 'A': 4} # b
{'F': 'LIT', 'L': 0, 'A': 0} # 0
{'F': 'STO', 'L': 1, 'A': 5} # z
{'F': 'LOD', 'L': 0, 'A': 4} # while b
{'F': 'LIT', 'L': 0, 'A': 0} # 0
{'F': 'OPR', 'L': 0, 'A': 12} # b > 0
{'F': 'JPC', 'L': 0, 'A': 29} #
{'F': 'LOD', 'L': 0, 'A': 4} # b
{'F': 'OPR', 'L': 0, 'A': 6} #
{'F': 'JPC', 'L': 0, 'A': 20} # if
{'F': 'LOD', 'L': 1, 'A': 5} # z
{'F': 'LOD', 'L': 0, 'A': 3} # a
{'F': 'OPR', 'L': 0, 'A': 2} #
{'F': 'STO', 'L': 1, 'A': 5} # z
{'F': 'LIT', 'L': 0, 'A': 2} # 2
{'F': 'LOD', 'L': 0, 'A': 3} # a
{'F': 'OPR', 'L': 0, 'A': 4} #
{'F': 'STO', 'L': 0, 'A': 3} # a
{'F': 'LOD', 'L': 0, 'A': 4} # b
{'F': 'LIT', 'L': 0, 'A': 2} # 2
{'F': 'OPR', 'L': 0, 'A': 5} #
{'F': 'STO', 'L': 0, 'A': 4} # b
{'F': 'JMP', 'L': 0, 'A': 9} # while
{'F': 'OPR', 'L': 0, 'A': 0} # multiply
{'F': 'INT', 'L': 0, 'A': 8} #
{'F': 'LIT', 'L': 0, 'A': 7} # 7
{'F': 'STO', 'L': 0, 'A': 3} # x
{'F': 'LIT', 'L': 0, 'A': 85} # 85
{'F': 'STO', 'L': 0, 'A': 4} # y
{'F': 'CAL', 'L': 0, 'A': 1} #
{'F': 'OPR', 'L': 0, 'A': 0} #
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
귀속 하강 식별기-컴파일링 원리작업용 단순화 반복 감소 인식기: 예: 문법 G[S]: S-> A|B M->A|# B->bN N->B|# ①문법은 좌귀속을 포함하지 않는다 follow 아니요 {a,b} 아니요 아니요 {b} 예. 예. {b,#} ①...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.