Search code examples
transformationrascal

Splitting declaration and initialization using RASCAL


I'm new to Rascal and experimenting with its transformation/term rewriting abilities.

I want to write a script that splits declarations like:

int x = 5;

into declaration/initializations like:

int x; x = 5;

How might I go about this? Let's say the language I'm trying to transform is Java.

Thanks for any help.


Solution

  • Sketch of a solution

    Good question. There are several ways to do this and I will show the most simplistic one. Note that your example is not the simplest possible example since it requires a conversion from a single statement to a list of statements (i.e., it is not type preserving).

    Here is without further ado a complete example, the explanation follows below.

    module Decl
    
    import IO;
    import ParseTree;
    
    // Decl, a trivial language, to demo simple program trafo
    
    lexical Id  = [a-z][a-z0-9]* !>> [a-z0-9] \ Reserved;
    lexical Natural = [0-9]+ ;
    lexical String = "\"" ![\"]*  "\"";
    
    layout Layout = WhitespaceAndComment* !>> [\ \t\n];
    
    lexical WhitespaceAndComment 
       = [\ \t\n\r]
       ;
    
    keyword Reserved = "int" | "str" | "if" | "then" | "else" | "fi" | "while" | "do" | "od";
    
    start syntax Program 
       = {Statement  ";"}* body
       ;
    
    syntax Type 
       = "int" 
       | "str"
       ;
    
    syntax Statement 
       = Type tp Id var
       | Type tp Id var ":=" Expression exp
       | Id var ":=" Expression val                                                                      
       | "if" Expression cond "then" {Statement ";"}*  thenPart "else" {Statement ";"}* elsePart "fi"   
       | "while" Expression cond "do" {Statement ";"}* body "od"                                   
       ;  
    
    syntax Expression 
       = Id name                                    
       | String string                          
       | Natural natcon                         
       | bracket "(" Expression e ")"                   
       > left ( Expression lhs "+" Expression rhs                                          
              | Expression lhs "-" Expression rhs  
              )
       ;
    
    str trafo1 () {
        p = parse(#start[Program], "int x := 1").top;
        newBody = "";
        for(stat <- p.body){
            if((Statement) `<Type tp> <Id var> := <Expression exp>` := stat){
                newBody += "<tp> <var>; <var> := <exp>";
            } else {
                newBody += "<stat>";
            }
        }
        return newBody;
    }
    

    The major part is a complete grammar of a simple language. The actual transformation is done by trafo1 which does:

    1. Parse the example.
    2. Introduce and initialize newBody (used to build the result).
    3. Iterate over the statements in the given body.
    4. Test for each statement whether it is of the desired form. If true, append the transformed statement. Note that string templates are used here to build the transformed statement. If false, append the original statement.
    5. Return the resulting string.

    Discussion

    The solution style large depends on your goal. Here we just build a string. If desired, you could return the parsed string as result.

    Alternatives:

    1. Transform as concrete parse tree (not so easy since some functionality is still lacking but we aim to make this the preferred solution).
    2. First transform to an abstract syntax tree (AST) and perform the transformation on the AST.

    Hope this helps you to get started.