A Little C Language


Summary

This article shows how to define a simple C-like language in XMF.  An interesting feature of this language is that it supports the weaving (embedding of) XCore within it using the '@' syntax.  See the C_XOCL grammar for the definition of this plug point.


Example

// Start in XCore ...

if self.timeForC()
then

// Let's drop into C ...

@C
    // Some C stuff ...

    int x;
    x = 10;
    while(x > 0) {

      // Back to XCore ...

      @x.println();

      // Back to C ...

      x = x - 1;

    }

end

// Back out to XCore

else
 self.noCforMe()
end

Language Definition


context Root


@Class Command isabstract

// The C parser produces commands...

@AbstractOp combine(next:Performable)

// Commands are combined...

end
end

context Root

@Class BasicCommand extends Command

// A basic command is just an XOCL expression...

@Attribute exp : Performable end

@Constructor(exp) end

@Operation combine(next:Performable)

// Combination just performs one then the next...

[| <exp>; <next> |]
end
end

context Root

@Class Local extends Command

// A local variable introduction...

@Attribute name : String end
@Attribute type : String end

@Constructor(type,name) end

@Operation combine(next:Performable)

// Combination must use an XOCL let and nest the following
// expression to get the scope right...
[| let <name> = <self.value()> in <next> end |]
end

@Operation value()
@Case type of
// A case per C-type...
"int" do [| 0 |] end
end
end
end

context Root

@Class C

@Grammar extends OCL::OCL.grammar

C ::=
// Start here...
C_BlockBody 'end'.

C_BlockBody ::=
// A sequence of commands. Combine to chain together and nest
// the lets correctly...
cs = C_Command*
{ cs->reverse->iterate(c e = [| null |] | c.combine(e)) }.

C_Command ::=
// A disjunction of commands...
C_Local | C_Update | C_If | C_Block | C_While | C_XOCL.

C_Block ::=
// The scopes will be properly local since the nested
// commands are pre-combined then returned as a basic command...
'{' b = C_BlockBody '}'
{ BasicCommand(b) }.

C_Local ::=
t = Name n = Name ';'
{ Local(t,n) }.

C_Update ::=
// Use the SimpleExp rule inherited from the XOCL grammar...
n = Name '=' e = SimpleExp ';'
{ BasicCommand([| <Var(n)> := <e> |]) }.

C_If ::=
'if' '(' e = Exp ')' c = C_Command
{ BasicCommand( [| if <e> then <c.combine([|null|])> end |]) }.

C_XOCL ::=
// Allow XOCL commands to occur in the C language by
// preceding them with an '@' char...
'@' e = SimpleExp ';' { BasicCommand(e) }.

C_While ::=
'while' '(' e = Exp ')' c = C_Command
{ BasicCommand([| @While <e> do <c.combine([| null |])> end |]) }.
end
end