Python Code Snippets

ply stands for python lex and yacc. it can be used to design parser/compiler/interpreter while it's not standard library. can be installed with: pip install ply

just_len = 60

from ply.lex import lex
from ply.yacc import yacc

Token List

tokens = ['NUM', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'LPAREN', 'RPAREN']

ignored characters

t_ignore = ' \t\n'

Token specifications (as regexs)

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

Token processing functions

def t_NUM(t):
    r'\d+'
    t.value = int(t.value)

    return t

Error handler

def t_error(t):
    print('Bad character: {!r}'.format(t.value[0]))
    t.skip(1)

build the lexer

lexer = lex()

Grammar rules and handler functions

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


def p_expr_term(p):
    '''
    expr : term
    '''
    p[0] = p[1]

def p_term(p):
    '''
    term : term TIMES factor
         | term DIVIDE factor
    '''
    if p[2] == '*':
        p[0] = p[1] * p[3]
    elif p[2] == '/':
        p[0] = p[1] / p[3]

def p_term_factor(p):
    '''
    term : factor
    '''
    p[0] = p[1]

def p_factor(p):
    '''
    factor : NUM
    '''
    p[0] = p[1]


def p_factor_group(p):
    '''
    factor : LPAREN expr RPAREN
    '''

    p[0] = p[2]

def p_error(p):
    print('Syntax error')


parser = yacc()
print('parse 2'.ljust(just_len),
      parser.parse('2'))

print('parse 2 + 3'.ljust(just_len),
      parser.parse('2 + 3'))
print('parse 2 + 3 * 4'.ljust(just_len),
      parser.parse('2 + 3 * 4'))

print('parse (2 + 3) * 4'.ljust(just_len),
      parser.parse('(2 + 3) * 4'))