Skip to content

Instantly share code, notes, and snippets.

@heidisu
Created June 25, 2015 21:30
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 heidisu/00d36641d320f9053393 to your computer and use it in GitHub Desktop.
Save heidisu/00d36641d320f9053393 to your computer and use it in GitHub Desktop.
Language and validator for solving the Zebra Puzzle with Xtext
grammar org.xtext.example.zebra.Zebra with org.eclipse.xtext.common.Terminals
generate zebra "http://www.xtext.org/example/zebra/Zebra"
Model:
houses+=House*;
enum Color:
Red | Blue | Green | Yellow | Ivory
;
enum Pet:
Fox | Horse | Snails | Dog | Zebra
;
enum Nationality:
Norwegian | Ukrainian | Englishman | Spaniard | Japanese
;
enum Drink:
Water | Tea | Milk | Orange_juice | Coffee
;
enum Smoke:
Kools | Chesterfield | Old_Gold | Lucky_Strike| Parliament
;
House :
'House {'
color=Color
pet=Pet
nationality=Nationality
drink=Drink
smoke=Smoke
'}'
;
/*
* generated by Xtext
*/
package org.xtext.example.zebra.validation
import org.eclipse.xtext.validation.Check
import org.xtext.example.zebra.zebra.Model
import org.xtext.example.zebra.zebra.ZebraPackage
import org.xtext.example.zebra.zebra.Drink
import org.xtext.example.zebra.zebra.Color
import org.xtext.example.zebra.zebra.Nationality
import org.xtext.example.zebra.zebra.Pet
import org.xtext.example.zebra.zebra.Smoke
/**
* This class contains custom validation rules.
*
* There are five houses.
* The Englishman lives in the red house.
* The Spaniard owns the dog.
* Coffee is drunk in the green house.
* The Ukrainian drinks tea.
* The green house is immediately to the right of the ivory house.
* The Old Gold smoker owns snails.
* Kools are smoked in the yellow house.
* Milk is drunk in the middle house.
* The Norwegian lives in the first house.
* The man who smokes Chesterfields lives in the house next to the man with the fox.
* Kools are smoked in the house next to the house where the horse is kept.
* The Lucky Strike smoker drinks orange juice.
* The Japanese smokes Parliaments.
* The Norwegian lives next to the blue house.
*/
class ZebraValidator extends AbstractZebraValidator {
@Check
def checkFiveHouses(Model model){
if(model.houses.size != 5){
warning('There must be five houses', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def checkDifferentColors(Model model){
val colors = model.houses.map[color]
if(!Color.values.forall[color|colors.contains(color)]){
warning('Houses must have distinct colors', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def checkDifferentDrinks(Model model){
val drinks = model.houses.map[drink]
if(!Drink.values.forall[drink|drinks.contains(drink)]){
warning('Houses must have distinct drinks', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def checkDifferentSmokes(Model model){
val smokes = model.houses.map[smoke];
if(!Smoke.values.forall[smoke|smokes.contains(smoke)]){
warning('Houses must have distinct smokes', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def checkDifferentPets(Model model){
val pets = model.houses.map[pet];
if(!Pet.values.forall[pet|pets.contains(pet)]){
warning('Houses must have distinct pets', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def checkDifferentNationalities(Model model){
val nationalities = model.houses.map[nationality];
if(!Nationality.values.forall[nationality|nationalities.contains(nationality)]){
warning('Houses must have distinct nationalities', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def englishmanLivesInTheRedHouse(Model model){
if(!model.houses.findFirst[house|house.color.equals(Color.RED)].nationality.equals(Nationality.ENGLISHMAN)){
warning('The Englishman must live in the red house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def spaniardOwnsTheDog(Model model){
if(!model.houses.findFirst[house|house.pet.equals(Pet.DOG)].nationality.equals(Nationality.SPANIARD)){
warning('The Spaniard must own the dog', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def coffeeIsDrunkInGreenHouse(Model model){
if(!model.houses.findFirst[house|house.drink.equals(Drink.COFFEE)].color.equals(Color.GREEN)){
warning('Coffee must be drunk in the green house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def ukranianDrinksTea(Model model){
if(!model.houses.findFirst[house| house.drink.equals(Drink.TEA)].nationality.equals(Nationality.UKRAINIAN)){
warning('The Ukrainian must drink tea', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def greenHouseNextToIvoryHouse(Model model){
var ivoryNumber = model.houses.indexed.findFirst[pair|pair.value.color.equals(Color.IVORY)].key
var greenNumber = model.houses.indexed.findFirst[pair|pair.value.color.equals(Color.GREEN)].key
if(ivoryNumber + 1 != greenNumber){
warning('The green house must be immediately to the right of the ivory house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def oldGoldSmokerHasSnails(Model model){
if(!model.houses.findFirst[house|house.smoke.equals(Smoke.OLD_GOLD)].pet.equals(Pet.SNAILS)){
warning('The Old Gold smoker must own the snails', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def koolsAreSmokedInYellowHouse(Model model){
if(!model.houses.findFirst[house|house.smoke.equals(Smoke.KOOLS)].color.equals(Color.YELLOW)){
warning('Kools must be smoked in the yellow house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def milkAreDrunkInTheMiddleHouse(Model model){
if(!model.houses.indexed.findFirst[pair|pair.key == 2].value.drink.equals(Drink.MILK)){
warning('Milk must be drunk in the middle house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def norwegianLivesInTheFirstHouse(Model model){
if(!model.houses.indexed.findFirst[pair|pair.key == 0].value.nationality.equals(Nationality.NORWEGIAN)){
warning('The Norwegian must live in the first house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def manWhoSmokesChesterfieldLivesInHouseNextToFox(Model model){
var chesterfieldNumber = model.houses.indexed.findFirst[pair|pair.value.smoke.equals(Smoke.CHESTERFIELD)].key
var foxNumber = model.houses.indexed.findFirst[pair|pair.value.pet.equals(Pet.FOX)].key
if(!(chesterfieldNumber == foxNumber + 1 || chesterfieldNumber == foxNumber - 1)){
warning('The man who smokes Chesterfields must live in the house next to the man with the fox',
ZebraPackage.Literals.MODEL__HOUSES
)
}
}
@Check
def koolsAreSmokedInHouseNextToHorse(Model model){
var koolsNumber = model.houses.indexed.findFirst[pair|pair.value.smoke.equals(Smoke.KOOLS)].key
var horseNumber = model.houses.indexed.findFirst[pair|pair.value.pet.equals(Pet.HORSE)].key
if(!(koolsNumber == horseNumber + 1 || koolsNumber == horseNumber - 1)){
warning('Kools must be smoked in the house next to the house where the horse is kept',
ZebraPackage.Literals.MODEL__HOUSES
)
}
}
@Check
def luckyStrikeSmokerDrinksOrangeJuice(Model model){
if(!model.houses.findFirst[house|house.drink.equals(Drink.ORANGE_JUICE)].smoke.equals(Smoke.LUCKY_STRIKE)){
warning('The Lucky Strike smoker must drink orange juice', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def japaneseSmokesParliament(Model model){
if(!model.houses.findFirst[house|house.smoke.equals(Smoke.PARLIAMENT)].nationality.equals(Nationality.JAPANESE)){
warning('The Japanese smokes Parliaments', ZebraPackage.Literals.MODEL__HOUSES)
}
}
@Check
def norwegianLivesNextToBlueHouse(Model model){
var norwegianNumber = model.houses.indexed.findFirst[pair|pair.value.nationality.equals(Nationality.NORWEGIAN)].key
var blueNumber = model.houses.indexed.findFirst[pair|pair.value.color.equals(Color.BLUE)].key
if(!(blueNumber == norwegianNumber + 1 || blueNumber == norwegianNumber - 1)){
warning('The Norwegian must live next to the blue house', ZebraPackage.Literals.MODEL__HOUSES)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment