@cirru/parser.ts 0.0.9 → 0.0.10

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.
Binary file
package/Agents.md CHANGED
@@ -16,7 +16,7 @@ Main exports: `parse(code)` and `parseOneLiner(code)` from `src/index.ts`.
16
16
  ## Quick Commands
17
17
 
18
18
  ```bash
19
- yarn test # run all 22 Jest tests
19
+ yarn test # run all Jest tests
20
20
  yarn bench # benchmark on bundled test fixtures (×20, ~16 KB)
21
21
  BENCH_FILE=/absolute/path/to/large.cirru yarn bench # benchmark on a real file
22
22
  yarn compile # emit lib/ (tsc -p tsconfig-compile.json)
@@ -184,15 +184,15 @@ Interpretation:
184
184
 
185
185
  ## File Map
186
186
 
187
- | File | Purpose |
188
- | ----------------------- | ----------------------------------------------------------- |
189
- | `src/index.ts` | Parser entry point; `lexAndBuild`, `parse`, `parseOneLiner` |
190
- | `src/tree.ts` | Tree helpers: `resolveDollar`, `resolveComma`, utilities |
191
- | `src/types.ts` | `ELexState`, `ELexControl`, `ICirruNode` |
192
- | `src/parser.test.ts` | All 22 tests |
193
- | `src/bench.ts` | Benchmark script |
194
- | `tsconfig.bench.json` | Separate tsconfig for bench (es2022, node types) |
195
- | `tsconfig-compile.json` | Library build config |
196
- | `test/cirru/*.cirru` | Test input fixtures |
197
- | `test/ast/*.json` | Expected AST outputs |
198
- | `lib/` | Compiled library output (committed) |
187
+ | File | Purpose |
188
+ | ----------------------- | ----------------------------------------------------------------------- |
189
+ | `src/index.ts` | Parser entry point; `lexAndBuild`, `parse`, `parseOneLiner` |
190
+ | `src/tree.ts` | Tree helpers: `resolveDollar`, `resolveComma`, utilities |
191
+ | `src/types.ts` | `ELexState`, `ELexControl`, `ICirruNode` |
192
+ | `src/parser.test.ts` | All 22 tests |
193
+ | `src/bench.ts` | Benchmark script |
194
+ | `tsconfig.bench.json` | Separate tsconfig for bench (es2022, node types) |
195
+ | `tsconfig-compile.json` | Library build config |
196
+ | `test/cirru/*.cirru` | Test input fixtures |
197
+ | `test/ast/*.json` | Expected AST outputs |
198
+ | `lib/` | Compiled library output (generated; not committed—run `yarn compile`) |
package/lib/index.js CHANGED
@@ -39,6 +39,8 @@ let lexAndBuild = (code) => {
39
39
  let state = types_1.ELexState.indent;
40
40
  let buffer = ""; // string content when escape sequences appear
41
41
  let level = 0;
42
+ // Track explicit balance separately from indentation-generated frames.
43
+ let parenDepth = 0;
42
44
  let indentCount = 0;
43
45
  let tokenStart = 0;
44
46
  let stringStart = 0;
@@ -69,6 +71,16 @@ let lexAndBuild = (code) => {
69
71
  else if (tok === ",")
70
72
  hasComma = true;
71
73
  };
74
+ const openParen = () => {
75
+ parenDepth++;
76
+ emitOpen();
77
+ };
78
+ const closeParen = () => {
79
+ if (parenDepth === 0)
80
+ throw new Error("Unexpected closing parenthesis ')'");
81
+ parenDepth--;
82
+ emitClose();
83
+ };
72
84
  // Called whenever a new line's first non-whitespace character is encountered.
73
85
  // newLevel = indentCount >> 1 (already validated as even before calling).
74
86
  // On the very first call: lazily emit the outer open, then any extra opens for depth.
@@ -112,10 +124,10 @@ let lexAndBuild = (code) => {
112
124
  indentCount = 0;
113
125
  break;
114
126
  case CHAR_LPAREN:
115
- emitOpen();
127
+ openParen();
116
128
  break;
117
129
  case CHAR_RPAREN:
118
- emitClose();
130
+ closeParen();
119
131
  break;
120
132
  case CHAR_DQUOTE:
121
133
  state = types_1.ELexState.string;
@@ -149,12 +161,12 @@ let lexAndBuild = (code) => {
149
161
  break;
150
162
  case CHAR_LPAREN:
151
163
  emitToken(code.slice(tokenStart, pointer - 1));
152
- emitOpen();
164
+ openParen();
153
165
  state = types_1.ELexState.space;
154
166
  break;
155
167
  case CHAR_RPAREN:
156
168
  emitToken(code.slice(tokenStart, pointer - 1));
157
- emitClose();
169
+ closeParen();
158
170
  state = types_1.ELexState.space;
159
171
  break;
160
172
  default:
@@ -175,7 +187,7 @@ let lexAndBuild = (code) => {
175
187
  state = types_1.ELexState.escape;
176
188
  break;
177
189
  case CHAR_NEWLINE:
178
- throw new Error("Expected newline in string");
190
+ throw new Error("Unexpected newline in string");
179
191
  default:
180
192
  if (stringHasEscape)
181
193
  buffer = buffer + code[pointer - 1];
@@ -233,10 +245,12 @@ let lexAndBuild = (code) => {
233
245
  if ((0, tree_1.isOdd)(indentCount))
234
246
  throw new Error(`Invalid indentation size ${indentCount}`);
235
247
  flushIndent(indentCount >> 1);
236
- emitOpen();
248
+ openParen();
237
249
  state = types_1.ELexState.space;
238
250
  indentCount = 0;
239
251
  break;
252
+ case CHAR_RPAREN:
253
+ throw new Error("Unexpected closing parenthesis ')' at line start");
240
254
  default:
241
255
  if ((0, tree_1.isOdd)(indentCount))
242
256
  throw new Error(`Invalid indentation size ${indentCount}`);
@@ -261,6 +275,8 @@ let lexAndBuild = (code) => {
261
275
  }
262
276
  if (first)
263
277
  return []; // no content was seen
278
+ if (parenDepth !== 0)
279
+ throw new Error("Unclosed parenthesis at end of input");
264
280
  // Close remaining open levels (mirrors the original: level closes + 1 final close)
265
281
  for (let i = 0; i < level; i++)
266
282
  emitClose();
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cirru/parser.ts",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Cirru Parser in TypeScript",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -42,6 +42,8 @@ let lexAndBuild = (code: string): ICirruNode[] => {
42
42
  let state = ELexState.indent as ELexState;
43
43
  let buffer = ""; // string content when escape sequences appear
44
44
  let level = 0;
45
+ // Track explicit balance separately from indentation-generated frames.
46
+ let parenDepth = 0;
45
47
  let indentCount = 0;
46
48
  let tokenStart = 0;
47
49
  let stringStart = 0;
@@ -73,6 +75,17 @@ let lexAndBuild = (code: string): ICirruNode[] => {
73
75
  else if (tok === ",") hasComma = true;
74
76
  };
75
77
 
78
+ const openParen = () => {
79
+ parenDepth++;
80
+ emitOpen();
81
+ };
82
+
83
+ const closeParen = () => {
84
+ if (parenDepth === 0) throw new Error("Unexpected closing parenthesis ')'");
85
+ parenDepth--;
86
+ emitClose();
87
+ };
88
+
76
89
  // Called whenever a new line's first non-whitespace character is encountered.
77
90
  // newLevel = indentCount >> 1 (already validated as even before calling).
78
91
  // On the very first call: lazily emit the outer open, then any extra opens for depth.
@@ -113,10 +126,10 @@ let lexAndBuild = (code: string): ICirruNode[] => {
113
126
  indentCount = 0;
114
127
  break;
115
128
  case CHAR_LPAREN:
116
- emitOpen();
129
+ openParen();
117
130
  break;
118
131
  case CHAR_RPAREN:
119
- emitClose();
132
+ closeParen();
120
133
  break;
121
134
  case CHAR_DQUOTE:
122
135
  state = ELexState.string;
@@ -150,12 +163,12 @@ let lexAndBuild = (code: string): ICirruNode[] => {
150
163
  break;
151
164
  case CHAR_LPAREN:
152
165
  emitToken(code.slice(tokenStart, pointer - 1));
153
- emitOpen();
166
+ openParen();
154
167
  state = ELexState.space;
155
168
  break;
156
169
  case CHAR_RPAREN:
157
170
  emitToken(code.slice(tokenStart, pointer - 1));
158
- emitClose();
171
+ closeParen();
159
172
  state = ELexState.space;
160
173
  break;
161
174
  default:
@@ -176,7 +189,7 @@ let lexAndBuild = (code: string): ICirruNode[] => {
176
189
  state = ELexState.escape;
177
190
  break;
178
191
  case CHAR_NEWLINE:
179
- throw new Error("Expected newline in string");
192
+ throw new Error("Unexpected newline in string");
180
193
  default:
181
194
  if (stringHasEscape) buffer = buffer + code[pointer - 1];
182
195
  break;
@@ -231,10 +244,12 @@ let lexAndBuild = (code: string): ICirruNode[] => {
231
244
  case CHAR_LPAREN:
232
245
  if (isOdd(indentCount)) throw new Error(`Invalid indentation size ${indentCount}`);
233
246
  flushIndent(indentCount >> 1);
234
- emitOpen();
247
+ openParen();
235
248
  state = ELexState.space;
236
249
  indentCount = 0;
237
250
  break;
251
+ case CHAR_RPAREN:
252
+ throw new Error("Unexpected closing parenthesis ')' at line start");
238
253
  default:
239
254
  if (isOdd(indentCount)) throw new Error(`Invalid indentation size ${indentCount}`);
240
255
  flushIndent(indentCount >> 1);
@@ -257,6 +272,7 @@ let lexAndBuild = (code: string): ICirruNode[] => {
257
272
  }
258
273
 
259
274
  if (first) return []; // no content was seen
275
+ if (parenDepth !== 0) throw new Error("Unclosed parenthesis at end of input");
260
276
 
261
277
  // Close remaining open levels (mirrors the original: level closes + 1 final close)
262
278
  for (let i = 0; i < level; i++) emitClose();
@@ -5,6 +5,33 @@ let { resolveDollar, resolveComma, resolveDollarComma } = require("./tree");
5
5
 
6
6
  test("single quote", () => expect(parse('a "\\\'"')).toEqual([["a", "'"]]));
7
7
 
8
+ describe("parenthesis syntax errors", () => {
9
+ test.each([")", " )", "\n)", "a)", "a )", "a (b))", "a (b) )", "a\n )"])("rejects unmatched closing parenthesis: %j", (code) => {
10
+ expect(() => parse(code)).toThrow(/Unexpected closing parenthesis/);
11
+ expect(() => parseOneLiner(code)).toThrow(/Unexpected closing parenthesis/);
12
+ });
13
+
14
+ test.each(["(", "a (b", "a ((b)", "a (b\n c"])("rejects unfinished parentheses: %j", (code) => {
15
+ expect(() => parse(code)).toThrow(/Unclosed parenthesis/);
16
+ expect(() => parseOneLiner(code)).toThrow(/Unclosed parenthesis/);
17
+ });
18
+
19
+ test("keeps quoted parentheses, balanced nesting and empty input", () => {
20
+ expect(parse('a "(" ")"')).toEqual([["a", "(", ")"]]);
21
+ expect(parse('a "\\\"(\\\""')).toEqual([["a", '"("']]);
22
+ expect(parse("a (b (c))")).toEqual([["a", ["b", ["c"]]]]);
23
+ expect(parse("a (b\n c)")).toEqual([["a", ["b", ["c"]]]]);
24
+ expect(parse("\n ")).toEqual([]);
25
+ });
26
+
27
+ test("preserves Cirru multiline frame closure and following tokens", () => {
28
+ expect(parse("a (b\n c) d")).toEqual([["a", ["b", ["c"], "d"]]]);
29
+ expect(parse("a (b\n c)\n d")).toEqual([["a", ["b", ["c"]], ["d"]]]);
30
+ expect(parse("a (b\n c) d (e)\nf")).toEqual([["a", ["b", ["c"], "d", ["e"]]], ["f"]]);
31
+ expect(parse("a (b\nc)")).toEqual([["a", ["b"], ["c"]]]);
32
+ });
33
+ });
34
+
8
35
  test("demo", () => {
9
36
  let code = fs.readFileSync(path.join(__dirname, "../test/cirru/demo.cirru"), "utf8");
10
37
  let data = require(path.join(__dirname, "../test/ast/demo.json"));