Search code examples
rascal

Priority in RascalMPL using extend


I was trying to extend a expression language in my DSL, but I get ambiguity prediction warning on the priority. How can I sort out the priority in this scenario(using extend)?


Solution

  • For example, we have a module A:

    module A
    
    lexical Id = [a-z]+; // for the sake of completeness
    
    syntax Exp 
        = Id
        | left Exp "+" Exp
        ;
    

    and then a module B that extends it:

    module B
    
    extend A;
    
    syntax Exp
        = left Exp "*" Exp
        ;
    

    And now when we generate the parser we get a warning about possible ambiguity between the * and the + rule.

    The first solution is to add a priority by repeating the original rule. This leads to this version of module B:

    module B
    
    extend A;
    
    syntax Exp
        = left Exp "*" Exp
        > left Exp "+" Exp
        ;
    

    The precondition is that the + rule must be replicated exactly, literally for this to work without introducing yet another ambiguity between the two version of the rule. This includes possible labels. So this would not work:

    module B
    
    extend A;
    
    syntax Exp
        = left Exp "*" Exp
        > left Exp lhs "+" Exp rhs
        ;
    

    This is a bit clumsy all, so there is the option to use the names of rules in priority declarations as well. For this the original rule must have a name. The module A becomes this:

    module A
    
    syntax Exp 
        = Id
        | left plus: Exp "+" Exp
        ;
    

    and then we can write this in module B:

    module B
    
    extend A;
    
    syntax Exp
        = left times:Exp "*" Exp
        > :plus // the reference to the other rule in module A
        ;
    

    In short: everywhere you can write a full rule, left or right of the > sign, inside an associativity group, etc, you can write :<label> to refer to any existing labeled rule for the same non-terminal but possibly in a different rule or even a different extended or imported module. If you don't want to add labels, then repeating the entire rule is necessary.