calc.py revision 6498
17585SAli.Saidi@arm.com# -----------------------------------------------------------------------------
27585SAli.Saidi@arm.com# calc.py
37585SAli.Saidi@arm.com#
47585SAli.Saidi@arm.com# This example shows how to run the parser in a debugging mode
57585SAli.Saidi@arm.com# with output routed to a logging object.
67585SAli.Saidi@arm.com# -----------------------------------------------------------------------------
77585SAli.Saidi@arm.com
87585SAli.Saidi@arm.comimport sys
97585SAli.Saidi@arm.comsys.path.insert(0,"../..")
107585SAli.Saidi@arm.com
117585SAli.Saidi@arm.comif sys.version_info[0] >= 3:
127585SAli.Saidi@arm.com    raw_input = input
137585SAli.Saidi@arm.com
147585SAli.Saidi@arm.comtokens = (
157585SAli.Saidi@arm.com    'NAME','NUMBER',
167585SAli.Saidi@arm.com    )
177585SAli.Saidi@arm.com
187585SAli.Saidi@arm.comliterals = ['=','+','-','*','/', '(',')']
197585SAli.Saidi@arm.com
207585SAli.Saidi@arm.com# Tokens
217585SAli.Saidi@arm.com
227585SAli.Saidi@arm.comt_NAME    = r'[a-zA-Z_][a-zA-Z0-9_]*'
237585SAli.Saidi@arm.com
247585SAli.Saidi@arm.comdef t_NUMBER(t):
257585SAli.Saidi@arm.com    r'\d+'
267585SAli.Saidi@arm.com    t.value = int(t.value)
277585SAli.Saidi@arm.com    return t
287585SAli.Saidi@arm.com
297585SAli.Saidi@arm.comt_ignore = " \t"
307585SAli.Saidi@arm.com
317585SAli.Saidi@arm.comdef t_newline(t):
327585SAli.Saidi@arm.com    r'\n+'
337585SAli.Saidi@arm.com    t.lexer.lineno += t.value.count("\n")
347585SAli.Saidi@arm.com
357585SAli.Saidi@arm.comdef t_error(t):
367585SAli.Saidi@arm.com    print("Illegal character '%s'" % t.value[0])
377585SAli.Saidi@arm.com    t.lexer.skip(1)
387585SAli.Saidi@arm.com
397585SAli.Saidi@arm.com# Build the lexer
407585SAli.Saidi@arm.comimport ply.lex as lex
417585SAli.Saidi@arm.comlex.lex()
427585SAli.Saidi@arm.com
437585SAli.Saidi@arm.com# Parsing rules
447585SAli.Saidi@arm.com
457585SAli.Saidi@arm.comprecedence = (
467723SAli.Saidi@ARM.com    ('left','+','-'),
477585SAli.Saidi@arm.com    ('left','*','/'),
487585SAli.Saidi@arm.com    ('right','UMINUS'),
497723SAli.Saidi@ARM.com    )
508143SAli.Saidi@ARM.com
517585SAli.Saidi@arm.com# dictionary of names
527585SAli.Saidi@arm.comnames = { }
537585SAli.Saidi@arm.com
548143SAli.Saidi@ARM.comdef p_statement_assign(p):
557585SAli.Saidi@arm.com    'statement : NAME "=" expression'
567585SAli.Saidi@arm.com    names[p[1]] = p[3]
577585SAli.Saidi@arm.com
587585SAli.Saidi@arm.comdef p_statement_expr(p):
597585SAli.Saidi@arm.com    'statement : expression'
607585SAli.Saidi@arm.com    print(p[1])
617585SAli.Saidi@arm.com
627585SAli.Saidi@arm.comdef p_expression_binop(p):
637585SAli.Saidi@arm.com    '''expression : expression '+' expression
647585SAli.Saidi@arm.com                  | expression '-' expression
657585SAli.Saidi@arm.com                  | expression '*' expression
667585SAli.Saidi@arm.com                  | expression '/' expression'''
677585SAli.Saidi@arm.com    if p[2] == '+'  : p[0] = p[1] + p[3]
687585SAli.Saidi@arm.com    elif p[2] == '-': p[0] = p[1] - p[3]
697585SAli.Saidi@arm.com    elif p[2] == '*': p[0] = p[1] * p[3]
707585SAli.Saidi@arm.com    elif p[2] == '/': p[0] = p[1] / p[3]
717585SAli.Saidi@arm.com
727585SAli.Saidi@arm.comdef p_expression_uminus(p):
737585SAli.Saidi@arm.com    "expression : '-' expression %prec UMINUS"
747585SAli.Saidi@arm.com    p[0] = -p[2]
757585SAli.Saidi@arm.com
767585SAli.Saidi@arm.comdef p_expression_group(p):
777585SAli.Saidi@arm.com    "expression : '(' expression ')'"
787585SAli.Saidi@arm.com    p[0] = p[2]
797585SAli.Saidi@arm.com
807585SAli.Saidi@arm.comdef p_expression_number(p):
817585SAli.Saidi@arm.com    "expression : NUMBER"
827585SAli.Saidi@arm.com    p[0] = p[1]
837585SAli.Saidi@arm.com
847585SAli.Saidi@arm.comdef p_expression_name(p):
857585SAli.Saidi@arm.com    "expression : NAME"
867585SAli.Saidi@arm.com    try:
877585SAli.Saidi@arm.com        p[0] = names[p[1]]
887585SAli.Saidi@arm.com    except LookupError:
897585SAli.Saidi@arm.com        print("Undefined name '%s'" % p[1])
907585SAli.Saidi@arm.com        p[0] = 0
917585SAli.Saidi@arm.com
927585SAli.Saidi@arm.comdef p_error(p):
937585SAli.Saidi@arm.com    if p:
947723SAli.Saidi@ARM.com        print("Syntax error at '%s'" % p.value)
957585SAli.Saidi@arm.com    else:
967585SAli.Saidi@arm.com        print("Syntax error at EOF")
977585SAli.Saidi@arm.com
987585SAli.Saidi@arm.comimport ply.yacc as yacc
997585SAli.Saidi@arm.comyacc.yacc()
1007585SAli.Saidi@arm.com
1018143SAli.Saidi@ARM.comimport logging
1028143SAli.Saidi@ARM.comlogging.basicConfig(
1038143SAli.Saidi@ARM.com    level=logging.INFO,
1048143SAli.Saidi@ARM.com    filename="parselog.txt"
1058143SAli.Saidi@ARM.com)
1068143SAli.Saidi@ARM.com
1078143SAli.Saidi@ARM.comwhile 1:
1088143SAli.Saidi@ARM.com    try:
1098143SAli.Saidi@ARM.com        s = raw_input('calc > ')
1108143SAli.Saidi@ARM.com    except EOFError:
1118143SAli.Saidi@ARM.com        break
1128143SAli.Saidi@ARM.com    if not s: continue
1138143SAli.Saidi@ARM.com    yacc.parse(s,debug=logging.getLogger())
1148143SAli.Saidi@ARM.com