PLY (ang. Python Lex-Yacc) – narzędzie służące do tworzenia kompilatorów oraz translatorów z opisu gramatyki zawierającego akcje w języku Python. Autorem jest David Beazley.

Zasadniczo PLY to bezpośrednia implementacja idei programów Lex oraz Yacc w języku Python

  • Implementacja całowicie w Pythonie
  • Używa parsera LR cechującego się rozsądną wydajnością oraz dobrą wsparciem dużych gramatyk.
  • PLY obsługuje większość standardowych możliwości lex/yacc włączając w to reguły pierwszeństwa, usuwanie błędów, obsługę niejednoznacznych gramatyk i pustych wyrażeń.

Przykład

edytuj

Poniższy przykład, pochodzący z dokumentacji PLY, zawiera implementację prostego kalkulatora operującego na liczbach całkowitych.

import ply.lex as lex
import ply.yacc as yacc


# Lex

tokens = (
   'NUMBER',
   'PLUS',
   'MINUS',
   'TIMES',
   'DIVIDE',
   'LPAREN',
   'RPAREN',
)

t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'

def t_NUMBER(t):
    r'[-+]?\d+'
    try:
         t.value = int(t.value)
    except ValueError:
         print "Line %d: Number %s is too large!" % (t.lineno,t.value)
         t.value = 0
    return t

def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

t_ignore = ' \t'

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


# Yacc

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]

def p_error(p):
    print "Syntax error in input!"


if __name__ == '__main__':
    lex.lex()
    yacc.yacc()

    while 1:
        try:
            s = raw_input('calc > ')
        except EOFError:
            break
        if not s: continue
        result = yacc.parse(s)
        print result

Linki zewnętrzne

edytuj