Path: blob/main/third_party/ply/example/closurecalc/calc.py
7087 views
# -----------------------------------------------------------------------------1# calc.py2#3# A calculator parser that makes use of closures. The function make_calculator()4# returns a function that accepts an input string and returns a result. All5# lexing rules, parsing rules, and internal state are held inside the function.6# -----------------------------------------------------------------------------78import sys9sys.path.insert(0,"../..")1011if sys.version_info[0] >= 3:12raw_input = input1314# Make a calculator function1516def make_calculator():17import ply.lex as lex18import ply.yacc as yacc1920# ------- Internal calculator state2122variables = { } # Dictionary of stored variables2324# ------- Calculator tokenizing rules2526tokens = (27'NAME','NUMBER',28)2930literals = ['=','+','-','*','/', '(',')']3132t_ignore = " \t"3334t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'3536def t_NUMBER(t):37r'\d+'38t.value = int(t.value)39return t4041def t_newline(t):42r'\n+'43t.lexer.lineno += t.value.count("\n")4445def t_error(t):46print("Illegal character '%s'" % t.value[0])47t.lexer.skip(1)4849# Build the lexer50lexer = lex.lex()5152# ------- Calculator parsing rules5354precedence = (55('left','+','-'),56('left','*','/'),57('right','UMINUS'),58)5960def p_statement_assign(p):61'statement : NAME "=" expression'62variables[p[1]] = p[3]63p[0] = None6465def p_statement_expr(p):66'statement : expression'67p[0] = p[1]6869def p_expression_binop(p):70'''expression : expression '+' expression71| expression '-' expression72| expression '*' expression73| expression '/' expression'''74if p[2] == '+' : p[0] = p[1] + p[3]75elif p[2] == '-': p[0] = p[1] - p[3]76elif p[2] == '*': p[0] = p[1] * p[3]77elif p[2] == '/': p[0] = p[1] / p[3]7879def p_expression_uminus(p):80"expression : '-' expression %prec UMINUS"81p[0] = -p[2]8283def p_expression_group(p):84"expression : '(' expression ')'"85p[0] = p[2]8687def p_expression_number(p):88"expression : NUMBER"89p[0] = p[1]9091def p_expression_name(p):92"expression : NAME"93try:94p[0] = variables[p[1]]95except LookupError:96print("Undefined name '%s'" % p[1])97p[0] = 09899def p_error(p):100if p:101print("Syntax error at '%s'" % p.value)102else:103print("Syntax error at EOF")104105106# Build the parser107parser = yacc.yacc()108109# ------- Input function110111def input(text):112result = parser.parse(text,lexer=lexer)113return result114115return input116117# Make a calculator object and use it118calc = make_calculator()119120while True:121try:122s = raw_input("calc > ")123except EOFError:124break125r = calc(s)126if r:127print(r)128129130131132