官方手册:http://www.dabeaz.com/ply/ply.html

以下例子都来自官方手册:

以四则运算为例: x = 3 + 42 * (s - t)

词法分析:

需要将其分解为:

'x','=', '3', '+', '42', '*', '(', 's', '-', 't', ')'

并且给每个部分起一个名字,标识这是什么东西。这些标识会用在后面的语法分析中。

('ID','x'), ('EQUALS','='), ('NUMBER','3'),
('PLUS','+'), ('NUMBER','42), ('TIMES','*'),
('LPAREN','('), ('ID','s'), ('MINUS','-'),
('ID','t'), ('RPAREN',')'

例子:

# ------------------------------------------------------------
# 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()

注意:

里面名字的命名格式是固定的,ID的名称必须叫tokens,每个ID具体的内容必须用t_ID来指定。

单个字符可以直接定义变量,复杂成分要用函数形式表示,并且一定要有一个该成分的正则表达式字符串

比如上面例子中,t_NUMBER函数中有一个r'\d+',这在一般的python程序中看起来没有意义,但是在ply中则是必须的!它指定了模块如何划分NUMBER。

更多注意事项参考官方手册。

具体使用:

# Test it out
data = '''
3 + 4 * 10
+ -20 *2
''' # Give the lexer some input
lexer.input(data) # Tokenize
while True:
tok = lexer.token()
if not tok:
break # No more input
print(tok)

结果:

$ python example.py
LexToken(NUMBER,3,2,1)
LexToken(PLUS,'+',2,3)
LexToken(NUMBER,4,2,5)
LexToken(TIMES,'*',2,7)
LexToken(NUMBER,10,2,10)
LexToken(PLUS,'+',3,14)
LexToken(MINUS,'-',3,16)
LexToken(NUMBER,20,3,18)
LexToken(TIMES,'*',3,20)
LexToken(NUMBER,2,3,21)

语法分析:

一个四则运算的语法结构是下面这个样子:

expression : expression + term
| expression - term
| term term : term * factor
| term / factor
| factor factor : NUMBER
| ( expression )

用ply实现四则运算语法分析:

# Yacc example

import ply.yacc as yacc

# Get the token map from the lexer.  This is required.
from calclex import tokens def p_expression_plus(p):
'expression : expression PLUS term'
p[0] = p[1] + p[3] def p_expression_minus(p):
'expression : expression MINUS term'
p[0] = p[1] - p[3] def p_expression_term(p):
'expression : term'
p[0] = p[1] def p_term_times(p):
'term : term TIMES factor'
p[0] = p[1] * p[3] def p_term_div(p):
'term : term DIVIDE factor'
p[0] = p[1] / p[3] def p_term_factor(p):
'term : factor'
p[0] = p[1] def p_factor_num(p):
'factor : NUMBER'
p[0] = p[1] def p_factor_expr(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
result = parser.parse(s)
print(result)

与词法分析一样,语法分析的命名方式也是固定的 p_成分名_动作。

函数一开始必须是一个声明字符串,格式是 “成分名 :成分名 成分名 ...”  其中成分名可以是词法分析中的ID,比如上面的PLUS, NUMBER等等。冒号右边的是这个函数结果的成分名。即,语法分析通过组合各个ID得到结构化的结果。

成分相同的结构可以合并,如同时定义加法和减法

def p_expression(p):
'''expression : expression PLUS term
| expression MINUS term'''
if p[2] == '+':
p[0] = p[1] + p[3]
elif p[2] == '-':
p[0] = p[1] - p[3]

可以看到字符串的内容有变化,多余一种组合的用 | 换行分隔。注意这个字符串的格式是固定的,不过PLUS和MINUS的顺序没有影响,哪个在上面都可以。

更多细节,参见手册。

												

【python】词法语法解析模块ply的更多相关文章

  1. python命令行解析模块--argparse

    python命令行解析模块--argparse 目录 简介 详解ArgumentParser方法 详解add_argument方法 参考文档: https://www.jianshu.com/p/aa ...

  2. 编译impala、拓展impala语法解析模块

    以前也编译过,但是每次编译都忘记怎么做,然后都得重新找需要下载的文件. 编译文件:buildall.sh 如果想只编译前端可以这样运行: buildall.sh -fe_only 编译时会去S3下载一 ...

  3. python之参数解析模块argparse

    2.7之后python不再对optparse模块进行扩展,python标准库推荐使用argparse模块对命令行进行解析. 简单入门 先来看个例子: argparse_test.py: import ...

  4. python argparse(参数解析模块)

    这是一个参数解析,可以用它快捷的为你的程序生成参数相关功能 import argparse(导入程序参数模块) # 创建argparse对象,并将产品简要说明加入show = '程序说明' ===&g ...

  5. python optparse命令解析模块

    来源:http://www.cnblogs.com/pping/p/3989098.html?utm_source=tuicool&utm_medium=referral 来源:http:// ...

  6. Python 命令行解析模块 —— argparse

    argparse是python标准库里面用来处理命令行参数的库,基本使用步骤如下: 1.import argparse    导入模块 2.parser = argparse.ArgumentPars ...

  7. 【python基础语法】模块和包管理,文件的操作(第8天课堂笔记)

    ''' 模块和包管理 模块和包的定义: 模块:模块是一个Python文件,以.py结尾,包含了Python对象定义和Python语句 包:Python中的包就是一个包含__init__.py文件的目录 ...

  8. Python中配置文件解析模块-ConfigParser

    Python中有ConfigParser类,可以很方便的从配置文件中读取数据(如DB的配置,路径的配置).配置文件的格式是: []包含的叫section, section 下有option=value ...

  9. python命令行参数解析模块argparse和docopt

    http://blog.csdn.net/pipisorry/article/details/53046471 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的o ...

随机推荐

  1. PHP 线程安全与非线程安全版本的区别深入解析

    Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分,这两者不同在于何处?到底应该用哪种?这里做一个简单的介绍 ...

  2. JAVA 如何使JScrollPane中的JTextArea自动滚动到最后一行?

    1.要使JTextArea带有滚动条,需将JTextArea对象添加到JScrollPane中. JTextArea logArea = new JTextArea(15, 35); //创建JTex ...

  3. java常量池存放在哪里

    运行以下方法: public class Test { public static void main(String[] args) { String str = "abc"; c ...

  4. php面向对象面试题

    php面试题之四--PHP面向对象(基础部分) 四.PHP面向对象 1. 写出 php 的 public.protected.private 三种访问控制模式的区别(新浪网技术部) public:公有 ...

  5. Javascript高级程序设计——BOM(浏览器对象模型)

    BOM(浏览器对象模型),它提供了独立于内容而与浏览器窗口进行交互的对象.BOM由一系列相关的对象构成.一.window对象      window对象表示整个浏览器窗口,但不必表示其中包含的内容.W ...

  6. phpcms学习的一点心得

    最近,在学习phpcms的二次开发,因为要调试搜索模块程序,需建立若干栏目,按照栏目搜索.这一过程中涉及到phpcms的一个概念:模型. 以前并不太注意这个东东. 经过摸索,发现模型其实也是一个栏目的 ...

  7. 霸气!Nginx 中缓存静态文件秘籍

    导读 这篇教程说明你应该怎样配置 nginx.设置 HTTP 头部过期时间,用 Cache-Control 中的 max-age 标记为静态文件(比如图片. CSS 和 Javascript 文件)设 ...

  8. Sqli-LABS通关笔录-12

    通过这个关卡我学习到了: 1.双引号千万别忘记,就是因为忘了弄了好一会儿.一直不报错. 2. 00x1万能密码构造二 报错的内容为: You have an error in your SQL syn ...

  9. JDBC连接MySQL数据库的方法和实例

    import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java. ...

  10. Codeforces 710 D. Two Arithmetic Progressions

    Description \(x=a_1k+b_1=a_2l+b_2,L\leqslant x \leqslant R\) 求满足这样条件的 \(x\) 的个数. Sol 扩展欧几里得+中国剩余定理. ...