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