1# ----------------------------------------------------------------------------- 2# calc.py 3# 4# This example shows how to run the parser in a debugging mode 5# with output routed to a logging object. 6# ----------------------------------------------------------------------------- 7 8import sys 9sys.path.insert(0, "../..") 10 11if sys.version_info[0] >= 3: 12 raw_input = input 13 14tokens = ( 15 'NAME', 'NUMBER', 16) 17 18literals = ['=', '+', '-', '*', '/', '(', ')'] 19 20# Tokens 21 22t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 23 24 25def t_NUMBER(t): 26 r'\d+' 27 t.value = int(t.value) 28 return t 29 30t_ignore = " \t" 31 32 33def t_newline(t): 34 r'\n+' 35 t.lexer.lineno += t.value.count("\n") 36 37 38def t_error(t): 39 print("Illegal character '%s'" % t.value[0]) 40 t.lexer.skip(1) 41 42# Build the lexer 43import ply.lex as lex 44lex.lex() 45 46# Parsing rules 47 48precedence = ( 49 ('left', '+', '-'), 50 ('left', '*', '/'), 51 ('right', 'UMINUS'), 52) 53 54# dictionary of names 55names = {} 56 57 58def p_statement_assign(p): 59 'statement : NAME "=" expression' 60 names[p[1]] = p[3] 61 62 63def p_statement_expr(p): 64 'statement : expression' 65 print(p[1]) 66 67 68def p_expression_binop(p): 69 '''expression : expression '+' expression 70 | expression '-' expression 71 | expression '*' expression 72 | expression '/' expression''' 73 if p[2] == '+': 74 p[0] = p[1] + p[3] 75 elif p[2] == '-': 76 p[0] = p[1] - p[3] 77 elif p[2] == '*': 78 p[0] = p[1] * p[3] 79 elif p[2] == '/': 80 p[0] = p[1] / p[3] 81 82 83def p_expression_uminus(p): 84 "expression : '-' expression %prec UMINUS" 85 p[0] = -p[2] 86 87 88def p_expression_group(p): 89 "expression : '(' expression ')'" 90 p[0] = p[2] 91 92 93def p_expression_number(p): 94 "expression : NUMBER" 95 p[0] = p[1] 96 97 98def p_expression_name(p): 99 "expression : NAME" 100 try: 101 p[0] = names[p[1]] 102 except LookupError: 103 print("Undefined name '%s'" % p[1]) 104 p[0] = 0 105 106 107def p_error(p): 108 if p: 109 print("Syntax error at '%s'" % p.value) 110 else: 111 print("Syntax error at EOF") 112 113import ply.yacc as yacc 114yacc.yacc() 115 116import logging 117logging.basicConfig( 118 level=logging.INFO, 119 filename="parselog.txt" 120) 121 122while 1: 123 try: 124 s = raw_input('calc > ') 125 except EOFError: 126 break 127 if not s: 128 continue 129 yacc.parse(s, debug=logging.getLogger()) 130