9

Necesito escribir un lenguaje de programación que he querido escribir. ¿Cómo lo hacen los niños en estos días? He estado fuera del circuito por más de una década; ¿Lo estás haciendo de forma diferente ahora que en los días previos a Internet y previos a la ventanilla? Ya sabes, cuando los codificadores "reales" codificaban en C, usaban la línea de comando y discutían sobre qué caparazón era superior.¿Cómo crear un idioma en estos días?

Solo para aclarar, quiero decir, no ¿Cómo se diseña una lengua (que puedo averiguar con bastante facilidad), pero, ¿cómo construir el compilador y librerías estándar y así sucesivamente? ¿Qué herramientas usan los niños en estos días?

+8

Para que quede constancia, los "niños" todavía usan la línea de comandos y objetan sobre qué caparazón es superior. O lo hago al menos. C está muerto. Debo huir de la acaparamiento de los programadores C, ¡así que nos veremos! –

+0

¿Qué tipo de lenguaje, interpretado o compilado? –

+0

interpretado o compilado? Hmmm buena pregunta. Asumiré que hace una diferencia, por lo que voy a decir ambas cosas para estar seguro. – Mike

Respuesta

2

Estoy bastante seguro de que haces lo que siempre se ha hecho.

Escriba un código y muestre sus resultados al mundo.

En comparación con los tiempos antiguos, hay algunas herramientas para hacer su trabajo más fácil sin embargo. ¿Puedo sugerir ANTLR para analizar su gramática de lenguaje?

0

codificadores reales sigue siendo de código en C. Así que es un litte más nítida.
Hmmm ... ¿diseño del lenguaje? o escribiendo un compilador? Si quiere escribir un compilador, debería usar Flex + Bison. (Google)

+1

Si desea escribir un buen compilador, podrá hacer manualmente su propio recursivo -desde el analizador sintáctico, porque si se trata de un analizador de Bison moderadamente complejo, pronto se encontrará con problemas (si no consigue que el lenguaje funcione, entonces hacer que el compilador/intérprete informe los errores). –

+0

+1 por la forma en que se refirió a C# – RCIX

+0

@chris Sí, tal vez, pero solo para LISP (ASM, Scheme ...) Escribir manualmente un compilador completo es lo último que desea hacer ... solo por la complejidad involucrada. – aviraldg

2

No debe aceptar soluciones Wimpy como el uso de las últimas herramientas. Debe iniciar el lenguaje escribiendo un compilador mínimo en Visual Basic para Aplicaciones o un lenguaje similar, luego escriba todas las herramientas de compilación en su nuevo idioma y luego autocompíquelo utilizando solo el idioma en sí.

Además, ¿cuál es el nombre propuesto para el idioma?

Creo que recientemente no ha habido idiomas con letras MAYÚSCULAS como COBOL y FORTRAN, así que espero que lo llames MIKELANG con mayúsculas.

+1

BÁSICO? Escuché que alguien estaba haciendo una investigación en función de si los chimpancés que martilleaban un teclado eran más limpios que el código BASIC de nivel de producción. Adivina ... – aviraldg

+2

idea genial. ¡Había escogido "Complicidad" hace varios años pero me gusta la idea de un lenguaje ALLCAPS! MIKTRAN, MOBOL, MIKEBASIC, MALEVOLENT, MALT, MARKV, MINGLE, MING, UNILANG ... – Mike

0
No

una respuesta fácil, pero ..

Esencialmente desea definir un conjunto de reglas escritas en el texto (tokens) y algo más de analizador que comprueba estas reglas y los ensambla en fragmentos.

http://www.mactech.com/articles/mactech/Vol.16/16.07/UsingFlexandBison/

La gente puede pasar años en esto, el artículo anterior habla sobre el uso de dos herramientas (Flex y Bison), que se pueden utilizar para convertir texto en código que puede alimentar a un compilador.

2

Hablando como alguien que acaba de construir muy montaje simple como lenguaje e intérprete, comenzaría con .NET framework o similar. Nada puede superar la poderosa sintaxis de C# + el respaldo de toda la comunidad .NET cuando intenta escribir la mayoría de las cosas. A partir de aquí diseñé un formato de bytecode simple y una sintaxis de ensamblaje y procedí a escribir mi intérprete + ensamblador.

Como he dicho, era un muy lenguaje sencillo.

+0

¿sintaxis poderosa? do#? Me estás tomando el pelo. Pero el framework .net y la comunidad son agradables. –

7

Una consideración que hay de nuevo desde la época de tarjeta perforada es la existencia de máquinas virtuales ya abundantemente provistos de "bibliotecas estándar." Dirigirse a JVM o .NET CLR en lugar de al antiguo "jardín de paredes de lenguaje" le ahorra un montón de bootstrapping. Si está creando un lenguaje compilado, también puede encontrar que el código de bytes de Java o MSIL es un destino de compilación más fácil que el código de máquina (por supuesto, si está en esto por la diversión de crear un compilador de optimización estricto, entonces verá esto como un error en lugar de una característica).

En el lado negativo, las expresiones idiomáticas de JVM o CLR pueden no ser las que usted desea para su idioma. Por lo tanto, puede terminar creando "bibliotecas estándar" solo para proporcionar interfaces idiomáticas sobre la plataforma. (Un ejemplo es que todos los idiomas y su perro parecen proporcionar su propio método para escribir en la consola, en lugar de dejar que los usuarios llamen manualmente a System.out.println o Console.WriteLine). Sin embargo, permite un desarrollo incremental de lo idiomático. bibliotecas, y significa que las bibliotecas más oscuras para las cuales usted nunca se acostumbra a construir interfaces idiomáticas todavía son accesibles, incluso si de una manera fea.

Si está pensando en un lenguaje interpretado, .NET también admite la interpretación eficiente a través del Dynamic Language Runtime (DLR). (No sé si hay un equivalente para la JVM). Esto debería ayudarlo a liberarse para concentrarse en el diseño del idioma sin tener que preocuparse demasiado por la optimización del intérprete.

+1

VM como JVM y .NET son un callejón sin salida evolutivo. –

+1

¡No es cierto! dado que las bibliotecas para las plataformas JVM y .NET no tienen que preocuparse por la idiosincrasia de las plataformas en las que se encuentran, pueden explorar libremente aspectos de diseño de la API que, de otro modo, quedarían intactos. – RCIX

+1

VM como JVM y .NET son un callejón sin salida evolutivo. –

0

Primero pasé un año más o menos para realmente pensar cómo debería verse el lenguaje. Al mismo tiempo, ayudé a desarrollar Ioke (www.ioke.org) para aprender el idioma interno.

He elegido Objective-C como plataforma de implementación ya que es rápido (suficiente), lenguaje simple y rico. También proporciona un marco de prueba, por lo que el enfoque ágil es una opción. También tiene una biblioteca estándar enriquecida sobre la que puedo basarme.

Dado que mi lenguaje es simple en el nivel sintáctico (sin palabras clave, solo literales, operadores y mensajes) podría ir con Ragel (http://www.complang.org/ragel/) para construir el escáner. Es rápido como el infierno y fácil de usar.

Ahora tengo un modelo de objeto de trabajo, un escáner y un simple cambio de operador más el código de arranque estándar de la biblioteca. Incluso puedo ejecutar programas simples, siempre y cuando quepan en un archivo :)

6

He escrito dos compiladores ahora en Haskell para idiomas específicos de dominios pequeños, y he descubierto que es una experiencia increíblemente productiva . La biblioteca parsec hace que jugar con sintaxis sea sencillo, y los intérpretes son muy simples para escribir sobre una estructura de datos Haskell. Hay una descripción de writing a Lisp interpreter in Haskell que encontré útil.

Si está interesado en un servidor de alto rendimiento, recomiendo LLVM. Tiene un código de bytes conciso y elegante y el mejor backend generador x86/amd64 que puedes encontrar. Hay un recolector de basura opcional y algunos backends experimentales que target the JVM and CLR.

Puede escribir un compilador en cualquier idioma que produzca el código de bytes LLVM. Si eres lo suficientemente aventurero para aprender Haskell pero quieres LLVM, hay un conjunto de enlaces Haskell-LLVM.

2

No tanto una implementación sino una decisión de diseño que afecta la implementación: si hace que cada enunciado de su idioma tenga un árbol de análisis único sin contexto, obtendrá algo que es fácil codificar manualmente un analizador, y no requiere grandes cantidades de trabajo para proporcionar resaltado de sintaxis para. Similarmente cosas simples como usar un símbolo diferente para espacios de nombres de módulos y espacios de nombres de objetos (a diferencia de Java que usa . para espacios de nombres de paquete y clase) significa que puede analizar el código sin cargar cada módulo al que hace referencia.

Bibliotecas estándar: incluyen el equivalente de todo en las bibliotecas estándar C99 distintas de setjmp. Agregue cualquier otra cosa que necesite para su dominio. Resuelva una manera fácil de hacer esto, ya sea algo como SWIG o un FFI en línea como Ruby's [no recuerdo el nombre del módulo] y los tipos de Python.

construcción tanto de la lengua en el idioma es una opción, pero los proyectos que se inician a cabo haciendo bien renuncian (rubinius trasladó a usar C++ para partes de su biblioteca estándar), o es sólo para fines de investigación (Mozilla Narcissus)

1

De hecho, estoy un niño, jaja. Nunca antes escribí un compilador real o diseñé un idioma, pero ya terminé The Red Dragon Book, así que supongo que tengo una idea (espero).

Que dependerá en primer lugar de la gramática. Si es LR o LALR supongo que herramientas como Bison/Flex funcionarían bien. Si es más LL, usaría Spirit, que es un componente de Boost. Le permite escribir la gramática del idioma en C++ en una sintaxis similar al EBNF, por lo que no debe confundirse con los generadores de códigos; el compilador de C++ compila la gramática para usted. Si alguno de estos falla, escribiría una gramática EBNF en papel, y luego procedería a hacer un análisis de descenso recursivo pesado, que parece funcionar; si C++ se puede analizar bastante bien usando RDP (como lo hace GCC), entonces supongo que con suficientes pruebas de unidad y paciencia podrías escribir compiladores enteros usando RDP.

Una vez que tengo un analizador de funcionamiento y algún tipo de representación intermedia, entonces depende de la forma en que se ejecuta. Si es un bytecode o compilador de código nativo, usaré LLVM o libJIT para procesarlo. LLVM es más adecuado para la compilación general, pero me gusta más la API y la documentación de libJIT. Alternativamente, si soy muy flojo, generaré código C y dejaré que GCC realice la compilación. Otra alternativa es apuntar a una VM existente, como Parrot o JVM o CLR. Parrot es la máquina virtual diseñada para Perl. Si solo es un intérprete, caminaré por el árbol de sintaxis.

Una alternativa radical es el uso de Prolog, que tiene características de sintaxis que notablemente simulan EBNF. No tengo experiencia con eso, y si no estoy equivocado (lo que casi con toda seguridad voy a ser), Prolog sería bastante lento si se usa para analizar los lenguajes de programación pesados ​​con muchas construcciones y peculiaridades sintácticas (léase: C++ y Perl).

Todo esto lo haré en C++, aunque sólo sea porque estoy más acostumbrado a escribir en él que C. Me quedaría lejos de Java/Python o algo por el estilo para el código de producción real (compiladores escritura en C/C++ ayuda a hacerlo portátil), pero podría verme usarlos como un lenguaje de creación de prototipos, especialmente Python, que me gusta. Por supuesto, nunca he hecho nada de esto antes, así que no soy uno para decir.

3

Lo que ha cambiado considerablemente, pero no se ha mencionado todavía es el soporte IDE y la interoperabilidad:

Hoy en día nos prácticamente esperar Intellisense, paso a paso la ejecución y la inspección del estado "justo en la ventana del editor", nuevo tipos que le dicen al depurador cómo tratarlos y mensajes de diagnóstico bastante útiles. El antiguo ejecutable "compilar .x -> .y" no es suficiente para crear un idioma. El entorno no es nada en lo que enfocarse primero, sino que afecta la disposición a adoptar.

Además, las bibliotecas se han convertido en mucho más potente, nadie quiere poner en práctica todo lo que en otro idioma. Intente pedir prestado, haga que sea fácil llamar al código existente y facilite que otro código lo llame.

Orientación de una máquina virtual - como se sugirió itowlson - es probablemente una buena manera de empezar. Si eso resulta un problema, aún puede ser reemplazado por compiladores nativos.

+2

"el viejo 'compilador .x -> .y' está prácticamente muerto" - jajajaja! Dime otra. ¡Adelante, eso fue genial! –

+0

alex: como en "todo lo que necesitas para un nuevo idioma es ...", creo que debería aclarar eso. – peterchen

-1

Mike -

Si está interesado en un compilador de generación de código nativo eficiente para Windows para que pueda orientarse - sin vadear a través de todos los widgets innecesarios, aparatos, y otras cosas sin sentido que el desorden las máquinas de hoy: recomiendo el sistema de desarrollo de inglés sencillo de la orden de Osmosian. Incluye una interfaz única, un administrador de archivos simplificado, un editor de texto amigable, un dumper hexadecimal útil, el compilador/enlazador (por supuesto) y una aplicación de diseño de página wysiwyg para la documentación. Escrito completamente en inglés sencillo, es una descarga rápida (menos de un megabyte), lo suficientemente pequeña como para entender en poco tiempo (aproximadamente 25,000 líneas de código inglés sencillo, con solo 4,000 en el compilador/enlazador), pero lo suficientemente potente para reproducirse en un Dell de gama baja en menos de tres segundos. En serio: tres segundos. Y es gratis para todos los que escriben y solicitan una copia, incluido el código fuente y un manual bastante ingenioso de 100 páginas. Ver www.osmosian.com para obtener más información sobre cómo obtener una copia, o escribir a mí directamente con preguntas o comentarios: [email protected]

0

Por supuesto, las técnicas más antiguas siguen siendo comunes (por ejemplo, usando Flex y Bison) muchas implementaciones de lenguaje más nuevas combinan la fase de lectura y análisis utilizando un analizador basado en una gramática de expresión de análisis (PEG). Esto funciona para analizadores de descenso recursivos creados mediante combinadores o memorando analizadores de Packrat. Muchos compiladores también se crean utilizando el marco Antlr.

1

Solo para aclarar, quiero decir, no ¿Cómo se diseña una lengua (que puede averiguar con bastante facilidad)

Sólo un consejo: Mira algunos bastante diferentes idiomas en primer lugar, antes de diseñando un nuevo lenguaje (es decir, idiomas con una estrategia de evaluación muy diferente). Haskell y Oz vienen a la mente. Aunque también debes saber Prolog and Scheme. Hace un año, yo también decía "hey, diseñemos un lenguaje que se comporte exactamente como yo quiero", pero por fortuna miré esos otros idiomas primero (o también podría decir desafortunadamente, porque ahora no sé cómo quiere un lenguaje para comportarse más ...).

1

Antes de empezar a crear un lenguaje que debe leer esto:

Hanspeter Moessenboeck, El arte de Niklaus Wirth

ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe00b.pdf

+0

Niklaus Wirth fue terrible en el diseño de compiladores. Él violó la Ley de Einstein: Haga que todo sea lo más fácil posible pero no más fácil. Sus idiomas eran fáciles de ser productivos. Por cierto, me gusta Modula3 que no fue diseñado por él. – Lothar

0

Uso bisonte/flex que es la versión GNU de yacc/lex. Esto book is extremely helpful.

La razón para usar bison es que atrapa cualquier conflicto en el idioma. Lo utilicé y me hizo la vida mucho más fácil (ok, estoy en mi segundo año, pero los primeros 6 meses fueron hace unos años escribiéndolo en C++ y el análisis/conflictos/resultados fueron terribles! :(.)

0

Hay un gran atajo para la implementación de un lenguaje que no veo en las otras respuestas aquí. Si usas una de las formas "sin apariencia" de Lukasiewicz (es decir, Forward Polish o Reverse Polish), ¡no necesitas un analizador en absoluto! Con el pulido inverso, las dependencias van de derecha a izquierda, por lo que simplemente ejecuta cada token a medida que se escanea. Con el pulido hacia adelante, es al revés de eso, por lo que realmente ejecuta el programa "hacia atrás", simplificando las subexpresiones hasta alcanzar el token de inicio.

Para comprender por qué esto funciona, debe investigar los 3 algoritmos principales de recorrido de árbol: preordenar, en orden, postordenar. Estos tres recorridos son el inverso de la tarea de análisis sintáctico que un lector de idiomas (i. Parser) debe realizar. Solo la notación en orden "requiere" un decente recursivo para reconstruir el árbol de expresiones. Con los otros dos, puedes salir con solo una pila.

Esto puede requerir más "pensar' y menos 'de ejecución'.

Por cierto, si ya has encontrado una respuesta (esta pregunta es un año de edad), puede publicar eso y aceptarlo.

Cuestiones relacionadas