130242014022 蓝宏铮 第2次实验

一、实验目的

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,VARIABLE,EQUALITY,INCREMENT,REDUCE = (
'INTEGER', 'PLUS', 'MINUS', 'MUL', 'DIV', 'LPAREN', 'RPAREN', 'EOF','VARIABLE','EQUALITY','INCREMENT','REDUCE')
class Token(object):
def __init__(self,type,value):
self.type = type
self.value = value
# toString
def __str__(self):
return 'Token({type},{value})'.format(
type=self.type,
value = self.value
)

class Lexer(object):
# 词法分析器
# 给每个词打标记
# text为输入的表达式
def __init__(self, text):
self.text = text
# pos为当前位置
self.pos = 0
# current_char为当前字符
self.current_char = self.text[self.pos]
# 取字符错误时调用的方法
def error(self):
# raise 抛出异常
raise Exception('Invalid Char')
#前进的方法,即取下一个字符
def advance(self):
# 往下走,取值
self.pos += 1
if self.pos > len(self.text) - 1:
self.current_char = None
else:
self.current_char = self.text[self.pos]

def variable(self):
# 变量处理
variable = ''
while self.current_char is not None and self.current_char.isalpha():
variable = variable + self.current_char
# 往下走,取值
self.advance()
# 取值完毕后,将该变量存入字典中
if variable not in variables:
variables[variable] = None
return variable
def integer(self):
# 多位整数处理
result = ''
while self.current_char is not None and self.current_char.isdigit():
result = result + self.current_char
# 往下走,取值
self.advance()
return int(result)
# 处理输入时的非法空格
def deal_space(self):
# 循环遍历,遇到空格则跳过,取下一个字符
while self.current_char is not None and self.current_char.isspace():
self.advance()

def get_next_token(self):
# 打标记:1)pos+1,2)返回Token(类型,数值)
while self.current_char is not None:
# 空格处理
if self.current_char.isspace():
self.deal_space()
# 数字处理(判断是否为多位整数)
if self.current_char.isdigit():
return Token(INTEGER, self.integer())
# 加号处理Plus
if self.current_char == '+':
# # 判断是自增还是加号
# if self.get_next_token() '+':
# self.advance()
# return Token(PLUS, '+')
self.advance()
return Token(PLUS, '+')
# 减号处理Minus
if self.current_char == '-':
self.advance()
return Token(MINUS, '-')
# 左括号
if self.current_char == '(':
self.advance()
return Token(LPAREN,'(')
# 右括号
if self.current_char == ')':
self.advance()
return Token(RPAREN,')')
# 乘号
if self.current_char == '*':
self.advance()
return Token(MUL,'*')
# 除号
if self.current_char == '/':
self.advance()
return Token(DIV,'/')
# 若是判断出字符则进入变量获取的方法
if self.current_char.isalpha():
return Token(VARIABLE,self.variable())
# 等号
if self.current_char == '=':
self.advance()
return Token(EQUALITY,'EQUALITY')
# # 自增
# if self.current_char == '++':
# self.advance()
# return Token(EQUALITY,'EQUALITY')

# 其余均为非法字符
self.error()
# 取到None字符 返回一个空的Token 表示循环结束
return Token(EOF, None)

class Interpreter(object):
# 句法分析
# 语法树
# 语法树中的一个参数为词法分析器Lexer
def __init__(self, lexer):
self.lexer = lexer
self.current_token = self.lexer.get_next_token()

def error(self):
raise Exception('Invalid Syntax')
# 当当前Token取值完毕
# 删除当前的Token,取下一个Token的值
def eat(self, token_type):
# 跳过与当前相同的Token,取下一个Token
if self.current_token.type == token_type:
self.current_token = self.lexer.get_next_token()
else:
# 若在删除的过程中出错,会引起整体的错误,故抛错
self.error()
# 工厂方法
def factor(self):
token = self.current_token
# 判断当前要删除的Token类型
if token.type == INTEGER:
self.eat(INTEGER)
return token.value
# 将类型为Variable的变量返回
if token.type == VARIABLE:
self.eat(VARIABLE)
return variables[token.value]
# 左括号
elif token.type == LPAREN:
self.eat(LPAREN)
result = self.expr()
self.eat(RPAREN)
return 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()
if token.type == DIV:
self.eat(DIV)
result = result / self.factor()
return 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()
if token.type == MINUS:
self.eat(MINUS)
result = result - self.term()
return result
def assignment(self):
if self.current_token.type == VARIABLE:
var = self.current_token.value
self.eat(VARIABLE)
if self.current_token.type == EQUALITY:
self.eat(EQUALITY)
variables[var] = self.expr()
return var
def printResult(text):
lexer = Lexer(text)
variableKey = Interpreter(lexer).assignment()
print(variableKey,"=",variables[variableKey])

def main():
while True:
try:
text = input('calc_> ')
except EOFError:
break

if not text:
continue
# try:
printResult(text)
# except Exception:
# print('Invalid Syntax')


if __name__ == '__main__':
main()

转载于:https://www.cnblogs.com/RealKing/p/7780189.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/268151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker exec和docker attach的作用和区别

在使用docker 容器的时候,我们总会想看看容器内部长什么样子,推荐使用 docker exec 命令进入容器内部 因为docker attach 容器,再退出会使容器停止。而使用docker exec -it进入容器再退出不会导致容器停止 #进入当前容器后开启一个新的终端…

GNU C __attribute__ 机制简介

原文链接:http://afreez.blog.51cto.com/59057/7351 摘要: 在学习linux内核代码及一些开源软件的源码(如:DirectFB),经常可以看到有关__attribute__的相关使用。本文结合自己的学习经历,较为详细…

数据库随机取n条记录

SQL Server SELECT TOP N * FROM 表名 ORDER BY NEWID() My SQL SELECT * FROM 表名 ORDER BY RAND() LIMIT N Oracle SELECT * FROM ( SELECT * FROM 表名ORDER BY DBMS_RANDOM.VALUE )WHERE ROWNUM < N; 转载于:https://www.cnblogs.com/enzo/archive/2010/0…

数据库排名网站

https://db-engines.com/en/ranking

2017-05-12-Linux文件操作

Linux学习笔记&#xff1a;文件操作 最近在学习Linux的命令行和shell编程&#xff0c;需要记忆和掌握的知识点很多&#xff0c;所以把一些经常用到的知识点记下来&#xff0c;加深一下印象。 文件系统是Linux最重要的部分&#xff0c;甚至Linux就是基于文件的&#xff0c;文件操…

最大最完整的---NAG Fortran 算法库

转载www.smart-cores.com中 NAG Fortran 算法库最大最完整的商用 Fortran 数值算法库NAG Fortran 软件库是由专家开发&#xff0c;适用于多种应用领域中&#xff0c;是 NAG 的核心产品。提供 1600 多个优质的函数享誉全球&#xff0c;是迄今最广泛的数学和统计算法算法库。 目…

统计软件简介

一、 SPSS统计软件 SPSS(Statistical Product and Service Solutions)&#xff0c;"统计产品与服务解决方案"软件。最初软件全称为"社会科学统计软件包"(SolutionsStatistical Package for the Social Sciences)&#xff0c;但是随着SPSS产品服务领域的扩…

Firebug Tutorial (Section 3): Script Tab :Javascript Debugging

2019独角兽企业重金招聘Python工程师标准>>> Firebug Tutorial – Script Tab : Javascript Debugging September 30, 2007 Firebug Tutorial Section 3: Script Tab : Javascript Debugging I’m going to show you how to debug the Javascript code with Firebug…

java程序员招聘现场

面试官&#xff1a;熟悉哪种语言 应聘者&#xff1a;Java。 面试官&#xff1a;知道什么叫类么 应聘者&#xff1a;我这人实在&#xff0c;工作努力&#xff0c;不知道什么叫累 面试官&#xff1a;知道什么是包? 应聘者&#xff1a;我这人实在 平常不带包 也不用公司准备了 面…

ecshop二次开发必备--数据库说明2

ecs_group_goods 该表应该是商品配件配置表 parent_id mediumint 父商品id goods_id mediumint 配件商品id goods_price decimal 配件商品的价格 admin_id tinyint 添加该配件的管理员的id ecs_keywords 页面搜索关键字搜索记录 date date 搜索日期 searchengine varchar 搜索引…

ObserveIT Client安装后屏幕延迟问题

前天几遇到一个很是郁闷的问题: 问题&#xff1a;当把ObserveIT服务器端安装好后&#xff0c;在其他XenAPP服务器上安装Client端时&#xff0c;一旦安装后&#xff0c;Client端就会出现屏幕延迟问题&#xff08;屏幕、菜单会卡1秒钟左右&#xff09;&#xff0c;最初以为是与服…

safari图片跨域

http://blog.csdn.net/renfufei/article/details/51675148转载于:https://www.cnblogs.com/lvshuya/p/7793705.html

写模拟挂用什么工具?

据说是VC&#xff0c; Delphi&#xff0c;还有易语言&#xff0c;动态语言推荐用AAuto(快手)。 个人喜欢用Delphi和快手。 要用delphi来写模拟挂&#xff0c;需要解决的最关键问题是找进程窗口句柄&#xff0c;模拟键盘&#xff0c;鼠标和找图&#xff0c;找色. 如果用快手的话…

mysql规范中每条命令可以使用; \g \G 结尾

select * from 表名; select * from 表名\g select * from 表名\G