Principalmente uso swi-prolog así que la mayor parte de lo que digo estará relacionado con swi-prolog. Sin embargo, otras implementaciones de prólogo pueden tener predicados/bibliotecas similares (tal vez con un nombre un poco diferente) por lo que puede buscar en sus manuales y encontrarlos. Además, estoy escribiendo un compilador, no un intérprete, en prólogo, así que tal vez algunas partes no estén tan relacionadas con el intérprete.
SWI-Prolog's documentation site es realmente bueno para encontrar cosas: use el cuadro de búsqueda para buscar cualquier predicado o hacer una búsqueda típica. Hay una gran cantidad de bibliotecas, pero es posible que desee implementar algunas cosas para ganar experiencia. Podrías terminar inventando la rueda, pero sería útil.
El libro "The Art of Prolog" (Sterling, Shapiro) tiene un capítulo dedicado a construir un compilador en prolog (y también es un buen libro para prólogos).
Quizás haya algunas herramientas equivalentes a lex/bison para prolog; Realmente nunca busqué.
Imho, el lexer es bastante fácil en el prólogo simple; naturalmente, se basará en gran medida en la coincidencia de patrones.
Para el analizador, sugiero usar DCG: gramáticas de cláusulas definidas: swi-prolog doc, google para obtener más detalles.
El problema es que tendrá que analizar todo el archivo (o al menos no he encontrado la manera de hacerlo de otra manera). Por cierto, el lexer también podría hacerse con los DCG, pero no creo que sea realmente mejor.
Si elige tener un código intermedio, un árbol de sintaxis abstracto es fácil de generar desde el analizador (también podría evaluar muchas cosas durante el análisis).
Acerca de las comprobaciones semánticas: en mi compilador para un lenguaje de juguete, realizo la mayoría de las comprobaciones semánticas (llamadas relacionadas con el alcance, funciones) durante el análisis sintáctico y el resto en un paso separado. Es un desordenado
otras cosas útiles bits: Asegúrate de hacer valer/1, las variables globales, meta predicates (maplist/[2-6]).
prólogo no es puro y es posible que el código sea demasiado imperativo al abusar de ellos (y entonces usted podría tener algunos efectos secundarios muy desagradables)
Para la tabla de símbolos (si la necesita) puede usar assert/1 para agregar predicados: swi-prolog usa tablas dinámicas para predicados dinámicos. advertencia: los predicados dinámicos son más lentos que los estáticos, por lo tanto, cuando complete la tabla y no haga ningún cambio, use compile_predicates/1 para que sean estáticos. Por ejemplo, cuando termino de analizar mi ST está listo, así que lo compilo. Otra solución para el ST es usar association lists. se implementan con árboles AVL, por lo que el costo es O (log (N)).
¿Desea crear un lenguaje en el que implemente el tiempo de ejecución mediante un código de bytes, o aspira a un enfoque de metainterpretadores? –
@Countably Infinite, estaba buscando un enfoque metainterpreter.La alternativa que has mencionado parece demasiado dada mi falta de experiencia. – arkate