Syntax change: remove line-folding pass, but accept \ + newline as word separator within command

This commit is contained in:
Tangent Wantwight 2023-11-19 00:56:31 -05:00
parent f5b79af2be
commit bc4a3d7eb7
4 changed files with 21 additions and 29 deletions

View file

@ -114,17 +114,20 @@ exports[`Parsing Notcl Misc Big mess of markup 1`] = `
{
"pos": 656,
"text": "
line endings escaped one slash
line endings escaped\\
one slash
not escaped if \\\\
two slashes
escaped with a slash if \\\\ three slashes
escaped with a slash if \\\\\\
three slashes
not escaped with two slashes if \\\\\\\\
four slashes
escaped with two slashes if \\\\\\\\ five slashes
escaped with two slashes if \\\\\\\\\\
five slashes
not escaped with three slashes if \\\\\\\\\\\\
six slashes

View file

@ -1,4 +1,4 @@
import { parse } from './parser';
import { parse } from "./parser";
describe("Parsing Notcl", () => {
describe("Commands", () => {
@ -25,13 +25,13 @@ describe("Parsing Notcl", () => {
it("does not split commands on folded newlines", () =>
expect(
parse(String.raw`a\
b`)
b`)
).toEqual([
true,
[
[
{ bare: "a", pos: 0 },
{ bare: "b", pos: 2 },
{ bare: "b", pos: 3 },
],
],
]));
@ -44,7 +44,7 @@ b`)
[
[
{ bare: "a", pos: 0 },
{ bare: "b", pos: 2 },
{ bare: "b", pos: 3 },
],
],
]));
@ -56,13 +56,13 @@ b`)
it("does not split commands on folded newlines with escaped backslashes", () =>
expect(
parse(String.raw`a\\\
b`)
b`)
).toEqual([
true,
[
[
{ text: "a\\", pos: 0 },
{ bare: "b", pos: 4 },
{ bare: "b", pos: 5 },
],
],
]));
@ -337,21 +337,21 @@ b`)
it("permits newlines in braces", () =>
expect(parse("{\n}")).toEqual([true, [[{ text: "\n", pos: 0 }]]]));
it("folds newlines in braces", () =>
it("doesn't fold newlines in braces", () =>
expect(
parse(String.raw`{\
}`)
).toEqual([true, [[{ text: " ", pos: 0 }]]]));
).toEqual([true, [[{ text: "\\\n", pos: 0 }]]]));
it("doesn't fold newlines in braces with escaped backslashes", () =>
expect(
parse(String.raw`{\\
}`)
).toEqual([true, [[{ text: "\\\\\n", pos: 0 }]]]));
it("folds newlines in braces with escaped backslashes", () =>
it("doesn't fold newlines in braces with escaped backslashes", () =>
expect(
parse(String.raw`{\\\
}`)
).toEqual([true, [[{ text: "\\\\ ", pos: 0 }]]]));
).toEqual([true, [[{ text: "\\\\\\\n", pos: 0 }]]]));
test.each(['{"}"', '"{"}'])(
"does not permit overlapping braces and quotes {%s}",

View file

@ -4,11 +4,11 @@ import {
InterpolatedPiece, Script, ScriptPiece, SimplifyWord, TextWord, Word as WordType
} from './words';
const Comment = Regex(/#[^\n]*/y)
const Comment = Regex(/#([^\\\n]|\\[^])*/y)
.expects("#")
.map(() => []);
const PreWordWhitespace = Regex(/[^\S\n;]+/y).expects("whitespace");
const PreWordWhitespace = Regex(/([^\S\n;]|\\\n)+/y).expects("whitespace");
const BackslashEscape = Sequence(
Regex(/\\/y).expects("BACKSLASH"),
@ -65,7 +65,7 @@ const Brace: Pattern<string> = Sequence(
Use(() => Brace)
.expects("{")
.map((text) => `{${text}}`),
Regex(/\\./y)
Regex(/\\[^]/y)
.expects("BACKSLASH")
.map(([escape]) => escape),
Regex(/[^\\{}]+/y)
@ -133,10 +133,6 @@ const ERROR_CONTEXT = /(?<=([^\n]{0,50}))([^\n]{0,50})/y;
* @returns - parsed list of commands, or error message on failure
*/
export function parse(code: string): [true, Script] | [false, string] {
/* Preprocess */
// fold line endings
code = code.replace(/(?<!\\)((\\\\)*)\\\n[ \t]*/g, "$1 ");
/* Parse */
const [commands, errorPos, expected] = Script.match(code, 0);

View file

@ -1,13 +1,6 @@
import {
AsText,
Concat,
ErrorResult,
InterpolatedPiece,
ProcResult,
Script,
TextPiece,
Word,
} from "./words";
AsText, Concat, ErrorResult, InterpolatedPiece, ProcResult, Script, TextPiece, Word
} from './words';
/**
* "Mode" of the environment a script runs in; determines access to mutability features and such.