@goreal-ai/echo-pdk 0.1.0
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/ai-judge/index.d.ts +177 -0
- package/dist/ai-judge/index.d.ts.map +1 -0
- package/dist/ai-judge/index.js +299 -0
- package/dist/ai-judge/index.js.map +1 -0
- package/dist/evaluator/evaluator.d.ts +136 -0
- package/dist/evaluator/evaluator.d.ts.map +1 -0
- package/dist/evaluator/evaluator.js +407 -0
- package/dist/evaluator/evaluator.js.map +1 -0
- package/dist/evaluator/index.d.ts +7 -0
- package/dist/evaluator/index.d.ts.map +1 -0
- package/dist/evaluator/index.js +8 -0
- package/dist/evaluator/index.js.map +1 -0
- package/dist/evaluator/operators.d.ts +105 -0
- package/dist/evaluator/operators.d.ts.map +1 -0
- package/dist/evaluator/operators.js +371 -0
- package/dist/evaluator/operators.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +388 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/ast.d.ts +106 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +260 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/index.d.ts +8 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +13 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/lexer.d.ts +199 -0
- package/dist/parser/lexer.d.ts.map +1 -0
- package/dist/parser/lexer.js +491 -0
- package/dist/parser/lexer.js.map +1 -0
- package/dist/parser/parser.d.ts +49 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +615 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/plugins/index.d.ts +62 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +170 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/renderer/index.d.ts +6 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +5 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/renderer.d.ts +97 -0
- package/dist/renderer/renderer.d.ts.map +1 -0
- package/dist/renderer/renderer.js +243 -0
- package/dist/renderer/renderer.js.map +1 -0
- package/dist/types.d.ts +255 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Echo DSL Lexer - Multi-Mode Tokenization
|
|
3
|
+
*
|
|
4
|
+
* This file implements the lexer (tokenizer) for Echo DSL using Chevrotain.
|
|
5
|
+
* Uses multi-mode lexing to handle context-sensitive token recognition.
|
|
6
|
+
*
|
|
7
|
+
* LEXER MODES:
|
|
8
|
+
* - DEFAULT_MODE: Normal text content, looking for directives and variables
|
|
9
|
+
* - DIRECTIVE_MODE: Inside [#IF ...], [#SECTION ...], etc.
|
|
10
|
+
* - VARIABLE_MODE: Inside {{ ... }}
|
|
11
|
+
*
|
|
12
|
+
* TOKEN STREAM EXAMPLE:
|
|
13
|
+
*
|
|
14
|
+
* Input: "Hello {{name}}! [#IF {{age}} #gt(18)]Adult[END IF]"
|
|
15
|
+
*
|
|
16
|
+
* Tokens:
|
|
17
|
+
* TEXT("Hello ")
|
|
18
|
+
* VARIABLE_OPEN("{{")
|
|
19
|
+
* IDENTIFIER("name")
|
|
20
|
+
* VARIABLE_CLOSE("}}")
|
|
21
|
+
* TEXT("! ")
|
|
22
|
+
* IF_OPEN("[#IF")
|
|
23
|
+
* VARIABLE_OPEN("{{")
|
|
24
|
+
* IDENTIFIER("age")
|
|
25
|
+
* VARIABLE_CLOSE("}}")
|
|
26
|
+
* OPERATOR("#gt")
|
|
27
|
+
* LPAREN("(")
|
|
28
|
+
* NUMBER("18")
|
|
29
|
+
* RPAREN(")")
|
|
30
|
+
* CLOSE_BRACKET("]")
|
|
31
|
+
* TEXT("Adult")
|
|
32
|
+
* END_IF("[END IF]")
|
|
33
|
+
*/
|
|
34
|
+
import { createToken, Lexer, } from 'chevrotain';
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// TOKEN DEFINITIONS
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// -----------------------------------------------------------------------------
|
|
39
|
+
// Token Categories
|
|
40
|
+
// These are abstract tokens that serve as parent categories.
|
|
41
|
+
// Mode-specific variants extend these categories so the parser can match either.
|
|
42
|
+
// -----------------------------------------------------------------------------
|
|
43
|
+
/**
|
|
44
|
+
* Category for variable open tokens ({{)
|
|
45
|
+
*/
|
|
46
|
+
export const VariableOpen = createToken({
|
|
47
|
+
name: 'VariableOpen',
|
|
48
|
+
pattern: Lexer.NA, // Abstract - no pattern
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Category for variable close tokens (}})
|
|
52
|
+
*/
|
|
53
|
+
export const VariableClose = createToken({
|
|
54
|
+
name: 'VariableClose',
|
|
55
|
+
pattern: Lexer.NA, // Abstract - no pattern
|
|
56
|
+
});
|
|
57
|
+
// -----------------------------------------------------------------------------
|
|
58
|
+
// Directive Keywords (Complete - no mode switch needed)
|
|
59
|
+
// -----------------------------------------------------------------------------
|
|
60
|
+
/**
|
|
61
|
+
* [END IF] - End of conditional block
|
|
62
|
+
*/
|
|
63
|
+
export const EndIf = createToken({
|
|
64
|
+
name: 'EndIf',
|
|
65
|
+
pattern: /\[END IF\]/,
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* [END SECTION] - End of section definition
|
|
69
|
+
*/
|
|
70
|
+
export const EndSection = createToken({
|
|
71
|
+
name: 'EndSection',
|
|
72
|
+
pattern: /\[END SECTION\]/,
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* [ELSE] - Else branch (complete token)
|
|
76
|
+
*/
|
|
77
|
+
export const Else = createToken({
|
|
78
|
+
name: 'Else',
|
|
79
|
+
pattern: /\[ELSE\]/,
|
|
80
|
+
});
|
|
81
|
+
// -----------------------------------------------------------------------------
|
|
82
|
+
// Directive Openers (Push to DIRECTIVE_MODE)
|
|
83
|
+
// -----------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* [#IF - Start of conditional (followed by condition)
|
|
86
|
+
*/
|
|
87
|
+
export const IfOpen = createToken({
|
|
88
|
+
name: 'IfOpen',
|
|
89
|
+
pattern: /\[#IF/,
|
|
90
|
+
push_mode: 'DIRECTIVE_MODE',
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
93
|
+
* [ELSE IF - Else-if branch (followed by condition)
|
|
94
|
+
*/
|
|
95
|
+
export const ElseIf = createToken({
|
|
96
|
+
name: 'ElseIf',
|
|
97
|
+
pattern: /\[ELSE IF/,
|
|
98
|
+
push_mode: 'DIRECTIVE_MODE',
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* [#SECTION - Section definition (followed by name="value")
|
|
102
|
+
*/
|
|
103
|
+
export const SectionOpen = createToken({
|
|
104
|
+
name: 'SectionOpen',
|
|
105
|
+
pattern: /\[#SECTION/,
|
|
106
|
+
push_mode: 'DIRECTIVE_MODE',
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* [#IMPORT - Import directive (followed by path)
|
|
110
|
+
*/
|
|
111
|
+
export const Import = createToken({
|
|
112
|
+
name: 'Import',
|
|
113
|
+
pattern: /\[#IMPORT/,
|
|
114
|
+
push_mode: 'DIRECTIVE_MODE',
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* [#INCLUDE - Include directive (followed by section name)
|
|
118
|
+
*/
|
|
119
|
+
export const Include = createToken({
|
|
120
|
+
name: 'Include',
|
|
121
|
+
pattern: /\[#INCLUDE/,
|
|
122
|
+
push_mode: 'DIRECTIVE_MODE',
|
|
123
|
+
});
|
|
124
|
+
// -----------------------------------------------------------------------------
|
|
125
|
+
// Variable Syntax - Mode-Specific Variants
|
|
126
|
+
// -----------------------------------------------------------------------------
|
|
127
|
+
/**
|
|
128
|
+
* {{ in DEFAULT_MODE - pushes to VARIABLE_MODE
|
|
129
|
+
* Extends VariableOpen category so parser can match it.
|
|
130
|
+
*/
|
|
131
|
+
const VariableOpenDefault = createToken({
|
|
132
|
+
name: 'VariableOpenDefault',
|
|
133
|
+
pattern: /\{\{/,
|
|
134
|
+
push_mode: 'VARIABLE_MODE',
|
|
135
|
+
categories: [VariableOpen],
|
|
136
|
+
});
|
|
137
|
+
/**
|
|
138
|
+
* {{ in DIRECTIVE_MODE - no mode change (conditions are inline)
|
|
139
|
+
* Extends VariableOpen category so parser can match it.
|
|
140
|
+
*/
|
|
141
|
+
const VariableOpenDirective = createToken({
|
|
142
|
+
name: 'VariableOpenDirective',
|
|
143
|
+
pattern: /\{\{/,
|
|
144
|
+
categories: [VariableOpen],
|
|
145
|
+
});
|
|
146
|
+
/**
|
|
147
|
+
* }} in VARIABLE_MODE - pops back to previous mode
|
|
148
|
+
* Extends VariableClose category so parser can match it.
|
|
149
|
+
*/
|
|
150
|
+
const VariableCloseVariable = createToken({
|
|
151
|
+
name: 'VariableCloseVariable',
|
|
152
|
+
pattern: /\}\}/,
|
|
153
|
+
pop_mode: true,
|
|
154
|
+
categories: [VariableClose],
|
|
155
|
+
});
|
|
156
|
+
/**
|
|
157
|
+
* }} in DIRECTIVE_MODE - no mode change
|
|
158
|
+
* Extends VariableClose category so parser can match it.
|
|
159
|
+
*/
|
|
160
|
+
const VariableCloseDirective = createToken({
|
|
161
|
+
name: 'VariableCloseDirective',
|
|
162
|
+
pattern: /\}\}/,
|
|
163
|
+
categories: [VariableClose],
|
|
164
|
+
});
|
|
165
|
+
// -----------------------------------------------------------------------------
|
|
166
|
+
// Directive Mode Tokens
|
|
167
|
+
// -----------------------------------------------------------------------------
|
|
168
|
+
/**
|
|
169
|
+
* ] - End of directive (pops back to DEFAULT_MODE)
|
|
170
|
+
*/
|
|
171
|
+
export const CloseBracket = createToken({
|
|
172
|
+
name: 'CloseBracket',
|
|
173
|
+
pattern: /\]/,
|
|
174
|
+
pop_mode: true,
|
|
175
|
+
});
|
|
176
|
+
/**
|
|
177
|
+
* Operator - #equals, #contains, #ai_judge, etc.
|
|
178
|
+
*/
|
|
179
|
+
export const Operator = createToken({
|
|
180
|
+
name: 'Operator',
|
|
181
|
+
pattern: /#[a-zA-Z_][a-zA-Z0-9_]*/,
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* Identifier - variable names, section names, etc.
|
|
185
|
+
* Supports nested paths: user.name, items[0]
|
|
186
|
+
*/
|
|
187
|
+
export const Identifier = createToken({
|
|
188
|
+
name: 'Identifier',
|
|
189
|
+
pattern: /[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*|\[\d+\])*/,
|
|
190
|
+
});
|
|
191
|
+
/**
|
|
192
|
+
* String literal - "value" or 'value'
|
|
193
|
+
*/
|
|
194
|
+
export const StringLiteral = createToken({
|
|
195
|
+
name: 'StringLiteral',
|
|
196
|
+
pattern: /"[^"]*"|'[^']*'/,
|
|
197
|
+
});
|
|
198
|
+
/**
|
|
199
|
+
* Number literal - integers and decimals
|
|
200
|
+
*/
|
|
201
|
+
export const NumberLiteral = createToken({
|
|
202
|
+
name: 'NumberLiteral',
|
|
203
|
+
pattern: /-?\d+(?:\.\d+)?/,
|
|
204
|
+
});
|
|
205
|
+
/**
|
|
206
|
+
* ( - Left parenthesis for operator arguments
|
|
207
|
+
* Pushes to OPERATOR_ARG_MODE to capture free-form text
|
|
208
|
+
*/
|
|
209
|
+
export const LParen = createToken({
|
|
210
|
+
name: 'LParen',
|
|
211
|
+
pattern: /\(/,
|
|
212
|
+
push_mode: 'OPERATOR_ARG_MODE',
|
|
213
|
+
});
|
|
214
|
+
/**
|
|
215
|
+
* ) - Right parenthesis for operator arguments (in DIRECTIVE_MODE)
|
|
216
|
+
*/
|
|
217
|
+
export const RParen = createToken({
|
|
218
|
+
name: 'RParen',
|
|
219
|
+
pattern: /\)/,
|
|
220
|
+
});
|
|
221
|
+
/**
|
|
222
|
+
* ) - Right parenthesis that pops from OPERATOR_ARG_MODE
|
|
223
|
+
*/
|
|
224
|
+
const RParenOperatorArg = createToken({
|
|
225
|
+
name: 'RParenOperatorArg',
|
|
226
|
+
pattern: /\)/,
|
|
227
|
+
pop_mode: true,
|
|
228
|
+
categories: [RParen], // Extends RParen so parser sees it the same
|
|
229
|
+
});
|
|
230
|
+
/**
|
|
231
|
+
* Operator argument text - captures everything until closing paren.
|
|
232
|
+
* This allows natural text like "My Girlfriend" without quotes.
|
|
233
|
+
*/
|
|
234
|
+
export const OperatorArgText = createToken({
|
|
235
|
+
name: 'OperatorArgText',
|
|
236
|
+
pattern: /[^)]+/,
|
|
237
|
+
});
|
|
238
|
+
/**
|
|
239
|
+
* , - Comma separator in argument lists
|
|
240
|
+
*/
|
|
241
|
+
export const Comma = createToken({
|
|
242
|
+
name: 'Comma',
|
|
243
|
+
pattern: /,/,
|
|
244
|
+
});
|
|
245
|
+
/**
|
|
246
|
+
* = - Equals sign for attribute assignment (name="value")
|
|
247
|
+
*/
|
|
248
|
+
export const Equals = createToken({
|
|
249
|
+
name: 'Equals',
|
|
250
|
+
pattern: /=/,
|
|
251
|
+
});
|
|
252
|
+
/**
|
|
253
|
+
* ?? - Default value operator
|
|
254
|
+
*/
|
|
255
|
+
export const DefaultOp = createToken({
|
|
256
|
+
name: 'DefaultOp',
|
|
257
|
+
pattern: /\?\?/,
|
|
258
|
+
});
|
|
259
|
+
/**
|
|
260
|
+
* Whitespace - skipped in directive and variable modes
|
|
261
|
+
*/
|
|
262
|
+
export const WhiteSpace = createToken({
|
|
263
|
+
name: 'WhiteSpace',
|
|
264
|
+
pattern: /\s+/,
|
|
265
|
+
group: Lexer.SKIPPED,
|
|
266
|
+
});
|
|
267
|
+
// -----------------------------------------------------------------------------
|
|
268
|
+
// Text Content
|
|
269
|
+
// -----------------------------------------------------------------------------
|
|
270
|
+
/**
|
|
271
|
+
* Text - Plain text content.
|
|
272
|
+
*
|
|
273
|
+
* Matches any character sequence that doesn't start a special Echo construct.
|
|
274
|
+
* The lexer must stop when encountering:
|
|
275
|
+
* - `{{` (variable start)
|
|
276
|
+
* - `[#` (directive start: [#IF, [#SECTION, [#IMPORT, [#INCLUDE)
|
|
277
|
+
* - `[E` (branch/end markers: [ELSE], [ELSE IF, [END IF], [END SECTION])
|
|
278
|
+
*
|
|
279
|
+
* REGEX BREAKDOWN: /(?:[^\[{]|\[(?![#E])|\{(?!\{))+/
|
|
280
|
+
*
|
|
281
|
+
* (?: Non-capturing group containing three alternatives:
|
|
282
|
+
* │
|
|
283
|
+
* ├─ [^\[{] Alt 1: Any character EXCEPT '[' or '{'
|
|
284
|
+
* │ These are safe - no special meaning
|
|
285
|
+
* │
|
|
286
|
+
* ├─ \[(?![#E]) Alt 2: A '[' NOT followed by '#' or 'E'
|
|
287
|
+
* │ │ Allows: [x, [1, [anything-else
|
|
288
|
+
* │ └─ (?![#E]) Negative lookahead excludes:
|
|
289
|
+
* │ - [# (directives like [#IF)
|
|
290
|
+
* │ - [E (branches like [ELSE], [END IF])
|
|
291
|
+
* │
|
|
292
|
+
* └─ \{(?!\{) Alt 3: A '{' NOT followed by another '{'
|
|
293
|
+
* │ Allows: single { in text
|
|
294
|
+
* └─ (?!\{) Negative lookahead excludes:
|
|
295
|
+
* - {{ (variable start)
|
|
296
|
+
* )+ One or more matches (greedy)
|
|
297
|
+
*
|
|
298
|
+
* EXAMPLES:
|
|
299
|
+
* "Hello world" → matches entirely (no special chars)
|
|
300
|
+
* "Hello {{name}}" → matches "Hello " then stops at {{
|
|
301
|
+
* "Price: $[100]" → matches entirely ([1 is not [# or [E)
|
|
302
|
+
* "Use {braces}" → matches entirely (single { is allowed)
|
|
303
|
+
* "[#IF ..." → matches nothing (starts with [#)
|
|
304
|
+
*/
|
|
305
|
+
export const Text = createToken({
|
|
306
|
+
name: 'Text',
|
|
307
|
+
pattern: /(?:[^\[{]|\[(?![#E])|\{(?!\{))+/,
|
|
308
|
+
line_breaks: true,
|
|
309
|
+
});
|
|
310
|
+
// =============================================================================
|
|
311
|
+
// TOKEN GROUPS
|
|
312
|
+
// =============================================================================
|
|
313
|
+
/**
|
|
314
|
+
* All tokens used in DEFAULT_MODE.
|
|
315
|
+
* Order matters - more specific patterns first.
|
|
316
|
+
*/
|
|
317
|
+
const defaultModeTokens = [
|
|
318
|
+
// Complete directive tokens (no mode change)
|
|
319
|
+
EndIf,
|
|
320
|
+
EndSection,
|
|
321
|
+
Else,
|
|
322
|
+
// Directive openers (push to DIRECTIVE_MODE)
|
|
323
|
+
IfOpen,
|
|
324
|
+
ElseIf,
|
|
325
|
+
SectionOpen,
|
|
326
|
+
Import,
|
|
327
|
+
Include,
|
|
328
|
+
// Variable (push to VARIABLE_MODE)
|
|
329
|
+
VariableOpenDefault,
|
|
330
|
+
// Plain text (catch-all - must be last)
|
|
331
|
+
Text,
|
|
332
|
+
];
|
|
333
|
+
/**
|
|
334
|
+
* Tokens used inside directives [#IF ...], [#SECTION ...], etc.
|
|
335
|
+
*/
|
|
336
|
+
const directiveModeTokens = [
|
|
337
|
+
// End directive (pop mode)
|
|
338
|
+
CloseBracket,
|
|
339
|
+
// Nested variable in conditions
|
|
340
|
+
VariableOpenDirective,
|
|
341
|
+
VariableCloseDirective,
|
|
342
|
+
// Operators and punctuation
|
|
343
|
+
Operator,
|
|
344
|
+
DefaultOp,
|
|
345
|
+
Equals,
|
|
346
|
+
LParen,
|
|
347
|
+
RParen,
|
|
348
|
+
Comma,
|
|
349
|
+
// Literals (before Identifier to catch numbers first)
|
|
350
|
+
StringLiteral,
|
|
351
|
+
NumberLiteral,
|
|
352
|
+
Identifier,
|
|
353
|
+
// Whitespace (skipped)
|
|
354
|
+
WhiteSpace,
|
|
355
|
+
];
|
|
356
|
+
/**
|
|
357
|
+
* Tokens used inside variables {{ ... }}
|
|
358
|
+
*/
|
|
359
|
+
const variableModeTokens = [
|
|
360
|
+
// End variable (pop mode)
|
|
361
|
+
VariableCloseVariable,
|
|
362
|
+
// Default operator
|
|
363
|
+
DefaultOp,
|
|
364
|
+
// Literals
|
|
365
|
+
StringLiteral,
|
|
366
|
+
NumberLiteral,
|
|
367
|
+
Identifier,
|
|
368
|
+
// Whitespace (skipped)
|
|
369
|
+
WhiteSpace,
|
|
370
|
+
];
|
|
371
|
+
/**
|
|
372
|
+
* Tokens used inside operator arguments ( ... )
|
|
373
|
+
* Captures free-form text until closing paren.
|
|
374
|
+
*/
|
|
375
|
+
const operatorArgModeTokens = [
|
|
376
|
+
// End of argument (pop mode)
|
|
377
|
+
RParenOperatorArg,
|
|
378
|
+
// Free-form text content
|
|
379
|
+
OperatorArgText,
|
|
380
|
+
];
|
|
381
|
+
// =============================================================================
|
|
382
|
+
// MULTI-MODE LEXER DEFINITION
|
|
383
|
+
// =============================================================================
|
|
384
|
+
/**
|
|
385
|
+
* Multi-mode lexer configuration.
|
|
386
|
+
* Enables context-sensitive tokenization.
|
|
387
|
+
*/
|
|
388
|
+
const multiModeLexerDefinition = {
|
|
389
|
+
modes: {
|
|
390
|
+
DEFAULT_MODE: defaultModeTokens,
|
|
391
|
+
DIRECTIVE_MODE: directiveModeTokens,
|
|
392
|
+
VARIABLE_MODE: variableModeTokens,
|
|
393
|
+
OPERATOR_ARG_MODE: operatorArgModeTokens,
|
|
394
|
+
},
|
|
395
|
+
defaultMode: 'DEFAULT_MODE',
|
|
396
|
+
};
|
|
397
|
+
/**
|
|
398
|
+
* All unique tokens (for parser configuration).
|
|
399
|
+
* Includes category tokens and all mode-specific variants.
|
|
400
|
+
*
|
|
401
|
+
* IMPORTANT: Category tokens must come BEFORE their child tokens
|
|
402
|
+
* in this array for Chevrotain to properly recognize them.
|
|
403
|
+
*/
|
|
404
|
+
export const allTokens = [
|
|
405
|
+
// Categories first (abstract tokens)
|
|
406
|
+
VariableOpen,
|
|
407
|
+
VariableClose,
|
|
408
|
+
// Directive keywords
|
|
409
|
+
EndIf,
|
|
410
|
+
EndSection,
|
|
411
|
+
Else,
|
|
412
|
+
IfOpen,
|
|
413
|
+
ElseIf,
|
|
414
|
+
SectionOpen,
|
|
415
|
+
Import,
|
|
416
|
+
Include,
|
|
417
|
+
// Mode-specific variable tokens (extend categories)
|
|
418
|
+
VariableOpenDefault,
|
|
419
|
+
VariableOpenDirective,
|
|
420
|
+
VariableCloseVariable,
|
|
421
|
+
VariableCloseDirective,
|
|
422
|
+
// Operators and punctuation
|
|
423
|
+
Operator,
|
|
424
|
+
DefaultOp,
|
|
425
|
+
Equals,
|
|
426
|
+
CloseBracket,
|
|
427
|
+
LParen,
|
|
428
|
+
RParen,
|
|
429
|
+
RParenOperatorArg,
|
|
430
|
+
Comma,
|
|
431
|
+
// Operator argument mode tokens
|
|
432
|
+
OperatorArgText,
|
|
433
|
+
// Literals
|
|
434
|
+
StringLiteral,
|
|
435
|
+
NumberLiteral,
|
|
436
|
+
Identifier,
|
|
437
|
+
// Whitespace
|
|
438
|
+
WhiteSpace,
|
|
439
|
+
// Text
|
|
440
|
+
Text,
|
|
441
|
+
];
|
|
442
|
+
// =============================================================================
|
|
443
|
+
// LEXER INSTANCE
|
|
444
|
+
// =============================================================================
|
|
445
|
+
/**
|
|
446
|
+
* The Echo multi-mode lexer instance.
|
|
447
|
+
* Uses different token sets depending on the current lexing context.
|
|
448
|
+
*/
|
|
449
|
+
export const EchoLexer = new Lexer(multiModeLexerDefinition, {
|
|
450
|
+
// Note: We disable ensureOptimizations because the Text token uses
|
|
451
|
+
// a complement set pattern which cannot be optimized by Chevrotain.
|
|
452
|
+
// The lexer still works correctly, just without first-char optimizations.
|
|
453
|
+
ensureOptimizations: false,
|
|
454
|
+
positionTracking: 'full', // Required for source locations
|
|
455
|
+
});
|
|
456
|
+
// =============================================================================
|
|
457
|
+
// PUBLIC API
|
|
458
|
+
// =============================================================================
|
|
459
|
+
/**
|
|
460
|
+
* Tokenize an Echo template.
|
|
461
|
+
*
|
|
462
|
+
* @param template - The template string to tokenize
|
|
463
|
+
* @returns Lexer result with tokens and errors
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```typescript
|
|
467
|
+
* const result = tokenize('Hello {{name}}!');
|
|
468
|
+
* if (result.errors.length > 0) {
|
|
469
|
+
* console.error('Lexer errors:', result.errors);
|
|
470
|
+
* } else {
|
|
471
|
+
* console.log('Tokens:', result.tokens);
|
|
472
|
+
* }
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
export function tokenize(template) {
|
|
476
|
+
return EchoLexer.tokenize(template);
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Format lexer errors for display.
|
|
480
|
+
*
|
|
481
|
+
* @param errors - Lexer errors from tokenize()
|
|
482
|
+
* @returns Formatted error messages
|
|
483
|
+
*/
|
|
484
|
+
export function formatLexerErrors(errors) {
|
|
485
|
+
return errors.map((error) => {
|
|
486
|
+
const line = error.line ?? 1;
|
|
487
|
+
const column = error.column ?? 1;
|
|
488
|
+
return `Lexer error at line ${line}, column ${column}: ${error.message}`;
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
//# sourceMappingURL=lexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.js","sourceRoot":"","sources":["../../src/parser/lexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Echo DSL Parser - AST Generation
|
|
3
|
+
*
|
|
4
|
+
* This file implements the parser for Echo DSL using Chevrotain.
|
|
5
|
+
* The parser converts a token stream into an Abstract Syntax Tree (AST).
|
|
6
|
+
*
|
|
7
|
+
* GRAMMAR (pseudo-BNF):
|
|
8
|
+
*
|
|
9
|
+
* template := (node)*
|
|
10
|
+
* node := text | variable | conditional | section | import | include
|
|
11
|
+
* text := TEXT
|
|
12
|
+
* variable := "{{" identifier ("??" defaultValue)? "}}"
|
|
13
|
+
* conditional := ifBlock (elseIfBlock)* (elseBlock)? endIf
|
|
14
|
+
* ifBlock := "[#IF" condition "]" (node)*
|
|
15
|
+
* elseIfBlock := "[ELSE IF" condition "]" (node)*
|
|
16
|
+
* elseBlock := "[ELSE]" (node)*
|
|
17
|
+
* endIf := "[END IF]"
|
|
18
|
+
* condition := "{{" identifier "}}" operator
|
|
19
|
+
* operator := "#" IDENTIFIER ("(" arguments ")")?
|
|
20
|
+
* arguments := value ("," value)*
|
|
21
|
+
* value := STRING | NUMBER | IDENTIFIER
|
|
22
|
+
* section := "[#SECTION" "name" "=" STRING "]" (node)* "[END SECTION]"
|
|
23
|
+
* import := "[#IMPORT" (STRING | path) "]"
|
|
24
|
+
* include := "[#INCLUDE" IDENTIFIER "]"
|
|
25
|
+
*/
|
|
26
|
+
import { type IToken } from 'chevrotain';
|
|
27
|
+
import type { ParseResult, SourceLocation } from '../types.js';
|
|
28
|
+
/**
|
|
29
|
+
* Extract source location from a token.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getTokenLocation(token: IToken): SourceLocation;
|
|
32
|
+
/**
|
|
33
|
+
* Parse an Echo template into an AST.
|
|
34
|
+
*
|
|
35
|
+
* @param template - The Echo template string
|
|
36
|
+
* @returns ParseResult with AST or errors
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const result = parse('Hello {{name}}!');
|
|
41
|
+
* if (result.success) {
|
|
42
|
+
* console.log('AST:', result.ast);
|
|
43
|
+
* } else {
|
|
44
|
+
* console.error('Errors:', result.errors);
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function parse(template: string): ParseResult;
|
|
49
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAA2B,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAEV,WAAW,EACX,cAAc,EAIf,MAAM,aAAa,CAAC;AAsrBrB;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAQ9D;AA2CD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CA6CnD"}
|