diff --git a/src/__snapshots__/parser.test.ts.snap b/src/__snapshots__/parser.test.ts.snap index 1f88662..99a1963 100644 --- a/src/__snapshots__/parser.test.ts.snap +++ b/src/__snapshots__/parser.test.ts.snap @@ -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 diff --git a/src/parser.test.ts b/src/parser.test.ts index 8614271..9f8e963 100644 --- a/src/parser.test.ts +++ b/src/parser.test.ts @@ -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}", diff --git a/src/parser.ts b/src/parser.ts index 90c8cde..9f325e5 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -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 = 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(/(?