2008-12-04 20 views
5

Escribo un juego en python y he decidido crear un DSL para los archivos de datos del mapa. Sé que podría escribir mi propio analizador con expresiones regulares, pero me pregunto si existen herramientas python existentes que puedan hacer esto más fácilmente, como re2c, que se usa en el motor PHP.Escribiendo un compilador para un DSL en python

Alguna información adicional:

  • Sí, lo hacen necesita una conexión ADSL, e incluso si no todavía quiero la experiencia de construir y usar una en un proyecto.
  • La DSL contiene solo datos (¿declarativos?), No se "ejecuta". La mayoría de las líneas se ven como:

    SOMETHING: !abc @123 #xyz/123

    sólo hay que leer el árbol de datos.

Respuesta

3

Sí, hay muchos - demasiados - herramientas de análisis, pero ninguno en la biblioteca estándar.

De lo que vi PLY y SPARK son populares. PLY es como yacc, pero haces todo en Python porque escribes tu gramática en docstrings.

Personalmente, me gusta el concepto de los combinadores de analizadores (tomados de la programación funcional), y me gusta bastante pyparsing: escribes tu gramática y tus acciones directamente en python y es fácil empezar. Sin embargo, terminé produciendo mis propios tipos de nodo de árbol con acciones, en lugar de usar su tipo predeterminado de ParserElement.

De lo contrario, también puede utilizar el lenguaje declarativo existente como YAML.

11

Siempre me ha impresionado pyparsing. El autor, Paul McGuire, está activo en el python list/comp.lang.python y siempre ha sido muy útil con cualquier consulta al respecto.

+0

que habría sugerido que si no hubiera hecho ya! PyParsing es increíble. –

6

Aquí hay un enfoque que funciona muy bien.

abc= ONETHING(...) 
xyz= ANOTHERTHING(...) 
pqr= SOMETHING(this=abc, that=123, more=(xyz,123)) 

Declarativo. Fácil de analizar.

Y ...

En realidad es Python. Algunas declaraciones de clase y el trabajo está hecho. El DSL es realmente declaraciones de clase.

Lo importante es que una DSL simplemente crea objetos. Cuando defines un DSL, primero debes comenzar con un modelo de objetos. Más tarde, pones algo de sintaxis alrededor de ese modelo de objetos. No comienzas con sintaxis, comienzas con el modelo.

+0

Sé lo que dices, pero escribir todos esos comentarios, paréntesis, equivalentes, prefijos está ofuscando los datos reales. Además, este método no se adapta bien a lenguajes más detallados como PHP o Java. –

+0

@ Peter. Discrepar. Puede usar argumentos posicionales y eliminar las etiquetas y = 's. Se traduce perfectamente en Java. Ya lo usé en aplicaciones de producción para definir un DSL declarativo. –

+0

He visto lo que está sugiriendo como una DSL interna. Me gusta este método Un problema podría ser que, aunque el método se transfiere a otros idiomas (he visto cosas como esta implementadas en C#), la sintaxis precisa de su DSL probablemente cambiará un poco. Los archivos de mapas no serán portátiles. – Mendelt

2

He escrito algo como esto en el trabajo para leer en las definiciones de notificación SNMP y generar automáticamente clases Java y archivos SNMP MIB a partir de esto. Usando esta pequeña DSL, podría escribir 20 líneas de mi especificación y generaría aproximadamente 80 líneas de código Java y un archivo MIB de 100 líneas.

Para implementar esto, en realidad solo usé el manejo de cadenas de Python (dividir(), cortar, etc.) para analizar el archivo.Encuentro que las capacidades de cadenas de Pitones son adecuadas para la mayoría de mis necesidades (simples) de análisis.

Además de las bibliotecas mencionadas por otros, si estuviera escribiendo algo más complejo y necesitara capacidades de análisis adecuadas, probablemente usaría ANTLR, que admite Python (y otros lenguajes).

2

Pedro,

DSL son una buena cosa, por lo que no es necesario para defenderse :-) Sin embargo, ¿ha considerado un DSL interna? Estos tienen tantos DSLs profesionales versus externos (analizados) que al menos merecen consideración. Mezclar un DSL con el poder del idioma nativo realmente resuelve muchos de los problemas para ti, y Python no es realmente malo en las DSL internas, con la instrucción with a mano.

+1

¿Cómo es que la declaración 'con' es útil para las DSL internas? Soy curioso – fferri

2

Para "idiomas pequeños" como el que está describiendo, utilizo una división simple, shlex (tenga en cuenta que el # define un comentario) o expresiones regulares.

>>> line = 'SOMETHING: !abc @123 #xyz/123' 

>>> line.split() 
['SOMETHING:', '!abc', '@123', '#xyz/123'] 

>>> import shlex 
>>> list(shlex.shlex(line)) 
['SOMETHING', ':', '!', 'abc', '@', '123'] 

El siguiente es un ejemplo, ya que no sé exactamente lo que estás buscando.

>>> import re 
>>> result = re.match(r'([A-Z]*): !([a-z]*) @([0-9]*) #([a-z0-9/]*)', line) 
>>> result.groups() 
('SOMETHING', 'abc', '123', 'xyz/123') 
Cuestiones relacionadas