tutorial smart remix español curso aprender antlr antlr4

antlr - smart - solidity español



ANTLR 4.5-La entrada ''x'' no coincide ''esperando'' x '' (1)

He estado empezando a usar ANTLR y he notado que es bastante inconstante con sus reglas de lexer. Un ejemplo extremadamente frustrante es el siguiente:

grammar output; test: FILEPATH NEWLINE TITLE ; FILEPATH: (''A''..''Z''|''a''..''z''|''0''..''9''|'':''|''//'|''/''|'' ''|''-''|''_''|''.'')+ ; NEWLINE: ''/r''? ''/n'' ; TITLE: (''A''..''Z''|''a''..''z''|'' '')+ ;

Esta gramática no coincidirá con algo como:

c: / test.txt
X

Curiosamente si cambio TITLE para que sea TITLE: ''x'' ; sigue fallando esta vez y muestra un mensaje de error que dice "entrada no coincidente ''x'' esperando ''x''", lo cual es muy confuso. Aún más extraño si sustituyo el uso de TITLE en test con FILEPATH todo funciona (aunque FILEPATH coincidirá más de lo que busco, así que en general no es una solución válida para mí).

Estoy muy confundido en cuanto a por qué ANTLR está cometiendo errores tan extraños y, de repente, funciona sin motivo aparente cuando baraja las cosas.


Esto parece ser un malentendido común de ANTLR :

Procesamiento de lenguaje en ANTLR:

El procesamiento del lenguaje se realiza en dos fases estrictamente separadas:

  • Lexing, es decir, particionar el texto en tokens
  • Análisis, es decir, la construcción de un árbol de análisis a partir de las fichas

Dado que el lexing debe preceder al análisis, hay una consecuencia: el lexer es independiente del analizador, el analizador no puede influir en el lexing .

Lexing

Lexing en ANTLR funciona de la siguiente manera:

  • Todas las reglas con primer carácter en mayúscula son reglas de lexer.
  • el lexer comienza al principio e intenta encontrar una regla que coincida mejor con la entrada actual
  • una mejor coincidencia es una coincidencia que tiene la longitud máxima , es decir, el token que resulta de agregar el siguiente carácter de entrada a la coincidencia de la longitud máxima no coincide con ninguna regla de lexer
  • Los tokens se generan a partir de partidos:
    • si una regla coincide con la longitud máxima, el token correspondiente se inserta en la secuencia del token
    • si varias reglas coinciden con la longitud máxima, el primer token definido en la gramática se empuja a la secuencia del token

Ejemplo: ¿Qué está mal con tu gramática?

Tu gramática tiene dos reglas que son críticas:

FILEPATH: (''A''..''Z''|''a''..''z''|''0''..''9''|'':''|''//'|''/''|'' ''|''-''|''_''|''.'')+ ; TITLE: (''A''..''Z''|''a''..''z''|'' '')+ ;

Cada coincidencia, que coincida con TITLE, también coincidirá con FILEPATH. Y FILEPATH se define antes de TITLE: por lo que cada token que espera que sea un título sería FILEPATH.

Hay dos pistas para eso:

  • mantenga las reglas de lexer disyuntadas (ninguna ficha debe coincidir con un superconjunto de otro).
  • Si sus fichas coinciden intencionalmente con las mismas cadenas, colóquelas en el orden correcto (en su caso, esto será suficiente).
  • Si necesita un lexer con parser, debe cambiar a otro generador de parser: PEG-Parsers o GLR-Parsers harán eso (pero, por supuesto, esto puede producir otros problemas).