Search code examples
rascalconcrete-syntax-tree

How I can convert concrete syntax values to other kinds of values?


Given some concrete syntax value, how I can I map it to a different type of value (in this case an int)?

// Syntax
start syntax MyTree = \node: "(" MyTree left "," MyTree right ")"
                    | leaf: Leaf leaf
                    ;

layout MyLayout = [\ \t\n\r]*;

lexical Leaf = [0-9]+;

This does not work unfortunately:

public Tree increment() {
    MyTree tree = (MyTree)`(3, (1, 10))`;

    return visit(tree) {
      case l:(Leaf)`3` => l + 1  
    };
}

Or is the only way to implode into an ADT where I specified the types?


Solution

  • Your question has different possible answers:

    1. using implode you can convert a parse tree to an abstract tree. If the constructors of the target abstract language expect int, then lexical trees which happen to match [0-9]+ will be automatically converted. For example the syntax tree for syntax Exp = intValue: IntValue; could be converted to constructor data Exp = intValue(int i); and it will actually build an i.
    2. in general to convert one type of values to another in Rascal you write (mutually) recursive functions, as in int eval (MyTree t) and int (Leaf l).
    3. if you want to actually increment the syntactic representation of a Leaf value, you have to convert back (parse or via a concrete pattern) from the resulting int back to the Leaf.

    Example:

    import String;
    MyTree increment() {
        MyTree tree = (MyTree)`(3, (1, 10))`;
    
        return visit(tree) {
          case Leaf l => [Leaf] "<toInt("<l>") + 1>";  
        };
    }
    

    First the lexical is converted to a string "<l>", this is then parsed as an int using toInt() and we add 1 using + 1 and then map the int back to a string "< ... >", after which we can call the Leaf parser using [Leaf].