130242014048-謝添華-第2次實驗,130242014048-謝添華
一、實驗目的
1.熟悉體繫結構的風格的概念
2.理解和應用管道過濾器型的風格。
3、理解解譯器的原理
4、理解編譯器模型
二、實驗環境
硬體:
軟體:Python或任何一種自己喜歡的語言
三、實驗內容
1、實現“四則運算”的簡易翻譯器。
結果要求:
1)實現加減乘除四則運算,允許同時又多個運算元,如:2+3*5-6 結果是11
2)被運算元為整數,整數可以有多位
3)處理空格
4)輸入錯誤顯示錯誤提示,並返回命令狀態“CALC”
圖1 實驗結果樣本
加強練習:
1、有能力的同學,可以嘗試實現指派陳述式,例如x=2+3*5-6,返回x=11。(注意:要實現解譯器的功能,而不是只是顯示)
2、嘗試實現自增和自減符號,例如x++
2、採用管道-過濾器(Pipes and Filters)風格實現解譯器
圖2 管道-過濾器風格
圖 3 編譯器模型
本實驗,實現的是詞法分析和文法分析兩個部分。
四、實驗步驟:
實際實現代碼:
INTEGER, PLUS, MINUS, MUL, DIV, LPAREN, RPAREN, EOF = 'INTEGER', 'PLUS', 'MINUS', "MUL", "DIV", "LPAREN", "RPAREN", 'EOF'VARIABLE, EQUALITY = 'VARIABLE', 'EQUALITY'B_INCREMENT, B_DECREMENT, A_INCREMENT, A_DECREMENT = "B_INCREMENT", "B_DECREMENT", "A_INCREMENT", "A_DECREMENT"VARIABLE_DICT = {}class Token(object): def __init__(self, type, value): self.type = type self.value = value def __str__(self): return 'Token({type}, {value})'.format( type=self.type, value=repr(self.value) ) def __repr__(self): return self.__str__()# 詞法分析器# 給每個詞打標記class Lexer(object): def __init__(self, text): self.text = text.replace(" ", "") self.pos = -1 self.current_char = None def error(self): raise Exception("") # 前進一步 def advance(self): self.pos += 1 if self.pos >= len(self.text): self.current_char = None else: self.current_char = self.text[self.pos] # 重頭開始 def recover(self): self.pos = -1 self.current_char = None # 處理輸入時的非法空格 def deal_space(self): # 迴圈遍曆,遇到空格則 while self.current_char is not None and self.current_char.isspace(): self.advance() # 多位整數的處理 def deal_integer(self): result = '' while self.current_char is not None and self.current_char.isdigit(): result = result + self.current_char # 往下走,取值 self.advance() self.pos -= 1 self.current_char = self.text[self.pos] return int(result) # 處理變數,用於打變數的標記 def deal_variable(self): result = '' while self.current_char is not None and self.current_char.isalpha(): result = result + self.current_char # 往下走,取值 self.advance() self.pos -= 1 self.current_char = self.text[self.pos] # 添加變數映射 if result not in VARIABLE_DICT: VARIABLE_DICT[result] = None return result # 處理加號標記的, 有可能是先自增和後自增,也有可能是加號 def deal_plus_sign(self): if self.current_char is not None and self.current_char == '+': if self.pos < len(self.text) - 1 and self.text[self.pos + 1] == '+': # 存在連續的兩個加號,即存在自增,需判斷是前自增還是後自增 if self.pos > 0 and self.text[self.pos - 1].isalpha(): # 後自增 self.advance() return A_INCREMENT elif self.pos < len(self.text) - 2 and self.text[self.pos + 2].isalpha(): # 前自增 self.advance() return B_INCREMENT else: self.error() else: return PLUS self.error() # 處理減號標記的, 有可能是先自減和後自減,也有可能是減號 def deal_minus_sign(self): if self.current_char is not None and self.current_char == '-': if self.pos < len(self.text) - 1 and self.text[self.pos + 1] == '-': # 存在連續的兩個減號,即存在自減,需判斷是前自減還是後自減 if self.pos > 0 and self.text[self.pos - 1].isalpha(): # 後自減 self.advance() return A_DECREMENT elif self.pos < len(self.text) - 2 and self.text[self.pos + 2].isalpha(): # 前自減 self.advance() return B_DECREMENT else: self.error() else: return MINUS self.error() # 打標記 1、pos+1 2、返回 Token(類型,數值) def get_next_token(self): self.advance() if self.current_char is None: return Token(EOF, None) if self.current_char.isspace(): self.deal_space() if self.current_char.isdigit(): return Token(INTEGER, self.deal_integer()) if self.current_char.isalpha(): return Token(VARIABLE, self.deal_variable()) if self.current_char == "=": return Token(EQUALITY, "=") if self.current_char == "+": # 處理加號標記的, 有可能是先自增和後自增,也有可能是加號 sign_type = self.deal_plus_sign() if sign_type == PLUS: return Token(PLUS, self.current_char) else: return Token(sign_type, "++") if self.current_char == "-": # 處理減號標記的, 有可能是先自減和後自減,也有可能是減號 sign_type = self.deal_minus_sign() if sign_type == MINUS: return Token(MINUS, self.current_char) else: return Token(sign_type, "--") if self.current_char == "*": return Token(MUL, self.current_char) if self.current_char == "/": return Token(DIV, self.current_char) if self.current_char == "(": return Token(LPAREN, self.current_char) if self.current_char == ")": return Token(RPAREN, self.current_char) self.error()# 句法分析 建立文法數class Interpreter(object): def __init__(self, lexer): self.lexer = lexer self.current_token = self.lexer.get_next_token() def error(self): raise Exception('Invalid Syntax') def eat(self, token_type): if self.current_token.type == token_type: # print(self.current_token.type) self.current_token = self.lexer.get_next_token() else: self.error() def printToken(self): while self.current_token.type is not EOF: print(self.current_token.type) self.eat(self.current_token.type) # 重頭開始 def recover(self): self.lexer.recover() self.current_token = self.lexer.get_next_token() def factor(self): token = self.current_token result = token.value if token.type == INTEGER: # 只有數字 self.eat(INTEGER) result = token.value elif token.type == LPAREN: # ( expr ) self.eat(LPAREN) result = self.expr() self.eat(RPAREN) elif token.type == VARIABLE: # 變數處理 1.只有變數 2.有後自增 3.有後自減 result = VARIABLE_DICT[token.value] # print(token.value) # print(VARIABLE_DICT) self.eat(VARIABLE) if self.current_token.type == A_INCREMENT: # 2.有後自增 VARIABLE_DICT[token.value] = result + 1 self.eat(A_INCREMENT) elif self.current_token.type == A_DECREMENT: # 3.有後自減 VARIABLE_DICT[token.value] = result - 1 self.eat(A_DECREMENT) elif token.type == B_INCREMENT: # 前自增 self.eat(B_INCREMENT) if self.current_token.type == VARIABLE: VARIABLE_DICT[self.current_token.value] = VARIABLE_DICT[self.current_token.value] + 1 result = VARIABLE_DICT[self.current_token.value] self.eat(VARIABLE) else: self.error() elif token.type == B_DECREMENT: # 前自減 self.eat(B_DECREMENT) if self.current_token.type == VARIABLE: VARIABLE_DICT[self.current_token.value] = VARIABLE_DICT[self.current_token.value] - 1 result = VARIABLE_DICT[self.current_token.value] self.eat(VARIABLE) else: self.error() else: self.error() # print(result) return int(result) def term(self): result = self.factor() while self.current_token.type in (MUL, DIV): token = self.current_token if token.type == MUL: self.eat(MUL) result = result * self.factor() elif token.type == DIV: self.eat(DIV) result = result / self.factor() return int(result) def expr(self): result = self.term() while self.current_token.type in (PLUS, MINUS): token = self.current_token if token.type == PLUS: self.eat(PLUS) result = result + self.term() elif token.type == MINUS: self.eat(MINUS) result = result - self.term() return int(result) def start(self): token = self.current_token if token.type == VARIABLE: self.eat(VARIABLE) if self.current_token.type == EQUALITY: # 處理如: x=x+1 self.eat(EQUALITY) result = self.expr() VARIABLE_DICT[token.value] = result # print(token.value) # print(VARIABLE_DICT[token.value]) return {'var_name':token.value,'result':result} # 處理如: x+1 self.recover() result = self.expr() return {'var_name':None,'result':result}def main(): while True: try: text = input("calc> ") except EOFError: break if not text: continue # Interpreter(Lexer(text)).printToken() lexer = Lexer(text) try: data = Interpreter(lexer).start() # print(data) if data["var_name"] == None: print(data['result']) else: print('{0}={1}'.format(data['var_name'], data['result'])) except Exception: print("輸入的運算式有誤") continueif __name__ == '__main__': main()
對應結構圖: (start處理賦值操作)
實驗:
五、實驗總結
體系架構就是將複雜事情簡單化,對此有了更深刻的理解。體繫結構包括一組組件以及組件之間的聯絡。就拿此次實驗來說,雖然只是做一個簡單的計算機,但也足以詮釋“複雜事情簡單化”這一句了。運算器包括加減乘除、自增、自減,以及含有變數的運算,這個運算式本身是一個複雜的運算,但只要拆分開,拆分成簡單的事情,就優先順序來說,可以把該運算拆分多個單元的相加減,即term單元;然後再term單元拆分多個更小單元的乘除,即factor單元;而factor單元則可以是一個整數、變數自增、變數自減、變數,當然也可以是一個括弧包圍的運算式,如此一來,即可將複雜事情簡單化。