python编程(ply库)

栏目: Python · 发布时间: 6年前

内容简介:python编程(ply库)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

长久以来,我一直对编译器都比较感兴趣。网上,大家推荐的龙书、《自制编译器》等等虽然也看过,但是我觉得都没有办法满足自己编写工业软件的要求。后来有一次看lua,发现 lua 早期也是使用lex&yacc完成字符解析的,一下子找到了方法。最近因为使用 python 的关系,想看看python有没有类似的库,结果就找到了ply库。

1、安装ply库

建议大家到 官网 下载,直接利用源代码安装

sudo python setup.py install

偷懒一点的朋友,也可以直接用apt安装,

sudo apt-get install python-ply

2、ply资料

关于ply的资料,最权威的还是 官方文档

3、词法分析和语法分析

和lex、yacc工具不同,ply本身的规则文件也是编写成python形式的。而lex和yacc都是将规则文件转换成c文件,然后一起编译。

4、示例代码

这份示例代码也是根据官网的代码做了一点修改。其中calclex.py完成词法分析,calc.py完成语法分析。

calclex.py文件如下,

##!/bin/python
# ------------------------------------------------------------
# calclex.py
#
# tokenizer for a simple expression evaluator for
# numbers and +,-,*,/
# ------------------------------------------------------------
import ply.lex as lex

# List of token names.   This is always required
tokens = (
   'NUMBER',
   'PLUS',
   'MINUS',
   'TIMES',
   'DIVIDE',
   'LPAREN',
   'RPAREN',
)

# Regular expression rules for simple tokens
t_PLUS    = r'\+'
t_MINUS   = r'-'
t_TIMES   = r'\*'
t_DIVIDE  = r'/'
t_LPAREN  = r'\('
t_RPAREN  = r'\)'

# A regular expression rule with some action code
def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)    
    return t

# Define a rule so we can track line numbers
def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

# A string containing ignored characters (spaces and tabs)
t_ignore  = ' \t'

# Error handling rule
def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# Build the lexer
lexer = lex.lex()

calc.py文件如下,

# Yacc example

import ply.yacc as yacc

# Get the token map from the lexer.  This is required.
from calclex import  tokens

def p_add(p):
    'expression : expression PLUS term'
    p[0] = p[1] + p[3]

def p_sub(p):
    'expression : expression MINUS term'
    p[0] = p[1] - p[3]

def p_term(p):
    'expression : term'
    p[0] = p[1]

def p_term_factor(p):
    'term : term TIMES factor'
    p[0] = p[1] * p[3]

def p_term_divide(p):
    'term : term DIVIDE factor'
    p[0] = p[1] / p[3]

def p_factor(p):
    'term : factor'
    p[0] = p[1]

def p_factor_num(p):
    'factor : NUMBER'
    p[0] = p[1]

def p_fact_param(p):
    'factor : LPAREN expression RPAREN'
    p[0] = p[2]

# Error rule for syntax errors
def p_error(p):
    print("Syntax error in input!")

# Build the parser
parser = yacc.yacc()

while True:
   try:
       s = raw_input('calc > ')
   except EOFError:
       break
   if not s: continue
   if s == 'q' or s =='Q': break
   result = parser.parse(s)
   print(result)

5、添加Makefile

因为编译的时候会生成很多中间文件,所以建议大家可以编一个Makefile,完成自动化清理和执行的工作。

.PHONY: all clean
all: run

run:process clean

process:
    python calc.py

clean:
    @rm -rf parser.out  *.pyc parsetab.py

6、后续

关于lex&yacc其实有两种用法,一种是生成ast,也就是抽象语法树,这样可以进一步进行语义分析、生成中间语言、优化、生成汇编代码等等。另外一种就是直接生成执行语言,这也是大多数脚本语言的做法,比如lua。脚本语言特别适合无编译运行,此外它的动态加载、垃圾回收、和c自由交互等系列功能也很实用。希望大家可以借ply这个 工具 好好了解一下。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Node.js实战

Node.js实战

[美] Mike Cantelon、[美] TJ Holowaychuk、[美] Nathan Rajlich / 吴海星 / 人民邮电出版社 / 2014-5 / 69.00元

服务器端JavaScript?没错。Node.js是一个JavaScript服务器,支持可伸缩的高性能Web应用。借助异步I/O,这个服务器可以同时做很多事情,能满足聊天、游戏和实时统计等应用的需求。并且既然是JavaScript,那你就可以全栈使用一种语言。 本书向读者展示了如何构建产品级应用,对关键概念的介绍清晰明了,贴近实际的例子,涵盖从安装到部署的各个环节,是一部讲解与实践并重的优秀......一起来看看 《Node.js实战》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试