prototype-3x5/notcl.js

71 lines
1.6 KiB
JavaScript

/**
* @typedef {Command[]} Script
* @typedef {Word[]} Command
* @typedef {object} Word
* @property {string} text
*/
/**
* Parse out a Notcl script into an easier-to-interpret representation.
* No script is actually executed yet.
*
* @param {string} code
* @returns Script
*/
function parseNotcl(code) {
/* Preprocess */
// fold line endings
code = code.replace(/(?<!\\)((\\\\)*)\\\n/g, "$1");
/* Parse */
function nextWord(/* TODO: null/] terminator */) {
// Strip whitespace
code = code.replace(/^[^\S\n;]*/, "");
// TODO: handle all kinds of brace/substitution stuff
const word = code.match(/^[^\s;]+/);
if (word) {
code = code.substring(word[0].length);
return { text: word[0] };
} else {
return null;
}
}
function nextCommand(/* TODO: null/] terminator */) {
const command = /** @type {Word[]} */ ([]);
while (true) {
// Strip whitespace
code = code.replace(/^\s*/, "");
// Strip comments
if (code[0] == "#") {
code = code.replace(/^.*\n/, "");
continue;
}
// Strip semicolons
if (code[0] == ";") {
code = code.substring(1);
continue;
}
break;
}
while (true) {
const word = nextWord();
if (word) {
command.push(word);
continue;
}
break;
}
return command;
}
/* Loop through commands, with safety check */
const script = /** @type {Command[]} */ ([]);
for (let i = 0; i < 1000 && code != ""; i++) {
script.push(nextCommand());
}
return script;
}