コード例 #1
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro):
     c = code.empty()
     if traza=="t":
         ( c
           / ("mc_traza('> Analizando %s\\n')" % self.regla())
           / "mc_dentro_traza()"
           )
     if garantizados== self.primeros(): # Sólo tenemos garantías si
         g= garantizados                # coinciden al principio y
     else:                              # en cada vuelta
         g= None
     ( c
       / "while True:"
       //   self.pd.genera_codigo_interno(pizda, orden, siguientesPadre, g, traza, esPuro)
       /    ("if %s: break" % _test_no_set(self.primeros()))
       )
     if traza=="t":
         ( c
           / "mc_fuera_traza()"
           / ("""mc_traza('< Fin de %s\\n')""" % self.regla())
           )
     c / ("if not %s:" % _test_set(self.missiguientes))
     if traza:
         c // "mc_traza('Error, no encontramos ninguno de los siguientes\\n')"
     c // ("mc_error('%s',%s)" % (self.mi_nt, _set_strlista(self.misaceptables)))
     return c
コード例 #2
0
def diccionarios(gramatica):
    # Diccionarios de primeros, siguientes, aceptables y anulables:
    c = code.empty()
    c / "mc_primeros = {"
    for nt in gramatica.noterminales:
        pr = ", ".join([repr(p) for p in nt.primeros()])
        c // ("'%s' : [%s]," % (nt, pr))
    c / "}"

    c / "mc_siguientes = {"
    for nt in gramatica.noterminales:
        pr = ", ".join([repr(p) for p in nt.siguientes()])
        c // ("'%s' : [%s]," % (nt, pr))
    c / "}"

    c / "mc_aceptables = {"
    for nt in gramatica.noterminales:
        pr = ", ".join([repr(p) for p in nt.aceptables()])
        c // ("'%s' : [%s]," % (nt, pr))
    c / "}"

    c / "mc_anulables = {"
    for nt in gramatica.noterminales:
        c // ("'%s' : %s," % (nt, nt.anulable()))
    c / "}"

    return c
コード例 #3
0
ファイル: analizador.py プロジェクト: rdonate/MiniCalc
 def mc_analiza_Compilador(self, Compilador):
     mc_al = self.mc_al
     if not mc_al.actual.cat == u'especificacion_lexica':
         mc_error('<Compilador>', [u'especificacion_lexica'])
     tratEOF = tratEOF1 = Atributos()
     Lineas = Lineas1 = Atributos()
     Compilador.abandonar = True
     especificacion_lexica = especificacion_lexica1 = especificacion_lexica_ = mc_al.actual
     mc_al.avanza()
     if mc_al.actual.cat == u'codigo':
         codigo = codigo1 = codigo_ = mc_al.actual
         mc_al.avanza()
     else:
         import analex
         codigo = analex.ComponenteLexico("codigo", mc_al.linea())
         codigo.cod = code.empty()
     Lineas.codusuario = codigo.cod
     tratEOF.codigo = None
     self.mc_analiza_tratEOF(tratEOF1)
     tratEOF_ = tratEOF1
     Lineas.l = []
     self.mc_analiza_Lineas(Lineas1)
     Lineas_ = Lineas1
     Compilador.abandonar = False
     lexica = [(td, None, REParser.stringAsRE(td[1:])) for td in directos]
     lexica += especificacion_lexica.esp
     Compilador.lexica = lexica
     if Lineas.inicial is None:
         Compilador.G = None
     else:
         Compilador.G = Gramatica(T.listanoterminales(), Lineas.inicial,
                                  Lineas.l, tratEOF.codigo)
     codusuario = Lineas.codusuario
     Compilador.codusuario = codusuario
コード例 #4
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
    def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro ):
        cuerpo = code.empty()
        if traza == "t":
            cuerpo / ("""mc_traza('Reconocido el terminal "%s"\\n')""" % self.nombre)
        elif traza == "A":
            ( cuerpo
              / (u"""mc_traza('("%s"\\n')""" % repr(self.nombre.replace('"','""'))[2:-1])
              / u"""mc_traza(' "lexema: %s"\\n' % mc_al.actual.lexema.replace('"','""'))"""
              / u"""mc_traza(u' "línea: %d"\\n' % mc_al.actual.nlinea)"""
              / """mc_traza(')\\n')"""
            ) #'<- para el font-lock
        if not esPuro and not self.directo:
            n= self.nombre+_gestion_orden(orden, self.nombre)
            if orden[self.nombre]== 1 and pizda.nombre!= self.nombre:
                cuerpo / ("%s = %s = %s_ = mc_al.actual" % (self.nombre, n, self.nombre))
            else:
                cuerpo / ("%s = %s_ = mc_al.actual" % (n, self.nombre))
        cuerpo / "mc_al.avanza()"
        if traza=="t":
            cuerpo / u"""mc_traza(u'Leído el terminal "%s"\\n' % self.mc_al.actual)"""

        if garantizados and len(garantizados)==1 and self.nombre in garantizados:
            c = cuerpo
        else:
            c = ( code.sentence("if mc_al.actual.cat == u'%s':" % self.nombre)
                  // cuerpo
                  % "else:"
                  ).code() # Si no, tenemos un _CodeControl y los siguientes van mal
            if traza:
                c // ("""mc_traza('Error no es un "%s"\\n')""" % self.nombre)
            if not self.error:
                c // ("mc_error('%s', [u'%s'])" % (pizda, self.nombre))
            else:
                c // self.error
        return c
コード例 #5
0
ファイル: analizador.py プロジェクト: rdonate/MiniCalc
 def mc_analiza_tratEOF(self, tratEOF):
     mc_al = self.mc_al
     self.mc_reintento.append(True)
     mc_reintentar = self.mc_reintentar
     while self.mc_reintento[-1]:
         self.mc_reintento[-1] = False
         try:
             if not mc_al.actual.cat in [
                     u'codigo', 'errordos', 'mc_EOF', 'noterminal'
             ]:
                 mc_error('<tratEOF>',
                          [u'codigo', 'errordos', 'mc_EOF', 'noterminal'])
             c = None
             while mc_al.actual.cat == u'errordos':
                 errordos = errordos1 = errordos_ = mc_al.actual
                 mc_al.avanza()
                 if c is None: c = code.empty()
                 c.addBrother(errordos_.codigo)
             if not mc_al.actual.cat in [u'codigo', 'mc_EOF', 'noterminal']:
                 mc_error('<tratEOF>',
                          [u'codigo', 'errordos', 'mc_EOF', 'noterminal'])
             tratEOF.codigo = c
         except mc_error_sintaxis, (mc_nt, mc_t):
             errores.append(
                 mc_al.linea(),
                 u"Al código inicial no le sigue el comienzo de una regla ni un tratamiento de error. Voy a saltar entrada hasta que encuentre algo."
             )
             mc_al.sincroniza(mc_primeros["<Lineas>"] + ["errordos"],
                              mc_abandonar)
             if mc_al.actual.cat == "errordos":
                 mc_reintentar()
コード例 #6
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizado, traza, esPuro):
     c= code.empty()
     if traza=="t":
         c / u"mc_traza('Reconocida una cadena vacía\\n')"
     elif traza=="A":
         c / """mc_traza('("")\\n')"""
     return c
コード例 #7
0
def genera_excepciones():
    # Las excepciones y algunas funciones auxiliares:
    return (code.empty() / "class mc_error_sintaxis(Exception): pass" /
            "class mc_error_noEOF(Exception): pass" /
            "class mc_error_abandonar(Exception): pass" /
            "def mc_error(nt, esp):" // "raise mc_error_sintaxis, (nt, esp)" %
            "def mc_abandonar():" // "raise mc_error_abandonar")
コード例 #8
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro):
     """Genera la parte del código de esta pdcha.
         pizda: parte izquierda de la regla que se está tratando
         ordenT: diccionarios para controlar la numeración de terminales y
           no terminales.
         siguientesPadre: conjunto de terminales que son siguientes del padre de
           la parte derecha.
         garantizados: conjunto de terminales que pueden llegar a este punto.
           Son siempre aceptables. None si no se sabe.
         traza: formato de la traza ("A" arbol, "t" traza).
         esPuro: cierto si se está generando un analizador sintáctico puro."""
     return code.empty()
コード例 #9
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro):
     c=code.empty()
     g= garantizados
     if traza=="t":
         ( c
           / ("mc_traza('> Analizando %s\\n')" % self.regla())
           /  "mc_dentro_traza()")
     for i in self.l:
         c / i.genera_codigo_interno(pizda, orden, i.siguientes(), g, traza, esPuro)
         if not isinstance(i,Vacia):
             g= None
     if traza=="t":
         ( c
           / "mc_fuera_traza()"
           / ("mc_traza('< Fin de %s\\n')" % self.regla())
           )
     return c
コード例 #10
0
def genera_puro(gram, traza):
    c = code.empty()
    # El analizador sintáctico:
    (c / "class AnalizadorSintactico:" //
     "def __init__(self, entrada, entorno = None):" //
     "self.mc_al = AnalizadorLexico(entrada)" / "self.mc_al.avanza()" /
     "try:" // ("self.mc_analiza_%s()" % gram.inicial.nombre) /
     "if self.mc_al.actual.cat != 'mc_EOF':" // "raise mc_error_noEOF" % None %
     "except mc_error_sintaxis, (nt,esp):" // "self.mc_error = True" /
     "self.mc_lineaError = self.mc_al.actual.nlinea" / "self.mc_ntError = nt" /
     "self.mc_tError = self.mc_al.actual" / "self.mc_esperado = esp" %
     "except mc_error_noEOF:" // "self.mc_error = True" /
     "self.mc_lineaError = self.mc_al.actual.nlinea" /
     "self.mc_ntError = None" / "self.mc_tError = self.mc_al.actual" /
     "self.mc_esperado = ['mc_EOF']" % "else:" // "self.mc_error = False")
    # Código de los no terminales:
    for nt in gram.noterminales:
        c // nt.genera_codigo(traza, True)
    return c
コード例 #11
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro):
     c = code.empty()
     primeros= self.pd.primeros()
     if traza=="t":
         c / ("mc_traza('> Analizando %s\\n')" % self.regla())
     ( c
       / ("if %s:" % _test_set(primeros))
       //  self.pd.genera_codigo_interno(pizda, orden, siguientesPadre, primeros, traza, esPuro)
       )
     if garantizados == None or garantizados < siguientesPadre | primeros:
         celif = code.sentence("elif %s:" % _test_no_set(siguientesPadre))
         if traza:
             celif / u"mc_traza(u'Error, no podemos asumir que esté vacía.\\n')"
         celif / ("mc_error('%s', %s)" % (pizda, _set_strlista(primeros|siguientesPadre)))
     if traza=="t":
         ( c
           / "else:"
           //  u"mc_traza(u'Se supone que ha generado la cadena vacía\\n')"
           )
     return c
コード例 #12
0
def genera_sintactico(gram, traza, codificacion):
    c = code.empty()
    # La clase para los atributos:
    c / "class Atributos: pass"

    # Preparamos el tratamiento del error cuando hay entrada tras EOF
    if gram.noEOF:  # Si se trata el error noEOF
        tratEOF = code.sentence("mc_al = self.mc_al") / gram.noEOF
    else:
        tratEOF = (code.sentence(
            u"sys.stderr.write((u'Error no tratado en línea %%d:\\n' %% self.mc_al.actual.nlinea).encode('%s'))"
            % codificacion
        ) / "sys.stderr.write('He encontrado entrada donde esperaba ver el final del fichero\\n')"
                   / "sys.exit(1)")

    # El analizador sintáctico:
    (c / "class AnalizadorSintactico:" //
     "def __init__(self, entrada, entorno = None):" //
     "self.mc_entorno = entorno" / "self.mc_al = AnalizadorLexico(entrada)" /
     "self.mc_al.avanza()" / "self.mc_reintento = [True]" /
     "mc_reintentar = self.mc_reintentar" / "while self.mc_reintento[-1]:" //
     "self.mc_reintento[-1] = False" / ("self.%s = Atributos()"
                                        "" % gram.inicial.nombre) / "try:" //
     ("self.mc_analiza_%s(self.%s)"
      "" % (gram.inicial.nombre, gram.inicial.nombre)) /
     "if self.mc_al.actual.cat != 'mc_EOF':" // "raise mc_error_noEOF" % None %
     "except mc_error_sintaxis, (nt, esp):" //
     u"sys.stderr.write('Error no tratado en línea %d:\\n' % self.mc_al.actual.nlinea)"
     /
     (u"sys.stderr.write((u'Estaba analizando la expansión del no terminal %%s y he encontrado\\n el terminal %%s.\\n' %% (nt, self.mc_al.actual)).encode('%s'))"
      % codificacion) / "if len(esp)==1:" //
     (u"sys.stderr.write((u'Sólo valía un %%s.\\n' %% mc_pretty_cat(esp[0])).encode('%s'))"
      % codificacion) % "else:" //
     (u"sys.stderr.write((u'Tendría que haber sido uno de los siguientes: %%s.\\n' %% ','.join(map(mc_pretty_cat,esp))).encode('%s'))"
      % codificacion) % "sys.exit(1)" % "except mc_error_noEOF:" // tratEOF %
     "except mc_error_abandonar:" // "pass" % None % None %
     "def mc_reintentar(self):" // "self.mc_reintento[-1] = True")
    # Código de los no terminales:
    for nt in gram.noterminales:
        c // nt.genera_codigo(traza)
    return c
コード例 #13
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro):
     c = code.empty()
     if traza=="t":
         ( c
           / ("mc_traza('> Analizando %s\\n')" % self.regla())
           / "mc_dentro_traza()"
           )
     ( c
       / ("while %s:" % _test_set(self.pd.primeros()))
       //  self.pd.genera_codigo_interno(pizda, orden, siguientesPadre, self.pd.primeros(), traza, esPuro)
       )
     if traza=="t":
         ( c
           / "mc_fuera_traza()"
           / ( "mc_traza('< Fin de %s\\n')" % self.regla())
           )
     c / ("if not %s:" % _test_set(self.missiguientes))
     if traza:
         c // "mc_traza('Error, no encontramos ninguno de los siguientes\\n')"
     c // ("mc_error('%s',%s)" % (self.mi_nt, _set_strlista(self.misaceptables)))
     return c
コード例 #14
0
ファイル: automaton.py プロジェクト: rdonate/MiniCalc
    def toCode(self, name, isMethod=False):
        if isMethod:
            header = code.sentence("def %s(self, i, s):" % name)
        else:
            header = code.sentence("def %s(i, s):" % name)
        q = self.getInitial()
        if q is None:
            return (header // "return False").code()
        body = code.sentence("q = %s" % q)
        if self.isFinal(q):
            (body / ("uf = %d" % q) / "ufi = i")
        else:
            (body / "uf = None" / "ufi = None")

        loop = (code.sentence("while i <= len(s):") // "if i == len(s):" //
                "c = ''" % "else:" // "c = s[i]").code()
        body / loop

        stateActions = []
        for q in self.states:
            action = code.empty()
            if self.isFinal(q):
                action / ("uf = %s" % self.info[q]) / "ufi = i"
            if q in self.movements:
                intervals = []
                for (cClass, end) in self.movements[q]:
                    intervals += [(interval[0], interval[1],
                                   code.sentence("q = %d" % end))
                                  for interval in cClass.toIntervals()]
                intervals.sort()
                testChar = code.intervalSearch(intervals, "c", "break",
                                               lambda c: unichr(ord(c) - 1))
            else:
                testChar = "break"
            action / testChar
            stateActions.append(action)
        (loop // code.binarySearch(stateActions, "q") / "i += 1")
        body / "return (uf, ufi)"

        return header // body
コード例 #15
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizados, traza, esPuro ):
     cuerpo = code.empty()
     if traza=="t":
         ( cuerpo
           / ("mc_traza('> Analizando %s\\n')" % self.regla())
           / "mc_dentro_traza()"
           )
     # No podemos hacer caso de las garantías si hay tratamiento de error;
     # no sabemos dónde se puede haber sincronizado.
     if garantizados and (esPuro or not self.traterror):
         g= garantizados.copy()
     else:
         g= None
     el = ""
     for opcion in self.l:
         aceptables= opcion.primeros()
         if opcion.anulable():
             aceptables= aceptables|siguientesPadre
         if g!= None:
             r= aceptables.intersection(g)
         else:
             r= aceptables
         interno = opcion.genera_codigo_interno(pizda, orden, siguientesPadre, r, traza, esPuro)
         if r:
             if g== None or len(r)< len(g): # Caso normal: los aceptables son menos que los garantizados
                 ( cuerpo
                   / (el+"if %s:" % _test_set(r))
                   // interno
                   )
                 el="el"
             elif len(r)== len(g):
                 if el== "": # Esta alternativa se lo lleva todo y no hemos visto ninguna otra
                     cuerpo / interno
                 else: # Estamos en la última alternativa
                     ( cuerpo
                       / "else:"
                       // interno
                       )
         if g:
             g.difference_update(r)
     if g== None: # Puede que haya un error en la entrada
         cuerpo / "else:"
         if traza:
             cuerpo // "mc_traza('Error, no hay ninguna alternativa aceptable.\\n')"
         cuerpo // ("mc_error('%s', %s)" % (pizda, _set_strlista(self.misaceptables)))
     if traza=="t":
         ( cuerpo
           / "mc_fuera_traza()"
           /("mc_traza('< Fin de %s\\n')" % self.regla())
           )
     if self.traterror and not esPuro:
         c = ( code.sentence("self.mc_reintento.append(True)")
               /  "mc_reintentar= self.mc_reintentar"
               /  "while self.mc_reintento[-1]:"
               //   "self.mc_reintento[-1]= False"
               /   "try:"
               //     cuerpo
               %   "except mc_error_sintaxis, (mc_nt, mc_t):"
               //     self.traterror
             )
         c / "self.mc_reintento.pop()"
     else:
         c= cuerpo
     return c
コード例 #16
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
 def genera_codigo_interno(self, pizda, orden, siguientesPadre, garantizado, traza, esPuro):
     if esPuro:
         return code.empty()
     else:
         return self.cod
コード例 #17
0
def genera_analizador(gram, elexica, codusuario, traza, salida, codificacion,
                      analex, tipoAnalizador):
    c = code.empty()
    # Preámbulo
    (c / "#!/usr/bin/env python" / ("# -*- coding: %s -*-" % codificacion) /
     u"# Este código ha sido generado por metacomp, versión 3.0beta5" /
     "import sys")
    if traza == "t" or traza == "A":
        (c / "sangrado_traza = 0" / "def mc_traza(l):" //
         ("sys.stderr.write((sangrado_traza*' '+l).encode('%s'))" %
          codificacion) % "def mc_dentro_traza():" // "global sangrado_traza" /
         "sangrado_traza += 2" % "def mc_fuera_traza():" //
         "global sangrado_traza" / "sangrado_traza -= 2")
    c / genera_excepciones()
    # Analizador léxico:
    if not analex:
        c / genera_analex(elexica, codificacion)
    else:
        c / ("from %s import AnalizadorLexico" % analex)

    # El código del usuario:
    c / u"# Código de usuario"
    c / codusuario

    if tipoAnalizador == "normal":
        # Los primeros y siguientes:
        c / diccionarios(gram)

        # El sintáctico:
        c / genera_sintactico(gram, traza, codificacion)

        # La llamada a main:
        (c / "if __name__ == '__main__':" // "try:" // "mc_main = main" %
         "except NameError:" // "def mc_main():" //
         "AnalizadorSintactico(sys.stdin)" % None % "mc_main()")
    elif tipoAnalizador == "puro":
        # Los primeros y siguientes:
        c / diccionarios(gram)

        # El sintáctico:
        c / genera_puro(gram, traza)

        # La llamada a main:
        (c / "if __name__=='__main__':" // "try:" // "mc_main = main" %
         "except NameError:" // "def mc_main():" //
         "A = AnalizadorSintactico(sys.stdin)" / "if not A.mc_error:" //
         u"print 'La entrada no tiene errores sintácticos.'" % "else:" //
         u"print 'Hay un error de sintaxis en la línea %d, provocado por el componente\\n\\t%s' % ( A.mc_lineaError, A.mc_tError)"
         / "if A.mc_ntError != None:" //
         "print 'y detectado al intentar analizar en no terminal %s.' % A.mc_ntError"
         % "else:" //
         "print 'y detectado cuando se esperaba el fin de la entrada.'" %
         None % None % None % "mc_main()")
    elif tipoAnalizador == "lexico":  # Si sólo generamos el léxico:
        (c / "if __name__=='__main__':" // "try:" // "mc_main = main" %
         "except NameError:" // "def mc_main():" //
         "A = AnalizadorLexico(sys.stdin)" / "comp = A.avanza()" /
         "while comp.cat != 'mc_EOF':" // "print A.actual" /
         "comp = A.avanza()" % None % None % "mc_main()")
    else:
        sys.stderr.write("Error interno.\n")
        sys.stderr.write(
            "Se ha especificado un tipo de analizador distinto de normal, puro y léxico.\n"
        )
        sys.exit(1)
    salida.write(unicode(c).encode(codificacion))
コード例 #18
0
def genera_analex(esplex, codificacion):
    """Genera un analizador léxico a partir de la especificación léxica. Esta es una
  lista de tuplas con categoría, función de tratamiento y expresión regular."""

    c = code.empty()

    #
    # Función auxiliar para escribir las categorías inmediatas
    #

    (c / "def mc_pretty_cat(cat):" // "if cat is None or cat[0]!='!':" //
     "return cat" % "else:" // "return '\"%s\"' % cat[1:]")

    #
    # Clase ComponenteLexico
    #
    (c / "class ComponenteLexico:" //
     "def __init__(self, cat, lexema, nlinea):" // "self.cat = cat" /
     "self.lexema = lexema" / "self.nlinea = nlinea" % "def __str__(self):" //
     "s = ['%s: %s' % (repr(k), repr(v)) for k, v in self.__dict__.items() if k != 'cat']"
     / "if s:" //
     "return '%s (%s)' % (mc_pretty_cat(self.cat), ', '.join(s))" % "else:" //
     "return mc_pretty_cat(self.cat)")
    #
    # Clase AnalizadorLexico:
    #
    (c / "class AnalizadorLexico:" // "def __init__(self, entrada):" //
     "if isinstance(entrada, basestring):" //
     "if isinstance(entrada, unicode):" // "self.l = entrada" % "else:" //
     ("self.l = entrada.decode('%s')" % codificacion) % None % "else:" //
     "try:" // "ll = entrada.readlines()" % "except:" //
     u"sys.stderr.write('Error: no he podido leer la entrada ¿es un fichero?\\n')"
     / "sys.exit(1)" % ("ll = [ l.decode('%s') for l in ll]" % codificacion) /
     "self.l = ''.join(ll)" / "entrada.close()" % "self.nlactual = 1" /
     "self.actual = ComponenteLexico(None, None, 0)" / "try:" //
     "self.error_lexico = error_lexico" % "except NameError:" //
     "self.error_lexico = self._error_lexico" % "self.i = 0")

    # Tratamiento por defecto del error léxico:
    (c // "def _error_lexico(self, linea_error, cars):" //
     (u"sys.stderr.write((u'Error léxico no tratado en línea %%d: No esperaba %%s.\\n' %% (linea_error, repr(cars))).encode('%s'))"
      % codificacion) / "sys.exit(1)")
    # Método línea:
    (c // "def linea(self):" // "return self.actual.nlinea")
    # Método sincroniza:
    (c // "def sincroniza(self, sincr, enEOF = mc_abandonar):" //
     "while self.actual.cat not in sincr and self.actual.cat != 'mc_EOF':" //
     "self.avanza()" %
     "if self.actual.cat =='mc_EOF' and not 'mc_EOF' in sincr:" // "enEOF()")

    # Método avanza:

    (c // "def avanza(self):" // "if self.i >= len(self.l):" //
     "self.actual = ComponenteLexico('mc_EOF', '', self.nlactual)" /
     "return self.actual" % "carsError, lineaError = [], 0" / "while 1:" //
     "(info, ni) = self.analiza(self.i, self.l)" / "if not info is None:" //
     "nl = self.nlactual" / "if carsError:" //
     "self.error_lexico(lineaError, ''.join(carsError))" /
     "self.nlactual += carsError.count('\\n')" /
     "carsError, lineaError = [], 0" % "cat, ff = info" /
     "lexema = self.l[self.i:ni]" / "self.i = ni" /
     "self.nlactual += lexema.count('\\n')" /
     "componente = ComponenteLexico(cat, lexema, nl)" / "if ff:" //
     "ff(componente)" % "if not componente.cat is None:" //
     "self.actual = componente" / "return componente" % "continue" % "else:" //
     "if self.i >= len(self.l):" // "if carsError:" //
     "self.error_lexico(lineaError, ''.join(carsError))" /
     "self.nlactual += carsError.count('\\n')" %
     "self.actual = ComponenteLexico('mc_EOF', '', self.nlactual)" /
     "return self.actual" % "if lineaError == 0: lineaError = self.nlactual" /
     "carsError.append(self.l[self.i])" / "self.i += 1" % None %
     "return self.actual")

    allEr = OrNode([
        Concatenation(er, Category(CategoryInfo(n, cat, ff)))
        for n, (cat, ff, er) in enumerate(esplex)
    ])
    c // re2a.re2a(allEr).toCode("analiza", True)
    return c
コード例 #19
0
ファイル: analizador.py プロジェクト: rdonate/MiniCalc
 def mc_analiza_Elemental(self, Elemental):
     mc_al = self.mc_al
     if not mc_al.actual.cat in [
             u'abre', 'accion', 'errordos', 'noterminal', 'terminal'
     ]:
         mc_error('<Elemental>',
                  [u'abre', 'accion', 'errordos', 'noterminal', 'terminal'])
     if mc_al.actual.cat == u'noterminal':
         noterminal = noterminal1 = noterminal_ = mc_al.actual
         mc_al.avanza()
         Elemental.pd = T.noterminal(noterminal.id, noterminal.nlinea)
     elif mc_al.actual.cat in [u'errordos', 'terminal']:
         error = None
         while mc_al.actual.cat == u'errordos':
             errordos = errordos1 = errordos_ = mc_al.actual
             mc_al.avanza()
             if error == None: error = code.empty()
             error.addBrother(errordos.codigo)
         if not mc_al.actual.cat == u'terminal':
             mc_error('<Elemental>', [u'errordos', 'terminal'])
         if mc_al.actual.cat == u'terminal':
             terminal = terminal1 = terminal_ = mc_al.actual
             mc_al.avanza()
         else:
             mc_error('<Elemental>', [u'terminal'])
         global directos
         if terminal.directo and terminal.id not in directos:
             directos.update((terminal.id, ))
         Elemental.pd = Terminal(terminal.id, terminal.directo, error,
                                 terminal.nlinea)
     elif mc_al.actual.cat == u'accion':
         accion = accion1 = accion_ = mc_al.actual
         mc_al.avanza()
         Elemental.pd = Accion(accion.codigo, accion.nlinea)
     else:
         ParteDerecha = ParteDerecha1 = Atributos()
         abre = abre1 = abre_ = mc_al.actual
         mc_al.avanza()
         global enparentesis
         par = enparentesis
         enparentesis = True
         self.mc_analiza_ParteDerecha(ParteDerecha1)
         ParteDerecha_ = ParteDerecha1
         Elemental.pd = ParteDerecha.pd
         if mc_al.actual.cat == u'cierra':
             cierra = cierra1 = cierra_ = mc_al.actual
             mc_al.avanza()
         else:
             mc_error('<Elemental>', [u'cierra'])
         enparentesis = par
         if mc_al.actual.cat in [u'asterisco', 'cruz', 'interrogante']:
             if mc_al.actual.cat == u'asterisco':
                 asterisco = asterisco1 = asterisco_ = mc_al.actual
                 mc_al.avanza()
                 if ParteDerecha.pd:
                     Elemental.pd = Iteracion(ParteDerecha.pd, abre.nlinea)
             elif mc_al.actual.cat == u'cruz':
                 cruz = cruz1 = cruz_ = mc_al.actual
                 mc_al.avanza()
                 if ParteDerecha.pd:
                     Elemental.pd = Repeticion(ParteDerecha.pd, abre.nlinea)
             else:
                 interrogante = interrogante1 = interrogante_ = mc_al.actual
                 mc_al.avanza()
                 if ParteDerecha.pd:
                     Elemental.pd = Opcional(ParteDerecha.pd, abre.nlinea)
コード例 #20
0
    def avanza(self):
        if self.finfichero:
            self.actual = ComponenteLexico("mc_EOF", self.nlactual)
            return self.actual

        if self.esprimera:
            self.esprimera = 0
            return self.lee_especificacion_lexica()

        while True:
            c = self.nuevo_caracter()
            if c == "":  # Fin de fichero
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("mc_EOF", self.nlactual)
                return self.actual
            elif c == ' ' or c == '\t' or c == '\r':  # Nos cargamos el espacio en blanco
                pass
            elif c == '#':  # Comentario
                while c != '\n' and c != "":
                    c = self.nuevo_caracter()
                self.devuelve(c)
            elif c == '\n':  # Nueva línea
                self.nlfichero = self.nlfichero + 1
            elif c == '<':  # Posible no terminal
                id = u''
                self.nlactual = self.nlfichero
                while True:
                    c = self.nuevo_caracter()
                    if c in letters or c == "_":
                        id = id + c
                    elif c == '>':
                        self.actual = ComponenteLexico("noterminal",
                                                       self.nlactual)
                        self.actual.id = id
                        if iskeyword(id):
                            errores.errores.append(
                                self.nlactual,
                                "El no terminal %s coincide con una palabra reservada de Python."
                                % id)
                        if id[-1] == "_":
                            errores.errores.append(
                                self.nlactual,
                                "Un no terminal no puede terminar en _")
                        return self.actual
                    else:
                        self.devuelve(c)
                        if id == '':
                            errores.errores.append(
                                self.nlactual,
                                u"El carácter < sólo puede utilizarse para no terminales."
                            )
                            break
                        errores.errores.append(
                            self.nlactual,
                            u"El no terminal %s no tiene el símbolo > al final"
                            % id)
                        self.actual = ComponenteLexico("noterminal",
                                                       self.nlactual)
                        self.actual.id = id
                        return self.actual
            elif c in letters or c == "_":  # Terminal
                lexema = c
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("terminal", self.nlactual)
                self.actual.directo = False
                while True:
                    c = self.nuevo_caracter()
                    if c in letters or c == "_":
                        lexema = lexema + c
                    else:
                        self.devuelve(c)
                        if lexema == "error":
                            self.actual = ComponenteLexico(
                                "tokenerror", self.nlactual)
                        elif iskeyword(lexema):
                            errores.errores.append(
                                self.nlactual,
                                u"Vaya, el identificador %s ya está reservado por Python."
                                % lexema)
                        if lexema[-1] == "_":
                            errores.errores.append(
                                self.nlactual,
                                u"Un identificador de categoría léxica no puede terminar en _"
                            )
                        self.actual.id = lexema
                        return self.actual
            elif c == '"':  # Terminal directo
                lexema = "!"
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("terminal", self.nlactual)
                self.actual.directo = True
                while True:
                    c = self.nuevo_caracter()
                    if c == '"':
                        self.actual.id = lexema
                        return self.actual
                    elif c in [" ", "\t", "\n"]:
                        errores.errores.append(
                            self.nlactual,
                            'He encontrado un terminal directo no terminado, asumire que es "%s"'
                            % lexema[1:])
                        self.devuelve(c)
                        self.actual.id = lexema
                        return self.actual
                    lexema = lexema + c
            elif c == "@":  # Posible acción
                self.nlactual = self.nlfichero
                lexema = ""
                self.actual = ComponenteLexico("accion", self.nlactual)
                escape = False
                while True:
                    c = self.nuevo_caracter()
                    lexema = lexema + c
                    if c == "@":
                        if escape:
                            escape = False
                        else:
                            self.actual.codigo = code.sentence(lexema[:-1])
                            return self.actual
                    elif c == "\\":
                        escape = True
                    elif c == "" or c == "\n":
                        errores.errores.append(
                            self.nlactual,
                            u"La acción semántica que empieza en esta línea no está terminada."
                        )
                        self.actual.codigo = code.empty()
                        if c == "\n": self.devuelve(c)
                        return self.actual
                    else:
                        escape = False
            elif c == "$":  # Error dos
                self.nlactual = self.nlfichero
                lexema = ""
                self.actual = ComponenteLexico("errordos", self.nlactual)
                escape = False
                while 1:
                    c = self.nuevo_caracter_avanzando()
                    lexema = lexema + c
                    if c == "$":
                        if escape:
                            escape = False
                        else:
                            self.actual.codigo = code.sentence(lexema[:-1])
                            return self.actual
                    elif c == "\\":
                        escape = True
                    elif c == "" or c == "\n":
                        errores.errores.append(
                            self.nlactual,
                            u"El tratamiento de error de tipo dos de esta línea no está terminado."
                        )
                        self.actual.codigo = code.empty()
                        if c == "\n": self.devuelve(c)
                        return self.actual
                    else:
                        escape = False
            elif c == "%":  # Código
                self.nlactual = self.nlfichero
                lexema = ""
                self.actual = ComponenteLexico("codigo", self.nlactual)
                finlinea = False
                while True:
                    c = self.nuevo_caracter_avanzando()
                    lexema = lexema + c
                    if (c == "%" and finlinea) or c == "":
                        if c == "%":
                            lexema = lexema[:-1]  # Quitamos el último %
                        codigo = [code.sentence(s) for s in lexema.split("\n")]
                        codigo = reduce(lambda c, s: c.addBrother(s), codigo)
                        self.actual.cod = codigo
                        return self.actual
                    finlinea = c == "\n"
            elif c == "-":  # Posible flecha
                c = self.nuevo_caracter()
                if c == ">":
                    self.nlactual = self.nlfichero
                    self.actual = ComponenteLexico("flecha", self.nlactual)
                    return self.actual
                else:
                    errores.errores.append(
                        self.nlfichero,
                        u"He encontrado un triste y solitario guión.")
                    self.devuelve(c)
            elif c == ";":  # Punto y coma
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("pyc", self.nlactual)
                return self.actual
            elif c == "*":  # Asterisco
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("asterisco", self.nlactual)
                return self.actual
            elif c == "+":  # Cruz
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("cruz", self.nlactual)
                return self.actual
            elif c == "?":  # Interrogante
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("interrogante", self.nlactual)
                return self.actual
            elif c == "|":  # Barra
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("barra", self.nlactual)
                return self.actual
            elif c == "(":  # Abre paréntesis
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("abre", self.nlactual)
                return self.actual
            elif c == ")":  # Cierra paréntesis
                self.nlactual = self.nlfichero
                self.actual = ComponenteLexico("cierra", self.nlactual)
                return self.actual
            else:
                errores.errores.append(
                    self.nlfichero,
                    u"He encontrado el carácter %s y no sé que hacer con él." %
                    c)
コード例 #21
0
ファイル: gramatica.py プロジェクト: rdonate/MiniCalc
    def genera_codigo(self, traza, esPuro= False):
        """ Genera el código de la regla.
            traza: genera código para escribir la traza (arbol: "A" o traza: "t").
            esPuro: si cierto genera un analizador puro (sin acciones semánticas).
        """
        if esPuro:
            c = code.sentence("def mc_analiza_%s(self):" % self.nombre)
        else:
            c = code.sentence("def mc_analiza_%s(self, %s):" % (self.nombre,self.nombre))
        # La traza:
        if traza=="t":
            ( c
              // (u"mc_traza('> %s %%s\\n' %% self.mc_al.actual)" % self)
              /  "mc_dentro_traza()"
              )
        elif traza=="A":
            ( c
              // (u"mc_traza(u'(\"%s\" \"línea: %%d\"\\n' %% self.mc_al.actual.nlinea)" % self)
              /  "mc_dentro_traza()"
              )
        # Hacemos accesible el analizador léxico:
        c // "mc_al = self.mc_al"

        # Cuerpo del analizador
        cuerpo = code.sentence("if not %s:" % _test_set(self.misaceptables))
        if traza:
          cuerpo // (u'mc_traza(u"Error, no se encuentra ningún elemento aceptable para %s.\\n")' % self)
        cuerpo // ("mc_error('%s', %s)" % (self, _set_strlista(self.misaceptables)))

        cadif= "if"
        for n, regla in enumerate(self.reglasizda):
            aceptables= regla.dcha.primeros()
            if regla.dcha.anulable():
                aceptables|= self.siguientes()
            # Cuerpo de la regla
            cuerpoRegla = code.empty()
            if traza=="t": # Si hay traza
                cuerpoRegla / ("mc_traza('Aplico regla: '+" + `regla.regla()` + "+'\\n')")
            if not esPuro:
                # Generamos los atributos y los alias:
                orden= {}
                for s in regla.simbolos:
                    _gestion_orden(orden, s.nombre)
                    if isinstance(s, NoTerminal):
                        nto= s.nombre+`orden[s.nombre]`
                        if orden[s.nombre]== 1 and s!= self:
                            cuerpoRegla / ("%s = %s = Atributos()" % (s.nombre, nto))
                        else:
                            cuerpoRegla / ("%s = Atributos()" % nto)
            # Generamos el código de la regla:
            cuerpoRegla / regla.dcha.genera_codigo_interno(self, {}, self.siguientes(), aceptables, traza, esPuro)

            if len(self.reglasizda)> 1: # Si hay más de una posibilidad, hay que poner una guarda
                if n == len(self.reglasizda)-1:
                    cuerpo / "else:"
                else:
                    cuerpo / (cadif+ " %s:" % _test_set(aceptables))
                cadif="elif"
                cuerpo // cuerpoRegla
            else:
                cuerpo / cuerpoRegla # No sangramos si sólo hay una posibilidad

        # Más traza, para avisar de que nos vamos
        if traza=="t":
            ( cuerpo
              /  "mc_fuera_traza()"
              /  (u"mc_traza('< %s\\n')" % self)
              )
        elif traza=="A":
            ( cuerpo
              /  "mc_fuera_traza()"
              /  "mc_traza(')\\n')"
              )

        # Comprobamos el tratamiento de errores:
        if self.traterror and not esPuro:
            ( c
              // "self.mc_reintento.append(True)"
              /  "mc_reintentar= self.mc_reintentar"
              /  "while self.mc_reintento[-1]:"
              //   "self.mc_reintento[-1]= False"
              /    "try:"
              //      cuerpo
              %    "except mc_error_sintaxis, (mc_nt, mc_t):"
              //      self.traterror
              % None % "self.mc_reintento.pop()"
              )
        else:
            c // cuerpo
        return c