Estoy escribiendo un analizador para un lenguaje de marcado que he creado (escrito en python, pero eso no es realmente relevante para esta pregunta; de hecho, si esto parece una mala idea, me encantaría una sugerencia para un mejor camino) .
Estoy leyendo sobre analizadores aquí: http://www.ferg.org/parsing/index.html , y estoy trabajando en escribir el lexer que debería, si lo entiendo correctamente, dividir el contenido en tokens. Lo que tengo problemas para entender es qué tipos de tokens debo usar o cómo crearlos. Por ejemplo, los tipos de tokens en el ejemplo al que me vinculé son:
- CUERDA
- IDENTIFICADOR
- NÚMERO
- Espacio en blanco
- COMENTARIO
- EOF
- Muchos símbolos como {y (cuentan como su propio tipo de token
El problema que tengo es que los tipos de tokens más generales me parecen un poco arbitrarios. Por ejemplo, por qué STRING es su propio tipo de token separado frente a IDENTIFICADOR. Una cadena se puede representar como STRING_START + (IDENTIFIER | WHITESPACE) + STRING_START.
Esto también puede tener que ver con las dificultades de mi idioma. Por ejemplo, las declaraciones de variables se escriben {var-name var value}
y se implementan con {var-name}
. Parece '{'
y '}'
debe ser sus propios tokens, pero son NOMBRE_VAR y VAR_VALUE tipos de tokens elegibles, o lo haría éstos ambos caen bajo IDENTIFICADOR? Además, VAR_VALUE puede contener espacios en blanco. El espacio en blanco después var-name
se usa para indicar el inicio del valor en la declaración ... cualquier otro espacio en blanco es parte del valor. ¿Este espacio en blanco se convierte en su propio token? El espacio en blanco solo tiene ese significado en este contexto. Además, {
puede no ser el comienzo de una declaración de variable ... depende del contexto (¡esa palabra está de nuevo!). {:
comienza una declaración de nombre y{
incluso se puede usar como parte de algún valor.
Mi lenguaje es similar a Python en que los bloques se crean con sangría. Estaba leyendo sobre cómo Python usa el lexer para crear tokens INDENT y DEDENT (que sirven más o menos como qué {
y }
harían en muchos otros idiomas). Python afirma estar libre de contexto, lo que significa para mí que al menos al lexer no debería importarle dónde está en la secuencia mientras crea tokens. ¿Cómo sabe el lexer de Python que está construyendo una ficha INDENT de una longitud específica sin conocer los caracteres anteriores (por ejemplo, que la línea anterior era una nueva línea, así que comience a crear los espacios para INDENT)? Pregunto porque necesito saber esto también.
Mi última pregunta es la más estúpida: ¿por qué es necesario un lexer? Me parece que el analizador podría ir personaje por personaje y descubrir dónde está y qué espera. ¿El lexer agrega el beneficio de la simplicidad?