Hola, de nuevo yo!
Bueno el compilador que estoy desarrollando es para el lenguaje E ( es un trabajo escolar).
Este es un ejemplo de lo que debo hacer (se que es muy largo pero es la unica manera que que quede mas claro), tengo la regla EBNF, pido tokens del archivo y comparo para ver si la sintaxis es correcta o no.
EBNF:
Program::= "main" "program" "(" ")" "begin" "end"
Entrada:
1 | main
2 | begin
3 |
4 | end
Tomando en cuenta esta entrada, los errores serian (sin recuperacion de errores):
Error Semántico en la línea 2, se esperaba "program" y se encontró "begin".
Error Semántico en la línea 4, se esperaba "(" y se encontró "end".
Error Semántico en la línea 4, se esperaba ")" y se encontró EOF.
Error Semántico en la línea 4, se esperaba "begin" y se encontró EOF.
Error Semántico en la línea 4, se esperaba "end" y se encontró EOF.
Esto debido a que cada que se compara un lexema en la regla con un lexema leido, si hay o no correspondecia, se lee el siguiente lexema EN LA REGLA y se lee el siguiente lexema DEL ARCHIVO (provocando de esta manera, errores en cascada; en el ejemplo anterior, los dos últimos).
Como comentaba la recuperacion de errores es tres token adelante y uno hacia atras.
Con la recuperación a nivel de frase con tres tokens (o lexemas) hacia adelante (sin el que es hacia atras), marcaría lo siguiente:
Error Semántico en la línea 2, se esperaba "program" y se encontró "begin".
Error Semántico en la línea 2, se esperaba "(" y se encontró "begin".
Error Semántico en la línea 2, se esperaba ")" y se encontró "begin".
Error Semántico en la línea 4, se esperaba "begin" y se encontró "end".
Ahora ya no marca tantos errores en cascada (solo uno, el último), ya que comparamos el lexema DE LA REGLA (primer lexema) contra el lexema leído DEL ARCHIVO (en este caso "program" de la regla contra "begin" del archivo), si NO hay correspondencia, marcamos el error y avanzamos al siguiente lexema DE LA REGLA (segundo lexema), para comparar con EL MISMO lexema que ya teníamos leido del archivo (ahora sería "(" de la regla contra "begin" del archivo) y si no vuelve a haber correspondencia, marcamos el error y avanzamos nuevamente EN LA REGLA (tercer lexema) y lo comparamos contra EL MISMO lexema que ya teníamos leído (es decir el ")" de la regla contra el "begin" del archivo) y si no hubo correspondencia una vez más marcamos el error y avanzamos al siguiente lexema DE LA REGLA (que se convertirá en el primer lexema) pero TAMBIÉN avanzamos al siguiente lexema DEL ARCHIVO (lo que nos quedaría como "begin" para LA REGLA y "end" para el lexema leído del archivo) y al buscar correspondencia no la habrá y se marcará el error (que es un error falso, pero aquí no lo podemos corregir y así sería correcto), avanzamos el lexema EN LA REGLA (segundo lexema) y ya se encuentra correspondencia con el lexema que teníamos leído y ya se recupera (para este ejemplo es "end" en la regla y en el lexema leído del archivo).
Lo que hacemos con la busqueda hacia atras es lo siguiente: avanzamos en la regla un lexema y leemos otro lexema del archivo cuando no hubieron las tres correspondencias (en el ejemplo anterior, nos quedaría "begin" en la regla y "end" en el lexema leído del archivo) pero ANTES de marcar el error por no haber correspondencia, REGRESAMOS al lexema anterior de los que estámos leyendo DEL ARCHIVO (es por eso que algunos de ustedes van guardando estos lexemas en alguna estructura para su posible futura comparación) para compararlo con el lexema ACTUAL DE LA REGLA (en este caso, al buscar el lexema (o token) hacia atras DEL ARCHIVO nos queda "begin" contra el lexema que tenemos actualmente en la regla, en este caso también "begin" por lo que ya no marcaría ningún error al haber correspondencía, por lo que ya podemos avanzar de token (o lexema) en la regla Y TAMBIÉN en el archivo para seguir con las revisiones posteriores).
Los errores que se marcarían a nivel de frase incluyendo la busqueda hacia atras serían:
Error Semántico en la línea 2, se esperaba "program" y se encontró "begin".
Error Semántico en la línea 2, se esperaba "(" y se encontró "begin".
Error Semántico en la línea 2, se esperaba ")" y se encontró "begin".
Lo cual elimina ya los errores en cascada.
Bueno la verdad no se como comenzar a implementarlo, espero me puedan dar una idea, yo pensaba hacer una funcion pero si creo que seria muy complicado, y pues implementarlo para cada regla seria demasiado repetitivo, no quiero que me hagan el trabajo solo que necesito otras opiniones.
Muchas gracias por su tiempo!
Adjunto el archivo que contiene toda la gramatica del lenguaje