[ Foro de Python ]

Funcionamiento de PLY

07-Jun-2016 20:24
Alberto Rioja
1 Respuestas

Estoy haciendo un traductor en Python con la librería PLY. Ya hice el lexer, pero no puedo hacer que corra el parser. He puesto los tokens en un archivo de texto y en un arreglo, con cambio de línea y sin él, pero no logro que corra el parser con esos tokens; no me genera el archivo .out.

Este es el código:

import ply.lex as lex
import ply.yacc as yacc

blank = 1
stCount = 1
tCount = 0
ban = 0
st = []
token = []
token2 = []

st.append("")

tokens = ['ON', 'OFF', 'SERIAL', 'WHEN', 'SHOW', 'LOOP', 'INLOOP', 'KEEP',   #Palabras reservadas
   'ENT', 'DEC', 'ONE', 'MANY',                                             #Palabras reservadas
   'MAYOR', 'MENOR', 'IGUAL', 'DIFERENTE', 'MAYEQL', 'MENEQL',              #Simbolos comparadores
   'MAS', 'MENOS', 'MUL', 'DIV', 'PARI', 'PARD', 'EQL',                     #Simbolos aritmeticos
   'INCREMENTO', 'DECREMENTO',                                              #Incremento y decremento
   'COMA', 'TILDE', 'LLAVEI', 'LLAVED', 'CLS', 'CONCAT',                    #Simbolos de puntuacion
   'ID', 'VENT', 'VDEC', 'VONE', 'VMANY']                                   #Tokens con valores en tabla
   #'COMMENT', 'space']                                                     #Espacios y comentarios (ignorados)

#PALABRAS RESERVADAS
def t_OFF (t) :
   r'off'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_SERIAL (t) :
   r'SERIAL'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_WHEN (t):
   r'when'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_SHOW (t) :
   r'show'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_LOOP (t) :
   r'loop'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_INLOOP (t) :
   r'inloop'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_KEEP (t):
   r'keep'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#TIPOS DE VARIABLES
def t_ENT (t) :
   r'ent'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_DEC (t) :
   r'dec'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MANY (t) :
   r'many'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_ONE (t):
   r'one'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_ON(t):                     #ON esta aqui por orden del lexer
   r'on'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#PUNTUACION
def t_CLS (t):
   r';'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_CONCAT (t):
   r'&'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_COMA (t):
   r','
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_TILDE (t):
   r'~'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_LLAVEI (t):
   r'{'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_LLAVED (t):
   r'}'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#INCREMENTO Y DECREMENTO
def t_INCREMENTO (t):
   r'\+\+'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_DECREMENTO (t):
   r'\-\-'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#COMPARADORES
def t_MAYEQL (t):
   r'>='
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MENEQL (t):
   r'<='
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MAYOR (t):
   r'>'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MENOR (t):
   r'<'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_IGUAL (t):
   r'=='
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_DIFERENTE (t):
   r'!='
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#OPERADORES
def t_EQL (t):
   r'='
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MAS(t):
   r'\+'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MENOS(t):
   r'\-'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_MUL(t):
   r'\*'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_DIV(t):
   r'/'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_PARI(t):
   r'\('
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

def t_PARD(t):
   r'\)'
   token.append(str(t.type))
   token2.append(str(t.type))
   return t

#TOKENS CON POSICION EN TABLA
def t_ID(t):
   r'_(\w)*'
   global ban
   global stCount
   global tCount
   global st
   ban = 1
   for i in st:
       if i == str(t.value):
           token.append(str(t.type) + " " + str(tCount))
           token2.append(str(t.type))
           ban = 0
           break
       else:
           tCount+=1
           ban = 1
   if ban == 1:
       st.append(str(t.value))
       token.append(str(t.type) + " " + str(stCount))
       token2.append(str(t.type))
       stCount+=1
       ban = 0
   tCount = 0
   return t

def t_VDEC(t):
   r'(\d+)(\.)(\d+)'
   t.value = float(t.value)
   global ban
   global stCount
   global tCount
   global st
   ban = 1
   for i in st:
       if i == str(t.value):
           token.append(str(t.type) + " " + str(tCount))
           token2.append(str(t.type))
           ban = 0
           break
       else:
           tCount+=1
           ban = 1
   if ban == 1:
       st.append(str(t.value))
       token.append(str(t.type) + " " + str(stCount))
       token2.append(str(t.type))
       stCount+=1
       ban = 0
   tCount = 0
   return t

def t_VENT(t):
   r'\d+'
   t.value = int(t.value)
   global ban
   global stCount
   global tCount
   global st
   ban = 1
   for i in st:
       if i == str(t.value):
           token.append(str(t.type) + " " + str(tCount))
           token2.append(str(t.type))
           ban = 0
           break
       else:
           tCount+=1
           ban = 1
   if ban == 1:
       st.append(str(t.value))
       token.append(str(t.type) + " " + str(stCount))
       token2.append(str(t.type))
       stCount+=1
       ban = 0
   tCount = 0
   return t

def t_VMANY (t):
   r'\"(.*)\"'
   t.value = str(t.value)
   global ban
   global stCount
   global tCount
   global st
   ban = 1
   for i in st:
       if i == str(t.value):
           token.append(str(t.type) + " " + str(tCount))
           token2.append(str(t.type))
           ban = 0
           break
       else:
           tCount+=1
           ban = 1
   if ban == 1:
       st.append(str(t.value))
       token.append(str(t.type) + " " + str(stCount))
       token2.append(str(t.type))
       stCount+=1
       ban = 0
   tCount = 0
   return t

def t_VONE(t):
   r'\"(.?)\"'
   t.value = str(t.value)
   global ban
   global stCount
   global tCount
   global st
   ban = 1
   for i in st:
       if i == str(t.value):
           token.append(str(t.type) + " " + str(tCount))
           token2.append(str(t.type))
           ban = 0
           break
       else:
           tCount+=1
           ban = 1
   if ban == 1:
       st.append(str(t.value))
       token.append(str(t.type) + " " + str(stCount))
       token2.append(str(t.type))
       stCount+=1
       ban = 0
   tCount = 0
   return t

#Ignorar comentarios y espacios para los tokens
t_ignore_COMMENT = r'\#.*\#'
t_ignore_space = r'\s'

#Validacion de caracteres ilegales
def t_error(t):
   print("Caracter ilegal " + t.value[0] + " en linea " + str(blank))
   t.lexer.skip(1)

#Linea nueva
def t_newline(t):
   r'\n+'
   global blank
   blank = blank + 1
   t.lexer.lineno += len(t.value)

#Posicion horizontal
def find_column(input,token):
   last_cr = input.rfind('\n' , 0, token.lexpos)
   if last_cr < 0:
       last_cr = 0
   column = (token.lexpos - last_cr) + 1
   return column

#Construccion del lexer
lexer = lex.lex()

#Apertura del archivo a leer
f = open('tokens.txt')
data = f.read()
f.close()
#Construccion de la lista de tokens con lex.lex()
lexer.input(data)
f = open('tprueba.txt', 'w')
while True:
   tok = lexer.token()
   f.write(str(tok) + '\n')
   if not tok:
       break
f.close()


#Escritura de la lista de tokens propia
archivo = open('MyTokens.txt', 'w')
for i in token:
   if i!="":
       archivo.write(i+'\n')
archivo.close()
#Escritura de la lista de tokens2 propia
archivo = open('MyTokens2.txt', 'w')
for i in token2:
   if i!="":
       archivo.write(i+'\t')
archivo.close()
#Escritura de la tabla de simbolos
a = 1
archivo = open('simboltable.txt', 'w')
for i in st:
   if i!="":
       archivo.write(str(a) + " " + i + '\n')
       a+=1
archivo.close()


#Parser

VERBOSE = 1

#Tabla de precedencia
precedence = (
       ('left','MAS','MENOS'),
       ('left','MUL','DIV'),
       ('left','PARI','PARD'),
       ('right','UMENOS'),
       )

#Reglas gramaticales
def p_main_s(p):
   's : code'
   p[0] = p[1]

def p_code (p):
   'code : ON statement OFF'
   p[0] = p[1]

def p_statement (p):
   '''statement : statement SERIAL TILDE asignacion COMA comparacion COMA incrdecr TILDE
                | statement INLOOP LLAVEI statement LLAVED TILDE  comparacion TILDE CLS
                | statement WHEN TILDE comparacion TILDE LLAVEI statement LLAVED
                | statement LOOP TILDE comparacion TILDE LLAVEI statement LLAVED
                | statement KEEP TILDE ID TILDE CLS
                | statement SHOW TILDE muestra TILDE CLS
                | statement tipov EQL valor CLS
                | statement operacion
                | empty '''
   #pass
   if(len(p) == 10):
       p[0] = p[1]+p[4]+p[6]+p[7]+p[8]
   elif(len(p) == 9):
       p[0] = p[1]+p[4]+p[7]
   elif(len(p) == 7):
       p[0] = p[1]+p[4]
   elif(len(p) == 6):
       p[0] = p[1]+p[2]+p[4]
   elif(len(p) == 3):
       p[0] = p[1]+p[2]+p[3]
   elif(len(p) == 2):
       p[0] = p[1]

def p_valor (p):
   '''valor : VENT
            | VDEC
            | VONE
            | VMANY '''
   pass

def p_tipov (p):
   ''' tipov : ENT
             | DEC
             | ONE
             | MANY '''
   pass

def p_comparacion (p):
   ''' comparacion : ID comparador ID
                   | ID comparador valor '''
   #pass
   p[0] = p[2]+p[3]

def p_comparador (p):
   ''' comparador : MAYOR
                  | MENOR
                  | IGUAL
                  | MAYEQL
                  | MENEQL
                  | DIFERENTE '''
   pass

def p_muestra (p):
   ''' muestra : muestra CONCAT valor
               | muestra CONCAT ID
               | valor
               | ID '''
   #pass
   if(len(p) == 4):
       p[0] = p[1]+p[3]
   elif(len(p) == 2):
       p[0] = p[1]

def p_incrdecr(p):
   ''' incrdecr : ID INCREMENTO
                | ID DECREMENTO '''
   pass

def p_asignacion(p):
   ''' asignacion : ID EQL muestra
                  | ID EQL operacion'''
   #pass
   p[0] = p[3]

def p_operacion (p):
   ''' operacion : operacion MAS expr
                 | operacion MENOS expr
                 | expr '''
   #pass
   if (len(p) == 4):
       if p[2] == '+':
           p[0] = p[1] + p[3]
       elif p[2] == '-':
           p[0] = p[1] - p[3]
   elif (len(p) == 2):
       p[0] = p[1]

def p_expr(p):
   ''' expr : expr MUL term
            | expr DIV term
            | term '''
   #pass
   if (len(p) == 4):
       if p[2] == '*':
           p[0] = p[1] * p[3]
       elif p[2] == '/':
           p[0] = p[1] / p[3]
   elif (len(p) == 2):
       p[0] = p[1]

def p_term(p):
   ''' term : ID
            | valor
            | PARI operacion PARD '''
   #pass
   if(len(p) == 4):
       p[0]=p[2]
   elif (len(p) == 2):
       p[0] = p[1]

def p_umenos(p):
       ''' term : MENOS term %prec UMENOS '''
       p[0] = -p[2]

def p_empty(p):
   ''' empty : '''
   pass

#Error
#def p_error(p):
#    print("Error sintactico en '%s'" % t.value)
#    if VERBOSE:
#        print("Error de sintaxis en " + str(p.lexer.lineno))
#    else:
#        raise Exception ('Syntax', 'error')

parser = yacc.yacc()
archivos = open('MyTokens2.txt')
data = archivos.read()
archivos.close()
result = parser.parse(data)
print parser


11-Jun-2016 11:31
Nacho Cabanes (+83)

Por mi parte, me temo que no puedo ayudarte, no he usado PLY.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)