130242014048-謝添華-第2次實驗,130242014048-謝添華

來源:互聯網
上載者:User

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單元則可以是一個整數、變數自增、變數自減、變數,當然也可以是一個括弧包圍的運算式,如此一來,即可將複雜事情簡單化。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.