proceso compilar compilacion como c compiler-construction programming-languages

compilacion - como compilar en c++



Comenzando un simple(¿el más simple quizás?) Compilador de C? (12)

Me encontré con esto: escribir un compilador usando Turbo Pascal

Tengo curiosidad por saber si hay algún tutorial o referencia que explique cómo crear un compilador de C simple. Quiero decir, es suficiente si me lleva al nivel de hacerlo entender operaciones aritméticas. Me puse muy curioso después de leer este artículo de Ken Thompson . La idea de escribir algo que se entiende a sí misma parece emocionante.

¿Por qué planteé esta pregunta en lugar de preguntarle a Google? Probé con Google y el de Pascal fue el primer enlace. El resto no parecía relevante y se agregó a eso ... No soy un especialista en CS (así que todavía necesito aprender qué hacen todas esas herramientas como yacc) y quiero aprender esto haciendo y espero que las personas con más experiencia sean Siempre mejor en estas cosas que Google. Quiero leer un artículo escrito con el mismo espíritu que el que mencioné anteriormente, pero que destaca al menos las fases de arranque de compilar un simple compilador de C.

Además, no sé la mejor manera de aprender. ¿Comienzo construyendo un compilador de C en C o en algún otro idioma? ¿Escribo un compilador de C o algún otro idioma? Siento que las preguntas como esta se responden mejor una vez que tengo una dirección para explorar. ¿Alguna sugerencia?

¿Alguna sugerencia?


¿Cómo puedo [comenzar a escribir] un simple compilador de C?

No hay nada simple en compilar C. El mejor compilador simple de C es lcc de Chris Fraser y David Hanson. Pasaron 10 años trabajando en el diseño para hacerlo lo más simple posible, al mismo tiempo que generaban códigos razonablemente buenos. Si tiene acceso a una biblioteca universitaria, debería poder obtener su libro.

¿Comienzo construyendo un compilador de C en C o en algún otro idioma?

Algún otro idioma. Una vez tuve que preguntarle a Hanson qué lecciones él y Fraser habían aprendido al pasar 10 años en el proyecto de la lcc. Lo principal que Hanson dijo fue

C es un lenguaje pésimo para escribir un compilador.

Es mejor que uses Haskell o algún dialecto de ML. Ambos lenguajes ofrecen funciones sobre tipos de datos algebraicos, lo cual es una combinación perfecta para los problemas que enfrenta el escritor de compiladores. Si todavía quieres seguir con C, podrías comenzar con CIL George Necula, que es una gran parte de un compilador de C escrito en ML.

Quiero leer un artículo escrito con el mismo espíritu que el que mencioné anteriormente, pero que destaca al menos las fases de arranque ...

No encontrarás otro artículo como el de Ken. Pero Andrew Appel ha escrito un buen artículo llamado Axiomatic Bootstrapping: Una guía para los piratas informáticos del compilador. No pude encontrar una versión gratuita, pero muchas personas tienen acceso a la Biblioteca digital de ACM.

¿Alguna sugerencia?

Si quieres escribir un compilador,

  • Use Haskell o ML como su lenguaje de implementación.

  • Para su primer compilador, elija un lenguaje muy simple como Oberon o como P0 del libro Algorithms + Data Structures = Programs de Niklaus Wirth. Wirth es famoso por diseñar lenguajes que son fáciles de compilar.

Puede escribir un compilador de C para su segundo compilador.


En el entorno de programación de Unix , Kernighan y Pike realizan 5 iteraciones para hacer que una calculadora trabaje desde un simple análisis léxico basado en C y una ejecución inmediata hasta el análisis yacc / lex y la generación de código para una máquina abstracta. Debido a que escriben tan maravillosamente, no puedo sugerir una introducción más fluida. Ciertamente es más pequeño que C, pero es probable que sea una ventaja.


Esta es mi opinión (y conjetura) que será difícil escribir un compilador sin entender las estructuras de datos que normalmente se cubren en las clases de Informática de pregrado (post secundaria). Esto no significa que no pueda, pero necesitará conocer las estructuras de datos esenciales, como listas vinculadas y árboles.

En lugar de escribir un compilador de lenguaje C completo o que cumpla con los estándares (al menos al principio), sugiero que se limite a un subconjunto básico del lenguaje, como operadores comunes, soporte entero único y funciones y punteros básicos. Un ejemplo clásico de esto fue el Small-C Ron Cain, popularizado por una serie de artículos escritos en el Dr. Dobbs Journal en I believe the 1980s. Publican un CD con el libro descatalogado de James Hendrix, A Small-C Compiler .

Lo que sugeriría es seguir el tutorial de Crenshaw, pero escribirlo para un compilador de lenguaje tipo C, y cualquier objetivo de CPU (Crenshaw se dirige a la CPU Motorola 68000) que desea apuntar. Para hacer esto, deberá conocer el ensamblaje básico del objetivo en el que desea ejecutar los programas compilados. Esto podría incluir un emulador para un 68000, o MIPS que son posiblemente conjuntos de instrucciones de ensamblaje más agradables que el venerable conjunto de instrucciones CISC del Intel x86 (16/32 bits).

Hay muchos libros potenciales que pueden usarse como puntos de partida para aprender la teoría y compilación del compilador / traductor. Lea las preguntas frecuentes de comp.compilers y las reseñas en varios vendedores de libros en línea. La mayoría de los libros introductorios se escriben como libros de texto para las clases de Ciencias de la Computación en el segundo y tercer grado, por lo que pueden ser de lectura lenta sin conocimientos previos de CS. Un libro anterior que podría ser más introductorio, pero más fácil de leer que " The Dragon Book " es Introducción a la construcción del compilador de Thomas Parsons. Es más antiguo, por lo que debería poder encontrar una copia usada de su elección de vendedores de libros en línea a un precio razonable.

Así que yo diría, intente comenzar con el tutorial Let''s Build a Compiler de Jack Crenshaw, escriba el suyo, siga sus ejemplos como guía y construya los conceptos básicos de un compilador simple . Una vez que tenga ese trabajo, puede decidir mejor dónde desea tomarlo desde ese punto.

Adicional:

En lo que respecta al proceso de arranque. Debido a que existen compiladores de C disponibles de forma gratuita, no necesita preocuparse por el arranque. Escriba su compilador con herramientas existentes separadas (GCC, Visual C ++ Express, Mingw / djgpp, tcc), y puede preocuparse por la compilación automática de su proyecto en una etapa posterior. Me sorprendió esta parte de la pregunta hasta que me di cuenta de que se te hizo la idea de escribir tu propio compilador leyendo el discurso del premio ACM Turing de Ken Thomas, Reflections on Trusting Trust , que entra en el proceso de arranque del compilador. Es un tema avanzado moderado, y también es simplemente una gran molestia. Incluso busco arrancar el compilador GCC C en sistemas Unix más antiguos (OSF digital / 1 en el Alpha de 64 bits) que incluye un compilador de C, un proceso lento y lento, propenso a errores.

La otra pregunta fue sobre qué hace una herramienta de compilación como Yacc. Yacc (Yet Another Compiler Compiler o Bison de GNU) es una herramienta diseñada para facilitar la escritura de un compilador (o traductor). Basado en la gramática formal del idioma de destino que ingresa a yacc, genera un analizador sintáctico , que es una parte del diseño general de un compilador. Luego está Lex (o flex de GNU) que solía generar un analizador léxico o escáner, que a menudo se usa en combinación con el analizador generado por yacc para formar el esqueleto del front-end de un compilador. Estas herramientas hacen que el escritor sea más accesible que escribir un analizador léxico y un analizador. El tutorial de Crenshaw no utiliza estas herramientas, y tampoco es necesario, muchos escritores de compiladores no siempre las usan. Por supuesto, Crenshaw admite que el analizador del tutorial es bastante básico.

El tutorial de Crenshaw también omite generar un AST (árbol de sintaxis abstracta), lo que simplifica pero también limita el compilador del tutorial. Carece de la mayoría, si no de todas, la optimización, y está muy ligada al lenguaje de programación específico y al lenguaje ensamblador particular emitido por el "back-end" del compilador. Normalmente, el AST es una pieza intermedia donde se puede realizar una optimización, y sirve para eliminar el diseño del front-end y back-end del compilador. Para un principiante sin conocimientos de Informática, sugiero que no te preocupes por no tener un AST para tu primer compilador (o al menos la primera versión del mismo). Creo que mantenerlo pequeño y simple te ayudará a terminar de escribir un compilador, en su primera versión, y puedes decidir a partir de ahí cómo quieres proceder.


No recomendaría comenzar con C como el lenguaje para implementar, ni con ninguna de las herramientas generador de compilador o generador de analizador. C es un lenguaje muy complicado, y probablemente sea una mejor idea inventar un idioma propio. Puede ser un poco parecido a un C (por ejemplo, usar conjuntos rizados si desea indicar el cuerpo de la función, usar los mismos nombres de tipo, para que no tenga que recordar cómo lo llamó todo).

Las herramientas para hacer compiladores y analizadores son geniales, pero tienen el problema de ser realmente una notación abreviada. Si no sabe cómo crear un compilador a mano, la abreviatura parecerá críptica, innecesariamente restrictiva, etc. Por lo tanto, primero escriba su compilador simple y luego continúe desde allí. También le recomiendo que no comience a generar código de máquina real a menos que coma y respire ensamblador. Cree su propio intérprete de bytecode con una VM.

En cuanto a qué idioma debe usar para crear su primer compilador: realmente no importa, siempre y cuando el lenguaje esté bastante completo. Leerá texto de entrada, construirá estructuras de datos a partir de ellos y escribirá datos binarios. Entonces, si un lenguaje facilita esas cosas de alguna manera, ese es un punto a favor. Escoge un idioma que conozcas bien, para que puedas enfocarte en crear el compilador, no aprendiendo el idioma. Usualmente uso un lenguaje OO, lo que hace que el árbol de sintaxis sea más fácil de escribir, un lenguaje funcional probablemente también funcionaría si usted está familiarizado con eso.

He escrito mucho sobre los lenguajes de programación, por lo que puede encontrar publicaciones útiles aquí: http://orangejuiceliberationfront.com/category/language-design/

En particular, http://orangejuiceliberationfront.com/how-to-write-a-compiler/ es un iniciador sobre los detalles de analizar construcciones comunes y generar algo útil a partir de eso, así como http://orangejuiceliberationfront.com/generating-machine-code-at-runtime/ que habla sobre escupir realmente instrucciones de Intel que hacen algo.

Oh, con respecto al arranque de un compilador: probablemente no podrá hacer eso desde el principio. Hay una buena cantidad de trabajo involucrado en la creación de un compilador. Por lo tanto, no solo escribir un compilador de arranque implica escribir el compilador (en otro idioma), una vez que lo tenga, tendrá que escribir una segunda versión del compilador usando el mismo. Eso es el doble de trabajo, más la depuración necesaria en el nuevo compilador existente y el bootstrap hasta que todo funcione. Dicho esto, una vez que tienes un compilador en funcionamiento, es una buena forma de probar su integridad. OK, tal vez no el doble del trabajo, pero más trabajo. Preferiría los éxitos fáciles primero, y luego seguir de allí.

En cualquier caso, diviértete!


Por lo que vale, el Tiny C Compiler es un compilador de C bastante completo en un paquete fuente relativamente pequeño. Puede beneficiarse de estudiar esa fuente, ya que es probablemente mucho más fácil de entender que tratando de comprender toda la base de fuentes de GCC, por ejemplo.


Puede interesarle el libro / curso Los elementos de los sistemas de computación: construir una computadora moderna a partir de los primeros principios .

Tenga en cuenta que esto no se trata de construir una "PC" de cosas que compró en newegg. Comienza con una descripción de los fundamentos lógicos booleanos y construye una computadora virtual desde los niveles más bajos de abstracción hasta niveles progresivamente más altos de abstracción. Los materiales del curso están en línea, y el libro en sí es bastante económico de Amazon.

En el curso, además de "construir el hardware", también implementará un ensamblador, máquina virtual, compilador y sistema operativo rudimentario, paso por paso. Creo que esto le daría suficientes antecedentes para ahondar en el tema con algunos de los recursos más comúnmente recomendados en las otras respuestas.


Si desea una experiencia alucinante que le enseñe a escribir compiladores que compilan, debe leer este documento desde 1964 .

META II un lenguaje de escritura compilador sintaxis de Val Schorre.

En 10 páginas, le dice cómo escribir compiladores, cómo escribir metacompiladores, proporciona un conjunto de instrucciones de metacompilador virtual y un compilador de muestra construido con el metacompilador.

Aprendí a escribir compiladores de este documento a finales de los años 60, y usé las ideas para construir lenguajes tipo C para varios miniordenadores y microprocesadores.

Si el documento es demasiado extenso por sí mismo (¡no lo es!) Hay un tutorial en línea que lo guiará a través de todo el trabajo.

Y si obtener el documento del enlace original es incómodo porque no eres miembro de ACM, encontrarás que el tutorial contiene todos los detalles de todos modos. (En mi humilde opinión, por el precio, el papel en sí vale la pena).

10 páginas!


También valdría la pena aprender sobre programación funcional. Los lenguajes funcionales son adecuados para escribir un compilador en y para . La clase de compiladores de intro de mi escuela contenía una introducción a los lenguajes funcionales y las tareas estaban todas en OCaml.

Es curioso que deberías preguntar esto hoy, ya que hace solo un par de días escribí un intérprete de cálculo lambda. Lambda calculus es el abuelo de todos los lenguajes funcionales. Tiene solo 200 líneas de longitud (en C ++, incluido el informe de errores, algunas impresiones bonitas, algunas Unicode) y tiene una estructura de dos fases, con un formato intermedio que podría usarse para generar código.

No solo es pequeño y se está desarrollando el enfoque más práctico para los compiladores, sino que también fomenta una buena práctica de organización modular.


Te aconsejo este tutorial:

Es un pequeño ejemplo de cómo implementar un compilador de "lenguaje pequeño". El código fuente es muy pequeño y se explica paso a paso.

También está la biblioteca frontal de C para la biblioteca LLVM (Máquina virtual de bajo nivel que representa la estructura interna de un programa):


Un compilador consta de tres piezas:

  1. Un analizador
  2. Un árbol sintáctico abstracto (AST)
  3. Un generador de código

Hay muchos buenos generadores de analizadores que comienzan con gramáticas de lenguaje. Tal vez ANTLR sería un buen lugar para que comiences. Si quieres mantenerte en C roots, prueba lex / yacc o bison.

Hay gramáticas para C, pero creo que C en su totalidad es complejo. Haría bien en comenzar con un subconjunto del idioma y seguir subiendo.

Una vez que tiene un AST, lo usa para generar el código de máquina que ejecutará.

Es factible, pero no trivial.

También verificaría en Amazon los libros sobre cómo escribir compiladores. El Dragon Book es el clásico, pero hay otros más modernos disponibles.

ACTUALIZACIÓN: Ha habido preguntas similares sobre el desbordamiento de pila, como esta . Echa un vistazo a esos recursos también.


Un compilador es un proyecto muy grande, aunque supongo que no estaría de más intentarlo.

Sé de al menos un compilador de C escrito en Pascal, así que no es lo más loco que podrías hacer. Personalmente, elegiría un lenguaje más moderno para implementar mi proyecto de compilador C, tanto por la simplicidad (es fácil para los paquetes d / l para Python, Ruby, C, C ++ o Java) y porque se verá mejor en su currículum.

Sin embargo, para hacer un compilador como un proyecto para principiantes, tendrás que beber todo el kool-aid ágil .

Siempre tenga algo funcionando, incluso si no hace mucho de nada. Agregue cosas a su compilador solo en pequeños pasos. ("Comunicados frecuentes"). Elija un subconjunto del lenguaje que sea extremadamente pequeño e impleméntelo primero. (Solo soporte i = 0; al principio y amplíe las cosas desde allí).


Un compilador es un tema complejo que cubre aspectos de

  • Procesamiento de entrada que implica Lexing, Parsing
  • Crear un almacén de símbolos de cada variable utilizada, como un Árbol de sintaxis abstracta (AST)
  • Desde el árbol AST, transpone y construye un código binario de máquina basado en la sintaxis

Esto no es exhaustivo ya que es una vista de pájaro abstracta desde la cima de una montaña, se reduce a obtener la notación de sintaxis correcta y asegurar que las entradas mal formadas no la tomen, de hecho, un buen procesamiento de entrada nunca debería caerse. de rodillas, no importa cuán malformados, terribles, abusados ​​sean los casos de aportes que se le arrojen. Y, también para decidir y saber qué salida va a ser, está en código máquina, lo que implicaría tener que conocer las instrucciones del procesador íntimamente ... incluyendo el direccionamiento de memoria para variables y demás ...

Aquí hay algunos enlaces para que pueda comenzar:

  • Había un port de Jack Crenshaw de su código para C .... (recuerdo haberlo descargado hace meses ...)
  • Aquí hay un enlace a una pregunta similar here en SO.
  • Además, aquí hay otro pequeño tutorial de compilación para el compilador ensamblador de Basic a x86.
  • Compilador Tiny C
  • Hendrix''s Small C Compiler encontrado here .