16498Snate@binkert.org# -----------------------------------------------------------------------------
26498Snate@binkert.org# calc.py
36498Snate@binkert.org#
46498Snate@binkert.org# This example shows how to run the parser in a debugging mode
56498Snate@binkert.org# with output routed to a logging object.
66498Snate@binkert.org# -----------------------------------------------------------------------------
76498Snate@binkert.org
86498Snate@binkert.orgimport sys
96498Snate@binkert.orgsys.path.insert(0,"../..")
106498Snate@binkert.org
116498Snate@binkert.orgif sys.version_info[0] >= 3:
126498Snate@binkert.org    raw_input = input
136498Snate@binkert.org
146498Snate@binkert.orgtokens = (
156498Snate@binkert.org    'NAME','NUMBER',
166498Snate@binkert.org    )
176498Snate@binkert.org
186498Snate@binkert.orgliterals = ['=','+','-','*','/', '(',')']
196498Snate@binkert.org
206498Snate@binkert.org# Tokens
216498Snate@binkert.org
226498Snate@binkert.orgt_NAME    = r'[a-zA-Z_][a-zA-Z0-9_]*'
236498Snate@binkert.org
246498Snate@binkert.orgdef t_NUMBER(t):
256498Snate@binkert.org    r'\d+'
266498Snate@binkert.org    t.value = int(t.value)
276498Snate@binkert.org    return t
286498Snate@binkert.org
296498Snate@binkert.orgt_ignore = " \t"
306498Snate@binkert.org
316498Snate@binkert.orgdef t_newline(t):
326498Snate@binkert.org    r'\n+'
336498Snate@binkert.org    t.lexer.lineno += t.value.count("\n")
346498Snate@binkert.org
356498Snate@binkert.orgdef t_error(t):
366498Snate@binkert.org    print("Illegal character '%s'" % t.value[0])
376498Snate@binkert.org    t.lexer.skip(1)
386498Snate@binkert.org
396498Snate@binkert.org# Build the lexer
406498Snate@binkert.orgimport ply.lex as lex
416498Snate@binkert.orglex.lex()
426498Snate@binkert.org
436498Snate@binkert.org# Parsing rules
446498Snate@binkert.org
456498Snate@binkert.orgprecedence = (
466498Snate@binkert.org    ('left','+','-'),
476498Snate@binkert.org    ('left','*','/'),
486498Snate@binkert.org    ('right','UMINUS'),
496498Snate@binkert.org    )
506498Snate@binkert.org
516498Snate@binkert.org# dictionary of names
526498Snate@binkert.orgnames = { }
536498Snate@binkert.org
546498Snate@binkert.orgdef p_statement_assign(p):
556498Snate@binkert.org    'statement : NAME "=" expression'
566498Snate@binkert.org    names[p[1]] = p[3]
576498Snate@binkert.org
586498Snate@binkert.orgdef p_statement_expr(p):
596498Snate@binkert.org    'statement : expression'
606498Snate@binkert.org    print(p[1])
616498Snate@binkert.org
626498Snate@binkert.orgdef p_expression_binop(p):
636498Snate@binkert.org    '''expression : expression '+' expression
646498Snate@binkert.org                  | expression '-' expression
656498Snate@binkert.org                  | expression '*' expression
666498Snate@binkert.org                  | expression '/' expression'''
676498Snate@binkert.org    if p[2] == '+'  : p[0] = p[1] + p[3]
686498Snate@binkert.org    elif p[2] == '-': p[0] = p[1] - p[3]
696498Snate@binkert.org    elif p[2] == '*': p[0] = p[1] * p[3]
706498Snate@binkert.org    elif p[2] == '/': p[0] = p[1] / p[3]
716498Snate@binkert.org
726498Snate@binkert.orgdef p_expression_uminus(p):
736498Snate@binkert.org    "expression : '-' expression %prec UMINUS"
746498Snate@binkert.org    p[0] = -p[2]
756498Snate@binkert.org
766498Snate@binkert.orgdef p_expression_group(p):
776498Snate@binkert.org    "expression : '(' expression ')'"
786498Snate@binkert.org    p[0] = p[2]
796498Snate@binkert.org
806498Snate@binkert.orgdef p_expression_number(p):
816498Snate@binkert.org    "expression : NUMBER"
826498Snate@binkert.org    p[0] = p[1]
836498Snate@binkert.org
846498Snate@binkert.orgdef p_expression_name(p):
856498Snate@binkert.org    "expression : NAME"
866498Snate@binkert.org    try:
876498Snate@binkert.org        p[0] = names[p[1]]
886498Snate@binkert.org    except LookupError:
896498Snate@binkert.org        print("Undefined name '%s'" % p[1])
906498Snate@binkert.org        p[0] = 0
916498Snate@binkert.org
926498Snate@binkert.orgdef p_error(p):
936498Snate@binkert.org    if p:
946498Snate@binkert.org        print("Syntax error at '%s'" % p.value)
956498Snate@binkert.org    else:
966498Snate@binkert.org        print("Syntax error at EOF")
976498Snate@binkert.org
986498Snate@binkert.orgimport ply.yacc as yacc
996498Snate@binkert.orgyacc.yacc()
1006498Snate@binkert.org
1016498Snate@binkert.orgimport logging
1026498Snate@binkert.orglogging.basicConfig(
1036498Snate@binkert.org    level=logging.INFO,
1046498Snate@binkert.org    filename="parselog.txt"
1056498Snate@binkert.org)
1066498Snate@binkert.org
1076498Snate@binkert.orgwhile 1:
1086498Snate@binkert.org    try:
1096498Snate@binkert.org        s = raw_input('calc > ')
1106498Snate@binkert.org    except EOFError:
1116498Snate@binkert.org        break
1126498Snate@binkert.org    if not s: continue
1136498Snate@binkert.org    yacc.parse(s,debug=logging.getLogger())
114