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

PLY (Python Lex-Yacc)基于Python的LEX和YACC  - ASFR! - 志同道合s Blog

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

版权声明:本文为c00107217原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/c00107217/archive/2013/04/10/3013343.html