#!/usr/bin/env python # -*- coding: latin-1 -*- # ############################################################################## # # metacomp 2.5beta3: a metacompiler for RLL(1) grammars # Copyright (C) 2008 Juan Miguel Vilar and Andrés Marzal # Universitat Jaume I, Castelló (Spain) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Any questions regarding this software should be directed to: # # Juan Miguel Vilar # Departament de Llenguatges i Sistemes Informàtics # Universitat Jaume I # E12071 Castellón (SPAIN) # # email: jvilar@lsi.uji.es # ############################################################################## # # Fichero: metacomp # # Fichero principal de metacomp2 # import sys, re, string from mc_modulos.analizador import AnalizadorSintactico from mc_modulos.gramatica import Gramatica from mc_modulos.errores import * from mc_modulos.generador import genera_analizador # # Ayuda: # def ayuda(): w = sys.stderr.write w(r""" metacomp 2.5beta3: a metacompiler for RLL(1) grammars Copyright (C) 2008 Juan Miguel Vilar and Andrés Marzal metacomp comes with ABSOLUTELY NO WARRANTY; for details use option "--licencia". This is free software, and you are welcome to redistribute it under certain conditions; use option "--licencia" for details. Uso: metacomp [] [fichero.mc] donde "fichero.mc" es el fichero de entrada, si no se especifica, se utiliza la entrada estándar. OPCIONES: -h|--help|-a|--ayuda: muestra este texto. -s|--salida : fichero de salida. -A|--arbol: añade código para mostrar el árbol de análisis. -t|--traza: añade código para mostrar trazas de ejecución. -e|--esquema: muestra el esquema de traducción, ocultando las zonas de código de usuario. -g|--gramatica: muestra el esquema de traducción, ocultando acciones, tratamiento de errores y zonas de código de usuario. -l|--lexico fichero: sustituye el analizador generado por metacomp por la línea "from import AnalizadorLexico". -L|--licencia: muestra la licencia del programa. -p|--puro: crea un analizador sintáctico "puro" (sin acciones semánticas). -S|--sololexico: genera únicamente el analizador léxico. """) # # Licencia: # def licencia(): sys.stderr.write(r""" metacomp 2.5beta3: a metacompiler for RLL(1) grammars Copyright (C) 2008 Juan Miguel Vilar and Andrés Marzal Universitat Jaume I, Castelló (Spain) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Any questions regarding this software should be directed to: Juan Miguel Vilar Departament de Llenguatges i Sistemes Informàtics Universitat Jaume I E12071 Castellón (SPAIN) email: jvilar@lsi.uji.es """) def argumento(l,i): if i< len(l): return l[i] else: escribe_error(sys.stderr, "Error: Falta el argumento de %s.\n" % l[i-1]) sys.exit(1) # # Principal: # def main(): fentrada= "" fsalida= "" traza= None # valores: None, "t": traza, "A": árbol muestra_gramatica= 0 muestra_esquema= 0 lexico= None tipoAnalizador="normal" # valores: normal, lexico, puro puro= 0 args= len(sys.argv) i= 1 while i< args: if sys.argv[i] in ["-e", "--esquema"]: muestra_esquema= 1 elif sys.argv[i] in ["-g", "--gramatica"]: muestra_gramatica= 1 elif sys.argv[i] in ["-h", "--help", "-a", "-ayuda"]: ayuda() sys.exit(-1) elif sys.argv[i] in ["-l", "--lexico"]: i= i+1 lexico = argumento(sys.argv,i) elif sys.argv[i] in ["-s", "--salida"]: i= i+1 fsalida = argumento(sys.argv,i) elif sys.argv[i] in ["-A", "--arbol"]: traza= "A" # arbol elif sys.argv[i] in ["-t", "--traza"]: traza= "t" # traza elif sys.argv[i] in ["-S", "--sololexico"]: tipoAnalizador= "lexico" elif sys.argv[i] in ["-p", "--puro"]: tipoAnalizador= "puro" elif sys.argv[i][0]== "-": ayuda() sys.exit(-1) else: fentrada= argumento(sys.argv,i) i= i+1 if not fentrada: entrada= sys.stdin else: try: entrada= open(fentrada, "r") except IOError: escribe_error(sys.stderr, "Error: No he podido abrir %s para lectura.\n" % fentrada) sys.exit(1) try: A= AnalizadorSintactico(entrada) G= A.G lexica= A.lexica codusuario= A.codusuario except DemasiadosErrores: muestra_errores_y_avisos() sys.exit(-1) if G== None: if errores.e: muestra_errores_y_avisos() else: escribe_error(sys.stderr, "Error: No he podido encontrar nada con sentido en tu fichero, lo siento.\n") sys.exit(-1) if G.reglas == []: if tipoAnalizador!= "lexico": escribe_error(sys.stderr, "Aviso: No se ha especificado ningún esquema de traducción, sólo generaré el analizador léxico.\n") tipoAnalizador= "lexico" # Mostrar el esquema o la gramática, si procede. if muestra_esquema: sys.stderr.write(str(G)) sys.stderr.write("\n") elif muestra_gramatica: sys.stderr.write(G.lista_reglas()) sys.stderr.write("\n") # Comprobar si todo símbolo no terminal es parte izquierda de al menos una producción for nt in G.noterminales: if len(nt.reglasizda)==0: escribe_error(sys.stderr, "Aviso: El símbolo %s no aparece en ninguna parte izquierda.\n" % nt) if errores.e or avisos.e: muestra_errores_y_avisos() if errores.e: sys.exit(-1) # Comprobación de conflictos: l= G.recursividad_izquierda() if l: for nt in l: escribe_error(sys.stderr, "Error: El no terminal %s tiene recursividad a izquierdas.\n" % nt) sys.exit(1) G.comprueba_conflictos(sys.stderr) # Generar el analizador if not lexica and not lexico: escribe_error(sys.stderr, "No puede haber una especificación léxica vacía si no se da un analizador léxico como parámetro.\n") sys.exit(1) if fsalida == "": salida = sys.stdout else: try: salida = open(fsalida, "w") except IOError: escribe_error(sys.stderr, "Error: No he podido abrir %s para escritura.\n" % fsalida) sys.exit(1) genera_analizador(G, lexica, codusuario, traza, salida, lexico, tipoAnalizador) try: if fsalida: os.chmod(fsalida, 0744) except: pass # Llamada al programa principal main()