下面的例子展示了如何使用lex.py对输入进行标记
~~~
# ------------------------------------------------------------
# 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()
~~~
为了使lexer工作,你需要给定一个输入,并传递给`input()`方法。然后,重复调用`token()`方法来获取标记序列,下面的代码展示了这种用法:
~~~
# 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)
~~~
Lexers也同时支持迭代,你可以把上面的循环写成这样:
~~~
for tok in lexer:
print tok
~~~
由lexer.token()方法返回的标记是LexToken类型的实例,拥有`tok.type`,`tok.value`,`tok.lineno`和`tok.lexpos`属性,下面的代码展示了如何访问这些属性:
~~~
# Tokenize
while True:
tok = lexer.token()
if not tok: break # No more input
print tok.type, tok.value, tok.line, tok.lexpos
~~~
`tok.type`和`tok.value`属性表示标记本身的类型和值。`tok.line`和`tok.lexpos`属性包含了标记的位置信息,`tok.lexpos`表示标记相对于输入串起始位置的偏移。
- 0 一些翻译约定
- 1 前言和预备
- 2 介绍
- 3 PLY概要
- 4 Lex
- 4.1 Lex的例子
- 4.2 标记列表
- 4.3 标记的规则
- 4.4 标记的值
- 4.5 丢弃标记
- 4.6 行号和位置信息
- 4.7 忽略字符
- 4.8 字面字符
- 4.9 错误处理
- 4.10 构建和使用lexer
- 4.11 @TOKEN装饰器
- 4.12 优化模式
- 4.13 调试
- 4.14 其他方式定义词法规则
- 4.15 额外状态维护
- 4.16 Lexer克隆
- 4.17 Lexer的内部状态
- 4.18 基于条件的扫描和启动条件
- 4.19 其他问题
- 5 语法分析基础
- 6 Yacc
- 6.1 一个例子
- 6.2 将语法规则合并
- 6.3 字面字符
- 6.4 空产生式
- 6.5 改变起始符号
- 6.6 处理二义文法
- 6.7 parser.out调试文件
- 6.8 处理语法错误
- 6.9 行号和位置的跟踪
- 6.10 构造抽象语法树
- 6.11 嵌入式动作
- 6.12 Yacc的其他
- 7 多个语法和词法分析器
- 8 使用Python的优化模式
- 9 高级调试
- 9.1 调试lex()和yacc()命令
- 9.2 运行时调试
- 10 如何继续