Pregunta

Estoy tratando de diseñar una gramática de la isla usando Rascal MPL , pero corrí a un Problema:

Al implementar una gramática de la isla en SDF, un enfoque muy común es definir una producción de agua de "Catch-TODA" utilizando el atributo {EVITE}. Esto evita que el analizador use esta producción si otros son aplicables. Esto permite especificar un comportamiento predeterminado de que puede ser anulado por otras producciones que generan abiguidades. Un ejemplo muy simple de esto sería:

context free syntax
    Chunk*         -> Input
    Water          -> Chunk
lexical syntax
    ~[\t\n\ ]+   -> Water {avoid}  // avoid the Water production

Intenté reproducir este comportamiento con Rascal MPL. Mi objetivo es crear una gramática de la isla que reúne todas las directivas de preprocesadores condicionales dentro de una pieza de código C / C ++ y salta el resto de la entrada utilizando producciones de agua.

layout LAYOUT = [\t\n\ ];
lexical WATER = ![\t\n\ ]+;

start syntax Program = Line*;       // program consists of lines

syntax Line = ConditionalDirective  // preprocessor directives
            > WATER;                // catch-all option

syntax ConditionalDirective = "#ifdef" 
                            | "#ifndef"
                            | "#if"
                            | "#elif";

Intenté crear el efecto {Evitar} dando la producción condicionaldirective una prioridad más alta utilizando el operador ">", pero esto no funciona aparentemente. El árbol de parse todavía contiene ambigüedades.

#ifdef asd

Si analizo el código anterior, por ejemplo, obtengo un árbol de análisis que se ve de la siguiente manera:

Árbol de parse ambiguo

En lo que puedo decir desde el rascal La documentación , utilizando la "prioridad", podría no ser la forma de ir en mi caso, pero no veo ninguna otra posibilidad. Aunque asumo que hay una manera, porque los autores de Rascal claramente afirman que cada gramática SDF se puede convertir a una gramática sinvergüenza.

¿Hay alguna manera de reproducir la funcionalidad SDFS {evitar} con Rascal MPL? ¿O es posible filtrar el bosque de parse de alguna manera, volver a aplicar las prioridades?

¿Fue útil?

Solución

Respuesta corta: EVITE está en SDF2 un filtro POST PERSE. En Rascal puede definirlos a usted mismo, consulte https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/sdf2/filters/preferavoid.rsc para un ejemplo que imita SDF2 Evite el comportamiento sin ignorar las cadenas de inyección y sin contar. Puede importarlo en su gramática y usar etiquetas @avoid y @prefer como en SDF2, o escribir sus propios filtros.

CAVEAT: Evite generalmente no era suficiente para definir el comportamiento del agua en SDF2 y tampoco está en el rascal. La razón es que el agua puede volverse más larga que su alternativa. Prefiera y evite solo puede elegir entre alternativas de igual longitud en términos de longitud de subsuelo. Uno Surefire, pero la forma lenta de lidiar con el agua en Rascal es contarla en cada alternativa y elegir derivaciones con menos agua.

Otro problema con preferir y evitar fue que los usos comenzarían a interferir, especialmente cuando se contabilizaran. Esto se puede evitar en Rascal especializando filtros para antiheminales específicos o incluso reglas alternativas.

Otra opción es usar el \ y! Operadores de desabacción. Ver el manual. Sin embargo, todos y todos Creo que la opción de filtrado posterior al parse es actualmente la mejor manera de lidiar con las gramáticas de la isla porque controlas lo que está pasando.

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