Domanda

Sto cercando di progettare una grammatica dell'isola utilizzando Il mascalzone MPL, ma ho riscontrato un problema:

Quando si implementa una grammatica dell'isola in SDF, un approccio molto comune è quello di definire una produzione di acqua "catch-all" utilizzando l'attributo {avoid}.Ciò impedisce al parser di utilizzare questa produzione se altre sono applicabili.Ciò consente di specificare a comportamento predefinito che può essere sovrastato da altre produzioni senza generare ambiguità.Un esempio molto semplice di questo sarebbe:

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

Ho provato a riprodurre questo comportamento con Rascal MPL.Il mio obiettivo è creare una grammatica dell'isola che raccolga tutte le direttive condizionali del preprocessore all'interno di un pezzo di codice C/C++ e salti il ​​resto dell'input utilizzando le produzioni Water.

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";

Ho provato a creare l'effetto {avoid} dando il Direttiva Condizionale produzione una priorità più alta utilizzando l'operatore ">", ma a quanto pare non funziona.L'albero di analisi contiene ancora ambiguità.

#ifdef asd

Se analizzo il codice sopra, ad esempio, ottengo un albero di analisi che appare come segue:

ambiguous parse tree

Per quanto ne so dal Documentazione furfante, usare l'operatore "prioritario" potrebbe non essere la strada da percorrere nel mio caso, ma non vedo altre possibilità.Presumo però che ci sia un modo, perché gli autori di rascal affermano chiaramente che ogni grammatica SDF può essere convertita in una grammatica rascal.

Esiste un modo per riprodurre la funzionalità SDF {evitare} con MPL mascalzone?Oppure è possibile filtrare in qualche modo la foresta di analisi, riapplicando le priorità?

È stato utile?

Soluzione

Risposta breve:evitare è in sdf2 un filtro post-analisi.In mascalzone puoi definirli tu stesso, vedi https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/sdf2/filters/PreferAvoid.rsc per un esempio che imita sdf2 evita il comportamento senza ignorare le catene di iniezione e senza contare.Puoi importarlo nella tua grammatica e utilizzare i tag @avoid e @prefer proprio come in sdf2, oppure scrivere i tuoi filtri.

Avvertimento:evitare generalmente non era sufficiente per definire il comportamento dell'acqua in sdf2 e non lo è nemmeno in rascal.Il motivo è che l'acqua può diventare più lunga della sua alternativa.Preferire ed evitare possono scegliere solo tra alternative di pari lunghezza in termini di lunghezza della sottofrase.Un modo infallibile ma lento per gestire l'acqua in modo malandrino è contarla in ogni alternativa e scegliere derivazioni con meno acqua.

Un altro problema con Preferisci ed Evita era che gli usi iniziavano a interferire, soprattutto quando venivano contati.Ciò può essere evitato in mascalzone specializzando filtri per specifici non terminali o anche regole alternative.

Un'altra opzione è utilizzare \ e !operatori di disambiguazione.Consulta il manuale.Tuttavia, tutto ciò che credo che l'opzione di filtraggio post analisi sia attualmente il modo migliore per gestire le grammatiche dell'isola perché controlli ciò che sta accadendo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top