@vibe-lang/runtime 0.2.5

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.
Files changed (250) hide show
  1. package/package.json +46 -0
  2. package/src/ast/index.ts +375 -0
  3. package/src/ast.ts +2 -0
  4. package/src/debug/advanced-features.ts +482 -0
  5. package/src/debug/bun-inspector.ts +424 -0
  6. package/src/debug/handoff-manager.ts +283 -0
  7. package/src/debug/index.ts +150 -0
  8. package/src/debug/runner.ts +365 -0
  9. package/src/debug/server.ts +565 -0
  10. package/src/debug/stack-merger.ts +267 -0
  11. package/src/debug/state.ts +581 -0
  12. package/src/debug/test/advanced-features.test.ts +300 -0
  13. package/src/debug/test/e2e.test.ts +218 -0
  14. package/src/debug/test/handoff-manager.test.ts +256 -0
  15. package/src/debug/test/runner.test.ts +256 -0
  16. package/src/debug/test/stack-merger.test.ts +163 -0
  17. package/src/debug/test/state.test.ts +400 -0
  18. package/src/debug/test/ts-debug-integration.test.ts +374 -0
  19. package/src/debug/test/ts-import-tracker.test.ts +125 -0
  20. package/src/debug/test/ts-source-map.test.ts +169 -0
  21. package/src/debug/ts-import-tracker.ts +151 -0
  22. package/src/debug/ts-source-map.ts +171 -0
  23. package/src/errors/index.ts +124 -0
  24. package/src/index.ts +358 -0
  25. package/src/lexer/index.ts +348 -0
  26. package/src/lexer.ts +2 -0
  27. package/src/parser/index.ts +792 -0
  28. package/src/parser/parse.ts +45 -0
  29. package/src/parser/test/async.test.ts +248 -0
  30. package/src/parser/test/destructuring.test.ts +167 -0
  31. package/src/parser/test/do-expression.test.ts +486 -0
  32. package/src/parser/test/errors/do-expression.test.ts +95 -0
  33. package/src/parser/test/errors/error-locations.test.ts +230 -0
  34. package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
  35. package/src/parser/test/errors/missing-tokens.test.ts +126 -0
  36. package/src/parser/test/errors/model-declaration.test.ts +185 -0
  37. package/src/parser/test/errors/nested-blocks.test.ts +226 -0
  38. package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
  39. package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
  40. package/src/parser/test/import-export.test.ts +143 -0
  41. package/src/parser/test/literals.test.ts +404 -0
  42. package/src/parser/test/model-declaration.test.ts +161 -0
  43. package/src/parser/test/nested-blocks.test.ts +402 -0
  44. package/src/parser/test/parser.test.ts +743 -0
  45. package/src/parser/test/private.test.ts +136 -0
  46. package/src/parser/test/template-literal.test.ts +127 -0
  47. package/src/parser/test/tool-declaration.test.ts +302 -0
  48. package/src/parser/test/ts-block.test.ts +252 -0
  49. package/src/parser/test/type-annotations.test.ts +254 -0
  50. package/src/parser/visitor/helpers.ts +330 -0
  51. package/src/parser/visitor.ts +794 -0
  52. package/src/parser.ts +2 -0
  53. package/src/runtime/ai/cache-chunking.test.ts +69 -0
  54. package/src/runtime/ai/cache-chunking.ts +73 -0
  55. package/src/runtime/ai/client.ts +109 -0
  56. package/src/runtime/ai/context.ts +168 -0
  57. package/src/runtime/ai/formatters.ts +316 -0
  58. package/src/runtime/ai/index.ts +38 -0
  59. package/src/runtime/ai/language-ref.ts +38 -0
  60. package/src/runtime/ai/providers/anthropic.ts +253 -0
  61. package/src/runtime/ai/providers/google.ts +201 -0
  62. package/src/runtime/ai/providers/openai.ts +156 -0
  63. package/src/runtime/ai/retry.ts +100 -0
  64. package/src/runtime/ai/return-tools.ts +301 -0
  65. package/src/runtime/ai/test/client.test.ts +83 -0
  66. package/src/runtime/ai/test/formatters.test.ts +485 -0
  67. package/src/runtime/ai/test/retry.test.ts +137 -0
  68. package/src/runtime/ai/test/return-tools.test.ts +450 -0
  69. package/src/runtime/ai/test/tool-loop.test.ts +319 -0
  70. package/src/runtime/ai/test/tool-schema.test.ts +241 -0
  71. package/src/runtime/ai/tool-loop.ts +203 -0
  72. package/src/runtime/ai/tool-schema.ts +151 -0
  73. package/src/runtime/ai/types.ts +113 -0
  74. package/src/runtime/ai-logger.ts +255 -0
  75. package/src/runtime/ai-provider.ts +347 -0
  76. package/src/runtime/async/dependencies.ts +276 -0
  77. package/src/runtime/async/executor.ts +293 -0
  78. package/src/runtime/async/index.ts +43 -0
  79. package/src/runtime/async/scheduling.ts +163 -0
  80. package/src/runtime/async/test/dependencies.test.ts +284 -0
  81. package/src/runtime/async/test/executor.test.ts +388 -0
  82. package/src/runtime/context.ts +357 -0
  83. package/src/runtime/exec/ai.ts +139 -0
  84. package/src/runtime/exec/expressions.ts +475 -0
  85. package/src/runtime/exec/frames.ts +26 -0
  86. package/src/runtime/exec/functions.ts +305 -0
  87. package/src/runtime/exec/interpolation.ts +312 -0
  88. package/src/runtime/exec/statements.ts +604 -0
  89. package/src/runtime/exec/tools.ts +129 -0
  90. package/src/runtime/exec/typescript.ts +215 -0
  91. package/src/runtime/exec/variables.ts +279 -0
  92. package/src/runtime/index.ts +975 -0
  93. package/src/runtime/modules.ts +452 -0
  94. package/src/runtime/serialize.ts +103 -0
  95. package/src/runtime/state.ts +489 -0
  96. package/src/runtime/stdlib/core.ts +45 -0
  97. package/src/runtime/stdlib/directory.test.ts +156 -0
  98. package/src/runtime/stdlib/edit.test.ts +154 -0
  99. package/src/runtime/stdlib/fastEdit.test.ts +201 -0
  100. package/src/runtime/stdlib/glob.test.ts +106 -0
  101. package/src/runtime/stdlib/grep.test.ts +144 -0
  102. package/src/runtime/stdlib/index.ts +16 -0
  103. package/src/runtime/stdlib/readFile.test.ts +123 -0
  104. package/src/runtime/stdlib/tools/index.ts +707 -0
  105. package/src/runtime/stdlib/writeFile.test.ts +157 -0
  106. package/src/runtime/step.ts +969 -0
  107. package/src/runtime/test/ai-context.test.ts +1086 -0
  108. package/src/runtime/test/ai-result-object.test.ts +419 -0
  109. package/src/runtime/test/ai-tool-flow.test.ts +859 -0
  110. package/src/runtime/test/async-execution-order.test.ts +618 -0
  111. package/src/runtime/test/async-execution.test.ts +344 -0
  112. package/src/runtime/test/async-nested.test.ts +660 -0
  113. package/src/runtime/test/async-parallel-timing.test.ts +546 -0
  114. package/src/runtime/test/basic1.test.ts +154 -0
  115. package/src/runtime/test/binary-operators.test.ts +431 -0
  116. package/src/runtime/test/break-statement.test.ts +257 -0
  117. package/src/runtime/test/context-modes.test.ts +650 -0
  118. package/src/runtime/test/context.test.ts +466 -0
  119. package/src/runtime/test/core-functions.test.ts +228 -0
  120. package/src/runtime/test/e2e.test.ts +88 -0
  121. package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
  122. package/src/runtime/test/error-locations/main-error.vibe +4 -0
  123. package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
  124. package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
  125. package/src/runtime/test/for-in.test.ts +312 -0
  126. package/src/runtime/test/helpers.ts +69 -0
  127. package/src/runtime/test/imports.test.ts +334 -0
  128. package/src/runtime/test/json-expressions.test.ts +232 -0
  129. package/src/runtime/test/literals.test.ts +372 -0
  130. package/src/runtime/test/logical-indexing.test.ts +478 -0
  131. package/src/runtime/test/member-methods.test.ts +324 -0
  132. package/src/runtime/test/model-config.test.ts +338 -0
  133. package/src/runtime/test/null-handling.test.ts +342 -0
  134. package/src/runtime/test/private-visibility.test.ts +332 -0
  135. package/src/runtime/test/runtime-state.test.ts +514 -0
  136. package/src/runtime/test/scoping.test.ts +370 -0
  137. package/src/runtime/test/string-interpolation.test.ts +354 -0
  138. package/src/runtime/test/template-literal.test.ts +181 -0
  139. package/src/runtime/test/tool-execution.test.ts +467 -0
  140. package/src/runtime/test/tool-schema-generation.test.ts +477 -0
  141. package/src/runtime/test/tostring.test.ts +210 -0
  142. package/src/runtime/test/ts-block.test.ts +594 -0
  143. package/src/runtime/test/ts-error-location.test.ts +231 -0
  144. package/src/runtime/test/types.test.ts +732 -0
  145. package/src/runtime/test/verbose-logger.test.ts +710 -0
  146. package/src/runtime/test/vibe-expression.test.ts +54 -0
  147. package/src/runtime/test/vibe-value-errors.test.ts +541 -0
  148. package/src/runtime/test/while.test.ts +232 -0
  149. package/src/runtime/tools/builtin.ts +30 -0
  150. package/src/runtime/tools/directory-tools.ts +70 -0
  151. package/src/runtime/tools/file-tools.ts +228 -0
  152. package/src/runtime/tools/index.ts +5 -0
  153. package/src/runtime/tools/registry.ts +48 -0
  154. package/src/runtime/tools/search-tools.ts +134 -0
  155. package/src/runtime/tools/security.ts +36 -0
  156. package/src/runtime/tools/system-tools.ts +312 -0
  157. package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
  158. package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
  159. package/src/runtime/tools/test/registry.test.ts +713 -0
  160. package/src/runtime/tools/test/security.test.ts +86 -0
  161. package/src/runtime/tools/test/system-tools.test.ts +679 -0
  162. package/src/runtime/tools/test/ts-schema.test.ts +357 -0
  163. package/src/runtime/tools/ts-schema.ts +341 -0
  164. package/src/runtime/tools/types.ts +89 -0
  165. package/src/runtime/tools/utility-tools.ts +198 -0
  166. package/src/runtime/ts-eval.ts +126 -0
  167. package/src/runtime/types.ts +797 -0
  168. package/src/runtime/validation.ts +160 -0
  169. package/src/runtime/verbose-logger.ts +459 -0
  170. package/src/runtime.ts +2 -0
  171. package/src/semantic/analyzer-context.ts +62 -0
  172. package/src/semantic/analyzer-validators.ts +575 -0
  173. package/src/semantic/analyzer-visitors.ts +534 -0
  174. package/src/semantic/analyzer.ts +83 -0
  175. package/src/semantic/index.ts +11 -0
  176. package/src/semantic/symbol-table.ts +58 -0
  177. package/src/semantic/test/async-validation.test.ts +301 -0
  178. package/src/semantic/test/compress-validation.test.ts +179 -0
  179. package/src/semantic/test/const-reassignment.test.ts +111 -0
  180. package/src/semantic/test/control-flow.test.ts +346 -0
  181. package/src/semantic/test/destructuring.test.ts +185 -0
  182. package/src/semantic/test/duplicate-declarations.test.ts +168 -0
  183. package/src/semantic/test/export-validation.test.ts +111 -0
  184. package/src/semantic/test/fixtures/math.ts +31 -0
  185. package/src/semantic/test/imports.test.ts +148 -0
  186. package/src/semantic/test/json-type.test.ts +68 -0
  187. package/src/semantic/test/literals.test.ts +127 -0
  188. package/src/semantic/test/model-validation.test.ts +179 -0
  189. package/src/semantic/test/prompt-validation.test.ts +343 -0
  190. package/src/semantic/test/scoping.test.ts +312 -0
  191. package/src/semantic/test/tool-validation.test.ts +306 -0
  192. package/src/semantic/test/ts-type-checking.test.ts +563 -0
  193. package/src/semantic/test/type-constraints.test.ts +111 -0
  194. package/src/semantic/test/type-inference.test.ts +87 -0
  195. package/src/semantic/test/type-validation.test.ts +552 -0
  196. package/src/semantic/test/undefined-variables.test.ts +163 -0
  197. package/src/semantic/ts-block-checker.ts +204 -0
  198. package/src/semantic/ts-signatures.ts +194 -0
  199. package/src/semantic/ts-types.ts +170 -0
  200. package/src/semantic/types.ts +58 -0
  201. package/tests/fixtures/conditional-logic.vibe +14 -0
  202. package/tests/fixtures/function-call.vibe +16 -0
  203. package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
  204. package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
  205. package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
  206. package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
  207. package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
  208. package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
  209. package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
  210. package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
  211. package/tests/fixtures/imports/nested-import/main.vibe +3 -0
  212. package/tests/fixtures/imports/nested-import/utils.ts +3 -0
  213. package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
  214. package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
  215. package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
  216. package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
  217. package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
  218. package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
  219. package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
  220. package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
  221. package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
  222. package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
  223. package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
  224. package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
  225. package/tests/fixtures/imports/ts-import/main.vibe +4 -0
  226. package/tests/fixtures/imports/ts-import/math.ts +9 -0
  227. package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
  228. package/tests/fixtures/imports/ts-variables/data.ts +10 -0
  229. package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
  230. package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
  231. package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
  232. package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
  233. package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
  234. package/tests/fixtures/multiple-ai-calls.vibe +10 -0
  235. package/tests/fixtures/simple-greeting.vibe +6 -0
  236. package/tests/fixtures/template-literals.vibe +11 -0
  237. package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
  238. package/tests/integration/basic-ai/basic-ai.vibe +12 -0
  239. package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
  240. package/tests/integration/bug-fix/buggy-code.ts +22 -0
  241. package/tests/integration/bug-fix/fix-bug.vibe +21 -0
  242. package/tests/integration/compress/compress.integration.test.ts +206 -0
  243. package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
  244. package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
  245. package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
  246. package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
  247. package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
  248. package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
  249. package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
  250. package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
@@ -0,0 +1,792 @@
1
+ import { CstParser } from 'chevrotain';
2
+ import * as T from '../lexer';
3
+
4
+ class VibeParser extends CstParser {
5
+ constructor() {
6
+ super(T.allTokens, {
7
+ recoveryEnabled: true,
8
+ });
9
+ this.performSelfAnalysis();
10
+ }
11
+
12
+ // ============================================================================
13
+ // Program
14
+ // ============================================================================
15
+
16
+ public program = this.RULE('program', () => {
17
+ this.MANY(() => {
18
+ this.SUBRULE(this.statement);
19
+ });
20
+ });
21
+
22
+ // ============================================================================
23
+ // Statements
24
+ // ============================================================================
25
+
26
+ private statement = this.RULE('statement', () => {
27
+ this.OR([
28
+ { ALT: () => this.SUBRULE(this.importDeclaration) },
29
+ { ALT: () => this.SUBRULE(this.exportDeclaration) },
30
+ {
31
+ GATE: () => this.LA(1).tokenType === T.Async,
32
+ ALT: () => this.SUBRULE(this.asyncStatement),
33
+ }, // Must be before let/const to capture async let/const
34
+ { ALT: () => this.SUBRULE(this.letDeclaration) },
35
+ { ALT: () => this.SUBRULE(this.constDeclaration) },
36
+ { ALT: () => this.SUBRULE(this.modelDeclaration) },
37
+ { ALT: () => this.SUBRULE(this.functionDeclaration) },
38
+ { ALT: () => this.SUBRULE(this.toolDeclaration) },
39
+ { ALT: () => this.SUBRULE(this.returnStatement) },
40
+ { ALT: () => this.SUBRULE(this.breakStatement) },
41
+ { ALT: () => this.SUBRULE(this.ifStatement) },
42
+ { ALT: () => this.SUBRULE(this.forInStatement) },
43
+ { ALT: () => this.SUBRULE(this.whileStatement) },
44
+ // Distinguish block statement from object literal expression:
45
+ // { identifier : ... } is an object literal, otherwise it's a block
46
+ {
47
+ GATE: () => !(this.LA(1).tokenType === T.LBrace && this.LA(2).tokenType === T.Identifier && this.LA(3).tokenType === T.Colon),
48
+ ALT: () => this.SUBRULE(this.blockStatement),
49
+ },
50
+ { ALT: () => this.SUBRULE(this.expressionStatement) },
51
+ ]);
52
+ });
53
+
54
+ // import { name1, name2 } from "path"
55
+ private importDeclaration = this.RULE('importDeclaration', () => {
56
+ this.CONSUME(T.Import);
57
+ this.CONSUME(T.LBrace);
58
+ this.SUBRULE(this.importSpecifierList);
59
+ this.CONSUME(T.RBrace);
60
+ this.CONSUME(T.From);
61
+ this.CONSUME(T.StringLiteral);
62
+ });
63
+
64
+ // name1, name2, name3
65
+ private importSpecifierList = this.RULE('importSpecifierList', () => {
66
+ this.CONSUME(T.Identifier);
67
+ this.MANY(() => {
68
+ this.CONSUME(T.Comma);
69
+ this.CONSUME2(T.Identifier);
70
+ });
71
+ });
72
+
73
+ // export function|let|const|model ...
74
+ private exportDeclaration = this.RULE('exportDeclaration', () => {
75
+ this.CONSUME(T.Export);
76
+ this.OR([
77
+ { ALT: () => this.SUBRULE(this.functionDeclaration) },
78
+ { ALT: () => this.SUBRULE(this.letDeclaration) },
79
+ { ALT: () => this.SUBRULE(this.constDeclaration) },
80
+ { ALT: () => this.SUBRULE(this.modelDeclaration) },
81
+ ]);
82
+ });
83
+
84
+ // async let/const declaration OR async standalone expression
85
+ // async let x = do "prompt" model
86
+ // async const x = tsFunc()
87
+ // async do "prompt" model (fire-and-forget)
88
+ // async tsFunc() (fire-and-forget)
89
+ private asyncStatement = this.RULE('asyncStatement', () => {
90
+ this.CONSUME(T.Async);
91
+ this.OR([
92
+ // async let declaration
93
+ {
94
+ GATE: () => this.LA(1).tokenType === T.Let,
95
+ ALT: () => this.SUBRULE(this.asyncLetDeclaration),
96
+ },
97
+ // async const declaration
98
+ {
99
+ GATE: () => this.LA(1).tokenType === T.Const,
100
+ ALT: () => this.SUBRULE(this.asyncConstDeclaration),
101
+ },
102
+ // async standalone expression (fire-and-forget)
103
+ { ALT: () => this.SUBRULE(this.asyncExpression) },
104
+ ]);
105
+ });
106
+
107
+ // async let ... (mirrors letDeclaration but marked as async)
108
+ private asyncLetDeclaration = this.RULE('asyncLetDeclaration', () => {
109
+ this.CONSUME(T.Let);
110
+ this.OR([
111
+ // Destructuring: async let { name: type } = expression
112
+ {
113
+ GATE: () => this.LA(1).tokenType === T.LBrace,
114
+ ALT: () => {
115
+ this.SUBRULE(this.destructuringPattern);
116
+ this.CONSUME(T.Equals);
117
+ this.SUBRULE(this.asyncExpression);
118
+ },
119
+ },
120
+ // Regular: async let [private] name : type = expression
121
+ {
122
+ ALT: () => {
123
+ this.OPTION(() => {
124
+ this.CONSUME(T.Private);
125
+ });
126
+ this.CONSUME(T.Identifier);
127
+ this.OPTION2(() => {
128
+ this.CONSUME(T.Colon);
129
+ this.SUBRULE(this.typeAnnotation);
130
+ });
131
+ this.CONSUME2(T.Equals);
132
+ this.SUBRULE2(this.asyncExpression);
133
+ },
134
+ },
135
+ ]);
136
+ });
137
+
138
+ // async const ... (mirrors constDeclaration but marked as async)
139
+ private asyncConstDeclaration = this.RULE('asyncConstDeclaration', () => {
140
+ this.CONSUME(T.Const);
141
+ this.OR([
142
+ // Destructuring: async const { name: type } = expression
143
+ {
144
+ GATE: () => this.LA(1).tokenType === T.LBrace,
145
+ ALT: () => {
146
+ this.SUBRULE(this.destructuringPattern);
147
+ this.CONSUME(T.Equals);
148
+ this.SUBRULE(this.asyncExpression);
149
+ },
150
+ },
151
+ // Regular: async const [private] name : type = expression
152
+ {
153
+ ALT: () => {
154
+ this.OPTION(() => {
155
+ this.CONSUME(T.Private);
156
+ });
157
+ this.CONSUME(T.Identifier);
158
+ this.OPTION2(() => {
159
+ this.CONSUME(T.Colon);
160
+ this.SUBRULE(this.typeAnnotation);
161
+ });
162
+ this.CONSUME2(T.Equals);
163
+ this.SUBRULE2(this.asyncExpression);
164
+ },
165
+ },
166
+ ]);
167
+ });
168
+
169
+ // Valid expressions for async: do, vibe, ts block, or function call
170
+ private asyncExpression = this.RULE('asyncExpression', () => {
171
+ this.OR([
172
+ // vibe "prompt" model
173
+ {
174
+ ALT: () => {
175
+ this.CONSUME(T.Vibe);
176
+ this.SUBRULE(this.expression);
177
+ this.SUBRULE(this.vibeModifiers);
178
+ },
179
+ },
180
+ // do "prompt" model
181
+ {
182
+ ALT: () => {
183
+ this.CONSUME(T.Do);
184
+ this.SUBRULE2(this.expression);
185
+ this.SUBRULE2(this.vibeModifiers);
186
+ },
187
+ },
188
+ // ts(...) { ... }
189
+ { ALT: () => this.CONSUME(T.TsBlock) },
190
+ // functionCall() - identifier followed by (
191
+ {
192
+ GATE: () => this.LA(1).tokenType === T.Identifier,
193
+ ALT: () => this.SUBRULE(this.postfixExpression),
194
+ },
195
+ ]);
196
+ });
197
+
198
+ private letDeclaration = this.RULE('letDeclaration', () => {
199
+ this.CONSUME(T.Let);
200
+ this.OR([
201
+ // Destructuring: let { name: type, name: type } = expression
202
+ {
203
+ GATE: () => this.LA(1).tokenType === T.LBrace,
204
+ ALT: () => {
205
+ this.SUBRULE(this.destructuringPattern);
206
+ this.CONSUME(T.Equals);
207
+ this.SUBRULE(this.expression);
208
+ },
209
+ },
210
+ // Regular: let private name : type = expression (private is optional)
211
+ {
212
+ ALT: () => {
213
+ this.OPTION(() => {
214
+ this.CONSUME(T.Private);
215
+ });
216
+ this.CONSUME(T.Identifier);
217
+ this.OPTION2(() => {
218
+ this.CONSUME(T.Colon);
219
+ this.SUBRULE(this.typeAnnotation);
220
+ });
221
+ this.OPTION3(() => {
222
+ this.CONSUME2(T.Equals);
223
+ this.SUBRULE2(this.expression);
224
+ });
225
+ },
226
+ },
227
+ ]);
228
+ });
229
+
230
+ // Type annotation: text, json, prompt, boolean, number, model, or any of these followed by []
231
+ private typeAnnotation = this.RULE('typeAnnotation', () => {
232
+ this.OR([
233
+ { ALT: () => this.CONSUME(T.TextType) },
234
+ { ALT: () => this.CONSUME(T.JsonType) },
235
+ { ALT: () => this.CONSUME(T.PromptType) },
236
+ { ALT: () => this.CONSUME(T.BooleanType) },
237
+ { ALT: () => this.CONSUME(T.NumberType) },
238
+ { ALT: () => this.CONSUME(T.Model) }, // model type for AI model parameters
239
+ ]);
240
+ // Optional array brackets: text[] or text[][]
241
+ this.MANY(() => {
242
+ this.CONSUME(T.LBracket);
243
+ this.CONSUME(T.RBracket);
244
+ });
245
+ });
246
+
247
+ private constDeclaration = this.RULE('constDeclaration', () => {
248
+ this.CONSUME(T.Const);
249
+ this.OR([
250
+ // Destructuring: const { name: type, name: type } = expression
251
+ {
252
+ GATE: () => this.LA(1).tokenType === T.LBrace,
253
+ ALT: () => {
254
+ this.SUBRULE(this.destructuringPattern);
255
+ this.CONSUME(T.Equals);
256
+ this.SUBRULE(this.expression);
257
+ },
258
+ },
259
+ // Regular: const private name : type = expression (private is optional)
260
+ {
261
+ ALT: () => {
262
+ this.OPTION(() => {
263
+ this.CONSUME(T.Private);
264
+ });
265
+ this.CONSUME(T.Identifier);
266
+ this.OPTION2(() => {
267
+ this.CONSUME(T.Colon);
268
+ this.SUBRULE(this.typeAnnotation);
269
+ });
270
+ this.CONSUME2(T.Equals);
271
+ this.SUBRULE2(this.expression);
272
+ },
273
+ },
274
+ ]);
275
+ });
276
+
277
+ // Destructuring pattern: { name: type, name: type, ... }
278
+ private destructuringPattern = this.RULE('destructuringPattern', () => {
279
+ this.CONSUME(T.LBrace);
280
+ this.SUBRULE(this.destructuringField);
281
+ this.MANY(() => {
282
+ this.CONSUME(T.Comma);
283
+ this.SUBRULE2(this.destructuringField);
284
+ });
285
+ this.CONSUME(T.RBrace);
286
+ });
287
+
288
+ // Single destructuring field: private name: type (private is optional)
289
+ private destructuringField = this.RULE('destructuringField', () => {
290
+ this.OPTION(() => {
291
+ this.CONSUME(T.Private);
292
+ });
293
+ this.CONSUME(T.Identifier);
294
+ this.CONSUME(T.Colon);
295
+ this.SUBRULE(this.typeAnnotation);
296
+ });
297
+
298
+ private modelDeclaration = this.RULE('modelDeclaration', () => {
299
+ this.CONSUME(T.Model);
300
+ this.CONSUME(T.Identifier);
301
+ this.CONSUME(T.Equals);
302
+ this.SUBRULE(this.objectLiteral);
303
+ });
304
+
305
+ private objectLiteral = this.RULE('objectLiteral', () => {
306
+ this.CONSUME(T.LBrace);
307
+ this.OPTION(() => {
308
+ this.SUBRULE(this.propertyList);
309
+ });
310
+ this.CONSUME(T.RBrace);
311
+ });
312
+
313
+ private propertyList = this.RULE('propertyList', () => {
314
+ this.SUBRULE(this.property);
315
+ this.MANY(() => {
316
+ this.CONSUME(T.Comma);
317
+ this.SUBRULE2(this.property);
318
+ });
319
+ });
320
+
321
+ private property = this.RULE('property', () => {
322
+ this.CONSUME(T.Identifier);
323
+ this.CONSUME(T.Colon);
324
+ this.SUBRULE(this.expression);
325
+ });
326
+
327
+ // function name(params): returnType { ... }
328
+ // Note: Functions always forget context on exit (no context mode support)
329
+ private functionDeclaration = this.RULE('functionDeclaration', () => {
330
+ this.CONSUME(T.Function);
331
+ this.CONSUME(T.Identifier);
332
+ this.CONSUME(T.LParen);
333
+ this.OPTION(() => {
334
+ this.SUBRULE(this.parameterList);
335
+ });
336
+ this.CONSUME(T.RParen);
337
+ // Optional return type
338
+ this.OPTION2(() => {
339
+ this.CONSUME(T.Colon);
340
+ this.SUBRULE(this.typeAnnotation);
341
+ });
342
+ this.SUBRULE(this.blockStatement);
343
+ });
344
+
345
+ // tool name(params): returnType @description "..." @param name "..." { ... }
346
+ private toolDeclaration = this.RULE('toolDeclaration', () => {
347
+ this.CONSUME(T.Tool);
348
+ this.CONSUME(T.Identifier);
349
+ this.CONSUME(T.LParen);
350
+ this.OPTION(() => {
351
+ this.SUBRULE(this.toolParameterList);
352
+ });
353
+ this.CONSUME(T.RParen);
354
+ // Optional return type
355
+ this.OPTION2(() => {
356
+ this.CONSUME(T.Colon);
357
+ this.SUBRULE(this.toolTypeAnnotation);
358
+ });
359
+ // Optional metadata (@description, @param)
360
+ this.MANY(() => {
361
+ this.SUBRULE(this.toolMetadata);
362
+ });
363
+ this.SUBRULE(this.blockStatement);
364
+ });
365
+
366
+ // Tool type annotation: can be a built-in type or an Identifier (imported TS type)
367
+ private toolTypeAnnotation = this.RULE('toolTypeAnnotation', () => {
368
+ this.OR([
369
+ { ALT: () => this.CONSUME(T.TextType) },
370
+ { ALT: () => this.CONSUME(T.JsonType) },
371
+ { ALT: () => this.CONSUME(T.PromptType) },
372
+ { ALT: () => this.CONSUME(T.BooleanType) },
373
+ { ALT: () => this.CONSUME(T.NumberType) },
374
+ { ALT: () => this.CONSUME(T.Identifier) }, // Imported TS type
375
+ ]);
376
+ // Optional array brackets
377
+ this.MANY(() => {
378
+ this.CONSUME(T.LBracket);
379
+ this.CONSUME(T.RBracket);
380
+ });
381
+ });
382
+
383
+ // Tool metadata: @description "text" or @param name "text"
384
+ private toolMetadata = this.RULE('toolMetadata', () => {
385
+ this.OR([
386
+ {
387
+ ALT: () => {
388
+ this.CONSUME(T.AtDescription);
389
+ this.CONSUME(T.StringLiteral);
390
+ },
391
+ },
392
+ {
393
+ ALT: () => {
394
+ this.CONSUME(T.AtParam);
395
+ this.CONSUME(T.Identifier);
396
+ this.CONSUME2(T.StringLiteral);
397
+ },
398
+ },
399
+ ]);
400
+ });
401
+
402
+ // Tool parameter: name: type (allows imported TS types as type annotation)
403
+ private toolParameter = this.RULE('toolParameter', () => {
404
+ this.CONSUME(T.Identifier);
405
+ this.CONSUME(T.Colon);
406
+ this.SUBRULE(this.toolTypeAnnotation);
407
+ });
408
+
409
+ private toolParameterList = this.RULE('toolParameterList', () => {
410
+ this.SUBRULE(this.toolParameter);
411
+ this.MANY(() => {
412
+ this.CONSUME(T.Comma);
413
+ this.SUBRULE2(this.toolParameter);
414
+ });
415
+ });
416
+
417
+ // name: type (type is REQUIRED)
418
+ private parameter = this.RULE('parameter', () => {
419
+ this.CONSUME(T.Identifier);
420
+ this.CONSUME(T.Colon);
421
+ this.SUBRULE(this.typeAnnotation);
422
+ });
423
+
424
+ private parameterList = this.RULE('parameterList', () => {
425
+ this.SUBRULE(this.parameter);
426
+ this.MANY(() => {
427
+ this.CONSUME(T.Comma);
428
+ this.SUBRULE2(this.parameter);
429
+ });
430
+ });
431
+
432
+ private returnStatement = this.RULE('returnStatement', () => {
433
+ this.CONSUME(T.Return);
434
+ this.OPTION(() => {
435
+ this.SUBRULE(this.expression);
436
+ });
437
+ });
438
+
439
+ private breakStatement = this.RULE('breakStatement', () => {
440
+ this.CONSUME(T.Break);
441
+ });
442
+
443
+ private ifStatement = this.RULE('ifStatement', () => {
444
+ this.CONSUME(T.If);
445
+ this.SUBRULE(this.expression);
446
+ this.SUBRULE(this.blockStatement);
447
+ this.OPTION(() => {
448
+ this.CONSUME(T.Else);
449
+ this.OR([
450
+ { ALT: () => this.SUBRULE2(this.ifStatement) },
451
+ { ALT: () => this.SUBRULE2(this.blockStatement) },
452
+ ]);
453
+ });
454
+ });
455
+
456
+ // for variable in iterable { ... } [forget|verbose|compress]
457
+ private forInStatement = this.RULE('forInStatement', () => {
458
+ this.CONSUME(T.For);
459
+ this.CONSUME(T.Identifier); // Loop variable
460
+ this.CONSUME(T.In);
461
+ this.SUBRULE(this.expression); // Iterable (array, number, or [start, end])
462
+ this.SUBRULE(this.blockStatement);
463
+ this.OPTION(() => {
464
+ this.SUBRULE(this.contextMode);
465
+ });
466
+ });
467
+
468
+ // while condition { ... } [forget|verbose|compress]
469
+ private whileStatement = this.RULE('whileStatement', () => {
470
+ this.CONSUME(T.While);
471
+ this.SUBRULE(this.expression); // Condition
472
+ this.SUBRULE(this.blockStatement);
473
+ this.OPTION(() => {
474
+ this.SUBRULE(this.contextMode);
475
+ });
476
+ });
477
+
478
+ // Context mode: forget | verbose | compress | compress(...args)
479
+ // compress supports: compress, compress(model), compress("prompt"),
480
+ // compress(promptVar), compress("prompt", model), compress(promptVar, model)
481
+ private contextMode = this.RULE('contextMode', () => {
482
+ this.OR([
483
+ { ALT: () => this.CONSUME(T.Forget) },
484
+ { ALT: () => this.CONSUME(T.Verbose) },
485
+ {
486
+ ALT: () => {
487
+ this.CONSUME(T.Compress);
488
+ this.OPTION(() => {
489
+ this.CONSUME(T.LParen);
490
+ // First argument: string literal or identifier
491
+ this.OR1([
492
+ { ALT: () => this.CONSUME(T.StringLiteral) },
493
+ { ALT: () => this.CONSUME1(T.Identifier) },
494
+ ]);
495
+ // Optional second argument: identifier (model)
496
+ this.OPTION1(() => {
497
+ this.CONSUME(T.Comma);
498
+ this.CONSUME2(T.Identifier);
499
+ });
500
+ this.CONSUME(T.RParen);
501
+ });
502
+ },
503
+ },
504
+ ]);
505
+ });
506
+
507
+ private blockStatement = this.RULE('blockStatement', () => {
508
+ this.CONSUME(T.LBrace);
509
+ this.MANY(() => {
510
+ this.SUBRULE(this.statement);
511
+ });
512
+ this.CONSUME(T.RBrace);
513
+ });
514
+
515
+ private expressionStatement = this.RULE('expressionStatement', () => {
516
+ this.SUBRULE(this.expression);
517
+ });
518
+
519
+ // ============================================================================
520
+ // Expressions (with operator precedence)
521
+ // Precedence (lowest to highest):
522
+ // 1. AI ops, assignment
523
+ // 2. or
524
+ // 3. and
525
+ // 4. comparison (== != < > <= >=)
526
+ // 5. additive (+ -)
527
+ // 6. multiplicative (* / %)
528
+ // 7. unary (not, -)
529
+ // 8. range (..)
530
+ // 9. postfix (calls, indexing, slicing)
531
+ // 10. primary
532
+ // ============================================================================
533
+
534
+ private expression = this.RULE('expression', () => {
535
+ this.OR([
536
+ // AI operation - vibe (multi-turn tool loop)
537
+ {
538
+ ALT: () => {
539
+ this.CONSUME(T.Vibe);
540
+ this.SUBRULE(this.expression); // prompt (required)
541
+ this.SUBRULE(this.vibeModifiers); // optional model and/or context
542
+ },
543
+ },
544
+ // AI operation - do (single-round, no tool loop)
545
+ {
546
+ ALT: () => {
547
+ this.CONSUME(T.Do);
548
+ this.SUBRULE2(this.expression); // prompt (required)
549
+ this.SUBRULE2(this.vibeModifiers); // optional model and/or context
550
+ },
551
+ },
552
+ // Assignment expression (identifier = expression)
553
+ {
554
+ GATE: () => this.LA(1).tokenType === T.Identifier && this.LA(2).tokenType === T.Equals,
555
+ ALT: () => this.SUBRULE(this.assignmentExpression),
556
+ },
557
+ // Logical or and below
558
+ { ALT: () => this.SUBRULE(this.orExpression) },
559
+ ]);
560
+ });
561
+
562
+ // Optional model and/or context for vibe/do expressions
563
+ // Syntaxes:
564
+ // (nothing) → no model, default context
565
+ // default | local → no model, explicit context
566
+ // identifier → explicit model, default context
567
+ // identifier contextSpecifier → explicit model, explicit context
568
+ private vibeModifiers = this.RULE('vibeModifiers', () => {
569
+ // Context keyword (default/local) without model
570
+ this.OPTION(() => {
571
+ this.OR([
572
+ {
573
+ GATE: () => this.LA(1).tokenType === T.Default || this.LA(1).tokenType === T.Local,
574
+ ALT: () => this.SUBRULE(this.contextSpecifier),
575
+ },
576
+ // Model identifier - only if NOT followed by ( (which would be a function call)
577
+ {
578
+ GATE: () => this.LA(1).tokenType === T.Identifier && this.LA(2).tokenType !== T.LParen,
579
+ ALT: () => {
580
+ this.CONSUME(T.Identifier); // model
581
+ this.OPTION2(() => {
582
+ this.SUBRULE2(this.contextSpecifier); // optional context
583
+ });
584
+ },
585
+ },
586
+ // Empty alternative - no modifiers (when next token doesn't match model/context pattern)
587
+ { ALT: () => { /* no-op */ } },
588
+ ]);
589
+ });
590
+ });
591
+
592
+ // Or: or (lowest precedence for logical)
593
+ private orExpression = this.RULE('orExpression', () => {
594
+ this.SUBRULE(this.andExpression);
595
+ this.MANY(() => {
596
+ this.CONSUME(T.Or);
597
+ this.SUBRULE2(this.andExpression);
598
+ });
599
+ });
600
+
601
+ // And: and
602
+ private andExpression = this.RULE('andExpression', () => {
603
+ this.SUBRULE(this.comparisonExpression);
604
+ this.MANY(() => {
605
+ this.CONSUME(T.And);
606
+ this.SUBRULE2(this.comparisonExpression);
607
+ });
608
+ });
609
+
610
+ // Comparison: == != < > <= >=
611
+ private comparisonExpression = this.RULE('comparisonExpression', () => {
612
+ this.SUBRULE(this.additiveExpression);
613
+ this.OPTION(() => {
614
+ this.OR([
615
+ { ALT: () => this.CONSUME(T.EqualEqual) }, { ALT: () => this.CONSUME(T.NotEqual) },
616
+ { ALT: () => this.CONSUME(T.LessThan) }, { ALT: () => this.CONSUME(T.GreaterThan) },
617
+ { ALT: () => this.CONSUME(T.LessEqual) }, { ALT: () => this.CONSUME(T.GreaterEqual) },
618
+ ]);
619
+ this.SUBRULE2(this.additiveExpression);
620
+ });
621
+ });
622
+
623
+ // Additive: + -
624
+ private additiveExpression = this.RULE('additiveExpression', () => {
625
+ this.SUBRULE(this.multiplicativeExpression);
626
+ this.MANY(() => {
627
+ this.OR([{ ALT: () => this.CONSUME(T.Plus) }, { ALT: () => this.CONSUME(T.Minus) }]);
628
+ this.SUBRULE2(this.multiplicativeExpression);
629
+ });
630
+ });
631
+
632
+ // Multiplicative: * / %
633
+ private multiplicativeExpression = this.RULE('multiplicativeExpression', () => {
634
+ this.SUBRULE(this.unaryExpression);
635
+ this.MANY(() => {
636
+ this.OR([
637
+ { ALT: () => this.CONSUME(T.Star) }, { ALT: () => this.CONSUME(T.Slash) },
638
+ { ALT: () => this.CONSUME(T.Percent) },
639
+ ]);
640
+ this.SUBRULE2(this.unaryExpression);
641
+ });
642
+ });
643
+
644
+ // Unary: not, -
645
+ private unaryExpression = this.RULE('unaryExpression', () => {
646
+ this.OR([
647
+ { ALT: () => { this.CONSUME(T.Not); this.SUBRULE(this.unaryExpression); } },
648
+ { // Unary minus
649
+ GATE: () => this.LA(1).tokenType === T.Minus,
650
+ ALT: () => { this.CONSUME(T.Minus); this.SUBRULE2(this.unaryExpression); },
651
+ },
652
+ { ALT: () => this.SUBRULE(this.rangeExpression) },
653
+ ]);
654
+ });
655
+
656
+ // Range: ..
657
+ private rangeExpression = this.RULE('rangeExpression', () => {
658
+ this.SUBRULE(this.postfixExpression);
659
+ this.OPTION(() => { this.CONSUME(T.DotDot); this.SUBRULE2(this.postfixExpression); });
660
+ });
661
+
662
+ private assignmentExpression = this.RULE('assignmentExpression', () => {
663
+ this.CONSUME(T.Identifier);
664
+ this.CONSUME(T.Equals);
665
+ this.SUBRULE(this.expression);
666
+ });
667
+
668
+ private contextSpecifier = this.RULE('contextSpecifier', () => {
669
+ this.OR([
670
+ { ALT: () => this.CONSUME(T.Default) },
671
+ { ALT: () => this.CONSUME(T.Local) },
672
+ { ALT: () => this.CONSUME(T.Identifier) },
673
+ ]);
674
+ });
675
+
676
+ // Postfix: function calls, indexing, slicing, member access
677
+ private postfixExpression = this.RULE('postfixExpression', () => {
678
+ this.SUBRULE(this.primaryExpression);
679
+ this.MANY(() => {
680
+ this.OR([
681
+ // Function call: (args)
682
+ {
683
+ ALT: () => {
684
+ this.CONSUME(T.LParen);
685
+ this.OPTION(() => {
686
+ this.SUBRULE(this.argumentList);
687
+ });
688
+ this.CONSUME(T.RParen);
689
+ },
690
+ },
691
+ // Indexing/slicing: [expr] or [expr,expr] or [,expr] or [expr,]
692
+ {
693
+ ALT: () => {
694
+ this.CONSUME(T.LBracket);
695
+ this.SUBRULE(this.indexOrSlice);
696
+ this.CONSUME(T.RBracket);
697
+ },
698
+ },
699
+ // Member access: .identifier
700
+ { ALT: () => { this.CONSUME(T.Dot); this.CONSUME(T.Identifier); } },
701
+ ]);
702
+ });
703
+ });
704
+
705
+ // Index or slice inside brackets (Python-style colon syntax)
706
+ // [expr] = single index
707
+ // [expr:expr] = slice (inclusive)
708
+ // [:expr] = slice from start
709
+ // [expr:] = slice to end
710
+ // [:] = full slice (copy)
711
+ private indexOrSlice = this.RULE('indexOrSlice', () => {
712
+ this.OR([
713
+ // Starts with colon: [:expr] or [:] (slice from start)
714
+ {
715
+ GATE: () => this.LA(1).tokenType === T.Colon,
716
+ ALT: () => {
717
+ this.CONSUME(T.Colon);
718
+ // Optional end expression: [:] vs [:expr]
719
+ this.OPTION(() => {
720
+ this.SUBRULE(this.expression);
721
+ });
722
+ },
723
+ },
724
+ // Starts with expression
725
+ {
726
+ ALT: () => {
727
+ this.SUBRULE2(this.expression);
728
+ // Check if followed by colon (slice)
729
+ this.OPTION2(() => {
730
+ this.CONSUME2(T.Colon);
731
+ // Optional end expression: [expr:] vs [expr:expr]
732
+ this.OPTION3(() => {
733
+ this.SUBRULE3(this.expression);
734
+ });
735
+ });
736
+ },
737
+ },
738
+ ]);
739
+ });
740
+
741
+ private argumentList = this.RULE('argumentList', () => {
742
+ this.SUBRULE(this.expression);
743
+ this.MANY(() => {
744
+ this.CONSUME(T.Comma);
745
+ this.SUBRULE2(this.expression);
746
+ });
747
+ });
748
+
749
+ private primaryExpression = this.RULE('primaryExpression', () => {
750
+ this.OR([
751
+ { ALT: () => this.CONSUME(T.TsBlock) }, // ts(params) { body }
752
+ { ALT: () => this.CONSUME(T.StringLiteral) },
753
+ { ALT: () => this.CONSUME(T.TemplateLiteral) },
754
+ { ALT: () => this.CONSUME(T.NumberLiteral) },
755
+ { ALT: () => this.CONSUME(T.True) }, { ALT: () => this.CONSUME(T.False) }, { ALT: () => this.CONSUME(T.Null) },
756
+ { ALT: () => this.SUBRULE(this.objectLiteralExpr) },
757
+ { ALT: () => this.SUBRULE(this.arrayLiteral) },
758
+ { ALT: () => this.CONSUME(T.Identifier) },
759
+ { ALT: () => { this.CONSUME(T.LParen); this.SUBRULE(this.expression); this.CONSUME(T.RParen); } },
760
+ ]);
761
+ });
762
+
763
+ private objectLiteralExpr = this.RULE('objectLiteralExpr', () => {
764
+ this.CONSUME(T.LBrace);
765
+ this.OPTION(() => {
766
+ this.SUBRULE(this.propertyList);
767
+ });
768
+ this.CONSUME(T.RBrace);
769
+ });
770
+
771
+ private arrayLiteral = this.RULE('arrayLiteral', () => {
772
+ this.CONSUME(T.LBracket);
773
+ this.OPTION(() => {
774
+ this.SUBRULE(this.elementList);
775
+ });
776
+ this.CONSUME(T.RBracket);
777
+ });
778
+
779
+ private elementList = this.RULE('elementList', () => {
780
+ this.SUBRULE(this.expression);
781
+ this.MANY(() => {
782
+ this.CONSUME(T.Comma);
783
+ this.SUBRULE2(this.expression);
784
+ });
785
+ });
786
+ }
787
+
788
+ // Create a singleton parser instance
789
+ export const vibeParser = new VibeParser();
790
+
791
+ // Export the parser class for visitor creation
792
+ export { VibeParser };