tarsec 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/parsers.d.ts CHANGED
@@ -68,7 +68,7 @@ export declare const alphanum: Parser<string>;
68
68
  export declare const word: Parser<string>;
69
69
  /** A parser that matches one or more digits. */
70
70
  export declare const num: Parser<string>;
71
- /** A parser that matches one single or double quote. */
71
+ /** A parser that matches one single quote, double quote, or backtick. */
72
72
  export declare const quote: Parser<string>;
73
73
  /** A parser that matches one tab character. */
74
74
  export declare const tab: Parser<string>;
@@ -76,7 +76,8 @@ export declare const tab: Parser<string>;
76
76
  export declare const newline: Parser<string>;
77
77
  /** A parser that succeeds on an empty string. Returns `null` as the result. */
78
78
  export declare const eof: Parser<null>;
79
- /** A parser that matches a quoted string, in single or double quotes.
79
+ /** A parser that matches a quoted string, in single quotes, double quotes, or backticks.
80
+ * The closing quote must match the opening quote.
80
81
  * Returns the string as the result, including the quotes.
81
82
  */
82
83
  export declare const quotedString: Parser<string>;
package/dist/parsers.js CHANGED
@@ -1,4 +1,4 @@
1
- import { many1WithJoin, manyWithJoin, seq } from "./combinators.js";
1
+ import { many1WithJoin } from "./combinators.js";
2
2
  import { trace } from "./trace.js";
3
3
  import { recordFailure, saveRightmostFailure, restoreRightmostFailure } from "./rightmostFailure.js";
4
4
  import { captureSuccess, failure, success, } from "./types.js";
@@ -140,8 +140,8 @@ export const alphanum = label("a letter or digit", oneOf("abcdefghijklmnopqrstuv
140
140
  export const word = label("a word", regexParser("^[a-z]+", "ui"));
141
141
  /** A parser that matches one or more digits. */
142
142
  export const num = label("a number", regexParser("^[0-9]+"));
143
- /** A parser that matches one single or double quote. */
144
- export const quote = label("a quote", oneOf(`'"`));
143
+ /** A parser that matches one single quote, double quote, or backtick. */
144
+ export const quote = label("a quote", oneOf(`'"\``));
145
145
  /** A parser that matches one tab character. */
146
146
  export const tab = char("\t");
147
147
  /** A parser that matches one newline ("\n" only) character. */
@@ -154,10 +154,44 @@ export const eof = (input) => {
154
154
  recordFailure(input, "end of input");
155
155
  return failure("expected end of input", input);
156
156
  };
157
- /** A parser that matches a quoted string, in single or double quotes.
157
+ /** A parser that matches a quoted string, in single quotes, double quotes, or backticks.
158
+ * The closing quote must match the opening quote.
158
159
  * Returns the string as the result, including the quotes.
159
160
  */
160
- export const quotedString = seq([quote, manyWithJoin(noneOf(`"'`)), quote], (results) => results.join(""));
161
+ export const quotedString = trace("quotedString", (input) => {
162
+ if (input.length === 0) {
163
+ recordFailure(input, "a quoted string");
164
+ return failure("unexpected end of input", input);
165
+ }
166
+ const q = input[0];
167
+ if (q !== '"' && q !== "'" && q !== "`") {
168
+ recordFailure(input, "a quoted string");
169
+ return failure(`expected a quote, got ${escape(input[0])}`, input);
170
+ }
171
+ let closeIdx = -1;
172
+ let searchFrom = 1;
173
+ while (true) {
174
+ const idx = input.indexOf(q, searchFrom);
175
+ if (idx === -1)
176
+ break;
177
+ // Count consecutive backslashes before the quote
178
+ let backslashes = 0;
179
+ for (let i = idx - 1; i >= 1 && input[i] === "\\"; i--)
180
+ backslashes++;
181
+ if (backslashes % 2 === 0) {
182
+ // Even number of backslashes (including 0) means the quote is unescaped
183
+ closeIdx = idx;
184
+ break;
185
+ }
186
+ searchFrom = idx + 1;
187
+ }
188
+ if (closeIdx === -1) {
189
+ recordFailure(input, "a quoted string");
190
+ return failure(`expected closing ${escape(q)}`, input);
191
+ }
192
+ const matched = input.slice(0, closeIdx + 1);
193
+ return success(matched, input.slice(closeIdx + 1));
194
+ });
161
195
  /**
162
196
  * Returns a parser that matches a regex. If you pass in a string,
163
197
  * it will get converted to a regex. The regex should always match from the start of the input.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tarsec",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A parser combinator library for TypeScript, inspired by Parsec.",
5
5
  "homepage": "https://github.com/egonSchiele/tarsec",
6
6
  "scripts": {