PLY (Python Lex-Yacc)基于Python的LEX和YACC
PLY (Python Lex-Yacc)基于Python的LEX和YACC
转载自:http://eatsalt.blog.163.com/blog/static/879402662009376956615/
PLY 是一个Python 的Lex/YACC 实现. 官方网站在这里http://www.dabeaz.com/ply/
作者:David Beazley
SWIG的发明人
PLY是很Pythonic的语言工具,使用起来也非常简明,学习周期短就可以实现一个简单的语法规则和翻译规则程序,对研究编译器原理很有价值。
官方网站给出的特性信息:
- It\’s implemented entirely in Python.
- It uses LR-parsing which is reasonably efficient and well suited for larger grammars.
- PLY provides most of the standard lex/yacc features including support for empty productions, precedence rules, error recovery, and support for ambiguous grammars.
- PLY is straightforward to use and provides very extensive error checking.
- PLY doesn\’t try to do anything more or less than provide the basic lex/yacc functionality. In other words, it\’s not a large parsing framework or a component of some larger system.
来一个简单的例子:
# —————————————————————————–
# calc.py
#
# A simple calculator with variables — all in one file.
# —————————————————————————–
tokens = (
\’NAME\’,\’NUMBER\’,
\’PLUS\’,\’MINUS\’,\’TIMES\’,\’DIVIDE\’,\’EQUALS\’,
\’LPAREN\’,\’RPAREN\’,
)
# Tokens
t_PLUS = r\’\+\’
t_MINUS = r\’-\’
t_TIMES = r\’\*\’
t_DIVIDE = r\’/\’
t_EQUALS = r\’=\’
t_LPAREN = r\’\(\’
t_RPAREN = r\’\)\’
t_NAME = r\'[a-zA-Z_][a-zA-Z0-9_]*\’
def t_NUMBER(t):
r\’\d+\’
try:
t.value = int(t.value)
except ValueError:
print “Integer value too large”, t.value
t.value = 0
return t
# Ignored characters
t_ignore = ” \t”
def t_newline(t):
r\’\n+\’
t.lexer.lineno += t.value.count(“\n”)
def t_error(t):
print “Illegal character \’%s\'” % t.value[0]
t.lexer.skip(1)
# Build the lexer
import ply.lex as lex
lex.lex()
# Parsing rules
precedence = (
(\’left\’,\’PLUS\’,\’MINUS\’),
(\’left\’,\’TIMES\’,\’DIVIDE\’),
(\’right\’,\’UMINUS\’),
)
# dictionary of names
names = { }
def p_statement_assign(t):
\’statement : NAME EQUALS expression\’
names[t[1]] = t[3]
def p_statement_expr(t):
\’statement : expression\’
print t[1]
def p_expression_binop(t):
\’\’\’expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression\’\’\’
if t[2] == \’+\’ : t[0] = t[1] + t[3]
elif t[2] == \’-\’: t[0] = t[1] – t[3]
elif t[2] == \’*\’: t[0] = t[1] * t[3]
elif t[2] == \’/\’: t[0] = t[1] / t[3]
def p_expression_uminus(t):
\’expression : MINUS expression %prec UMINUS\’
t[0] = -t[2]
def p_expression_group(t):
\’expression : LPAREN expression RPAREN\’
t[0] = t[2]
def p_expression_number(t):
\’expression : NUMBER\’
t[0] = t[1]
def p_expression_name(t):
\’expression : NAME\’
try:
t[0] = names[t[1]]
except LookupError:
print “Undefined name \’%s\'” % t[1]
t[0] = 0
def p_error(t):
print “Syntax error at \’%s\'” % t.value
import ply.yacc as yacc
yacc.yacc()
while 1:
try:
s = raw_input(\’calc > \’)
except EOFError:
break
yacc.parse(s)
想要了解更多,你可以参考官方文档(英文):http://www.dabeaz.com/ply/ply.html