¿Cómo escribir una gramática de bisontes para WDI?

Necesito ayuda con la construcción de gramática de bisonte.

De mi otra pregunta: estoy tratando de hacer un metalenguaje para escribir código de marcado (como xml y html) que se puede incrustar directamente en el código C / C ++. Aquí hay una muestra simple escrita en este idioma, la llamo WDI (Interfaz de desarrollo web):

/* * Simple wdi/html sample source code */ #include  string name = "myName"; string toCapital(string str); html { head { title { mySiteTitle; } link(rel="stylesheet", href="style.css"); } body(id="default") { // Page content wrapper div(id="wrapper", class="some_class") { h1 { "Hello, " + toCapital(name) + "!"; } // Lists post ul(id="post_list") { for(post in posts) { li { a(href=post.getID()) { post.tilte; } } } } } } } 

Básicamente es una fuente C con una interfaz fácil de usar para html. Como puede ver, el estilo tradicional basado en tags se sustituye por C, con bloques delimitados por llaves. Necesito construir un intérprete para traducir este código a html y posteriormente insertarlo en C, para que pueda ser comstackdo. La parte C permanece intacta. Dentro de la fuente de wdi no es necesario usar impresiones, cada statement de retorno se usará para la salida (en la función printf). La salida del progtwig será código html limpio.

Entonces, por ejemplo, una etiqueta de encabezado 1 se transformaría así:

 h1 { "Hello, " + toCapital(name) + "!"; } // would become: printf("

Hello, %s!

", toCapital(name));

Mi objective principal es crear un intérprete para traducir la fuente de wdi a html de esta manera:

tag(attributes) {content} => content

En segundo lugar, el código html devuelto por el intérprete debe insertarse en el código C con printfs. Las variables y funciones que ocurren dentro de wdi también deben clasificarse para usarlas como parámetros printf (el caso de toCapital (nombre) en la fuente de muestra).

Aquí están mis archivos de flex / bison:

 id [a-zA-Z_]([a-zA-Z0-9_])* number [0-9]+ string \".*\" %% {id} { yylval.string = strdup(yytext); return(ID); } {number} { yylval.number = atoi(yytext); return(NUMBER); } {string} { yylval.string = strdup(yytext); return(STRING); } "(" { return(LPAREN); } ")" { return(RPAREN); } "{" { return(LBRACE); } "}" { return(RBRACE); } "=" { return(ASSIGN); } "," { return(COMMA); } ";" { return(SEMICOLON); } \n|\r|\f { /* ignore EOL */ } [ \t]+ { /* ignore whitespace */ } . { /* return(CCODE); Find C source */ } %% 

 %start wdi %token LPAREN RPAREN LBRACE RBRACE ASSIGN COMMA SEMICOLON CCODE QUOTE %union { int number; char *string; } %token  ID STRING %token  NUMBER %% wdi : /* empty */ | blocks ; blocks : block | blocks block ; block : head SEMICOLON | head body ; head : ID | ID attributes ; attributes : LPAREN RPAREN | LPAREN attribute_list RPAREN ; attribute_list : attribute | attribute COMMA attribute_list ; attribute : key ASSIGN value ; key : ID {$$=$1} ; value : STRING {$$=$1} /*| NUMBER*/ /*| CCODE*/ ; body : LBRACE content RBRACE ; content : /* */ | blocks | STRING SEMICOLON | NUMBER SEMICOLON | CCODE ; %% 

Tengo dificultades para definir una gramática adecuada para el idioma, especialmente para dividir el código WDI y C. Empecé a aprender técnicas de procesamiento del lenguaje, así que necesito orientación. ¿Alguien podría corregir mi código o dar algunos ejemplos de cuál es la forma correcta de resolver este problema?

Si tu intención es analizar el código C y el código WDI incrustado, te espera un duro viaje. Los generadores de analizadores LALR (1) (incluido Bison) son notoriamente malos para analizar C, y mucho menos cosas más complicadas que C (es decir, C + WDI).

O bien, tendrá que:

a) aprender cómo hacer Bison parse C al enredar el análisis sintáctico y la construcción de la tabla de símbolos (es decir, luchar con GNU GCC para ver cómo lo hicieron),

b) Cambie a un generador de analizador más fuerte, como un generador de analizadores GLR (para lo cual Bison tiene una opción) y aprenda a manejar gramáticas ambiguas y cómo resolverlas,

o

c) diseñar WDI como una especie de grammer de isla, en la que el objective es seleccionar el código de WDI y dejar todo lo que no sea WDI como cadenas opacas (en su caso destinado a emitirse como presunto código C). Este último enfoque es mucho más fácil, y es más o menos lo que hacen todos los lenguajes de página web (ASP, PHP, JSP …). Lo bueno es que esto es mucho más fácil, y usted solo tiene que escribir la gramática para WDI y un lexer que recogerá todo lo que no es WDI como una cadena de caracteres. El inconveniente es que no podrá hacer que WDI y C interactúen bien / y / o verifique la validez de un progtwig de WDI con su analizador. Vea esta pregunta SO para más antecedentes:

Gramática de la isla antlr3

Esto sería más fácil si aprende más sobre tecnología de comstackción con más detalle antes de comenzar este proyecto.