Parse command substitutions
This commit is contained in:
parent
ca5d64eca7
commit
a97f38a7b9
4 changed files with 147 additions and 13 deletions
|
@ -17,13 +17,23 @@ exports[`Parsing Notcl Misc Big mess of markup 1`] = `
|
|||
"enchanted": "para",
|
||||
},
|
||||
{
|
||||
"text": "[2",
|
||||
},
|
||||
{
|
||||
"enchanted": "+",
|
||||
},
|
||||
{
|
||||
"text": "2]",
|
||||
"pieces": [
|
||||
{
|
||||
"script": [
|
||||
[
|
||||
{
|
||||
"enchanted": "2",
|
||||
},
|
||||
{
|
||||
"enchanted": "+",
|
||||
},
|
||||
{
|
||||
"enchanted": "2",
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
|
|
|
@ -129,7 +129,118 @@ b`)
|
|||
// variables- bare, brace
|
||||
});
|
||||
|
||||
describe("command interpolation", () => {});
|
||||
describe("command interpolation", () => {
|
||||
it("can parse empty command interpolations", () =>
|
||||
expect(parse("[]")).toEqual([true, [[{ pieces: [{ script: [] }] }]]]));
|
||||
it("can parse one-word command interpolations", () =>
|
||||
expect(parse("[a]")).toEqual([
|
||||
true,
|
||||
[[{ pieces: [{ script: [[{ enchanted: "a" }]] }] }]],
|
||||
]));
|
||||
it("can parse multi-word command interpolations", () =>
|
||||
expect(parse("[a b c]")).toEqual([
|
||||
true,
|
||||
[
|
||||
[
|
||||
{
|
||||
pieces: [
|
||||
{
|
||||
script: [
|
||||
[
|
||||
{ enchanted: "a" },
|
||||
{ enchanted: "b" },
|
||||
{ enchanted: "c" },
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
]));
|
||||
it("can parse multi-command command interpolations", () =>
|
||||
expect(parse("[a; b c]")).toEqual([
|
||||
true,
|
||||
[
|
||||
[
|
||||
{
|
||||
pieces: [
|
||||
{
|
||||
script: [
|
||||
[{ enchanted: "a" }],
|
||||
[{ enchanted: "b" }, { enchanted: "c" }],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
]));
|
||||
it("can parse nested command interpolations", () =>
|
||||
expect(parse("[[a]]")).toEqual([
|
||||
true,
|
||||
[
|
||||
[
|
||||
{
|
||||
pieces: [
|
||||
{
|
||||
script: [[{ pieces: [{ script: [[{ enchanted: "a" }]] }] }]],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
]));
|
||||
|
||||
it("can parse pre-word command interpolations", () =>
|
||||
expect(parse("[a]b")).toEqual([
|
||||
true,
|
||||
[[{ pieces: [{ script: [[{ enchanted: "a" }]] }, { text: "b" }] }]],
|
||||
]));
|
||||
it("can parse mid-word command interpolations", () =>
|
||||
expect(parse("a[b]c")).toEqual([
|
||||
true,
|
||||
[
|
||||
[
|
||||
{
|
||||
pieces: [
|
||||
{ text: "a" },
|
||||
{ script: [[{ enchanted: "b" }]] },
|
||||
{ text: "c" },
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
]));
|
||||
it("can parse end-word command interpolations", () =>
|
||||
expect(parse("a[b]")).toEqual([
|
||||
true,
|
||||
[[{ pieces: [{ text: "a" }, { script: [[{ enchanted: "b" }]] }] }]],
|
||||
]));
|
||||
it("can parse multiple command interpolations in a word", () =>
|
||||
expect(parse("[a][b]")).toEqual([
|
||||
true,
|
||||
[
|
||||
[
|
||||
{
|
||||
pieces: [
|
||||
{ script: [[{ enchanted: "a" }]] },
|
||||
{ script: [[{ enchanted: "b" }]] },
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
]));
|
||||
|
||||
test.each(["[", "a["])(
|
||||
"does not permit unterminated commands {%s}",
|
||||
(text) => expect(parse(text)).toMatchObject([false, {}])
|
||||
);
|
||||
test.each(['["]"', '"["]', "[{]}", "{[}]"])(
|
||||
"does not permit overlapping commands and quotes {%s}",
|
||||
(text) => expect(parse(text)).toMatchObject([false, {}])
|
||||
);
|
||||
});
|
||||
|
||||
describe("brace words", () => {
|
||||
it("can parse empty braces", () =>
|
||||
|
|
19
src/notcl.ts
19
src/notcl.ts
|
@ -13,6 +13,7 @@ import {
|
|||
EnchantedWord as EnchantedWordType,
|
||||
InterpolatedPiece,
|
||||
Script,
|
||||
ScriptPiece,
|
||||
SimplifyWord,
|
||||
TextWord,
|
||||
Word as WordType,
|
||||
|
@ -24,7 +25,7 @@ const Comment = Regex(/#[^\n]*/y)
|
|||
|
||||
const PreWordWhitespace = Regex(/[^\S\n;]+/y).expects("whitespace");
|
||||
|
||||
const EnchantedWord = Regex(/[^\]\[\}\{$\\";\s]+(?=[\s;]|$)/y)
|
||||
const EnchantedWord = Regex(/[^\]\[\}\{$\\";\s]+(?=[\s;\]]|$)/y)
|
||||
.map(([enchanted]) => ({ enchanted } as EnchantedWordType))
|
||||
.expects("ENCHANTED_WORD");
|
||||
|
||||
|
@ -32,7 +33,16 @@ const BackslashEscape = Regex(/\\(.)/y)
|
|||
.expects("\\")
|
||||
.map(([, char]) => ({ text: char }));
|
||||
|
||||
const BARE_WORD_CHAR = /[^\s\\;]+/y;
|
||||
const BARE_WORD_CHAR = /[^\s\\;\[]+/y;
|
||||
const BARE_BRACKET_WORD_CHAR = /[^\s\\;\[\]]+/y;
|
||||
|
||||
let BracketScript: Pattern<Script>;
|
||||
const Bracket: Pattern<ScriptPiece> = Sequence(
|
||||
Regex(/\[/y).expects("["),
|
||||
Use(() => BracketScript)
|
||||
)
|
||||
.expects("[")
|
||||
.map(([, script]) => ({ script }));
|
||||
|
||||
function bareWordTmpl(charRegex: RegExp) {
|
||||
return Sequence(
|
||||
|
@ -41,6 +51,7 @@ function bareWordTmpl(charRegex: RegExp) {
|
|||
1,
|
||||
Choose<InterpolatedPiece>(
|
||||
BackslashEscape,
|
||||
Bracket,
|
||||
Regex(charRegex)
|
||||
.expects("CHAR")
|
||||
.map(([text]) => ({ text }))
|
||||
|
@ -55,7 +66,8 @@ const QuotedWord = Sequence(
|
|||
0,
|
||||
Choose<InterpolatedPiece>(
|
||||
BackslashEscape,
|
||||
Regex(/[^"\\]+/y)
|
||||
Bracket,
|
||||
Regex(/[^"\\\[]+/y)
|
||||
.expects("CHAR")
|
||||
.map(([text]) => ({ text }))
|
||||
)
|
||||
|
@ -128,6 +140,7 @@ function scriptTmpl(bareWordCharRegex: RegExp, endPattern: Pattern<unknown>) {
|
|||
}
|
||||
|
||||
const Script = scriptTmpl(BARE_WORD_CHAR, End());
|
||||
BracketScript = scriptTmpl(BARE_BRACKET_WORD_CHAR, Regex(/\]/y).expects("]"));
|
||||
|
||||
const ERROR_CONTEXT = /(?<=([^\n]{0,50}))([^\n]{0,50})/y;
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ export type HtmlWord = {
|
|||
|
||||
export type TextPiece = TextWord;
|
||||
export type VariablePiece = { variable: string };
|
||||
export type CommandPiece = { command: unknown };
|
||||
export type InterpolatedPiece = TextPiece | VariablePiece | CommandPiece;
|
||||
export type ScriptPiece = { script: Script };
|
||||
export type InterpolatedPiece = TextPiece | VariablePiece | ScriptPiece;
|
||||
|
||||
/**
|
||||
* A word whose value needs to be determined by evaluating some combination of variable and command
|
||||
|
|
Loading…
Reference in a new issue