samedi 31 octobre 2015

How to do an IF statement in PLY?

I'm doing a compiler using PLY. I have successfully implemented arithmetic and logical operations, but I'm having trouble with the 'if statement'.

This is my current code:

-Lexer:

tokens = (
    'NAME','INT', 'DOUBLE', 'GREATER', 'LESS',
    'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
    'LPAREN','RPAREN', 'CHAR', 'TRUE', 'FALSE',
    'GREATEQ', 'LESSEQ', 'EQEQ', 'NOTEQ', 'AND',
    'OR', 'COLON', 'IF'
    )

# Reserved words
reserved = {
    'if' : 'IF'
}

# Tokens

t_PLUS    = r'\+'
t_MINUS   = r'-'
t_TIMES   = r'\*'
t_DIVIDE  = r'/'
t_EQUALS  = r'='
t_LPAREN  = r'\('
t_RPAREN  = r'\)'
t_NAME    = r'[a-zA-Z][a-zA-Z0-9_]*'
t_CHAR    = r'\'[a-zA-Z0-9_+\*\- :,\s]*\''
t_TRUE    = r'\t'
t_FALSE   = r'\f'
t_GREATER = r'>'
t_LESS    = r'<'
t_GREATEQ = r'>='
t_LESSEQ  = r'<='
t_EQEQ    = r'=='
t_NOTEQ   = r'!='
t_AND     = r'&'
t_OR      = r'\|'
t_COLON   = r':'

def t_DOUBLE(t):
    r'[0-9]+\.[0-9]+'
    try:
        t.value = float(t.value)
    except ValueError:
        print("Integer value too large %d", t.value)
        t.value = 0
    return t

def t_INT(t):
    r'[0-9]+'
    try:
        t.value = int(t.value)
    except ValueError:
        print("Double value too large %d", t.value)
        t.value = 0
    return t

# Ignored characters
t_ignore = " \t"

def t_IF(t):
    r'if'
    return t

def t_newline(t):
    r'\n+'
    t.lexer.lineno += t.value.count("\n")

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# Build the lexer
import ply.lex as lex
lexer = lex.lex()

-Parser:

# Parsing rules

precedence = (
    ('left','AND','OR'),
    ('left','GREATER','LESS', 'GREATEQ', 'LESSEQ', 'EQEQ', 'NOTEQ'),
    ('left','PLUS','MINUS'),
    ('left','TIMES','DIVIDE'),
    ('right','UMINUS'),
    )

# dictionary of names
names = { }

def p_statement_assign(t):
    'statement : NAME EQUALS expression'
    names[t[1]] = t[3]

def p_statement_expr(t):
    'statement : expression'
    print(t[1])

def p_statement_if(t):
    'statement : IF LPAREN expression RPAREN DP statement'  
    pass

def p_expression_ariop(t):
    '''expression : expression PLUS expression
                  | expression MINUS expression
                  | expression TIMES expression
                  | expression DIVIDE expression'''
    if t[2] == '+'  : t[0] = t[1] + t[3]
    elif t[2] == '-': t[0] = t[1] - t[3]
    elif t[2] == '*': t[0] = t[1] * t[3]
    elif t[2] == '/': t[0] = t[1] / t[3]

def p_expression_logop(t):
    '''expression : expression GREATER expression
                  | expression LESS expression
                  | expression GREATEQ expression
                  | expression LESSEQ expression
                  | expression EQEQ expression
                  | expression NOTEQ expression
                  | expression AND expression
                  | expression OR expression'''
    if t[2] == '>'  : t[0] = t[1] > t[3]
    elif t[2] == '<': t[0] = t[1] < t[3]
    elif t[2] == '>=': t[0] = t[1] >= t[3]
    elif t[2] == '<=': t[0] = t[1] <= t[3]
    elif t[2] == '==': t[0] = t[1] == t[3]
    elif t[2] == '!=': t[0] = t[1] != t[3]
    elif t[2] == '&': t[0] = t[1] and t[3]
    elif t[2] == '|': t[0] = t[1] or t[3]

def p_expression_uminus(t):
    'expression : MINUS expression %prec UMINUS'
    t[0] = -t[2]

def p_expression_group(t):
    'expression : LPAREN expression RPAREN'
    t[0] = t[2]

def p_expression_int(t):
    'expression : INT'
    t[0] = t[1]

def p_expression_double(t):
    'expression : DOUBLE'
    t[0] = t[1]

def p_expression_char(t):
    'expression : CHAR'
    t[0] = t[1]

def p_expression_name(t):
    'expression : NAME'
    try:
        t[0] = names[t[1]]
    except LookupError:
        print("Undefined name '%s'" % t[1])
        t[0] = 0

def p_expression_bool(t):
    'expression : bool'
    t[0] = t[1]

def p_true(t):
    'bool : TRUE'
    t[0] = True

def p_false(t):
    'bool : FALSE'
    t[0] = False

def p_error(t):
    print("Syntax error at '%s'" % t.value)

import ply.yacc as yacc
parser = yacc.yacc()

I have also try something like this in the parser:

def p_statement_if(t):
    'statement : IF expression COLON statement' 
    t[0] = ('if',t[2],t[4])

Whether the expression is true or false, my compiler always does the statement
What am I doing wrong?

Thanks

Aucun commentaire:

Enregistrer un commentaire