This is a simple page demonstrating an nlScript language for configuring a fluorescence staining robot. This is just a proof of principal and does not contain any functionality, but demonstrates what such a language could look like.
let parser = new nlScript.Parser();
let liquids = new Set();
parser.defineType("dispenser", "dispenser-01", pn => 1);
parser.defineType("dispenser", "dispenser-02", pn => 2);
parser.defineType("dispenser", "dispenser-03", pn => 3);
parser.defineType("dispenser", "dispenser-04", pn => 4);
parser.defineType("dispenser", "dispenser-05", pn => 5);
parser.defineType("dispenser", "dispenser-06", pn => 6);
parser.defineType("dispenser", "dispenser-07", pn => 7);
parser.defineType("dispenser", "dispenser-08", pn => 8);
parser.defineType("dispenser", "dispenser-09", pn => 9);
parser.defineType("dispenser", "dispenser-10", pn => 10);
for(let i = 0; i < 12; i++) {
let c = i < 9 ? "0" + (i + 1) : "" + (i + 1);
parser.defineType("well-column", c, undefined);
}
for(let i = 0; i < 8; i++)
parser.defineType("well-row", String.fromCharCode('A'.charCodeAt(0) + i), undefined);
parser.defineType("well", "{row:well-row}/{column:well-column}", undefined, true);
parser.defineType("well-range", "{start:well}-{stop:well}", undefined, true);
parser.defineType("well-or-range", "{well:well}", undefined, true);
parser.defineType("well-or-range", "{range:well-range}", undefined, true);
parser.defineType("wells", "{wells:list:+}", undefined);
parser.defineType("amount", "{n:int} uL", pn => pn.evaluate("n"), true);
parser.defineType("liquid-name", "'{liquid:[^']:+}'", pn => pn.getParsedString("liquid"), true);
parser.defineType("n-times", "once", pn => 1);
parser.defineType("n-times", "twice", pn => 2);
parser.defineType("n-times", "{n:int} times", pn => pn.evaluate("n"), true);
parser.defineType("liquid", "PBS", pn => pn.getParsedString());
parser.defineType("percentage", "{percentage:float}% {liquid:liquid}", undefined, true);
parser.defineType("another-percentage", ", {percentage:percentage}", undefined, true);
parser.defineSentence("Define solution {name:liquid-name} by diluting {first:percentage}{others:another-percentage:*} in {liquid:liquid}.", undefined).onSuccessfulParsed((pn) => {
if(pn.getMatcher().state == nlScript.ParsingState.SUCCESSFUL) {
const parsed = pn.evaluate("name");
if(!liquids.has(parsed)) {
liquids.add(parsed);
parser.defineType("liquid", parsed, undefined);
}
}
});
parser.defineType("time-unit", "second(s)", undefined);
parser.defineType("time-unit", "minute(s)", undefined);
parser.defineType("time-unit", "hour(s)", undefined);
parser.defineType("duration", "{n:float} {time-unit:time-unit}", undefined, true);
parser.defineType("temperature", "room temperature", null);
parser.defineType("temperature", "{n:float} \u00B0C", null, true);
parser.defineSentence("Connect {dispenser:dispenser} to {liquid:liquid-name}.", null).onSuccessfulParsed((pn) => {
if(pn.getMatcher().state == nlScript.ParsingState.SUCCESSFUL) {
const parsed = pn.evaluate("liquid");
if(!liquids.has(parsed)) {
liquids.add(parsed);
parser.defineType("liquid", parsed, undefined);
}
}
});
parser.defineSentence("Incubate well(s) {wells:wells} {n:n-times} with {amount:amount} {liquid:liquid} for {duration:duration} at {temperature:temperature}.", null);
parser.defineSentence("Wash well(s) {wells:wells} {n:n-times} with {amount:amount} {liquid:liquid} for {duration:duration} at {temperature:temperature}.", null);
parser.defineSentence("Rinse well(s) {wells:wells} {n:n-times} with {amount:amount} {liquid:liquid}.", null);
parser.addParseStartListener(() => {
liquids.clear();
parser.undefineType("liquid");
});
new nlScript.ACEditor(parser, document.getElementById("nls-container"));