ritajs-v2
ritajs-v2 copied to clipboard
Grammars in Twine
I'd like to support the following two types of grammar cases (with and without closing tag). Can you see if this is possible?
<<rg $rules >>
<<rg>>
{
rules
}
<</rg>>
I think this
<<rg $rules>> <<rg>>{}<</rg>>
is not possible at least in sugarCube... coz a Macro is either self-closing or have closing tag, and there can't be two Marcos of the same name
it is possible to have something like this
<<rg $rules>>
<<rg {"start":"a"}>>
//must be a valid json object without line break
//or
<<rg '{ start: "a" }'>>
//can be json or js object and have line-breaker, but must pass in as a string
ok, can you include (either here or in a notebook) the simplest possible code for a <<rg>> macro as below:
<<rg>>{start: $rule1, ... }<</rg>>
<<rg>>$rules<</rg>>
and also with an optional start rule:
<<rg 'optionalStartRuleName'>>$rules<</rg>>
where rules is either a literal JS object, or a previously declared twine variable no need for JSON unless it is an external .json file (not sure how this works in twine)
note: the only added benefit of doing this, over what what he have now, is that we can pass State.variables to grammar.expand automatically
https://observablehq.com/@real-john-cheung/riscript-and-rigrammar-in-twine rules can be a literal JS object, a json object or a twine variable
setup.JSLoaded = false;
setup.lockID = LoadScreen.lock();
function parseObject (obj) {
return Function('"use strict";return (' + obj + ')')();
}
importScripts("https://unpkg.com/rita").then(function () {
Macro.add('rg',{
skipArgs: false,
tags: null,
handler: function () {
let s = this.payload[0].contents.trim();
let o;
try {
o = JSON.parse(s);
} catch(e) {
}
if (!o) {
try {
o = parseObject(s);
} catch {
}
}
if (!o && /^\$[A-Za-z0-9$_]+$/.test(s)){
s = s.replace('$','');
o = State.variables[s] ? State.variables[s] : undefined;
}
if (!o) throw Error("fail to parse grammar, " + s + " is not a vaild object.");
$(this.output).wiki(RiTa.grammar(o).expand(this.args[0],State.variables));
}
});
setup.JSLoaded = true;
Engine.play(passage(), true);
LoadScreen.unlock(setup.lockID);
}).catch(function (err) {
alert(err);
});
the grammar() function already accepts json and js objects, no? why parse them separately ?
because what inside Macro.playload.contents is string, so it need to be parsed into object
grammar() actually can take in JSON string but literal jsobject string need to parsed first
so we don't need JSON.parse in there, correct?
We don't need it (i.e. we can code another (I think will be more complex) version that do the same without it) but maybe we should keep the JSON.parse() because we don't want to pass a random(unchecked) string into grammar(), and with it we can make sure that the type of the parameter pass in grammar() is always object.
sounds good, reassigning to myself