Search code examples
rascal

How to handle multiple optionals in grammar


I would like to know how I can handle multiple optionals without concrete pattern matching for each possible permutation.

Below is a simplified example of the problem I am facing:

lexical Int = [0-9]+;
syntax Bool = "True" | "False";
syntax Period = "Day" | "Month" | "Quarter" | "Year";
layout Standard = [\ \t\n\f\r]*; 
syntax Optionals = Int? i Bool? b Period? p;

str printOptionals(Optionals opt){
    str res = "";
    if(!isEmpty("<opt.i>")) { // opt has i is always true (same for opt.i?)
        res += printInt(opt.i);
    }
    if(!isEmpty("<opt.b>")){
        res += printBool(opt.b);
    }
    if(!isEmpty("<opt.p>")) {
        res += printPeriod(opt.period);
    }
    return res;
}

str printInt(Int i) = "<i>";
str printBool(Bool b) = "<b>";
str printPeriod(Period p) = "<p>";

However this gives the error message:

The called signature: printInt(opt(lex("Int"))), does not match the declared signature: str printInt(sort("Int"));

How do I get rid of the opt part when I know it is there?


Solution

  • I'm not sure how ideal this is, but you could do this for now:

    if (/Int i := opt.i) {
        res += printInt(i);
    }
    

    This will extract the Int from within opt.i if it is there, but the match will fail if Int was not provided as one of the options.