码迷,mamicode.com
首页 > 其他好文 > 详细

130242014048-谢添华-第2次实验

时间:2017-10-28 23:58:17      阅读:421      评论:0      收藏:0      [点我收藏+]

标签:分析   连续   col   incr   ima   object   整数   计算器   lte   

一、实验目的

  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("输入的表达式有误")
            continue


if __name__ == __main__:
    main()

 

对应结构图:   (start处理赋值操作)

     技术分享

 

 

 

实验截图:

     技术分享

 

五、实验总结

  体系架构就是将复杂事情简单化,对此有了更深刻的理解。体系结构包括一组部件以及部件之间的联系。就拿此次实验来说,虽然只是做一个简单的计算器,但也足以诠释“复杂事情简单化”这一句了。运算器包括加减乘除、自增、自减,以及含有变量的运算,这个表达式本身是一个复杂的运算,但只要拆分开,拆分成简单的事情,就优先级来说,可以把该运算拆分多个单元的相加减,即term单元;然后再term单元拆分多个更小单元的乘除,即factor单元;而factor单元则可以是一个整数、变量自增、变量自减、变量,当然也可以是一个括号包围的表达式,如此一来,即可将复杂事情简单化。

 

130242014048-谢添华-第2次实验

标签:分析   连续   col   incr   ima   object   整数   计算器   lte   

原文地址:http://www.cnblogs.com/Xth8013/p/7748501.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!