Skip to content

Instantly share code, notes, and snippets.

@neopunisher
Created May 21, 2018 15:31
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 neopunisher/2c6838ad56c33519b5351ab78aaa403e to your computer and use it in GitHub Desktop.
Save neopunisher/2c6838ad56c33519b5351ab78aaa403e to your computer and use it in GitHub Desktop.
let tokens = [];
let dsl = new Proxy({}, {
get(state, token) {
// Before anything, we're going to try and access a variable
if (tokens.length === 0 && state[token] !== undefined) {
return state[token];
}
tokens.push(token);
const rule = grammar[tokens[0]];
if (rule) {
if (tokens.length !== rule.length) {
return dsl;
}
return rule({ dsl, state, tokens }, ...tokens.slice(1));
}
// No matching rule, just keep on chugging along
return dsl;
}
});
const grammar = {
fizzz({ dsl, tokens }) {
tokens.splice(0, tokens.length);
dsl.log('Fizz');
return dsl;
},
buzzz({ dsl, tokens }) {
tokens.splice(0, tokens.length);
dsl.log('Buzz');
return dsl;
},
loop({ dsl, tokens }) {
tokens.splice(0, tokens.length);
return (predicate, body) => {
while (predicate()) {
body();
}
return dsl;
};
},
iff({ dsl, tokens }) {
tokens.splice(0, tokens.length);
return (...args) => {
for (let i = 0; i < args.length; i += 2) {
let predicate = args[i];
let body = args[i + 1];
// If there's no body, this must be the `else` clause
if (!body) {
predicate();
return dsl;
}
if (predicate()) {
body();
return dsl;
}
}
return dsl;
};
},
set({ dsl, state, tokens }, identifier) {
tokens.splice(0, tokens.length);
return (value) => {
state[identifier] = value;
return dsl;
};
},
fizz({ dsl, tokens }, buzz) {
if (buzz !== 'buzz') {
throw new SyntaxError(`Expected "buzz", got "${buzz}"`);
}
tokens.splice(0, tokens.length);
dsl.log('FizzBuzz');
return dsl;
},
log({ dsl, tokens }) {
tokens.splice(0, tokens.length);
return (...args) => {
console.log(...args);
return dsl;
};
}
};
dsl.
set.i(1).
set.isFizz(x => x % 3 === 0).
set.isBuzz(x => x % 5 === 0).
loop(() => dsl.i <= 100, () =>
dsl.
iff(
() => dsl.isFizz(dsl.i) && dsl.isBuzz(dsl.i), () =>
dsl.fizz.buzz,
() => dsl.isFizz(dsl.i), () =>
dsl.fizzz,
() => dsl.isBuzz(dsl.i), () =>
dsl.buzzz,
() => dsl.log(dsl.i)
).
set.i(dsl.i + 1)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment