Path: blob/main/third_party/ply/example/unicalc/calc.py
7087 views
# -----------------------------------------------------------------------------1# calc.py2#3# A simple calculator with variables. This is from O'Reilly's4# "Lex and Yacc", p. 63.5#6# This example uses unicode strings for tokens, docstrings, and input.7# -----------------------------------------------------------------------------89import sys10sys.path.insert(0,"../..")1112tokens = (13'NAME','NUMBER',14'PLUS','MINUS','TIMES','DIVIDE','EQUALS',15'LPAREN','RPAREN',16)1718# Tokens1920t_PLUS = ur'\+'21t_MINUS = ur'-'22t_TIMES = ur'\*'23t_DIVIDE = ur'/'24t_EQUALS = ur'='25t_LPAREN = ur'\('26t_RPAREN = ur'\)'27t_NAME = ur'[a-zA-Z_][a-zA-Z0-9_]*'2829def t_NUMBER(t):30ur'\d+'31try:32t.value = int(t.value)33except ValueError:34print "Integer value too large", t.value35t.value = 036return t3738t_ignore = u" \t"3940def t_newline(t):41ur'\n+'42t.lexer.lineno += t.value.count("\n")4344def t_error(t):45print "Illegal character '%s'" % t.value[0]46t.lexer.skip(1)4748# Build the lexer49import ply.lex as lex50lex.lex()5152# Parsing rules5354precedence = (55('left','PLUS','MINUS'),56('left','TIMES','DIVIDE'),57('right','UMINUS'),58)5960# dictionary of names61names = { }6263def p_statement_assign(p):64'statement : NAME EQUALS expression'65names[p[1]] = p[3]6667def p_statement_expr(p):68'statement : expression'69print p[1]7071def p_expression_binop(p):72'''expression : expression PLUS expression73| expression MINUS expression74| expression TIMES expression75| expression DIVIDE expression'''76if p[2] == u'+' : p[0] = p[1] + p[3]77elif p[2] == u'-': p[0] = p[1] - p[3]78elif p[2] == u'*': p[0] = p[1] * p[3]79elif p[2] == u'/': p[0] = p[1] / p[3]8081def p_expression_uminus(p):82'expression : MINUS expression %prec UMINUS'83p[0] = -p[2]8485def p_expression_group(p):86'expression : LPAREN expression RPAREN'87p[0] = p[2]8889def p_expression_number(p):90'expression : NUMBER'91p[0] = p[1]9293def p_expression_name(p):94'expression : NAME'95try:96p[0] = names[p[1]]97except LookupError:98print "Undefined name '%s'" % p[1]99p[0] = 0100101def p_error(p):102if p:103print "Syntax error at '%s'" % p.value104else:105print "Syntax error at EOF"106107import ply.yacc as yacc108yacc.yacc()109110while 1:111try:112s = raw_input('calc > ')113except EOFError:114break115if not s: continue116yacc.parse(unicode(s))117118119