Pregunta

Además de hacer un trabajo real, tengo picazón. Mi picazón es escribir un motor de vista que imite de cerca un sistema de plantillas de otro idioma (Template Toolkit / Perl). Este es uno de esos si tuviera tiempo / lo hago para aprender algo nuevo en proyectos.

He pasado tiempo mirando CoCo / R y ANTLR, y honestamente, me duele el cerebro, pero algunos de CoCo / R se están hundiendo. Desafortunadamente, la mayoría de los ejemplos tratan de crear un compilador que lea el código fuente , pero ninguno parece cubrir cómo crear un procesador para plantillas.

Sí, son lo mismo, pero no puedo entender cómo definir el idioma para las plantillas donde la mayor parte del código fuente es el html, en lugar de analizar y ejecutar el código real.

¿Hay algún buen recurso para principiantes para este tipo de cosas? Tomé un ganer en Spark, que no parecía tener la gramática en el repositorio.

Tal vez eso sea excesivo, y uno podría simplemente reemplazar la sintaxis de la plantilla con c # en el archivo y compilarlo. http://msdn.microsoft.com/en-us/magazine/ cc136756.aspx # S2

Si estuviera en mi lugar y no fuera un experto en creación de idiomas, ¿por dónde empezaría?

¿Fue útil?

Solución

La gramática de Spark se implementa con un lenguaje específico de dominio fluido.

Se declara en algunas capas. Las reglas que reconocen la sintaxis html se declaran en MarkupGrammar.cs : se basan en reglas gramaticales copiadas directamente de la especificación xml.

Las reglas de marcado se refieren a un subconjunto limitado de reglas de sintaxis csharp declaradas en CodeGrammar.cs : estos son un subconjunto porque Spark solo necesita reconocer suficiente csharp para ajustar las comillas simples alrededor de las cadenas a comillas dobles, emparejar llaves, etc.

Las reglas individuales son del tipo ParseAction < !> lt; TValue > delegado que acepta una Posición y devuelva un ParseResult . ParseResult es una clase simple que contiene el elemento de datos TValue analizado por la acción y una nueva instancia de Position que se ha avanzado más allá del contenido que produjo TValue.

Eso no es muy útil por sí solo hasta que introduzca un pequeño número de operadores , como se describe en Análisis de la gramática de expresión , que puede combinar acciones de análisis individuales para crear expresiones muy detalladas y robustas sobre la forma de diferentes construcciones de sintaxis.

La técnica de usar un delegado como acción de análisis provino de una publicación de blog de Luke H Combinadores de analizador monádico con C # 3.0 . También escribí una publicación sobre Crear un dominio específico Idioma para analizar .

También es completamente posible, si lo desea, hacer referencia al ensamblado Spark.dll y heredar una clase del CharGrammar base para crear una gramática completamente nueva para una sintaxis particular. Probablemente sea la forma más rápida de comenzar a experimentar con esta técnica, y un ejemplo de eso se puede encontrar en CharGrammarTester.cs .

Otros consejos

Paso 1. Use expresiones regulares (sustitución de expresiones regulares) para dividir su cadena de plantilla de entrada en una lista de tokens, por ejemplo, dividir

hel<b>lo[if foo]bar is [bar].[else]baz[end]world</b>!

a

write('hel<b>lo')
if('foo')
write('bar is')
substitute('bar')
write('.')
else()
write('baz')
end()
write('world</b>!')

Paso 2. Convierta su lista de tokens en un árbol de sintaxis:

* Sequence
** Write
*** ('hel<b>lo')
** If
*** ('foo')
*** Sequence
**** Write
***** ('bar is')
**** Substitute
***** ('bar')
**** Write
***** ('.')
*** Write
**** ('baz')
** Write
*** ('world</b>!')

class Instruction {
}
class Write : Instruction {
  string text;
}
class Substitute : Instruction {
  string varname;
}
class Sequence : Instruction {
  Instruction[] items;
}
class If : Instruction {
  string condition;
  Instruction then;
  Instruction else;
}

Paso 3. Escribe una función recursiva (llamada intérprete), que puede recorrer tu árbol y ejecutar las instrucciones allí.

Otro enfoque alternativo (en lugar de los pasos 1 a 3) si su idioma admite eval () (como Perl, Python, Ruby): utilice una sustitución regexp para convertir la plantilla en una cadena capaz de evaluar () el idioma del host y ejecute eval () para crear una instancia de la plantilla.

Hay tantas cosas que hacer. Pero funciona en una declaración GET simple más una prueba. Eso es un comienzo.

http://github.com/claco/tt.net/

Al final, ya tenía demasiado tiempo en ANTLR para probar el método de loudejs. Quería pasar un poco más de tiempo en todo el proceso en lugar del analizador / lexer. Tal vez en la versión 2 pueda probar Spark cuando mi cerebro entienda un poco más las cosas.

Vici Parser (anteriormente conocido como LazyParser.NET) es de código abierto tokenizer / template parser / expression parser que puede ayudarlo a comenzar.

Si no es lo que está buscando, puede obtener algunas ideas mirando el código fuente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top