cluaupp 0.2.2 → 1.0.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +14 -75
  2. package/README.md +42 -88
  3. package/docs/README.md +25 -21
  4. package/docs/architecture.md +13 -76
  5. package/docs/cli.md +12 -64
  6. package/docs/comparison.md +6 -24
  7. package/docs/config.md +6 -7
  8. package/docs/cpp-advanced.md +6 -3
  9. package/docs/cpp-types.md +2 -0
  10. package/docs/examples/combat.md +19 -227
  11. package/docs/examples/hud.md +13 -81
  12. package/docs/examples/index.md +9 -16
  13. package/docs/examples/leaderstats.md +44 -115
  14. package/docs/getting-started.md +20 -135
  15. package/docs/intellisense.md +5 -42
  16. package/docs/intro.md +16 -15
  17. package/docs/libraries/dataservice.md +4 -1
  18. package/docs/libraries/index.md +2 -1
  19. package/docs/libraries/more.md +3 -1
  20. package/docs/libraries/ui.md +76 -0
  21. package/docs/migration.md +38 -0
  22. package/docs/oop/file-tags.md +12 -36
  23. package/docs/oop/index.md +18 -11
  24. package/docs/roblox-api.md +4 -56
  25. package/docs/syntax.md +54 -179
  26. package/editors/vscode/extension.js +1 -1
  27. package/editors/vscode/package.json +4 -4
  28. package/examples/README.md +5 -7
  29. package/examples/game/.vscode/extensions.json +2 -2
  30. package/examples/game/.vscode/settings.json +6 -23
  31. package/examples/game/src/client/hud.client.clpp +54 -0
  32. package/examples/game/src/client/init.client.clpp +6 -0
  33. package/examples/game/src/server/combat.server.clpp +85 -0
  34. package/examples/game/src/server/leaderstats.server.clpp +28 -0
  35. package/examples/game/src/shared/PlayerData.clh +20 -0
  36. package/examples/game/src/shared/config.clp +6 -0
  37. package/examples/game/src/shared/features.clp +88 -0
  38. package/generated/api.js +15 -1
  39. package/generated/cli.js +40 -24
  40. package/generated/clpp/contract.js +5 -0
  41. package/generated/clpp/index.js +27 -0
  42. package/generated/clpp/paths.js +121 -0
  43. package/generated/clpp/postprocess.js +78 -0
  44. package/generated/clpp/runner.js +102 -0
  45. package/generated/compile.js +26 -138
  46. package/generated/emit.js +79 -3
  47. package/generated/intellisense.js +83 -207
  48. package/generated/lex.js +3 -0
  49. package/generated/libs.js +1 -1
  50. package/generated/lsp.js +1 -8
  51. package/generated/parse.js +119 -24
  52. package/generated/preprocess.js +8 -179
  53. package/generated/system-understander.js +1 -1
  54. package/generated/transpile.js +3 -50
  55. package/generated/utils/project.js +13 -28
  56. package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +5 -1
  57. package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
  58. package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
  59. package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
  60. package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
  61. package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
  62. package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
  63. package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
  64. package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
  65. package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
  66. package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
  67. package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
  68. package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
  69. package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
  70. package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
  71. package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
  72. package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
  73. package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
  74. package/include/clpp/libs.clh +24 -0
  75. package/include/clpp/roblox.clh +31 -0
  76. package/package.json +20 -16
  77. package/src/api.ts +15 -1
  78. package/src/cli.ts +39 -25
  79. package/src/clpp/contract.ts +39 -0
  80. package/src/clpp/index.ts +18 -0
  81. package/src/clpp/paths.ts +117 -0
  82. package/src/clpp/postprocess.ts +93 -0
  83. package/src/clpp/runner.ts +102 -0
  84. package/src/compile.ts +26 -149
  85. package/src/intellisense.ts +82 -211
  86. package/src/libs.ts +1 -1
  87. package/src/lsp.ts +1 -5
  88. package/src/preprocess.ts +8 -180
  89. package/src/system-understander.ts +1 -1
  90. package/src/transpile.ts +9 -52
  91. package/src/utils/project.ts +12 -28
  92. package/templates/game/.vscode/extensions.json +2 -2
  93. package/templates/game/.vscode/settings.json +6 -23
  94. package/templates/game/src/client/init.client.clpp +6 -0
  95. package/templates/game/src/server/leaderstats.server.clpp +29 -0
  96. package/templates/game/src/shared/config.clp +6 -0
  97. package/examples/game/.clangd +0 -25
  98. package/examples/game/.vscode/c_cpp_properties.json +0 -27
  99. package/examples/game/compile_flags.txt +0 -6
  100. package/examples/game/src/client/hud.client.cpp +0 -12
  101. package/examples/game/src/client/init.client.cpp +0 -6
  102. package/examples/game/src/server/combat.server.cpp +0 -23
  103. package/examples/game/src/server/leaderstats.server.cpp +0 -29
  104. package/examples/game/src/shared/config.cpp +0 -5
  105. package/examples/game/src/shared/config.h +0 -5
  106. package/include/cluaupp/libs.hpp +0 -25
  107. package/include/cluaupp/roblox.hpp +0 -47
  108. package/src/architecture.ts +0 -500
  109. package/src/ast.ts +0 -37
  110. package/src/emit.ts +0 -531
  111. package/src/emitter/luau-codegen.ts +0 -187
  112. package/src/emitter/translators.ts +0 -168
  113. package/src/headers.ts +0 -233
  114. package/src/layout.ts +0 -114
  115. package/src/lex.ts +0 -155
  116. package/src/parse.ts +0 -630
  117. package/src/parser/collector.ts +0 -148
  118. package/src/parser/index.ts +0 -27
  119. package/src/tree-sitter-cpp.d.ts +0 -4
  120. package/src/understand.ts +0 -322
  121. package/templates/game/.vscode/c_cpp_properties.json +0 -27
  122. package/templates/game/src/client/init.client.cpp +0 -6
  123. package/templates/game/src/server/leaderstats.server.cpp +0 -29
  124. package/templates/game/src/shared/config.cpp +0 -5
  125. package/templates/game/src/shared/config.h +0 -5
  126. /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
  127. /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
  128. /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
  129. /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
package/src/parse.ts DELETED
@@ -1,630 +0,0 @@
1
- // @ts-nocheck
2
- import { tokenize } from "./lex.js";
3
-
4
- function parse(source, fileName) {
5
- const tokens = tokenize(source);
6
- let i = 0;
7
-
8
- const peek = (offset = 0) => tokens[i + offset] || tokens[tokens.length - 1];
9
- const at = (type, value) => {
10
- const token = peek();
11
- if (type && token.type !== type) {
12
- return false;
13
- }
14
- if (value !== undefined && token.value !== value) {
15
- return false;
16
- }
17
- return true;
18
- };
19
- const eat = (type, value) => {
20
- if (!at(type, value)) {
21
- const token = peek();
22
- throw error(`expected ${value || type}, got '${token.value}'`, token);
23
- }
24
- const token = peek();
25
- i += 1;
26
- return token;
27
- };
28
- const error = (message, token = peek()) => {
29
- const err = new Error(`${fileName}:${token.line}:${token.col}: ${message}`);
30
- err.line = token.line;
31
- err.col = token.col;
32
- return err;
33
- };
34
-
35
- const skipSemicolons = () => {
36
- while (at("op", ";")) {
37
- i += 1;
38
- }
39
- };
40
-
41
- const skipTemplate = () => {
42
- if (!at("op", "<")) {
43
- return null;
44
- }
45
- eat("op", "<");
46
- const name = eat("ident").value;
47
- eat("op", ">");
48
- return name;
49
- };
50
-
51
- function parseType() {
52
- if (at("kw", "const")) {
53
- i += 1;
54
- }
55
- if (at("kw", "auto") || at("kw", "void") || at("kw", "int") || at("kw", "bool") || at("kw", "float") || at("kw", "double")) {
56
- const name = eat("kw").value;
57
- while (at("op", "*")) {
58
- i += 1;
59
- }
60
- return name;
61
- }
62
- if (!at("ident")) {
63
- return null;
64
- }
65
- const name = eat("ident").value;
66
- while (at("op", "*")) {
67
- i += 1;
68
- }
69
- return name;
70
- }
71
-
72
- function parseArgs() {
73
- eat("op", "(");
74
- const args = [];
75
- if (!at("op", ")")) {
76
- args.push(parseExpr());
77
- while (at("op", ",")) {
78
- i += 1;
79
- args.push(parseExpr());
80
- }
81
- }
82
- eat("op", ")");
83
- return args;
84
- }
85
-
86
- function parseInitList() {
87
- eat("op", "{");
88
- const fields = [];
89
- while (!at("op", "}") && !at("eof")) {
90
- if (at("op", ".")) {
91
- i += 1;
92
- const name = eat("ident").value;
93
- eat("op", "=");
94
- fields.push({ name, value: parseExpr() });
95
- } else {
96
- throw error("expected designated initializer .Field = value");
97
- }
98
- if (at("op", ",")) {
99
- i += 1;
100
- } else {
101
- break;
102
- }
103
- }
104
- eat("op", "}");
105
- return { type: "initlist", fields };
106
- }
107
-
108
- function parsePrimary() {
109
- if (at("kw", "true") || at("kw", "false")) {
110
- return { type: "bool", value: eat("kw").value === "true" };
111
- }
112
- if (at("kw", "nullptr")) {
113
- i += 1;
114
- return { type: "null" };
115
- }
116
- if (at("number")) {
117
- return { type: "number", value: eat("number").value };
118
- }
119
- if (at("string")) {
120
- return { type: "string", value: eat("string").value };
121
- }
122
- if (at("kw", "new")) {
123
- i += 1;
124
- const className = eat("ident").value;
125
- const args = at("op", "(") ? parseArgs() : [];
126
- return { type: "new", className, args };
127
- }
128
- if (at("ident", "GetService") && peek(1).value === "<") {
129
- i += 1;
130
- const service = skipTemplate();
131
- eat("op", "(");
132
- eat("op", ")");
133
- return { type: "getService", service };
134
- }
135
- if (at("ident")) {
136
- return { type: "ident", name: eat("ident").value };
137
- }
138
- if (at("op", "(")) {
139
- i += 1;
140
- const expr = parseExpr();
141
- eat("op", ")");
142
- return expr;
143
- }
144
- if (at("op", "{")) {
145
- return parseInitList();
146
- }
147
- throw error("invalid expression");
148
- }
149
-
150
- function parseUnary() {
151
- if (at("op", "-") || at("op", "!")) {
152
- const op = eat("op").value;
153
- return { type: "unary", op, argument: parseUnary() };
154
- }
155
- return parsePostfix();
156
- }
157
-
158
- function parsePostfix() {
159
- let node = parsePrimary();
160
- for (;;) {
161
- if (at("op", "->") || at("op", ".") || at("op", "::")) {
162
- const access = eat("op").value;
163
- const name = eat("ident").value;
164
- if (name === "GetService" && at("op", "<")) {
165
- const service = skipTemplate();
166
- eat("op", "(");
167
- eat("op", ")");
168
- node = { type: "getService", service };
169
- continue;
170
- }
171
- if (at("op", "(")) {
172
- node = { type: "call", object: node, name, args: parseArgs(), access };
173
- } else {
174
- node = { type: "member", object: node, name, access };
175
- }
176
- continue;
177
- }
178
- if (at("op", "(") && node.type === "ident") {
179
- node = { type: "call", object: null, name: node.name, args: parseArgs(), access: "." };
180
- continue;
181
- }
182
- if (at("op", "{") && (node.type === "ident" || node.type === "member")) {
183
- node = parseInitList();
184
- continue;
185
- }
186
- break;
187
- }
188
- return node;
189
- }
190
-
191
- function parseBinary() {
192
- let left = parseUnary();
193
- while (["==", "!=", "<=", ">=", "<", ">", "&&", "||", "+", "-", "*", "/"].includes(peek().value)) {
194
- const op = eat("op").value;
195
- const right = parseUnary();
196
- left = { type: "binary", op, left, right };
197
- }
198
- return left;
199
- }
200
-
201
- function parseShift() {
202
- let left = parseBinary();
203
- while (at("op", "<<")) {
204
- eat("op", "<<");
205
- const right = parseBinary();
206
- left = { type: "binary", op: "<<", left, right };
207
- }
208
- return left;
209
- }
210
-
211
- function parseExpr() {
212
- const left = parseShift();
213
- if (at("op", "=")) {
214
- i += 1;
215
- return { type: "assign", left, right: parseExpr() };
216
- }
217
- return left;
218
- }
219
-
220
- function parseBlock() {
221
- eat("op", "{");
222
- const body = [];
223
- while (!at("op", "}") && !at("eof")) {
224
- skipSemicolons();
225
- if (at("op", "}")) {
226
- break;
227
- }
228
- body.push(parseStmt());
229
- skipSemicolons();
230
- }
231
- eat("op", "}");
232
- return body;
233
- }
234
-
235
- function parseSwitch() {
236
- eat("kw", "switch");
237
- eat("op", "(");
238
- const discriminant = parseExpr();
239
- eat("op", ")");
240
- eat("op", "{");
241
- const cases = [];
242
- let current = null;
243
- const flush = () => {
244
- if (current) {
245
- cases.push(current);
246
- current = null;
247
- }
248
- };
249
- while (!at("eof") && !at("op", "}")) {
250
- skipSemicolons();
251
- if (at("op", "}")) {
252
- break;
253
- }
254
- if (at("kw", "case")) {
255
- i += 1;
256
- const value = parseExpr();
257
- eat("op", ":");
258
- if (current && current.body.length === 0 && !current.isDefault) {
259
- current.values.push(value);
260
- } else {
261
- flush();
262
- current = { values: [value], body: [], isDefault: false };
263
- }
264
- continue;
265
- }
266
- if (at("kw", "default")) {
267
- i += 1;
268
- eat("op", ":");
269
- flush();
270
- current = { values: [], body: [], isDefault: true };
271
- continue;
272
- }
273
- if (!current) {
274
- throw error("switch body needs case or default before statements");
275
- }
276
- if (at("op", "{")) {
277
- current.body.push(...parseBlock());
278
- continue;
279
- }
280
- current.body.push(parseStmt());
281
- }
282
- flush();
283
- eat("op", "}");
284
- return { type: "switch", discriminant, cases };
285
- }
286
-
287
- function parseIf() {
288
- eat("kw", "if");
289
- eat("op", "(");
290
- const test = parseExpr();
291
- eat("op", ")");
292
- const consequent = at("op", "{") ? parseBlock() : [parseStmt()];
293
- let alternate = null;
294
- if (at("kw", "else")) {
295
- i += 1;
296
- alternate = at("op", "{") ? parseBlock() : [parseStmt()];
297
- }
298
- return { type: "if", test, consequent, alternate };
299
- }
300
-
301
- function parseFor() {
302
- eat("kw", "for");
303
- eat("op", "(");
304
- if (at("kw", "auto") || at("ident") || at("kw", "int") || at("kw", "const")) {
305
- const isConst = at("kw", "const");
306
- if (isConst) {
307
- i += 1;
308
- }
309
- parseType();
310
- const name = eat("ident").value;
311
- if (at("op", ":")) {
312
- i += 1;
313
- const iter = parseExpr();
314
- eat("op", ")");
315
- const body = at("op", "{") ? parseBlock() : [parseStmt()];
316
- return { type: "foreach", name, iter, body, isConst };
317
- }
318
- }
319
- throw error("only range-for is supported: for (auto* x : list)");
320
- }
321
-
322
- function parseDeclOrExpr() {
323
- const isConst = at("kw", "const");
324
- if (isConst) {
325
- i += 1;
326
- }
327
- const saved = i;
328
- const maybeType = parseType();
329
- if (maybeType && at("ident") && (peek(1).value === "=" || peek(1).value === ";")) {
330
- const name = eat("ident").value;
331
- let value = null;
332
- if (at("op", "=")) {
333
- i += 1;
334
- value = parseExpr();
335
- }
336
- return { type: "decl", name, valueType: maybeType, value, isConst: isConst || maybeType === "const" };
337
- }
338
- i = saved;
339
- if (isConst) {
340
- i = saved - 1;
341
- }
342
- return { type: "expr", expr: parseExpr() };
343
- }
344
-
345
- function parseStmt() {
346
- if (at("kw", "if")) {
347
- return parseIf();
348
- }
349
- if (at("kw", "switch")) {
350
- return parseSwitch();
351
- }
352
- if (at("kw", "for")) {
353
- return parseFor();
354
- }
355
- if (at("kw", "return")) {
356
- i += 1;
357
- const value = at("op", ";") || at("op", "}") ? null : parseExpr();
358
- return { type: "return", value };
359
- }
360
- if (at("kw", "break")) {
361
- i += 1;
362
- skipSemicolons();
363
- return { type: "break" };
364
- }
365
- if (at("kw", "while")) {
366
- i += 1;
367
- eat("op", "(");
368
- const test = parseExpr();
369
- eat("op", ")");
370
- const body = at("op", "{") ? parseBlock() : [parseStmt()];
371
- return { type: "while", test, body };
372
- }
373
- return parseDeclOrExpr();
374
- }
375
-
376
- function parseParam() {
377
- const valueType = parseType();
378
- if (at("ident")) {
379
- return { name: eat("ident").value, valueType };
380
- }
381
- return { name: "arg", valueType };
382
- }
383
-
384
- function parseQualifiedName() {
385
- const parts = [eat("ident").value];
386
- while (at("op", "::")) {
387
- i += 1;
388
- parts.push(eat("ident").value);
389
- }
390
- return {
391
- parts,
392
- name: parts[parts.length - 1],
393
- owner: parts.length > 1 ? parts.slice(0, -1).join("::") : null,
394
- };
395
- }
396
-
397
- function parseFunction() {
398
- const returnType = parseType();
399
- if (!returnType || !at("ident")) {
400
- throw error("invalid function declaration");
401
- }
402
- const qualified = parseQualifiedName();
403
- eat("op", "(");
404
- const params = [];
405
- if (!at("op", ")")) {
406
- params.push(parseParam());
407
- while (at("op", ",")) {
408
- i += 1;
409
- params.push(parseParam());
410
- }
411
- }
412
- eat("op", ")");
413
- if (at("op", ";")) {
414
- i += 1;
415
- return { type: "proto", name: qualified.name, owner: qualified.owner, returnType, params };
416
- }
417
- const body = parseBlock();
418
- return { type: "function", name: qualified.name, owner: qualified.owner, returnType, params, body };
419
- }
420
-
421
- function parseStruct() {
422
- eat("kw");
423
- const name = at("ident") ? eat("ident").value : "_anon";
424
- if (at("op", ";")) {
425
- i += 1;
426
- return { type: "struct", name, fields: [], methods: [] };
427
- }
428
- eat("op", "{");
429
- const fields = [];
430
- const methods = [];
431
- while (!at("eof") && !at("op", "}")) {
432
- skipSemicolons();
433
- if (at("op", "}")) {
434
- break;
435
- }
436
- if (at("kw", "public") || at("kw", "private") || at("kw", "protected")) {
437
- i += 1;
438
- if (at("op", ":")) {
439
- i += 1;
440
- }
441
- continue;
442
- }
443
- if (at("kw", "struct") || at("kw", "class")) {
444
- const nested = parseStruct();
445
- if (nested.instance) {
446
- fields.push({
447
- type: "decl",
448
- name: nested.instance.name,
449
- valueType: nested.name,
450
- value:
451
- nested.instance.value || {
452
- type: "initlist",
453
- fields: nested.fields.map((field) => ({
454
- name: field.name,
455
- value: field.value || { type: "null" },
456
- })),
457
- },
458
- isConst: false,
459
- owner: name,
460
- });
461
- } else {
462
- fields.push(...nested.fields);
463
- methods.push(...nested.methods);
464
- }
465
- continue;
466
- }
467
- const saved = i;
468
- const isConst = at("kw", "const");
469
- if (isConst) {
470
- i += 1;
471
- }
472
- const valueType = parseType();
473
- if (valueType && at("ident")) {
474
- if (peek(1).value === "(") {
475
- i = saved;
476
- const method = parseFunction();
477
- method.owner = method.owner || name;
478
- methods.push(method);
479
- continue;
480
- }
481
- const fieldName = eat("ident").value;
482
- let value = null;
483
- if (at("op", "=")) {
484
- i += 1;
485
- value = parseExpr();
486
- }
487
- skipSemicolons();
488
- fields.push({ type: "decl", name: fieldName, valueType, value, isConst, owner: name });
489
- continue;
490
- }
491
- i = saved;
492
- skipBalanced();
493
- }
494
- eat("op", "}");
495
- let instance = null;
496
- if (at("ident")) {
497
- instance = { name: eat("ident").value, value: null };
498
- if (at("op", "=")) {
499
- i += 1;
500
- instance.value = parseExpr();
501
- }
502
- }
503
- skipSemicolons();
504
- return { type: "struct", name, fields, methods, instance };
505
- }
506
-
507
- function parseTopLevelDecl(isConst, valueType) {
508
- const name = eat("ident").value;
509
- let value = null;
510
- if (at("op", "=")) {
511
- i += 1;
512
- value = parseExpr();
513
- }
514
- skipSemicolons();
515
- return { type: "decl", name, valueType, value, isConst };
516
- }
517
-
518
- function skipBalanced() {
519
- if (at("op", "{")) {
520
- let depth = 0;
521
- while (!at("eof")) {
522
- if (at("op", "{")) {
523
- depth += 1;
524
- } else if (at("op", "}")) {
525
- depth -= 1;
526
- i += 1;
527
- if (depth === 0) {
528
- break;
529
- }
530
- continue;
531
- }
532
- i += 1;
533
- }
534
- skipSemicolons();
535
- return;
536
- }
537
- while (!at("op", ";") && !at("eof") && !at("op", "}")) {
538
- i += 1;
539
- }
540
- skipSemicolons();
541
- }
542
-
543
- function skipTypeDecl() {
544
- while (at("kw", "template") || at("kw", "struct") || at("kw", "class") || at("kw", "enum") || at("kw", "typedef") || at("kw", "extern")) {
545
- i += 1;
546
- }
547
- while (!at("eof") && !at("op", "{") && !at("op", ";")) {
548
- i += 1;
549
- }
550
- skipBalanced();
551
- }
552
-
553
- function skipNamespace() {
554
- eat("kw", "namespace");
555
- if (at("ident")) {
556
- i += 1;
557
- }
558
- if (at("op", "{")) {
559
- const inner = parseProgramInside();
560
- eat("op", "}");
561
- return inner;
562
- }
563
- eat("op", ";");
564
- return [];
565
- }
566
-
567
- function parseProgramInside() {
568
- const decls = [];
569
- while (!at("eof") && !at("op", "}")) {
570
- skipSemicolons();
571
- if (at("eof") || at("op", "}")) {
572
- break;
573
- }
574
- if (at("kw", "namespace")) {
575
- decls.push(...skipNamespace());
576
- continue;
577
- }
578
- if (at("kw", "using")) {
579
- while (!at("op", ";") && !at("eof")) {
580
- i += 1;
581
- }
582
- skipSemicolons();
583
- continue;
584
- }
585
- if (at("kw", "struct") || at("kw", "class")) {
586
- const parsed = parseStruct();
587
- decls.push(...parsed.fields);
588
- decls.push(...parsed.methods);
589
- continue;
590
- }
591
- if (at("kw", "enum") || at("kw", "template") || at("kw", "typedef") || at("kw", "extern")) {
592
- skipTypeDecl();
593
- continue;
594
- }
595
- const saved = i;
596
- const isConst = at("kw", "const");
597
- if (isConst) {
598
- i += 1;
599
- }
600
- const maybeType = parseType();
601
- if (maybeType && at("ident")) {
602
- const next = peek(1);
603
- if (next.value === "(" || next.value === "::") {
604
- i = saved;
605
- decls.push(parseFunction());
606
- skipSemicolons();
607
- continue;
608
- }
609
- if (next.value === "=" || next.value === ";") {
610
- decls.push(parseTopLevelDecl(isConst, maybeType));
611
- continue;
612
- }
613
- }
614
- i = saved;
615
- if (at("ident") && (peek(1).value === "::" || peek(1).value === "(" || peek(1).value === "." || peek(1).value === "->")) {
616
- const expr = parseExpr();
617
- skipSemicolons();
618
- decls.push({ type: "expr", expr });
619
- continue;
620
- }
621
- decls.push(parseFunction());
622
- skipSemicolons();
623
- }
624
- return decls;
625
- }
626
-
627
- return { type: "program", body: parseProgramInside(), fileName };
628
- }
629
-
630
- export { parse };