openalgo-script 0.1.0-alpha.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 (266) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +12 -0
  3. package/README.md +255 -0
  4. package/dist/core/ast/annotations.d.ts +56 -0
  5. package/dist/core/ast/annotations.d.ts.map +1 -0
  6. package/dist/core/ast/annotations.js +27 -0
  7. package/dist/core/ast/annotations.js.map +1 -0
  8. package/dist/core/ast/build.d.ts +25 -0
  9. package/dist/core/ast/build.d.ts.map +1 -0
  10. package/dist/core/ast/build.js +26 -0
  11. package/dist/core/ast/build.js.map +1 -0
  12. package/dist/core/ast/children.d.ts +15 -0
  13. package/dist/core/ast/children.d.ts.map +1 -0
  14. package/dist/core/ast/children.js +103 -0
  15. package/dist/core/ast/children.js.map +1 -0
  16. package/dist/core/ast/expressions.d.ts +178 -0
  17. package/dist/core/ast/expressions.d.ts.map +1 -0
  18. package/dist/core/ast/expressions.js +50 -0
  19. package/dist/core/ast/expressions.js.map +1 -0
  20. package/dist/core/ast/header.d.ts +50 -0
  21. package/dist/core/ast/header.d.ts.map +1 -0
  22. package/dist/core/ast/header.js +2 -0
  23. package/dist/core/ast/header.js.map +1 -0
  24. package/dist/core/ast/index.d.ts +30 -0
  25. package/dist/core/ast/index.d.ts.map +1 -0
  26. package/dist/core/ast/index.js +21 -0
  27. package/dist/core/ast/index.js.map +1 -0
  28. package/dist/core/ast/name.d.ts +24 -0
  29. package/dist/core/ast/name.d.ts.map +1 -0
  30. package/dist/core/ast/name.js +2 -0
  31. package/dist/core/ast/name.js.map +1 -0
  32. package/dist/core/ast/node.d.ts +34 -0
  33. package/dist/core/ast/node.d.ts.map +1 -0
  34. package/dist/core/ast/node.js +70 -0
  35. package/dist/core/ast/node.js.map +1 -0
  36. package/dist/core/ast/script.d.ts +57 -0
  37. package/dist/core/ast/script.d.ts.map +1 -0
  38. package/dist/core/ast/script.js +2 -0
  39. package/dist/core/ast/script.js.map +1 -0
  40. package/dist/core/ast/statements.d.ts +161 -0
  41. package/dist/core/ast/statements.d.ts.map +1 -0
  42. package/dist/core/ast/statements.js +10 -0
  43. package/dist/core/ast/statements.js.map +1 -0
  44. package/dist/core/ast/walk.d.ts +39 -0
  45. package/dist/core/ast/walk.d.ts.map +1 -0
  46. package/dist/core/ast/walk.js +54 -0
  47. package/dist/core/ast/walk.js.map +1 -0
  48. package/dist/core/catalogue/catalogue.generated.d.ts +1590 -0
  49. package/dist/core/catalogue/catalogue.generated.d.ts.map +1 -0
  50. package/dist/core/catalogue/catalogue.generated.js +162 -0
  51. package/dist/core/catalogue/catalogue.generated.js.map +1 -0
  52. package/dist/core/catalogue/index.d.ts +15 -0
  53. package/dist/core/catalogue/index.d.ts.map +1 -0
  54. package/dist/core/catalogue/index.js +4 -0
  55. package/dist/core/catalogue/index.js.map +1 -0
  56. package/dist/core/catalogue/lookup.d.ts +14 -0
  57. package/dist/core/catalogue/lookup.d.ts.map +1 -0
  58. package/dist/core/catalogue/lookup.js +19 -0
  59. package/dist/core/catalogue/lookup.js.map +1 -0
  60. package/dist/core/catalogue/template.d.ts +15 -0
  61. package/dist/core/catalogue/template.d.ts.map +1 -0
  62. package/dist/core/catalogue/template.js +33 -0
  63. package/dist/core/catalogue/template.js.map +1 -0
  64. package/dist/core/catalogue/types.d.ts +34 -0
  65. package/dist/core/catalogue/types.d.ts.map +1 -0
  66. package/dist/core/catalogue/types.js +6 -0
  67. package/dist/core/catalogue/types.js.map +1 -0
  68. package/dist/core/catalogue/values.generated.d.ts +565 -0
  69. package/dist/core/catalogue/values.generated.d.ts.map +1 -0
  70. package/dist/core/catalogue/values.generated.js +6 -0
  71. package/dist/core/catalogue/values.generated.js.map +1 -0
  72. package/dist/core/diagnostics/collector.d.ts +46 -0
  73. package/dist/core/diagnostics/collector.d.ts.map +1 -0
  74. package/dist/core/diagnostics/collector.js +55 -0
  75. package/dist/core/diagnostics/collector.js.map +1 -0
  76. package/dist/core/diagnostics/diagnostic.d.ts +40 -0
  77. package/dist/core/diagnostics/diagnostic.d.ts.map +1 -0
  78. package/dist/core/diagnostics/diagnostic.js +29 -0
  79. package/dist/core/diagnostics/diagnostic.js.map +1 -0
  80. package/dist/core/diagnostics/index.d.ts +12 -0
  81. package/dist/core/diagnostics/index.d.ts.map +1 -0
  82. package/dist/core/diagnostics/index.js +3 -0
  83. package/dist/core/diagnostics/index.js.map +1 -0
  84. package/dist/core/index.d.ts +28 -0
  85. package/dist/core/index.d.ts.map +1 -0
  86. package/dist/core/index.js +22 -0
  87. package/dist/core/index.js.map +1 -0
  88. package/dist/core/lex/blocks.d.ts +51 -0
  89. package/dist/core/lex/blocks.d.ts.map +1 -0
  90. package/dist/core/lex/blocks.js +56 -0
  91. package/dist/core/lex/blocks.js.map +1 -0
  92. package/dist/core/lex/characters.d.ts +38 -0
  93. package/dist/core/lex/characters.d.ts.map +1 -0
  94. package/dist/core/lex/characters.js +50 -0
  95. package/dist/core/lex/characters.js.map +1 -0
  96. package/dist/core/lex/comments.d.ts +50 -0
  97. package/dist/core/lex/comments.d.ts.map +1 -0
  98. package/dist/core/lex/comments.js +64 -0
  99. package/dist/core/lex/comments.js.map +1 -0
  100. package/dist/core/lex/index.d.ts +12 -0
  101. package/dist/core/lex/index.d.ts.map +1 -0
  102. package/dist/core/lex/index.js +12 -0
  103. package/dist/core/lex/index.js.map +1 -0
  104. package/dist/core/lex/layout.d.ts +40 -0
  105. package/dist/core/lex/layout.d.ts.map +1 -0
  106. package/dist/core/lex/layout.js +143 -0
  107. package/dist/core/lex/layout.js.map +1 -0
  108. package/dist/core/lex/lexer.d.ts +13 -0
  109. package/dist/core/lex/lexer.d.ts.map +1 -0
  110. package/dist/core/lex/lexer.js +419 -0
  111. package/dist/core/lex/lexer.js.map +1 -0
  112. package/dist/core/lex/numbers.d.ts +22 -0
  113. package/dist/core/lex/numbers.d.ts.map +1 -0
  114. package/dist/core/lex/numbers.js +58 -0
  115. package/dist/core/lex/numbers.js.map +1 -0
  116. package/dist/core/lex/statements.d.ts +24 -0
  117. package/dist/core/lex/statements.d.ts.map +1 -0
  118. package/dist/core/lex/statements.js +90 -0
  119. package/dist/core/lex/statements.js.map +1 -0
  120. package/dist/core/lex/strings.d.ts +27 -0
  121. package/dist/core/lex/strings.d.ts.map +1 -0
  122. package/dist/core/lex/strings.js +92 -0
  123. package/dist/core/lex/strings.js.map +1 -0
  124. package/dist/core/lex/unexpected.d.ts +31 -0
  125. package/dist/core/lex/unexpected.d.ts.map +1 -0
  126. package/dist/core/lex/unexpected.js +114 -0
  127. package/dist/core/lex/unexpected.js.map +1 -0
  128. package/dist/core/parse/annotations.d.ts +4 -0
  129. package/dist/core/parse/annotations.d.ts.map +1 -0
  130. package/dist/core/parse/annotations.js +49 -0
  131. package/dist/core/parse/annotations.js.map +1 -0
  132. package/dist/core/parse/blocks.d.ts +18 -0
  133. package/dist/core/parse/blocks.d.ts.map +1 -0
  134. package/dist/core/parse/blocks.js +47 -0
  135. package/dist/core/parse/blocks.js.map +1 -0
  136. package/dist/core/parse/branches.d.ts +17 -0
  137. package/dist/core/parse/branches.d.ts.map +1 -0
  138. package/dist/core/parse/branches.js +66 -0
  139. package/dist/core/parse/branches.js.map +1 -0
  140. package/dist/core/parse/cursor.d.ts +119 -0
  141. package/dist/core/parse/cursor.d.ts.map +1 -0
  142. package/dist/core/parse/cursor.js +305 -0
  143. package/dist/core/parse/cursor.js.map +1 -0
  144. package/dist/core/parse/expressions.d.ts +57 -0
  145. package/dist/core/parse/expressions.d.ts.map +1 -0
  146. package/dist/core/parse/expressions.js +373 -0
  147. package/dist/core/parse/expressions.js.map +1 -0
  148. package/dist/core/parse/functions.d.ts +16 -0
  149. package/dist/core/parse/functions.d.ts.map +1 -0
  150. package/dist/core/parse/functions.js +92 -0
  151. package/dist/core/parse/functions.js.map +1 -0
  152. package/dist/core/parse/index.d.ts +13 -0
  153. package/dist/core/parse/index.d.ts.map +1 -0
  154. package/dist/core/parse/index.js +13 -0
  155. package/dist/core/parse/index.js.map +1 -0
  156. package/dist/core/parse/loops.d.ts +13 -0
  157. package/dist/core/parse/loops.d.ts.map +1 -0
  158. package/dist/core/parse/loops.js +78 -0
  159. package/dist/core/parse/loops.js.map +1 -0
  160. package/dist/core/parse/names.d.ts +34 -0
  161. package/dist/core/parse/names.d.ts.map +1 -0
  162. package/dist/core/parse/names.js +122 -0
  163. package/dist/core/parse/names.js.map +1 -0
  164. package/dist/core/parse/script.d.ts +23 -0
  165. package/dist/core/parse/script.d.ts.map +1 -0
  166. package/dist/core/parse/script.js +55 -0
  167. package/dist/core/parse/script.js.map +1 -0
  168. package/dist/core/parse/statements.d.ts +14 -0
  169. package/dist/core/parse/statements.d.ts.map +1 -0
  170. package/dist/core/parse/statements.js +292 -0
  171. package/dist/core/parse/statements.js.map +1 -0
  172. package/dist/core/parse/switches.d.ts +16 -0
  173. package/dist/core/parse/switches.d.ts.map +1 -0
  174. package/dist/core/parse/switches.js +98 -0
  175. package/dist/core/parse/switches.js.map +1 -0
  176. package/dist/core/render/index.d.ts +10 -0
  177. package/dist/core/render/index.d.ts.map +1 -0
  178. package/dist/core/render/index.js +10 -0
  179. package/dist/core/render/index.js.map +1 -0
  180. package/dist/core/render/terminal.d.ts +11 -0
  181. package/dist/core/render/terminal.d.ts.map +1 -0
  182. package/dist/core/render/terminal.js +51 -0
  183. package/dist/core/render/terminal.js.map +1 -0
  184. package/dist/core/source/index.d.ts +7 -0
  185. package/dist/core/source/index.d.ts.map +1 -0
  186. package/dist/core/source/index.js +2 -0
  187. package/dist/core/source/index.js.map +1 -0
  188. package/dist/core/source/source.d.ts +41 -0
  189. package/dist/core/source/source.d.ts.map +1 -0
  190. package/dist/core/source/source.js +67 -0
  191. package/dist/core/source/source.js.map +1 -0
  192. package/dist/core/span/index.d.ts +3 -0
  193. package/dist/core/span/index.d.ts.map +1 -0
  194. package/dist/core/span/index.js +2 -0
  195. package/dist/core/span/index.js.map +1 -0
  196. package/dist/core/span/span.d.ts +67 -0
  197. package/dist/core/span/span.d.ts.map +1 -0
  198. package/dist/core/span/span.js +27 -0
  199. package/dist/core/span/span.js.map +1 -0
  200. package/dist/core/tokens/index.d.ts +8 -0
  201. package/dist/core/tokens/index.d.ts.map +1 -0
  202. package/dist/core/tokens/index.js +2 -0
  203. package/dist/core/tokens/index.js.map +1 -0
  204. package/dist/core/tokens/kind.d.ts +53 -0
  205. package/dist/core/tokens/kind.d.ts.map +1 -0
  206. package/dist/core/tokens/kind.js +94 -0
  207. package/dist/core/tokens/kind.js.map +1 -0
  208. package/dist/core/tokens/token.d.ts +36 -0
  209. package/dist/core/tokens/token.d.ts.map +1 -0
  210. package/dist/core/tokens/token.js +2 -0
  211. package/dist/core/tokens/token.js.map +1 -0
  212. package/package.json +52 -0
  213. package/spec/README.md +48 -0
  214. package/spec/errors.json +3204 -0
  215. package/src/core/ast/annotations.ts +68 -0
  216. package/src/core/ast/build.ts +35 -0
  217. package/src/core/ast/children.ts +110 -0
  218. package/src/core/ast/expressions.ts +254 -0
  219. package/src/core/ast/header.ts +53 -0
  220. package/src/core/ast/index.ts +102 -0
  221. package/src/core/ast/name.ts +24 -0
  222. package/src/core/ast/node.ts +120 -0
  223. package/src/core/ast/script.ts +60 -0
  224. package/src/core/ast/statements.ts +193 -0
  225. package/src/core/ast/walk.ts +67 -0
  226. package/src/core/catalogue/catalogue.generated.ts +171 -0
  227. package/src/core/catalogue/index.ts +20 -0
  228. package/src/core/catalogue/lookup.ts +23 -0
  229. package/src/core/catalogue/template.ts +38 -0
  230. package/src/core/catalogue/types.ts +37 -0
  231. package/src/core/catalogue/values.generated.ts +160 -0
  232. package/src/core/diagnostics/collector.ts +87 -0
  233. package/src/core/diagnostics/diagnostic.ts +72 -0
  234. package/src/core/diagnostics/index.ts +12 -0
  235. package/src/core/index.ts +146 -0
  236. package/src/core/lex/blocks.ts +92 -0
  237. package/src/core/lex/characters.ts +56 -0
  238. package/src/core/lex/comments.ts +75 -0
  239. package/src/core/lex/index.ts +11 -0
  240. package/src/core/lex/layout.ts +188 -0
  241. package/src/core/lex/lexer.ts +486 -0
  242. package/src/core/lex/numbers.ts +77 -0
  243. package/src/core/lex/statements.ts +94 -0
  244. package/src/core/lex/strings.ts +119 -0
  245. package/src/core/lex/unexpected.ts +125 -0
  246. package/src/core/parse/annotations.ts +60 -0
  247. package/src/core/parse/blocks.ts +52 -0
  248. package/src/core/parse/branches.ts +77 -0
  249. package/src/core/parse/cursor.ts +348 -0
  250. package/src/core/parse/expressions.ts +441 -0
  251. package/src/core/parse/functions.ts +109 -0
  252. package/src/core/parse/index.ts +12 -0
  253. package/src/core/parse/loops.ts +97 -0
  254. package/src/core/parse/names.ts +135 -0
  255. package/src/core/parse/script.ts +64 -0
  256. package/src/core/parse/statements.ts +329 -0
  257. package/src/core/parse/switches.ts +105 -0
  258. package/src/core/render/index.ts +9 -0
  259. package/src/core/render/terminal.ts +62 -0
  260. package/src/core/source/index.ts +6 -0
  261. package/src/core/source/source.ts +102 -0
  262. package/src/core/span/index.ts +2 -0
  263. package/src/core/span/span.ts +84 -0
  264. package/src/core/tokens/index.ts +15 -0
  265. package/src/core/tokens/kind.ts +123 -0
  266. package/src/core/tokens/token.ts +39 -0
@@ -0,0 +1,98 @@
1
+ import { makeNode } from '../ast/index.js';
2
+ import { spanning } from '../span/index.js';
3
+ import { parseBlock } from './blocks.js';
4
+ import { parseCondition } from './expressions.js';
5
+ import { finishStatement } from './statements.js';
6
+ /**
7
+ * `switch`, in both forms of language.md 10.6.
8
+ *
9
+ * With a subject each case value is compared against it, and without one each
10
+ * case value is a condition. The difference is the absent subject and needs no
11
+ * flag beside it.
12
+ *
13
+ * The arms are the whole of a switch body. A `default` that is not last would
14
+ * leave the arms after it unreachable, so the arm that follows one is OS1017,
15
+ * and the arm is kept in the tree all the same: a reader who moves the default
16
+ * should not then be told about the arms one at a time.
17
+ */
18
+ export function parseSwitchStatement(cursor) {
19
+ const keyword = cursor.advance();
20
+ const subject = cursor.atStatementEnd() ? undefined : parseCondition(cursor);
21
+ finishStatement(cursor);
22
+ const cases = [];
23
+ let defaultCase;
24
+ let end = keyword.span;
25
+ if (!cursor.at('indent')) {
26
+ if (!cursor.reportedHere)
27
+ cursor.report('OS1010', keyword.span, { header: 'switch' });
28
+ return makeNode('switchStatement', spanning(keyword.span, end), {
29
+ subject,
30
+ cases,
31
+ defaultCase,
32
+ });
33
+ }
34
+ if (!cursor.openBlock(cursor.token.span)) {
35
+ cursor.skipBlockBody();
36
+ return makeNode('switchStatement', spanning(keyword.span, end), {
37
+ subject,
38
+ cases,
39
+ defaultCase,
40
+ });
41
+ }
42
+ cursor.advance();
43
+ while (!cursor.at('dedent') && !cursor.at('endOfFile')) {
44
+ const before = cursor.position;
45
+ const word = cursor.token;
46
+ if (cursor.at('case')) {
47
+ if (defaultCase !== undefined)
48
+ cursor.report('OS1017', word.span, { word: word.text });
49
+ const arm = parseCase(cursor);
50
+ cases.push(arm);
51
+ end = arm.span;
52
+ }
53
+ else if (cursor.at('default')) {
54
+ const arm = parseDefault(cursor);
55
+ if (defaultCase === undefined)
56
+ defaultCase = arm;
57
+ else
58
+ cursor.report('OS1017', word.span, { word: word.text });
59
+ end = arm.span;
60
+ }
61
+ else {
62
+ // A line in a switch body that is not an arm. The catalogue has no code
63
+ // for it, and OS1017 carries the rule it breaks: the arms are the whole
64
+ // of the body, so this line belongs inside one of them or above the
65
+ // switch.
66
+ cursor.report('OS1017', word.span, { word: 'case' });
67
+ cursor.skipStatement();
68
+ }
69
+ if (cursor.position === before)
70
+ cursor.skipStatement();
71
+ }
72
+ cursor.closeBlock();
73
+ cursor.take('dedent');
74
+ return makeNode('switchStatement', spanning(keyword.span, end), { subject, cases, defaultCase });
75
+ }
76
+ /** One arm. Several values separated by commas are one arm, not several. */
77
+ function parseCase(cursor) {
78
+ cursor.beginStatement();
79
+ const keyword = cursor.advance();
80
+ const values = [parseCondition(cursor)];
81
+ while (cursor.take(',') !== undefined) {
82
+ const before = cursor.position;
83
+ values.push(parseCondition(cursor));
84
+ if (cursor.position === before)
85
+ break;
86
+ }
87
+ finishStatement(cursor);
88
+ const body = parseBlock(cursor, 'case', keyword.span);
89
+ return makeNode('switchCase', spanning(keyword.span, body.span), { values, body });
90
+ }
91
+ function parseDefault(cursor) {
92
+ cursor.beginStatement();
93
+ const keyword = cursor.advance();
94
+ finishStatement(cursor);
95
+ const body = parseBlock(cursor, 'default', keyword.span);
96
+ return makeNode('switchDefault', spanning(keyword.span, body.span), { body });
97
+ }
98
+ //# sourceMappingURL=switches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switches.js","sourceRoot":"","sources":["../../../src/core/parse/switches.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Turning a diagnostic into something a reader sees.
3
+ *
4
+ * Only the terminal shape lives here. An editor puts the same diagnostic in a
5
+ * gutter and a chart puts it over a pane, and both take the Diagnostic and the
6
+ * span rather than this text, which is why rendering is a module of its own
7
+ * rather than a method on the diagnostic.
8
+ */
9
+ export { renderDiagnostic, renderDiagnostics } from './terminal.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Turning a diagnostic into something a reader sees.
3
+ *
4
+ * Only the terminal shape lives here. An editor puts the same diagnostic in a
5
+ * gutter and a chart puts it over a pane, and both take the Diagnostic and the
6
+ * span rather than this text, which is why rendering is a module of its own
7
+ * rather than a method on the diagnostic.
8
+ */
9
+ export { renderDiagnostic, renderDiagnostics } from './terminal.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Diagnostic } from '../diagnostics/index.js';
2
+ import type { SourceFile } from '../source/index.js';
3
+ export declare function renderDiagnostic(file: SourceFile, diagnostic: Diagnostic): string;
4
+ /**
5
+ * Every diagnostic, in the order a reader walks the file, separated by a blank
6
+ * line. The file's name is printed once above them rather than on each one,
7
+ * because a compile reports on one file and repeating its name on twenty
8
+ * diagnostics buries the twenty.
9
+ */
10
+ export declare function renderDiagnostics(file: SourceFile, diagnostics: readonly Diagnostic[]): string;
11
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/core/render/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AA0BrD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAmBjF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,SAAS,UAAU,EAAE,GACjC,MAAM,CAIR"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The renderer for a terminal, and the shape is the one errors.md section 2
3
+ * fixes as the contract:
4
+ *
5
+ * 14 | len = 9
6
+ * | ^^^
7
+ * OS2002: len is already declared at line 1, so a second one cannot be declared here.
8
+ * Fix: rename this one, or drop the inner declaration and let the assignment update the len at line 1.
9
+ *
10
+ * The line, then the caret, then what happened, then what to do. The fix is on
11
+ * its own line because it is the line the reader acts on, and a reader who has
12
+ * understood the message from the caret alone should be able to skip to it.
13
+ */
14
+ /** A tab is one column wide here, so the caret below the line still lines up. */
15
+ const TAB_WIDTH_FOR_DISPLAY = ' ';
16
+ function countCharacters(text) {
17
+ // Code points, not code units: a terminal draws one character per code point,
18
+ // and padding by code units would push the caret right by one for every
19
+ // astral character earlier on the line. See the span module on columns.
20
+ return [...text].length;
21
+ }
22
+ export function renderDiagnostic(file, diagnostic) {
23
+ const { line, column, length } = diagnostic.span;
24
+ const shown = file.lineText(line).replace(/\t/g, TAB_WIDTH_FOR_DISPLAY);
25
+ const lineNumber = String(line);
26
+ const gutter = ' '.repeat(lineNumber.length);
27
+ const beforeCaret = shown.slice(0, Math.max(column - 1, 0));
28
+ // A span that runs past the end of its line, which an unterminated bracket
29
+ // produces, is drawn to the end of the line rather than off it.
30
+ const underCaret = shown.slice(beforeCaret.length, beforeCaret.length + length);
31
+ const caretWidth = Math.max(countCharacters(underCaret), 1);
32
+ return [
33
+ `${lineNumber} | ${shown}`,
34
+ `${gutter} | ${' '.repeat(countCharacters(beforeCaret))}${'^'.repeat(caretWidth)}`,
35
+ `${diagnostic.code}: ${diagnostic.message}`,
36
+ `Fix: ${diagnostic.fix}`,
37
+ ].join('\n');
38
+ }
39
+ /**
40
+ * Every diagnostic, in the order a reader walks the file, separated by a blank
41
+ * line. The file's name is printed once above them rather than on each one,
42
+ * because a compile reports on one file and repeating its name on twenty
43
+ * diagnostics buries the twenty.
44
+ */
45
+ export function renderDiagnostics(file, diagnostics) {
46
+ if (diagnostics.length === 0)
47
+ return '';
48
+ const body = diagnostics.map((diagnostic) => renderDiagnostic(file, diagnostic));
49
+ return [`${file.name}`, ...body].join('\n\n');
50
+ }
51
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/core/render/terminal.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH,iFAAiF;AACjF,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC,SAAS,eAAe,CAAC,IAAY;IACnC,8EAA8E;IAC9E,wEAAwE;IACxE,wEAAwE;IACxE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAgB,EAAE,UAAsB;IACvE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IAExE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,gEAAgE;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5D,OAAO;QACL,GAAG,UAAU,MAAM,KAAK,EAAE;QAC1B,GAAG,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;QAClF,GAAG,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE;QAC3C,QAAQ,UAAU,CAAC,GAAG,EAAE;KACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAgB,EAChB,WAAkC;IAElC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The source text and the index over it. The one place that normalises a file,
3
+ * so every offset in the compiler means the same thing.
4
+ */
5
+ export type { SourceFile, SourcePosition } from './source.js';
6
+ export { normaliseSource, sourceFile } from './source.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/source/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { normaliseSource, sourceFile } from './source.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/source/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { Span } from '../span/index.js';
2
+ /** A place in the source, one-based on both axes. See the span module on columns. */
3
+ export interface SourcePosition {
4
+ readonly line: number;
5
+ readonly column: number;
6
+ }
7
+ /**
8
+ * A file the compiler is working on: its normalised text, and the index that
9
+ * turns an offset into a line and a column.
10
+ *
11
+ * Every stage needs the same two answers, and computing them by scanning from
12
+ * the top of the file each time is how a compiler becomes quadratic on the one
13
+ * input that has many diagnostics. The line starts are built once.
14
+ */
15
+ export interface SourceFile {
16
+ /** What the file is called, for the first line of a rendered diagnostic. */
17
+ readonly name: string;
18
+ /** The text after normalisation. Offsets and spans index this, not the bytes on disk. */
19
+ readonly text: string;
20
+ readonly lineCount: number;
21
+ /** The line's text, without its newline. An out of range line is empty. */
22
+ lineText(line: number): string;
23
+ /** The offset the line starts at. */
24
+ lineStart(line: number): number;
25
+ positionAt(offset: number): SourcePosition;
26
+ offsetAt(position: SourcePosition): number;
27
+ /** The span covering length code units from offset, with its line and column worked out. */
28
+ spanAt(offset: number, length: number): Span;
29
+ }
30
+ /**
31
+ * Drops a leading byte order mark and turns CRLF into LF, which language.md 3.1
32
+ * requires to happen before anything else reads the file, so that a script
33
+ * written on one operating system compiles identically on another.
34
+ *
35
+ * A lone carriage return is deliberately left alone. It is not a line ending
36
+ * the language accepts, so it belongs to the lexer as OS1001 on the character
37
+ * rather than being silently repaired here.
38
+ */
39
+ export declare function normaliseSource(raw: string): string;
40
+ export declare function sourceFile(name: string, raw: string): SourceFile;
41
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../src/core/source/source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,qCAAqC;IACrC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC;IAC3C,4FAA4F;IAC5F,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD;AAUD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CA4ChE"}
@@ -0,0 +1,67 @@
1
+ import { makeSpan } from '../span/index.js';
2
+ const BYTE_ORDER_MARK = '';
3
+ /**
4
+ * Drops a leading byte order mark and turns CRLF into LF, which language.md 3.1
5
+ * requires to happen before anything else reads the file, so that a script
6
+ * written on one operating system compiles identically on another.
7
+ *
8
+ * A lone carriage return is deliberately left alone. It is not a line ending
9
+ * the language accepts, so it belongs to the lexer as OS1001 on the character
10
+ * rather than being silently repaired here.
11
+ */
12
+ export function normaliseSource(raw) {
13
+ const withoutMark = raw.startsWith(BYTE_ORDER_MARK) ? raw.slice(BYTE_ORDER_MARK.length) : raw;
14
+ return withoutMark.includes('\r\n') ? withoutMark.replace(/\r\n/g, '\n') : withoutMark;
15
+ }
16
+ function lineStartsOf(text) {
17
+ const starts = [0];
18
+ for (let i = 0; i < text.length; i++) {
19
+ if (text.charCodeAt(i) === 10)
20
+ starts.push(i + 1);
21
+ }
22
+ return starts;
23
+ }
24
+ export function sourceFile(name, raw) {
25
+ const text = normaliseSource(raw);
26
+ const starts = lineStartsOf(text);
27
+ const clampLine = (line) => Math.min(Math.max(Math.trunc(line), 1), starts.length);
28
+ const lineStart = (line) => starts[clampLine(line) - 1] ?? 0;
29
+ const lineEnd = (line) => {
30
+ const next = starts[clampLine(line)];
31
+ if (next === undefined)
32
+ return text.length;
33
+ // The next line starts one past the newline, which this line does not own.
34
+ return next - 1;
35
+ };
36
+ const positionAt = (offset) => {
37
+ const at = Math.min(Math.max(Math.trunc(offset), 0), text.length);
38
+ let low = 0;
39
+ let high = starts.length - 1;
40
+ while (low < high) {
41
+ const middle = (low + high + 1) >> 1;
42
+ if ((starts[middle] ?? 0) <= at)
43
+ low = middle;
44
+ else
45
+ high = middle - 1;
46
+ }
47
+ return { line: low + 1, column: at - (starts[low] ?? 0) + 1 };
48
+ };
49
+ return {
50
+ name,
51
+ text,
52
+ lineCount: starts.length,
53
+ lineText: (line) => text.slice(lineStart(line), lineEnd(line)),
54
+ lineStart,
55
+ positionAt,
56
+ offsetAt: (position) => {
57
+ const start = lineStart(position.line);
58
+ const end = lineEnd(position.line);
59
+ return Math.min(start + Math.max(Math.trunc(position.column), 1) - 1, end);
60
+ },
61
+ spanAt: (offset, length) => {
62
+ const { line, column } = positionAt(offset);
63
+ return makeSpan(offset, Math.max(length, 0), line, column);
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../../src/core/source/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { Positioned, Span } from './span.js';
2
+ export { containsOffset, endOffset, makeSpan, spanning } from './span.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/span/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { containsOffset, endOffset, makeSpan, spanning } from './span.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/span/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Where something is in the source text.
3
+ *
4
+ * Every token and every node carries one of these, and every diagnostic is
5
+ * drawn under one, so the definition of a column here decides where a caret
6
+ * lands for every reader of the language. It is stated rather than implied.
7
+ *
8
+ * ## A column counts UTF-16 code units
9
+ *
10
+ * An editor and a terminal disagree about what a column is, and there is no
11
+ * answer that is right for both, so the question is which one gets the stored
12
+ * number and which one converts.
13
+ *
14
+ * The stored number is UTF-16 code units, one-based, because that is what the
15
+ * things that consume a column ask for: a browser text component indexes the
16
+ * text it holds in UTF-16, and the language server protocol an editor speaks
17
+ * counts positions in UTF-16 by default. Storing anything else means converting
18
+ * at every token on the hot path of a compile that runs while somebody waits,
19
+ * and converting is exactly where an off-by-one caret comes from.
20
+ *
21
+ * A terminal counts characters, not code units, so the renderer does not use
22
+ * the column at all. It takes the source line and the span's offsets and counts
23
+ * code points itself when it pads the caret, which is why a caret sitting after
24
+ * a string literal holding an astral character still lands under the right
25
+ * character in a terminal.
26
+ *
27
+ * The practical reach of the difference is small and worth knowing: outside a
28
+ * string literal the language accepts ASCII only (language.md 3.1), so a column
29
+ * can only diverge from a character count on a line that holds a string literal
30
+ * with non-ASCII text in it.
31
+ *
32
+ * ## Offsets index the normalised text
33
+ *
34
+ * A byte order mark is dropped and CRLF becomes LF before anything else reads
35
+ * the file (language.md 3.1), so an offset counts into the text after those two
36
+ * changes. A host that has to point back into the file on disk adds the mark
37
+ * and the carriage returns back itself; see the source module, which is the one
38
+ * place that does the normalising.
39
+ */
40
+ export interface Span {
41
+ /** Zero-based UTF-16 code unit index into the normalised source text. */
42
+ readonly offset: number;
43
+ /** Length in UTF-16 code units. Zero where a diagnostic points between two characters. */
44
+ readonly length: number;
45
+ /** One-based, because that is the first line an editor shows. */
46
+ readonly line: number;
47
+ /** One-based UTF-16 code unit count from the start of the line. */
48
+ readonly column: number;
49
+ }
50
+ /** Anything the compiler can point a caret at. */
51
+ export interface Positioned {
52
+ readonly span: Span;
53
+ }
54
+ export declare function makeSpan(offset: number, length: number, line: number, column: number): Span;
55
+ /** One past the last code unit the span covers. */
56
+ export declare function endOffset(span: Span): number;
57
+ /**
58
+ * The span from the start of the first to the end of the last.
59
+ *
60
+ * This is how a node gets a span: a call expression runs from its callee to its
61
+ * closing bracket, and the caret under it covers the whole call rather than the
62
+ * one token the parser happened to be holding.
63
+ */
64
+ export declare function spanning(first: Span, last: Span): Span;
65
+ /** Whether an offset falls inside the span. A zero length span contains nothing. */
66
+ export declare function containsOffset(span: Span, offset: number): boolean;
67
+ //# sourceMappingURL=span.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span.d.ts","sourceRoot":"","sources":["../../../src/core/span/span.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,IAAI;IACnB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE3F;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAOtD;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE"}
@@ -0,0 +1,27 @@
1
+ export function makeSpan(offset, length, line, column) {
2
+ return { offset, length, line, column };
3
+ }
4
+ /** One past the last code unit the span covers. */
5
+ export function endOffset(span) {
6
+ return span.offset + span.length;
7
+ }
8
+ /**
9
+ * The span from the start of the first to the end of the last.
10
+ *
11
+ * This is how a node gets a span: a call expression runs from its callee to its
12
+ * closing bracket, and the caret under it covers the whole call rather than the
13
+ * one token the parser happened to be holding.
14
+ */
15
+ export function spanning(first, last) {
16
+ return {
17
+ offset: first.offset,
18
+ length: Math.max(endOffset(last) - first.offset, 0),
19
+ line: first.line,
20
+ column: first.column,
21
+ };
22
+ }
23
+ /** Whether an offset falls inside the span. A zero length span contains nothing. */
24
+ export function containsOffset(span, offset) {
25
+ return offset >= span.offset && offset < endOffset(span);
26
+ }
27
+ //# sourceMappingURL=span.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span.js","sourceRoot":"","sources":["../../../src/core/span/span.ts"],"names":[],"mappings":"AAuDA,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,MAAc,EAAE,IAAY,EAAE,MAAc;IACnF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAW,EAAE,IAAU;IAC9C,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,MAAc;IACvD,OAAO,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The token vocabulary of language.md section 3. Types and the two tables the
3
+ * types are derived from; the lexer that produces them is the next stage.
4
+ */
5
+ export type { KeywordKind, LayoutKind, LiteralKind, NameKind, PunctuationKind, TokenKind, } from './kind.js';
6
+ export { PUNCTUATORS, RESERVED_WORDS } from './kind.js';
7
+ export type { NumberToken, SimpleToken, StringToken, Token } from './token.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tokens/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACR,eAAe,EACf,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAExD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { PUNCTUATORS, RESERVED_WORDS } from './kind.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/tokens/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Every kind of token language.md section 3 describes. Types and the two tables
3
+ * they are derived from, and no scanning: the lexer is the next stage.
4
+ *
5
+ * A keyword's kind is the word, and a punctuation token's kind is the symbol,
6
+ * so a parser reads as `token.kind === 'if'` and `token.kind === '('` rather
7
+ * than through a second vocabulary that has to be learned and kept in step.
8
+ */
9
+ /**
10
+ * The reserved words of language.md 3.4, which cannot be used as names.
11
+ *
12
+ * `import`, `map`, `matrix`, `type` and `as` are reserved and unused in version
13
+ * 1. They are here so that adding them later cannot break a script that used
14
+ * one as a variable name.
15
+ *
16
+ * Two words the grammar treats as keywords are deliberately absent, because 3.4
17
+ * does not reserve them: `version` and `limits` are recognised by position in
18
+ * the parser and are ordinary identifiers to the lexer.
19
+ */
20
+ export declare const RESERVED_WORDS: readonly ["and", "array", "as", "bool", "break", "case", "color", "continue", "default", "else", "false", "fn", "for", "if", "import", "in", "is", "live", "map", "matrix", "none", "not", "number", "or", "return", "series", "step", "string", "strategy", "study", "switch", "to", "true", "type", "var", "while"];
21
+ export type KeywordKind = (typeof RESERVED_WORDS)[number];
22
+ /**
23
+ * The operator and punctuation tokens of language.md 3.12, longest first so a
24
+ * lexer taking them in order takes the longest match.
25
+ *
26
+ * `!` is not in the list and is not an operator on its own: it exists only as
27
+ * the first half of `!=`, and a lone one is OS1001 with the fix to write `not`.
28
+ * There are no bitwise, increment or exponent operators for the same reason
29
+ * they are missing from the specification, so there is nothing here to add.
30
+ */
31
+ export declare const PUNCTUATORS: readonly ["==", "!=", "<=", ">=", "+=", "-=", "*=", "/=", "%=", "+", "-", "*", "/", "%", "<", ">", "=", "(", ")", "[", "]", ",", ".", "?", ":"];
32
+ export type PunctuationKind = (typeof PUNCTUATORS)[number];
33
+ /**
34
+ * A name, and the literals that are not words.
35
+ *
36
+ * A named colour such as `aqua` is an identifier rather than a literal: 3.8
37
+ * makes the nineteen names ordinary globals so the standard library can add
38
+ * more without a grammar change. `hexColor` is only the `#rrggbb` and
39
+ * `#rrggbbaa` forms. `true`, `false` and `none` are keywords, being words.
40
+ */
41
+ export type LiteralKind = 'numberLiteral' | 'stringLiteral' | 'hexColor';
42
+ export type NameKind = 'identifier';
43
+ /**
44
+ * The layout tokens of 3.10.
45
+ *
46
+ * A comment and a line carrying no token produce nothing at all, which is the
47
+ * whole of the rule that lets a commented-out statement sit at column zero
48
+ * inside a block without closing it. So there is no comment kind and no blank
49
+ * line kind here, and nothing downstream has to skip them.
50
+ */
51
+ export type LayoutKind = 'newline' | 'indent' | 'dedent' | 'endOfFile';
52
+ export type TokenKind = KeywordKind | PunctuationKind | LiteralKind | NameKind | LayoutKind;
53
+ //# sourceMappingURL=kind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kind.d.ts","sourceRoot":"","sources":["../../../src/core/tokens/kind.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,uTAqCjB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,iJA0Bd,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,eAAe,GAAG,UAAU,CAAC;AAEzE,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvE,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC"}