阅读更多

11顶
0踩

编程语言

原创新闻 Python:160行代码写一个编辑器和解释器

2008-06-23 14:58 by 副主编 QQbyte 评论(8) 有15502人浏览
M. Taylor写道:我在几周前开始学习Python,作为一个学习用的项目,我给自己设定的目标是编写一个简单的while语句的编辑器和解释器。写Python代码如同梦幻,工作流程如下:思考你如何解决这个问题,尝试用最高级别eval loop去解决,如果不能完成,找另外的途径,如果可行,把它放入你的模块。终于我成功了!

我用最简单的方式来写python:

stmtlist   := (statement)*
statement  :=    'if' condition stmtlist ['else' stmtlist] 'endif'
               | 'while' condition stmtlist 'endwhile'
               | label '=' expression
               | 'print' expression
condition  := expression ('=='|'!=') expression
expression := term ('+'|'-' term)*
term       := label|digit


下面是全部代码:

#****************** Lexer ************************

tokenlist = []
currtoken = ("", "", 0)
keywords = set(["while", "endwhile", "if", "else", "endif", "print", "=", "==", "!=", "+", "-"])
symboltable = dict()

def nextToken():
    global currtoken, symboltable
    if(len(tokenlist) > 0):
        s = tokenlist.pop(0)
        if s in keywords:
            currtoken = (s, "", 0)
        elif s.isdigit():
            currtoken = ("digit", "", int(s))
        elif s.isalnum():
            symboltable[s] = 0
            currtoken = ("label", s, 0)
        else:
            print "syntax error: " + s
    else:
        currtoken = ("", "", 0)

def consume(expected):
    if currtoken[0] == expected:
        nextToken()
    else:
        print "expected " + expected + " not found" 

#****************** Parser ************************

def parseFile(filename):
    inputfile = open(filename, "r")
    inputstring = inputfile.read()
    global tokenlist
    tokenlist = inputstring.split()
    nextToken()
    return doStatementList()

def doStatementList():
    stmts = []
    newstmt = []    
    while currtoken[0] in ["while", "if", "print", "label"]:
        if currtoken[0] == "while":
            # ["while", [condition], [statementlist]]
            consume("while")
            newstmt = ["while"]
            newstmt.append(doCondition())
            newstmt.append(doStatementList())
            consume("endwhile")
        elif currtoken[0] == "if":
            # ["if", [condition], [then part], [else part]]
            consume("if")
            newstmt = ["if"]
            newstmt.append(doCondition())
            newstmt.append(doStatementList())
            if currtoken[0] == "else":
                consume("else")
                newstmt.append(doStatementList())
            consume("endif")
        elif currtoken[0] == "print":
            # ["print", [expression]]
            consume("print")
            newstmt = ["print"]
            newstmt.append(doExpression())
        elif currtoken[0] == "label":
            # ["=", [expression], [expression]]
            label = [currtoken[1]]
            nextToken()
            consume("=")
            newstmt = ["="]
            newstmt.append(label)
            newstmt.append(doExpression())
        else:
            print "invalid statement: " + currtoken[0]
        stmts.append(newstmt)
    return stmts

def doCondition():
    exp = doExpression()
    # ["==|!=", [left side], [right side]]
    if currtoken[0] in ["==", "!="]:
        retval = [currtoken[0]]
        retval.append(exp)
        nextToken()
        retval.append(doExpression())
    else:
        print "expected == or != not found"
    return retval
    
def doExpression():
    term = doTerm()
    # carry the term in case there's no +|-
    exp = term
    # ["+|-", [left side], [right side]]
    while currtoken[0] in ["+", "-"]:
        exp = [currtoken[0]]
        nextToken()
        exp.append(term)
        exp.append(doExpression())
    return exp

def doTerm():
    if currtoken[0] == "label":
        retval = currtoken[1]
        nextToken()
    elif currtoken[0] == "digit":
        retval = currtoken[2]
        nextToken()
    return [retval]

#****************** Interpreter ************************
stack = []
def execStatementList(pgm):
    for stmt in pgm:
        execStatement(stmt)
        
def execStatement(stmt):
    if stmt[0] == "while":
        execCondition(stmt[1])
        while stack.pop():
            execStatementList(stmt[2])
            execCondition(stmt[1])
    elif stmt[0] == "if":
        execCondition(stmt[1])
        if stack.pop():
            execStatementList(stmt[2])
        elif len(stmt) == 4:
            execStatementList(stmt[3])
    elif stmt[0] == "=":
        execExpression(stmt[2])
        symboltable[stmt[1][0]] = stack.pop()
    elif stmt[0] == "print":
        execExpression(stmt[1])
        print "output:" + str(stack.pop())
    else:
        print "invalid statement"
    
def execCondition(cond):
    execExpression(cond[1])
    execExpression(cond[2])
    if cond[0] == "==":
        stack.append(stack.pop() == stack.pop())
    elif cond[0] == "!=":
        stack.append(stack.pop() != stack.pop())

def execExpression(exp):
    if len(exp) == 3:
        execExpression(exp[1])
        execExpression(exp[2])
        if exp[0] == "+":
            stack.append(stack.pop() + stack.pop())
        else:
            stack.append(stack.pop() - stack.pop())
    else:
        if type(exp[0]) == int:
            stack.append(exp[0])
        else:
            stack.append(symboltable[exp[0]])
来自: jroller.com
11
0
评论 共 8 条 请登录后发表评论
8 楼 wu_093 2014-05-15 18:27
execExpression中

execExpression(exp[1])
execExpression(exp[2])
顺序反了
7 楼 fangzhouxing 2008-06-25 08:21
支持python,已经从java转向python开发Web应用!
6 楼 simonli 2008-06-24 15:25
Python代码简洁,优雅
接触后就爱上了
5 楼 AllenZhang 2008-06-24 13:02
语法太过于简单,不过确实写的比较精炼
4 楼 caixicai 2008-06-24 11:29
我也好想学呀。好玩吗?  但是怕没时间
3 楼 shaka 2008-06-24 08:36
弄得我也对python感兴趣了
2 楼 hellas 2008-06-23 18:21
是很有趣,不过用了pyparsing的话,会更简单。
1 楼 QQbyte 2008-06-23 14:59
python代码很有趣。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • Ext左树有表格 增删改查

    Ext左树有表格 增删改查, 添加子节点,重命名

  • Ext.NET官方案例

    Ext.NET官方案例,每个控件详细说明

  • 创建左树右表基础资料1

    创建左树右表基础资料1

  • css左树右表,layui左树dtree右列表table

    layui左树dtree右列表tabledtree样式引入字体引入位置:static/layuiadmin/dtree/font/dtreefont.css样式引入位置:static/layuiadmin/dtree/dtree.cssjs引入位置:static/layuiadmin/modules/dtree.js前端页面xmlns...

  • 左树右对话框

    左树右对话框

  • 左树右表结构,el-table内容溢出元素框时不出现横向滚动条问题

    flex布局不变,flex: 1换成css3提供的动态计算属性。布局下并且自适应了宽度才会出现这种问题。对比了其它布局,发现只有。

  • layui左树右表

    html部分 <div class="layui-fluid"> <div class="layui-row layui-col-space15"> <!-- 左树 --> <div class="layui-col-sm12 layui-col-md4 layui-col-lg3"> ...

  • 十万字全网最全数据结构代码

    借汉诺塔理解栈与递归 单调栈 双端单调队列 单调队列优化的背包问题 01背包问题 完全背包问题 多重背包问题 串的定长表示 串的堆分配实现 KMP 一、引子 二、分析总结 三、基本操作 四、原理 五、复杂度分析 ...

  • 左树右表demo

    左树右表-数据demo 1. 后端出接口: 字段说明:(所有字段大小写敏感) 字段 是否必须 类型 默认值 说明 1. NAME Y String undefined 展示的节点名字 2. ID Y Number/String – 结点ID 3. PARENT_ID ...

  • Vue.js知识点总结 (element框架混用 制作一个左树右表布局)

    文章目录element框架混用一,安装二,引入使用找到文件并编辑使用(1)第一,加入name名作为组件导出的索引名,我们这里起名为ele(2)在App.vue下导出(3)运行(4)用CSS美化设计三,完成 >>> ...

  • JeeSite4.0.1+实现左树右表

    JeeSite4.0.1+实现左树右表 最近刚开始接触JeeSIte框架,需要做一个左树右表的页面,类似下图的用户管理。 JeeSite在4.0.1版本(官方文档这么说,但本人只测试了4.3版本并没有,4.5才有的)后添加了左树右表的代码...

  • ERP软件左树菜单图标

    用于开发左树菜单程序专用图标,使界面变得更加友好。

  • jeecgboot 左树右表记录

    左树又表 格式

  • Layui左树右表

    <div class="layui-fluid"> <div class="layui-row layui-col-space15"&gt...-- 左树 --> <div class="layui-col-sm12 layui-col-md4 layui-col-lg3"> <div class="layui-card"> <div c

  • antd左树右表联动(9)

    -- 左树 --> <div class="left-card" > <a-col :span="25"> <a-tree :treeData="treeData" @select="handleSelect" > <template slot="custom" slot-scope="item"> ...

  • 客户、供应商、科目实现左树右表显示

    客户、供应商、科目实现左树右表显示

  • vue 左树右内容联动布局

    前言 由于是开发完成后直接上传并记录知识点,所以这里就不再通过详细讲解 在普通开发中,左右...[gitee:](left_right_layout_linkage: 左树右内容联动 代码可视化 (gitee.com)) 待定代码 更改tree内容元素为a标签使

  • 左树节点动态拖到右侧面板

    js+ztree 实现左侧树将节点拖到右侧面板,动态加载div,动态加载样式

  • 基于JEECG-BOOT制作“左树右表”交互页面

    左侧树、右侧列表信息是信息管理系统中非常常见的交互方式,本文基于jeecg-boot自动生成的代码,在很少代码量的情况下,实现了左树右表效果。

  • EAS BOS 左树右表实现

    1、创建左树右表形式的UI,为treeMain添加值改变事件保存并发布 为treeMain添加值改变事件: 2、对发布后生成的代码进行修改 package com.kingdee.eas.dj.test.client; import javax.swing.event....

Global site tag (gtag.js) - Google Analytics