diff --git a/3x5.js b/3x5.js index 355aa05..940da9a 100644 --- a/3x5.js +++ b/3x5.js @@ -24,7 +24,7 @@ * @returns {string} Markup to render / output */ function renderCard(state, code) { - const script = parseNotcl(code); + const script = Notcl.parse(code); state.output = JSON.stringify(script, null, 2); return state.output; } diff --git a/notcl.js b/notcl.js index 180d15c..187e36a 100644 --- a/notcl.js +++ b/notcl.js @@ -1,84 +1,88 @@ /** - * @typedef {Command[]} Script - * @typedef {Word[]} Command - * @typedef {object} Word + * @typedef {Notcl.Command[]} Notcl.Script + * @typedef {Notcl.Word[]} Notcl.Command + * @typedef {object} Notcl.Word * @property {string} text */ -const InterCommandWhitespace = Peg.Regex(/[^\S\n;]*/y); +var Notcl = (() => { + const InterCommandWhitespace = Peg.Regex(/[^\S\n;]*/y); -const CommentPattern = Peg.Regex(/#.*\n/y); + const Comment = Peg.Regex(/#.*\n/y); -const PreWordWhitespace = Peg.Regex(/[^\S\n;]*/y); + const PreWordWhitespace = Peg.Regex(/[^\S\n;]*/y); -const BasicWord = Peg.Map(Peg.Regex(/[^\s;]+/y), ([word]) => ({ - text: word, -})); + const BasicWord = Peg.Map(Peg.Regex(/[^\s;]+/y), ([word]) => ({ + text: word, + })); -const WordPattern = Peg.Map( - Peg.Sequence(PreWordWhitespace, BasicWord), - ([_, word]) => word -); + const Word = Peg.Map( + Peg.Sequence(PreWordWhitespace, BasicWord), + ([_, word]) => word + ); -/** - * 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"); + return { + /** + * Parse out a Notcl script into an easier-to-interpret representation. + * No script is actually executed yet. + * + * @param {string} code + * @returns Script + */ + parse(code) { + /* Preprocess */ + // fold line endings + code = code.replace(/(?<!\\)((\\\\)*)\\\n/g, "$1"); - /* Parse */ - function nextWord(/* TODO: null/]/" terminator */) { - // TODO: handle all kinds of brace/substitution stuff - const [word, nextIndex] = WordPattern(code, 0) ?? [null, 0]; - if (word) { - code = code.substring(nextIndex); - return word; - } 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; + /* Parse */ + function nextWord(/* TODO: null/]/" terminator */) { + // TODO: handle all kinds of brace/substitution stuff + const [word, nextIndex] = Word(code, 0) ?? [null, 0]; + if (word) { + code = code.substring(nextIndex); + return word; + } else { + return null; + } } - // Strip semicolons - if (code[0] == ";") { - code = code.substring(1); - continue; + + function nextCommand(/* TODO: null/]/" terminator */) { + const command = /** @type {Notcl.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; } - break; - } - while (true) { - const word = nextWord(); - if (word) { - command.push(word); - continue; + /* Loop through commands, with safety check */ + const script = /** @type {Notcl.Command[]} */ ([]); + for (let i = 0; i < 1000 && code != ""; i++) { + script.push(nextCommand()); } - 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; -} + return script; + }, + }; +})();