@words-lang/parser 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/analyser/analyser.d.ts +106 -0
- package/dist/analyser/analyser.d.ts.map +1 -0
- package/dist/analyser/analyser.js +291 -0
- package/dist/analyser/analyser.js.map +1 -0
- package/dist/analyser/diagnostics.d.ts +166 -0
- package/dist/analyser/diagnostics.d.ts.map +1 -0
- package/dist/analyser/diagnostics.js +139 -0
- package/dist/analyser/diagnostics.js.map +1 -0
- package/dist/analyser/workspace.d.ts +198 -0
- package/dist/analyser/workspace.d.ts.map +1 -0
- package/dist/analyser/workspace.js +403 -0
- package/dist/analyser/workspace.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer/lexer.d.ts +120 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +365 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/lexer/token.d.ts +247 -0
- package/dist/lexer/token.d.ts.map +1 -0
- package/dist/lexer/token.js +250 -0
- package/dist/lexer/token.js.map +1 -0
- package/dist/parser/ast.d.ts +685 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +3 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/parser.d.ts +411 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +1600 -0
- package/dist/parser/parser.js.map +1 -0
- package/package.json +23 -0
- package/src/analyser/analyser.ts +403 -0
- package/src/analyser/diagnostics.ts +232 -0
- package/src/analyser/workspace.ts +457 -0
- package/src/index.ts +7 -0
- package/src/lexer/lexer.ts +379 -0
- package/src/lexer/token.ts +331 -0
- package/src/parser/ast.ts +798 -0
- package/src/parser/parser.ts +1815 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* token.ts
|
|
3
|
+
*
|
|
4
|
+
* Defines every token type the WORDS lexer can produce, the Token interface
|
|
5
|
+
* that carries a token's value and source location, and a convenience
|
|
6
|
+
* constructor for creating tokens in tests and the lexer itself.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// ── Token types ───────────────────────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Every token type the WORDS lexer can produce.
|
|
13
|
+
*
|
|
14
|
+
* Grouped by category:
|
|
15
|
+
* - Top-level construct keywords (system, module, state, ...)
|
|
16
|
+
* - Block keywords (modules, props, uses, returns, ...)
|
|
17
|
+
* - Process / transition keywords (when, enter)
|
|
18
|
+
* - Control flow keywords (if, for, as, is, is not)
|
|
19
|
+
* - Primitive types (tstring, tinteger, ...)
|
|
20
|
+
* - Literals (string_lit, integer_lit, ...)
|
|
21
|
+
* - Identifiers (pascal_ident, camel_ident)
|
|
22
|
+
* - Punctuation ((, ), ,, .)
|
|
23
|
+
* - Special (comment, newline, eof, unknown)
|
|
24
|
+
*
|
|
25
|
+
* Enum values are the string representation of each token — useful for
|
|
26
|
+
* readable error messages and debug output without a separate lookup table.
|
|
27
|
+
*
|
|
28
|
+
* Note on naming conventions: method names, callback prop names, and handler
|
|
29
|
+
* method names (including names like `switch`, `onLoad`, `onSubmit`) are all
|
|
30
|
+
* plain camelCase identifiers chosen by the designer. None of them are
|
|
31
|
+
* reserved keywords in the WORDS language.
|
|
32
|
+
*/
|
|
33
|
+
export enum TokenType {
|
|
34
|
+
|
|
35
|
+
// ── Top-level construct keywords ─────────────────────────────────────────
|
|
36
|
+
// These keywords open a named construct body at the top level of a file
|
|
37
|
+
// or inside a module definition.
|
|
38
|
+
|
|
39
|
+
/** `system` — opens the system declaration. Appears exactly once per project. */
|
|
40
|
+
System = 'system',
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* `module` — opens a module definition body, or appears alone on a line
|
|
44
|
+
* as an ownership declaration at the top of component files.
|
|
45
|
+
* e.g. `module AuthModule` (ownership) or `module AuthModule "..." (` (definition)
|
|
46
|
+
*/
|
|
47
|
+
Module = 'module',
|
|
48
|
+
|
|
49
|
+
/** `process` — opens a process definition inside a module body. */
|
|
50
|
+
Process = 'process',
|
|
51
|
+
|
|
52
|
+
/** `state` — opens a state definition. */
|
|
53
|
+
State = 'state',
|
|
54
|
+
|
|
55
|
+
/** `context` — opens a context definition. */
|
|
56
|
+
Context = 'context',
|
|
57
|
+
|
|
58
|
+
/** `screen` — opens a screen definition, or activates a screen inside a `uses` block. */
|
|
59
|
+
Screen = 'screen',
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* `view` — opens a view definition, or activates a view inside a `uses` block.
|
|
63
|
+
* e.g. `view LoginFormSection "..." (` or `view UIModule.LoginForm (`
|
|
64
|
+
*/
|
|
65
|
+
View = 'view',
|
|
66
|
+
|
|
67
|
+
/** `provider` — opens a provider definition, or activates a provider in a `uses` block. */
|
|
68
|
+
Provider = 'provider',
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* `adapter` — opens an adapter definition, or activates an adapter in a `uses` block.
|
|
72
|
+
* e.g. `adapter AuthAdapter.login credentials is state.context`
|
|
73
|
+
*/
|
|
74
|
+
Adapter = 'adapter',
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* `interface` — opens an interface component definition, activates one in a
|
|
78
|
+
* `uses` block, or introduces an inline interface block inside a module body.
|
|
79
|
+
*/
|
|
80
|
+
Interface = 'interface',
|
|
81
|
+
|
|
82
|
+
// ── Block keywords ────────────────────────────────────────────────────────
|
|
83
|
+
// These keywords open named sub-blocks inside a construct body.
|
|
84
|
+
|
|
85
|
+
/** `modules` — opens the module list inside a system body. */
|
|
86
|
+
Modules = 'modules',
|
|
87
|
+
|
|
88
|
+
/** `props` — opens the props block inside a view, provider, adapter, or interface. */
|
|
89
|
+
Props = 'props',
|
|
90
|
+
|
|
91
|
+
/** `uses` — opens the uses block inside a state, screen, view, provider, or interface. */
|
|
92
|
+
Uses = 'uses',
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* `returns` — appears in two roles:
|
|
96
|
+
* 1. Opens the returns clause inside a state: `returns AccountCredentials`
|
|
97
|
+
* 2. Declares the return type of a method: `getProducts returns(list(Product))`
|
|
98
|
+
*/
|
|
99
|
+
Returns = 'returns',
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* `receives` — opens the receives clause on a state definition.
|
|
103
|
+
* e.g. `state Unauthenticated receives ?AuthError`
|
|
104
|
+
*/
|
|
105
|
+
Receives = 'receives',
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* `start` — names the initial state of a module.
|
|
109
|
+
* e.g. `start Unauthenticated`
|
|
110
|
+
*/
|
|
111
|
+
Start = 'start',
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* `implements` — opens a cross-module handler implementation block
|
|
115
|
+
* inside a module body.
|
|
116
|
+
* e.g. `implements RoutingModule.RouteSwitchHandler (`
|
|
117
|
+
*/
|
|
118
|
+
Implements = 'implements',
|
|
119
|
+
|
|
120
|
+
// ── Process / transition keywords ────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* `when` — opens a transition rule inside a process body.
|
|
124
|
+
* e.g. `when Unauthenticated returns AccountCredentials`
|
|
125
|
+
*/
|
|
126
|
+
When = 'when',
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* `enter` — names the next state to transition to in a `when` rule
|
|
130
|
+
* or an `implements` branch.
|
|
131
|
+
* e.g. `enter StartAuthenticating "The user tries to authenticate"`
|
|
132
|
+
*/
|
|
133
|
+
Enter = 'enter',
|
|
134
|
+
|
|
135
|
+
// ── Control flow keywords ─────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* `if` — opens a conditional block inside a `uses` block or an
|
|
139
|
+
* `implements` handler body.
|
|
140
|
+
* e.g. `if state.context is AccountDeauthenticated (`
|
|
141
|
+
*/
|
|
142
|
+
If = 'if',
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* `for` — opens an iteration block inside a `uses` block.
|
|
146
|
+
* e.g. `for state.context.notifications as notification (`
|
|
147
|
+
*/
|
|
148
|
+
For = 'for',
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* `as` — binds the iteration variable(s) in a `for` block.
|
|
152
|
+
* For lists: `as notification` — one binding.
|
|
153
|
+
* For maps: `as category, products` — two bindings.
|
|
154
|
+
*/
|
|
155
|
+
As = 'as',
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* `is` — the assignment and equality operator.
|
|
159
|
+
* As assignment: `type is "warning"`, `path is "/home"`
|
|
160
|
+
* As comparison: `if state.context is AccountDeauthenticated`
|
|
161
|
+
* Context determines which role it plays.
|
|
162
|
+
*/
|
|
163
|
+
Is = 'is',
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* `is not` — the inequality operator, normalised from the two-word
|
|
167
|
+
* sequence `is not` into a single token during lexing.
|
|
168
|
+
* e.g. `if state.context is not AccountRecovered`
|
|
169
|
+
*/
|
|
170
|
+
IsNot = 'is_not',
|
|
171
|
+
|
|
172
|
+
// ── Primitive types ───────────────────────────────────────────────────────
|
|
173
|
+
// These keywords name the built-in scalar and collection types.
|
|
174
|
+
|
|
175
|
+
/** `string` — text value type. Default: `""` */
|
|
176
|
+
TString = 'tstring',
|
|
177
|
+
|
|
178
|
+
/** `integer` — whole number type. Default: `0` */
|
|
179
|
+
TInteger = 'tinteger',
|
|
180
|
+
|
|
181
|
+
/** `float` — decimal number type. Default: `0.0` */
|
|
182
|
+
TFloat = 'tfloat',
|
|
183
|
+
|
|
184
|
+
/** `boolean` — true/false type. Default: `false` */
|
|
185
|
+
TBoolean = 'tboolean',
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* `context` — opaque context type used only in the system interface
|
|
189
|
+
* declaration for `getContext` and `setContext`.
|
|
190
|
+
*/
|
|
191
|
+
TContext = 'tcontext',
|
|
192
|
+
|
|
193
|
+
/** `list` — ordered collection type. Parameterised: `list(Product)`. Default: `[]` */
|
|
194
|
+
TList = 'tlist',
|
|
195
|
+
|
|
196
|
+
/** `map` — key-value collection type. Parameterised: `map(string, OrderSummary)`. Default: `{}` */
|
|
197
|
+
TMap = 'tmap',
|
|
198
|
+
|
|
199
|
+
// ── Literals ──────────────────────────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A double-quoted string literal.
|
|
203
|
+
* The token value includes the surrounding quotes.
|
|
204
|
+
* e.g. `"The user authenticated successfully"`, `"/home"`
|
|
205
|
+
*/
|
|
206
|
+
StringLit = 'string_lit',
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A whole number literal.
|
|
210
|
+
* e.g. `42`, `5000`, `0`
|
|
211
|
+
*/
|
|
212
|
+
IntegerLit = 'integer_lit',
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* A decimal number literal.
|
|
216
|
+
* e.g. `0.0`, `3.14`
|
|
217
|
+
*/
|
|
218
|
+
FloatLit = 'float_lit',
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* A boolean literal — `true` or `false`.
|
|
222
|
+
* Lexed as keyword-style tokens with value `"true"` or `"false"`.
|
|
223
|
+
*/
|
|
224
|
+
BooleanLit = 'boolean_lit',
|
|
225
|
+
|
|
226
|
+
// ── Identifiers ───────────────────────────────────────────────────────────
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* A PascalCase identifier — names a construct (state, context, module, etc.)
|
|
230
|
+
* or a type reference.
|
|
231
|
+
* e.g. `AuthModule`, `AccountCredentials`, `LoginScreen`, `Product`
|
|
232
|
+
*/
|
|
233
|
+
PascalIdent = 'pascal_ident',
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* A camelCase identifier — names a prop, method, argument, or iteration variable.
|
|
237
|
+
* This includes all designer-chosen names: callback prop names, method names,
|
|
238
|
+
* and handler method names regardless of what they are called.
|
|
239
|
+
* e.g. `onSubmit`, `credentials`, `fullName`, `notification`, `switch`, `onLoad`
|
|
240
|
+
*/
|
|
241
|
+
CamelIdent = 'camel_ident',
|
|
242
|
+
|
|
243
|
+
// ── Punctuation ───────────────────────────────────────────────────────────
|
|
244
|
+
|
|
245
|
+
/** `(` — opens a body block or argument list. */
|
|
246
|
+
LParen = '(',
|
|
247
|
+
|
|
248
|
+
/** `)` — closes a body block or argument list. */
|
|
249
|
+
RParen = ')',
|
|
250
|
+
|
|
251
|
+
/** `,` — separates entries in a list — props, arguments, context names. */
|
|
252
|
+
Comma = ',',
|
|
253
|
+
|
|
254
|
+
/** `.` — separates parts of a qualified name or access expression. */
|
|
255
|
+
Dot = '.',
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* `?` — marks an optional type or receives clause.
|
|
259
|
+
* e.g. `?AuthError`, `?Product`
|
|
260
|
+
* Always immediately precedes a PascalIdent.
|
|
261
|
+
*/
|
|
262
|
+
Question = '?',
|
|
263
|
+
|
|
264
|
+
// ── Special ───────────────────────────────────────────────────────────────
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* A `//` line comment. The token value includes the `//` prefix and
|
|
268
|
+
* everything up to (but not including) the newline.
|
|
269
|
+
* Comments are included in the token stream so the parser can attach
|
|
270
|
+
* them to adjacent nodes for hover documentation.
|
|
271
|
+
*/
|
|
272
|
+
Comment = 'comment',
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* A newline character `\n`.
|
|
276
|
+
* Newlines are significant in WORDS for distinguishing an ownership
|
|
277
|
+
* declaration (`module AuthModule` on its own line) from a construct
|
|
278
|
+
* opening (`module AuthModule "..." (`).
|
|
279
|
+
*/
|
|
280
|
+
Newline = 'newline',
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* End of file sentinel. Always the last token in the stream.
|
|
284
|
+
* The parser uses this to detect unexpected end of input.
|
|
285
|
+
*/
|
|
286
|
+
EOF = 'eof',
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* An unrecognised character. Emitted rather than throwing so the lexer
|
|
290
|
+
* can continue and collect all errors in a single pass.
|
|
291
|
+
*/
|
|
292
|
+
Unknown = 'unknown',
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ── Token ─────────────────────────────────────────────────────────────────────
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* A single token produced by the lexer.
|
|
299
|
+
*
|
|
300
|
+
* `type` — the token's category, used by the parser for matching.
|
|
301
|
+
* `value` — the raw source text that produced this token. For string
|
|
302
|
+
* literals this includes the surrounding quotes. For `is not`
|
|
303
|
+
* this is the normalised string `"is not"`.
|
|
304
|
+
* `line` — 1-based line number of the token's first character.
|
|
305
|
+
* `column` — 1-based column number of the token's first character.
|
|
306
|
+
* `offset` — byte offset from the start of the source string. Used by the
|
|
307
|
+
* LSP to convert between source positions and editor positions.
|
|
308
|
+
*/
|
|
309
|
+
export interface Token {
|
|
310
|
+
type: TokenType
|
|
311
|
+
value: string
|
|
312
|
+
line: number
|
|
313
|
+
column: number
|
|
314
|
+
offset: number
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ── Convenience constructor ───────────────────────────────────────────────────
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Creates a Token with the given fields.
|
|
321
|
+
* Used internally by the lexer and in tests to avoid repetitive object literals.
|
|
322
|
+
*/
|
|
323
|
+
export function token(
|
|
324
|
+
type: TokenType,
|
|
325
|
+
value: string,
|
|
326
|
+
line: number,
|
|
327
|
+
column: number,
|
|
328
|
+
offset: number
|
|
329
|
+
): Token {
|
|
330
|
+
return { type, value, line, column, offset }
|
|
331
|
+
}
|