Skip to content

Instantly share code, notes, and snippets.

@svenefftinge
Created September 22, 2015 07:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svenefftinge/4f8259049088a5c55969 to your computer and use it in GitHub Desktop.
Save svenefftinge/4f8259049088a5c55969 to your computer and use it in GitHub Desktop.
// Part 1
org.xtext.homeautomation
// To Be Parsed
Device Window can be OPEN, CLOSED
Device Heating can be ON, OFF
Rule 'Close Window, when heating turned on'
when Heating.ON
then Window.CLOSED
Rule 'Switch off heating, when windows gets opened'
when Window.OPEN
then Heating.OFF
// Grammar
Model:
declarations+=Declaration*
;
Declaration :
Device | Rule
;
Device :
'Device' name=ID 'can' 'be'
(states+=State (',' states+=State)*)?
;
State :
name=ID
;
Rule:
'Rule' description=STRING
'when' when=[State|QualifiedName]
'then' then=[State|QualifiedName];
QualifiedName : ID ('.' ID)*;
// Test
@Inject extension ParseHelper<Model>
@Inject ValidationTestHelper validator
@Inject IGenerator generator
@Test def void testSimpleFile() {
val model = '''
Device Window can be opened, closed
Device Heating can be on, off
Rule 'Close the window when the heating is on'
when Heating.on
then Window.closed
Rule 'Turn off heating when window gets opened'
when Window.opened
then Heating.off
'''.parse
validator.assertNoErrors(model)
val fsa = new InMemoryFileSystemAccess
generator.doGenerate(model.eResource, fsa)
fsa.allFiles.values.head.toString.contains('''
public static void fire(String event) {
if (event.equals("opened")) {
System.out.println("Window is now opened!");
}
if (event.equals("closed")) {
System.out.println("Window is now closed!");
}
if (event.equals("on")) {
System.out.println("Heating is now on!");
}
if (event.equals("off")) {
System.out.println("Heating is now off!");
}
if (event.equals("on")) {
fire("closed");
}
if (event.equals("opened")) {
fire("off");
}
}
''')
}
// Generator
/*
* generated by Xtext
*/
package org.xtext.homeautomation.generator
import java.util.Scanner
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.generator.IGenerator
import org.xtext.homeautomation.rules.Declaration
import org.xtext.homeautomation.rules.Device
import org.xtext.homeautomation.rules.Rule
/**
* Generates code from your model files on save.
*
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
*/
class RulesGenerator implements IGenerator {
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
val simpleClassName = resource.getURI.trimFileExtension.lastSegment
if (resource.contents?.head == null) {
return;
}
val declarations = resource.contents.head.eContents.filter(Declaration)
fsa.generateFile(simpleClassName + '.java', '''
public class «simpleClassName» {
public static void fire(String event) {
«FOR device : declarations.filter(Device)»
«FOR state : device.states»
if (event.equals("«state.name»")) {
System.out.println("«device.name» is now «state.name»!");
}
«ENDFOR»
«ENDFOR»
«FOR rule : declarations.filter(Rule)»
if (event.equals("«rule.when.name»")) {
fire("«rule.then.name»");
}
«ENDFOR»
}
public static void main(String... args) {
try («Scanner.name» scanner = new «Scanner.name»(System.in)) {
System.out.println("Welcome home!");
System.out.println("Available commands : ");
«FOR device : declarations.filter(Device)»
«FOR state : device.states»
System.out.println(" «device.name» «state.name»" );
«ENDFOR»
«ENDFOR»
System.out.println("Have fun!");
while(true) {
String command = scanner.next();
«FOR device : declarations.filter(Device)»
if (command.equalsIgnoreCase("«device.name»")) {
String secondaryCommand = scanner.next();
«FOR state : device.states»
if (secondaryCommand.equalsIgnoreCase("«state.name»")) {
fire("«state.name»");
} else
«ENDFOR»
{
System.out.println("«device.name» can only have the following states: «device.states.map[name].
join(',')».");
}
}
«ENDFOR»
if (command.equalsIgnoreCase("bye")) {
System.out.println("Ciao!");
break;
}
}
}
}
}
''')
}
def ruleMethodName(Rule device) {
'execute' + device.description.replaceAll('\\W', '_')
}
}
// domain model
package com.acme {
entity Person {
name : String
givenName : String
op getFullName() : String {
if (givenName == null) {
return name
} else {
return givenName + " " + name
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment