Navigation
Synopsis An Exp evaluator that uses a manually written conversion from parse tree to abstract syntaxt tree.
Examples First we define a parse function for Exp:
module demo::lang::Exp::Combined::Manual::Parse
import demo::lang::Exp::Concrete::WithLayout::Syntax;
import ParseTree;

public Tree parseExp(str txt) = parse(#Exp, txt); 
and test it:
rascal>import demo::lang::Exp::Combined::Manual::Parse;
ok
rascal>parseExp("2+3");
Tree: `2+3`
Tree: appl(prod(sort("Exp"),[sort("Exp"),layouts("Whitespace"),lit("+"),layouts("Whitespace"),sort("Exp")],{assoc(left())}),[appl(prod(sort("Exp"),[lex("IntegerLiteral")],{}),[appl(prod(lex("IntegerLiteral"),[iter(\char-class([range(48,57)]))],{}),[appl(regular(iter(\char-class([range(48,57)]))),[char(50)])[@loc=|file://-|(0,1,<1,0>,<1,1>)]])[@loc=|file://-|(0,1,<1,0>,<1,1>)]])[@loc=|file://-|(0,1,<1,0>,<1,1>)],appl(prod(layouts("Whitespace"),[\iter-star(\char-class([range(9,10),range(13,13),range(32,32)]))],{}),[appl(regular(\iter-star(\char-class([range(9,10),range(13,13),range(32,32)]))),[])[@loc=|file://-|(1,0,<1,1>,<1,1>)]])[@loc=|file://-|(1,0,<1,1>,<1,1>)],appl(prod(lit("+"),[\char-class([range(43,43)])],{}),[char(43)]),appl(prod(layouts("Whitespace"),[\iter-star(\char-class([range(9,10),range(13,13),range(32,32)]))],{}),[appl(regular(\iter-star(\char-class([range(9,10),range(13,13),range(32,32)]))),[])[@loc=|file://-|(2,0,<1,2>,<1,2>)]])[@loc=|file://-|(2,0,<1,2>,<1,2>)],appl(prod(sort("Exp"),[lex("IntegerLiteral")],{}),[appl(prod(lex("IntegerLiteral"),[iter(\char-class([range(48,57)]))],{}),[appl(regular(iter(\char-class([range(48,57)]))),[char(51)])[@loc=|file://-|(2,1,<1,2>,<1,3>)]])[@loc=|file://-|(2,1,<1,2>,<1,3>)]])[@loc=|file://-|(2,1,<1,2>,<1,3>)]])[@loc=|file://-|(0,3,<1,0>,<1,3>)]
Next, we define a load function:
module demo::lang::Exp::Combined::Manual::Load

import demo::lang::Exp::Concrete::WithLayout::Syntax;  
import demo::lang::Exp::Abstract::Syntax;              
import demo::lang::Exp::Combined::Manual::Parse;       
import String;
import ParseTree;

public Exp loadExp(str txt) = load(parseExp(txt));        
     
public Exp load((Exp)`<IntegerLiteral l>`)             
       = con(toInt("<l>"));       
public Exp load((Exp)`<Exp e1> * <Exp e2>`) 
       = mul(load(e1), load(e2));  
public Exp load((Exp)`<Exp e1> + <Exp e2>`)
       = add(load(e1), load(e2)); 
public Exp load((Exp)`( <Exp e> )`) 
       = load(e);                    
Some comments:
  • We reuse the previously defined concrete syntax with layout.
  • We also reuse the previously defined abstract syntax.
  • Import the Parse module defined above.
  • The top level load function that converts a string to an abstract syntax tree.
  • The conversion from parse tree to abstract syntax tree start here. Note that we explicitly use demo::lang::Exp::Concrete::WithLayout::Syntax::Exp in these rules to distinguish from demo::lang::Exp::Abstract::Syntax::Exp.
Let's try it:
rascal>import demo::lang::Exp::Combined::Manual::Load;
ok
rascal>loadExp("2+3");
Exp: add(
  con(2),
  con(3))


What remains is to write the interpreter using the above components:
module demo::lang::Exp::Combined::Manual::Eval

import demo::lang::Exp::Abstract::Syntax;
import demo::lang::Exp::Abstract::Eval;
import demo::lang::Exp::Combined::Manual::Load;

public int eval(str txt) = eval(loadExp(txt));
Here is how it works:
rascal>import demo::lang::Exp::Combined::Manual::Eval;
ok
rascal>eval("2+3");
int: 5
Is this page unclear, or have you spotted an error? Please add a comment below and help us to improve it. For all other questions and remarks, visit ask.rascal-mpl.org.