I'm trying to design an island grammar using Rascal MPL, but I ran into a problem:
When implementing an Island Grammar in SDF a very common approach is to define a "catch-all" water production using the {avoid} attribute. This prevents the parser from using this production if others are applicable. This allows to specify a default behaviour that can be overridden by other productions whitout generating abiguities. A very simple example of this would be:
context free syntax
Chunk* -> Input
Water -> Chunk
lexical syntax
~[\t\n\ ]+ -> Water {avoid} // avoid the Water production
I tried reproducing this behaviour with Rascal MPL. My goal is to create an island grammar that gathers all conditional preprocessor directives inside a piece of C/C++ code and skips the rest of the input using Water productions.
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";
I tried to create the {avoid} effect by giving the ConditionalDirective production a higher priority using the ">" operator, but this doesn't work apparently. The parse tree still contains ambiguities.
#ifdef asd
If I parse the above code for example, I get a parse tree that looks as follows:
As far as I can tell from the Rascal Documentation, using the "priority"-operator might not be the way to go in my case, but I don't see any other possibilities. I assume there is a way though, because the authors of rascal clearly state that every SDF grammar can be converted to a rascal grammar.
Is there a way to reproduce SDFs {avoid} functionality with rascal MPL? Or is it possible to filter the parse forest somehow, reapplying the priorities?