You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, I've fiddled with a piece of code which is similar to yours in terms of functionalities.
I've distinguished allocation from interpolation:
Allocation: [[ key = {{ value | modifier : parameter }} ]]
Interpolation: {{ value | modifier : parameter }}
As you can see the allocation can also contains an interpolation, but it's not necessary when you have to pop, to do that: [[ key = POP ]]
With this syntax is possible to chain modifier with their parameter: {{ value | modifier1 | modifier2 : param1 | modifier3 : param1 : param2 }}
In the example value is fed to modifier1 which has no params, the result is then fed into modifier2 which has a single param and all is ultimately fed into modifier3 which has a couple of params.
class Grammar {
constructor() {
this.rules = {};
this.modifiers = {};
this.variables = {};
this.randomFn = Math.random;
}
// rule: "key -> value1 | value2 | value3"
setRule(rule) {
let validationRegex = /^ *[^->]+ * -> *[^->|]+( *\| *[^->| ]+[^->|]*)* *$/;
if (!validationRegex.test(rule)) {
console.error("Something wrong in your rule");
return;
}
let [key, values] = rule.split(/ *-> */);
values = values.split(/ *\| */);
this.rules[key] = values;
}
setModifier(name, fn) {
this.modifiers[name] = fn;
}
pickRandom(list) {
return list[Math.floor(this.randomFn() * list.length)];
}
evaluate(expr) {
let [value, ...modifiers] = expr.split(/ *\| */);
if (this.variables[expr]) {
return this.variables[expr][this.variables[expr].length - 1];
}
if (!this.rules[value]) {
console.error("No rule found with the name: " + value);
return;
}
value = this.pickRandom(this.rules[value]);
if (!modifiers.length) {
return value;
}
for (let modifier of modifiers) {
let [modifierName, ...params] = modifier.split(/ *: */);
if (!this.modifiers[modifierName]) {
console.error("No modifier found with the name: " + modifierName);
return;
}
value = this.modifiers[modifierName](value, ...params)
}
return value;
}
expand(text) {
console.log(text); // Console each step
let interpolation = " *{{ *([^|]+?( *\\| *([^: ]+( *: *[^: ]+)*) *?)*) *}} *";
let allocation = ` *\\[\\[ *([^{}[\\]]+?) *=(${interpolation}| *POP *)\\]\\] *`;
let interpolationRegex = new RegExp(`^${interpolation}$`);
let allocationRegex = new RegExp(`^${allocation}$`);
if (!(new RegExp(interpolation)).test(text) && !(new RegExp(allocation)).test(text)) {
return text;
}
let result = text.replace(/(\[\[(.*?)\]\]|{{(.*?)}})/g, text => {
if (allocationRegex.test(text)) {
let [_, key, pop, expr] = text.match(allocationRegex);
if (pop.trim() === "POP") {
if (!this.variables[key]) {
console.error("Nothing to pop at: " + key);
return;
}
this.variables[key].pop();
if (!this.variables[key].length) {
delete this.variables[key];
}
return "";
}
let value = this.evaluate(expr);
if (!this.variables[key]) {
this.variables[key] = [];
}
this.variables[key].push(value);
return value;
}
if (interpolationRegex.test(text)) {
let expr = text.match(interpolationRegex)[1];
return this.evaluate(expr);
}
console.error("Something wrong in your text");
});
this.expand(result);
}
}
var g = new Grammar();
g.setRule("adj -> dark | stormy | beautiful");
g.setRule("noun -> {{adj}} night");
g.setModifier("discapitalize", (text, howMany) => {
howMany = Number(howMany);
let result = "";
for (let i = 0; i < text.length; i++) {
if (i < howMany) {
result += text[i].toLowerCase();
} else {
result += text[i];
}
}
return result;
});
g.setModifier("capitalize", (text, howMany) => {
howMany = Number(howMany);
let result = "";
for (let i = 0; i < text.length; i++) {
if (i < howMany) {
result += text[i].toUpperCase();
} else {
result += text[i];
}
}
return result;
});
g.expand("It was a [[ adjective = {{ adj | capitalize : 3 | discapitalize : 2 }} ]] and {{ adjective }} {{ noun }}");
// The above expansion will result in the following rounds:
// Step 0: It was a [[ adjective = {{ adj | capitalize : 3 | discapitalize : 2 }} ]] and {{ adjective }} {{ noun }}
// Step 1: It was a beAutiful and beAutiful {{adj}} night
// Step 2: It was a beAutiful and beAutiful dark night
The text was updated successfully, but these errors were encountered:
Hi, I've fiddled with a piece of code which is similar to yours in terms of functionalities.
I've distinguished allocation from interpolation:
Allocation:
[[ key = {{ value | modifier : parameter }} ]]
Interpolation:
{{ value | modifier : parameter }}
As you can see the allocation can also contains an interpolation, but it's not necessary when you have to pop, to do that:
[[ key = POP ]]
With this syntax is possible to chain modifier with their parameter:
{{ value | modifier1 | modifier2 : param1 | modifier3 : param1 : param2 }}
In the example
value
is fed tomodifier1
which has no params, the result is then fed intomodifier2
which has a single param and all is ultimately fed intomodifier3
which has a couple of params.The text was updated successfully, but these errors were encountered: