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,40 @@
1
+ import type { DiagnosticSink } from '../diagnostics/index.js';
2
+ import type { SourceFile } from '../source/index.js';
3
+ import type { Token, TokenKind } from '../tokens/index.js';
4
+ /**
5
+ * What the shape of a file means: where a statement begins, where a block opens
6
+ * and closes, and what a line's leading whitespace is worth.
7
+ *
8
+ * It is a separate thing from the scanner because it works in lines and
9
+ * statements where the scanner works in characters, and because it is where the
10
+ * two rules that a naive lexer gets wrong live: a line that carries no token is
11
+ * never asked about its indentation, and a line indented past its siblings is
12
+ * one error rather than a new block.
13
+ *
14
+ * It writes the layout tokens straight into the list the scanner is filling, so
15
+ * an indent lands in front of the token that opened the block rather than being
16
+ * threaded back in afterwards.
17
+ */
18
+ export declare class Layout {
19
+ #private;
20
+ constructor(file: SourceFile, sink: DiagnosticSink, tokens: Token[]);
21
+ /** Holds a line's leading whitespace, which may turn out to mean nothing at all. */
22
+ beginLine(line: number, offset: number, width: number, text: string, hasTab: boolean): void;
23
+ /** The line is over. Whatever it was holding was never wanted. */
24
+ endLine(): void;
25
+ /**
26
+ * Turns the leading whitespace into block structure, at the moment the line
27
+ * turns out to carry a token and not before. A line that produces no token
28
+ * never reaches here, which is the whole of the rule that a blank line and a
29
+ * comment-only line carry no indentation at all (3.10).
30
+ */
31
+ admit(continuing: boolean): void;
32
+ /** The first token of a statement decides whether a block may open under it. */
33
+ observe(kind: TokenKind): void;
34
+ endStatement(): void;
35
+ /** A second statement beginning on a line that already held one, after a `;`. */
36
+ beginStatement(line: number, indent: number): void;
37
+ /** The end of the file closes every block still open. */
38
+ closeBlocks(at: number): void;
39
+ }
40
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/core/lex/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA2B3D;;;;;;;;;;;;;GAaG;AACH,qBAAa,MAAM;;gBAUL,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE;IAMnE,oFAAoF;IACpF,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAI3F,kEAAkE;IAClE,OAAO,IAAI,IAAI;IAIf;;;;;OAKG;IACH,KAAK,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;IAsEhC,gFAAgF;IAChF,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAK9B,YAAY,IAAI,IAAI;IAWpB,iFAAiF;IACjF,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIlD,yDAAyD;IACzD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAkB9B"}
@@ -0,0 +1,143 @@
1
+ import { BlockStack } from './blocks.js';
2
+ import { endsWithArrow, opensBlock } from './statements.js';
3
+ /**
4
+ * What the shape of a file means: where a statement begins, where a block opens
5
+ * and closes, and what a line's leading whitespace is worth.
6
+ *
7
+ * It is a separate thing from the scanner because it works in lines and
8
+ * statements where the scanner works in characters, and because it is where the
9
+ * two rules that a naive lexer gets wrong live: a line that carries no token is
10
+ * never asked about its indentation, and a line indented past its siblings is
11
+ * one error rather than a new block.
12
+ *
13
+ * It writes the layout tokens straight into the list the scanner is filling, so
14
+ * an indent lands in front of the token that opened the block rather than being
15
+ * threaded back in afterwards.
16
+ */
17
+ export class Layout {
18
+ #file;
19
+ #sink;
20
+ #tokens;
21
+ #blocks = new BlockStack();
22
+ #pending;
23
+ #statement;
24
+ #previous;
25
+ constructor(file, sink, tokens) {
26
+ this.#file = file;
27
+ this.#sink = sink;
28
+ this.#tokens = tokens;
29
+ }
30
+ /** Holds a line's leading whitespace, which may turn out to mean nothing at all. */
31
+ beginLine(line, offset, width, text, hasTab) {
32
+ this.#pending = { line, offset, width, text, hasTab };
33
+ }
34
+ /** The line is over. Whatever it was holding was never wanted. */
35
+ endLine() {
36
+ this.#pending = undefined;
37
+ }
38
+ /**
39
+ * Turns the leading whitespace into block structure, at the moment the line
40
+ * turns out to carry a token and not before. A line that produces no token
41
+ * never reaches here, which is the whole of the rule that a blank line and a
42
+ * comment-only line carry no indentation at all (3.10).
43
+ */
44
+ admit(continuing) {
45
+ const pending = this.#pending;
46
+ if (pending === undefined)
47
+ return;
48
+ this.#pending = undefined;
49
+ if (pending.hasTab) {
50
+ this.#sink.report('OS1002', this.#span(pending.offset, pending.width), {});
51
+ }
52
+ if (continuing) {
53
+ this.#checkContinuation(pending);
54
+ return;
55
+ }
56
+ this.#enterBlock(pending);
57
+ this.#statement = { line: pending.line, indent: pending.width, firstKind: undefined };
58
+ }
59
+ /**
60
+ * A continuation line belongs to a statement that began above it, so it opens
61
+ * and closes nothing. It only has to sit further right than the line that
62
+ * began the statement, so that it can never be read as a new one (3.11).
63
+ *
64
+ * That is OS1028 rather than the block rule of OS1003, and the difference is
65
+ * not a formality: there is no block here, so OS1003's message would name an
66
+ * indentation no line carries and its fix would offer to end a block the file
67
+ * never opened.
68
+ */
69
+ #checkContinuation(pending) {
70
+ const statement = this.#statement;
71
+ if (statement === undefined || pending.width > statement.indent)
72
+ return;
73
+ this.#sink.report('OS1028', this.#span(pending.offset, pending.width), {
74
+ found: pending.width,
75
+ statement: statement.indent,
76
+ line: statement.line,
77
+ });
78
+ }
79
+ #enterBlock(pending) {
80
+ const firstToken = pending.offset + pending.width;
81
+ const event = this.#blocks.enter(pending.width, this.#afterHeader(), this.#previous?.line ?? pending.line);
82
+ switch (event.kind) {
83
+ case 'same':
84
+ break;
85
+ case 'open':
86
+ this.#tokens.push({
87
+ kind: 'indent',
88
+ span: this.#span(pending.offset, pending.width),
89
+ text: pending.text,
90
+ });
91
+ break;
92
+ case 'close':
93
+ this.#dedent(event.count, firstToken);
94
+ break;
95
+ case 'mismatch':
96
+ this.#dedent(event.count, firstToken);
97
+ this.#sink.report('OS1003', this.#span(pending.offset, pending.width), {
98
+ found: pending.width,
99
+ expected: event.expected,
100
+ line: event.openerLine,
101
+ });
102
+ break;
103
+ }
104
+ }
105
+ /** The first token of a statement decides whether a block may open under it. */
106
+ observe(kind) {
107
+ const statement = this.#statement;
108
+ if (statement !== undefined && statement.firstKind === undefined)
109
+ statement.firstKind = kind;
110
+ }
111
+ endStatement() {
112
+ const statement = this.#statement;
113
+ this.#statement = undefined;
114
+ if (statement === undefined || statement.firstKind === undefined)
115
+ return;
116
+ this.#previous = {
117
+ line: statement.line,
118
+ firstKind: statement.firstKind,
119
+ arrowAtEnd: endsWithArrow(this.#tokens),
120
+ };
121
+ }
122
+ /** A second statement beginning on a line that already held one, after a `;`. */
123
+ beginStatement(line, indent) {
124
+ this.#statement = { line, indent, firstKind: undefined };
125
+ }
126
+ /** The end of the file closes every block still open. */
127
+ closeBlocks(at) {
128
+ this.#dedent(this.#blocks.closeAll(), at);
129
+ }
130
+ #dedent(count, at) {
131
+ for (let i = 0; i < count; i++) {
132
+ this.#tokens.push({ kind: 'dedent', span: this.#span(at, 0), text: '' });
133
+ }
134
+ }
135
+ #afterHeader() {
136
+ const previous = this.#previous;
137
+ return previous !== undefined && opensBlock(previous.firstKind, previous.arrowAtEnd);
138
+ }
139
+ #span(offset, length) {
140
+ return this.#file.spanAt(offset, length);
141
+ }
142
+ }
143
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/core/lex/layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { DiagnosticSink } from '../diagnostics/index.js';
2
+ import type { SourceFile } from '../source/index.js';
3
+ import type { Token } from '../tokens/index.js';
4
+ /**
5
+ * Reads a file into tokens, reporting what it cannot read and carrying on.
6
+ *
7
+ * Nothing here throws. One character the language does not have should cost the
8
+ * reader that character and not the rest of the file, so every lexical error is
9
+ * reported against its own span and the scan resumes at the next thing it can
10
+ * recognise.
11
+ */
12
+ export declare function lex(file: SourceFile, diagnostics: DiagnosticSink): readonly Token[];
13
+ //# sourceMappingURL=lexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../../src/core/lex/lexer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAA4B,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAwd1E;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,GAAG,SAAS,KAAK,EAAE,CAEnF"}
@@ -0,0 +1,419 @@
1
+ import { PUNCTUATORS, RESERVED_WORDS } from '../tokens/index.js';
2
+ import { APOSTROPHE, BACKSLASH, DOT, HASH, isBlank, isDigit, isNamePart, isNameStart, LINE_FEED, QUOTE, SEMICOLON, SLASH, SPACE, TAB, } from './characters.js';
3
+ import { closesComment, commentRegion, hasCloser, opensComment } from './comments.js';
4
+ import { Layout } from './layout.js';
5
+ import { scanNumber } from './numbers.js';
6
+ import { continuesLine } from './statements.js';
7
+ import { scanString } from './strings.js';
8
+ import { describeUnexpected, isNonAsciiLetter } from './unexpected.js';
9
+ const RESERVED = new Set(RESERVED_WORDS);
10
+ const ONE_CHARACTER = new Set(PUNCTUATORS.filter((mark) => mark.length === 1));
11
+ const TWO_CHARACTER = new Set(PUNCTUATORS.filter((mark) => mark.length === 2));
12
+ /**
13
+ * The two character operators of other languages, which this one does not have
14
+ * (3.12). They are matched as a pair so that the message names the operator the
15
+ * reader wrote and offers the one to write instead, rather than reporting one
16
+ * ampersand and leaving them to work out which half was wrong.
17
+ */
18
+ const REJECTED_PAIRS = new Set(['&&', '||', '**', '++']);
19
+ const OPENING_BRACKETS = new Set(['(', '[']);
20
+ const CLOSING_BRACKETS = new Set([')', ']']);
21
+ const HEX_ONLY = /^[0-9a-fA-F]+$/;
22
+ class Lexer {
23
+ #file;
24
+ #text;
25
+ #sink;
26
+ #tokens = [];
27
+ #layout;
28
+ #offset = 0;
29
+ #line = 1;
30
+ #indent = 0;
31
+ #brackets = 0;
32
+ #continuing = false;
33
+ #lineHasToken = false;
34
+ #droppedAfterToken = false;
35
+ /** Whether a block comment marker opened a region that no closer has ended yet. */
36
+ #inComment = false;
37
+ constructor(file, sink) {
38
+ this.#file = file;
39
+ this.#text = file.text;
40
+ this.#sink = sink;
41
+ this.#layout = new Layout(file, sink, this.#tokens);
42
+ }
43
+ run() {
44
+ while (this.#offset < this.#text.length)
45
+ this.#readLine();
46
+ this.#finish();
47
+ return this.#tokens;
48
+ }
49
+ // -------------------------------------------------------------------------
50
+ // Lines
51
+ // -------------------------------------------------------------------------
52
+ #readLine() {
53
+ const start = this.#offset;
54
+ let i = start;
55
+ // A tab is one character of indentation here, and OS1002 as soon as the line
56
+ // turns out to carry a token. It is counted rather than expanded because the
57
+ // report is what matters and a width would be a guess at an editor setting.
58
+ let hasTab = false;
59
+ while (isBlank(this.#text.charCodeAt(i))) {
60
+ if (this.#text.charCodeAt(i) === TAB)
61
+ hasTab = true;
62
+ i++;
63
+ }
64
+ this.#indent = i - start;
65
+ this.#layout.beginLine(this.#line, start, this.#indent, this.#text.slice(start, i), hasTab);
66
+ this.#offset = i;
67
+ this.#lineHasToken = false;
68
+ this.#droppedAfterToken = false;
69
+ if (this.#inComment)
70
+ this.#skipComment(this.#offset);
71
+ let backslash = false;
72
+ while (this.#offset < this.#text.length) {
73
+ const code = this.#text.charCodeAt(this.#offset);
74
+ if (code === LINE_FEED)
75
+ break;
76
+ if (code === SPACE) {
77
+ this.#offset++;
78
+ continue;
79
+ }
80
+ if (code === SLASH && this.#text.charCodeAt(this.#offset + 1) === SLASH) {
81
+ // A comment produces no token, which is what lets a commented out line
82
+ // sit at column zero inside a block without closing it (3.10).
83
+ this.#offset = this.#endOfLine(this.#offset);
84
+ break;
85
+ }
86
+ if (opensComment(this.#text, this.#offset)) {
87
+ this.#openComment();
88
+ continue;
89
+ }
90
+ if (closesComment(this.#text, this.#offset)) {
91
+ // A closer with nothing open. The region it was meant to end was never
92
+ // read as one, so the marker is reported where it sits and read as
93
+ // nothing at all.
94
+ this.#sink.report('OS1026', this.#span(this.#offset, 2), { marker: '*/' });
95
+ this.#offset += 2;
96
+ continue;
97
+ }
98
+ if (code === BACKSLASH && this.#isBlankTo(this.#offset + 1)) {
99
+ backslash = true;
100
+ this.#offset = this.#endOfLine(this.#offset);
101
+ break;
102
+ }
103
+ this.#readToken();
104
+ }
105
+ this.#endLine(backslash);
106
+ }
107
+ #endLine(backslash) {
108
+ // A line carrying no token says nothing about the statement around it, so a
109
+ // blank line and a comment-only line inside a continuation leave it open
110
+ // (3.11) by never being asked.
111
+ if (this.#lineHasToken || backslash) {
112
+ // A trailing operator whose operand was rejected promised nothing: the
113
+ // operand was written, it was just not written in this language. Letting
114
+ // it continue would hand the next line to a broken statement, and one bad
115
+ // character would take a line that has nothing wrong with it.
116
+ const promised = !this.#droppedAfterToken && continuesLine(this.#tokens);
117
+ this.#continuing = this.#brackets > 0 || backslash || promised;
118
+ }
119
+ if (this.#lineHasToken && !this.#continuing) {
120
+ this.#layout.endStatement();
121
+ const atEnd = this.#offset >= this.#text.length;
122
+ this.#emitNewline(this.#span(this.#offset, atEnd ? 0 : 1));
123
+ }
124
+ if (this.#offset < this.#text.length) {
125
+ this.#offset++;
126
+ this.#line++;
127
+ }
128
+ this.#layout.endLine();
129
+ }
130
+ #finish() {
131
+ const last = this.#tokens[this.#tokens.length - 1];
132
+ if (last !== undefined && last.kind !== 'newline') {
133
+ // A bracket that is never closed reads the rest of the file as one
134
+ // statement (3.11), and that statement still has to end somewhere for the
135
+ // parser to report it against.
136
+ this.#layout.endStatement();
137
+ this.#emitNewline(this.#span(this.#text.length, 0));
138
+ }
139
+ this.#layout.closeBlocks(this.#text.length);
140
+ this.#tokens.push({ kind: 'endOfFile', span: this.#span(this.#text.length, 0), text: '' });
141
+ }
142
+ /**
143
+ * A region the writer meant as a comment, from its opener to its closer.
144
+ *
145
+ * It is reported once, at the opener, and then skipped. Reading the prose
146
+ * inside it as tokens would report the operators it happens to contain and
147
+ * the statements it appears to hold, which is several diagnostics about a
148
+ * program the writer did not write, and none of them would name the comment
149
+ * (3.2).
150
+ */
151
+ #openComment() {
152
+ this.#sink.report('OS1026', this.#span(this.#offset, 2), { marker: '/*' });
153
+ this.#skipComment(this.#offset + 2);
154
+ // A closer written nowhere makes no region: the marker costs this line and
155
+ // the file is read on from the next one, rather than being swallowed whole
156
+ // by a form the language does not have (3.2).
157
+ this.#inComment = this.#inComment && hasCloser(this.#text, this.#offset);
158
+ }
159
+ /**
160
+ * The region, to its closer or to the end of the line, said once and then
161
+ * skipped: one region is one mistake however many lines it runs to, so a
162
+ * line below the opener is read as prose rather than reported again.
163
+ */
164
+ #skipComment(from) {
165
+ const region = commentRegion(this.#text, from);
166
+ this.#inComment = region.open;
167
+ this.#offset = region.end;
168
+ }
169
+ #endOfLine(from) {
170
+ const at = this.#text.indexOf('\n', from);
171
+ return at === -1 ? this.#text.length : at;
172
+ }
173
+ #isBlankTo(from) {
174
+ for (let i = from; i < this.#text.length; i++) {
175
+ const code = this.#text.charCodeAt(i);
176
+ if (code === LINE_FEED)
177
+ return true;
178
+ if (!isBlank(code))
179
+ return false;
180
+ }
181
+ return true;
182
+ }
183
+ // -------------------------------------------------------------------------
184
+ // Tokens
185
+ // -------------------------------------------------------------------------
186
+ #readToken() {
187
+ const start = this.#offset;
188
+ const code = this.#text.charCodeAt(start);
189
+ if (isNameStart(code)) {
190
+ this.#readName(start);
191
+ return;
192
+ }
193
+ if (isDigit(code) || (code === DOT && isDigit(this.#text.charCodeAt(start + 1)))) {
194
+ this.#readNumber(start);
195
+ return;
196
+ }
197
+ if (code === QUOTE || code === APOSTROPHE) {
198
+ this.#readString(start);
199
+ return;
200
+ }
201
+ if (code === HASH) {
202
+ this.#readColour(start);
203
+ return;
204
+ }
205
+ if (code === SEMICOLON) {
206
+ this.#readSemicolon(start);
207
+ return;
208
+ }
209
+ this.#readPunctuation(start);
210
+ }
211
+ /**
212
+ * A name, and with it every reserved word, which is spelled like one and told
213
+ * apart by the table rather than by the scanner.
214
+ *
215
+ * A reserved word keeps its own kind here even where the parser will accept it
216
+ * as a named argument label (3.4). The lexer cannot make that call: the same
217
+ * word before an `=` is a legal label inside a call and is OS1019 inside a
218
+ * parameter list, and only the parser knows which of the two it is reading.
219
+ */
220
+ #readName(start) {
221
+ const word = this.#word(start);
222
+ if (word.foreign !== undefined) {
223
+ // Identifiers are ASCII (3.3). The whole word is taken as one name so that
224
+ // the statement around it still parses and one bad character reports once.
225
+ this.#sink.report('OS1001', this.#span(word.foreign.offset, word.foreign.written.length), describeUnexpected(word.foreign.written));
226
+ }
227
+ const text = this.#text.slice(start, word.end);
228
+ const kind = RESERVED.has(text) ? text : 'identifier';
229
+ this.#emit({ kind, span: this.#span(start, word.end - start), text });
230
+ this.#offset = word.end;
231
+ }
232
+ /**
233
+ * A number literal, and the run that is not one: a base prefix the language
234
+ * does not have, a unit written against a quantity, a literal that ends in an
235
+ * underscore (3.5).
236
+ *
237
+ * Such a run is reported whole, as OS1029. Every character in it is one the
238
+ * language accepts, so naming the leading digit would name something legal,
239
+ * and deleting it, which is what OS1001 tells a reader to do with the
240
+ * character it names, leaves a valid name behind and a program that compiles
241
+ * and means something else.
242
+ */
243
+ #readNumber(start) {
244
+ const literal = scanNumber(this.#text, start);
245
+ const after = this.#text.codePointAt(literal.end);
246
+ if (after !== undefined && (isNamePart(after) || isNonAsciiLetter(after))) {
247
+ // A name cannot begin with a digit (3.3), and a letter written against a
248
+ // number is that mistake rather than two tokens that happen to touch.
249
+ const word = this.#word(literal.end);
250
+ const written = this.#text.slice(start, word.end);
251
+ this.#sink.report('OS1029', this.#span(start, word.end - start), {
252
+ written,
253
+ number: this.#text.slice(start, literal.end),
254
+ });
255
+ this.#emit({
256
+ kind: 'identifier',
257
+ span: this.#span(start, word.end - start),
258
+ text: written,
259
+ });
260
+ this.#offset = word.end;
261
+ return;
262
+ }
263
+ this.#emit({
264
+ kind: 'numberLiteral',
265
+ span: this.#span(start, literal.end - start),
266
+ text: this.#text.slice(start, literal.end),
267
+ value: literal.value,
268
+ });
269
+ this.#offset = literal.end;
270
+ }
271
+ #readString(start) {
272
+ const literal = scanString(this.#text, start);
273
+ for (const bad of literal.badEscapes) {
274
+ this.#sink.report('OS1005', this.#span(bad.offset, bad.length), { sequence: bad.text });
275
+ }
276
+ if (literal.unterminated) {
277
+ this.#sink.report('OS1004', this.#span(start, 1), { quote: this.#text.charAt(start) });
278
+ }
279
+ // The token is emitted either way. The reader is told once that the quote is
280
+ // missing; they do not also need to be told that the statement around it
281
+ // makes no sense without it.
282
+ this.#emit({
283
+ kind: 'stringLiteral',
284
+ span: this.#span(start, literal.end - start),
285
+ text: this.#text.slice(start, literal.end),
286
+ value: literal.value,
287
+ });
288
+ this.#offset = literal.end;
289
+ }
290
+ /**
291
+ * `#rrggbb` and `#rrggbbaa` (3.8).
292
+ *
293
+ * A run of the wrong length, or one carrying a character that is not a
294
+ * hexadecimal digit, is a colour the writer had nearly right, and it is
295
+ * OS1027 over the whole of what they wrote. The OS1001 sentence about `#`
296
+ * says to delete the character or to put the text in a string, which is the
297
+ * answer for a `#` standing on its own and would throw the colour away here.
298
+ */
299
+ #readColour(start) {
300
+ const word = this.#word(start + 1);
301
+ const digits = this.#text.slice(start + 1, word.end);
302
+ const isColour = word.foreign === undefined &&
303
+ (digits.length === 6 || digits.length === 8) &&
304
+ HEX_ONLY.test(digits);
305
+ if (isColour) {
306
+ this.#emit({
307
+ kind: 'hexColor',
308
+ span: this.#span(start, word.end - start),
309
+ text: this.#text.slice(start, word.end),
310
+ });
311
+ this.#offset = word.end;
312
+ return;
313
+ }
314
+ if (digits.length === 0) {
315
+ // Nothing was written against it, so there is no colour here to have got
316
+ // wrong: this is the character on its own (3.1).
317
+ this.#sink.report('OS1001', this.#span(start, 1), describeUnexpected('#'));
318
+ this.#droppedAfterToken = true;
319
+ this.#offset = start + 1;
320
+ return;
321
+ }
322
+ this.#sink.report('OS1027', this.#span(start, word.end - start), {
323
+ written: this.#text.slice(start, word.end),
324
+ });
325
+ this.#droppedAfterToken = true;
326
+ this.#offset = word.end;
327
+ }
328
+ #readSemicolon(start) {
329
+ this.#sink.report('OS1007', this.#span(start, 1), {});
330
+ this.#droppedAfterToken = true;
331
+ this.#offset = start + 1;
332
+ // The fix is to put the second statement on its own line, so the token
333
+ // stream is given exactly that and the rest of the line is read as the
334
+ // statement the writer meant. Inside brackets there is no statement to end,
335
+ // so there the character is only dropped.
336
+ if (this.#brackets > 0 || !this.#lineHasToken)
337
+ return;
338
+ this.#layout.endStatement();
339
+ this.#emitNewline(this.#span(start, 1));
340
+ this.#layout.beginStatement(this.#line, this.#indent);
341
+ }
342
+ #readPunctuation(start) {
343
+ const pair = this.#text.slice(start, start + 2);
344
+ if (REJECTED_PAIRS.has(pair)) {
345
+ this.#sink.report('OS1001', this.#span(start, 2), describeUnexpected(pair));
346
+ this.#droppedAfterToken = true;
347
+ this.#offset = start + 2;
348
+ return;
349
+ }
350
+ if (TWO_CHARACTER.has(pair)) {
351
+ this.#emit({ kind: pair, span: this.#span(start, 2), text: pair });
352
+ this.#offset = start + 2;
353
+ return;
354
+ }
355
+ const one = this.#text.charAt(start);
356
+ if (ONE_CHARACTER.has(one)) {
357
+ if (OPENING_BRACKETS.has(one))
358
+ this.#brackets++;
359
+ else if (CLOSING_BRACKETS.has(one) && this.#brackets > 0)
360
+ this.#brackets--;
361
+ this.#emit({ kind: one, span: this.#span(start, 1), text: one });
362
+ this.#offset = start + 1;
363
+ return;
364
+ }
365
+ // Everything the language does not have, reported where it sits rather than
366
+ // three tokens later (3.1). An astral character is two code units and is
367
+ // taken whole, so a message never quotes half of one.
368
+ const written = String.fromCodePoint(this.#text.codePointAt(start) ?? 0);
369
+ this.#sink.report('OS1001', this.#span(start, written.length), describeUnexpected(written));
370
+ this.#droppedAfterToken = true;
371
+ this.#offset = start + written.length;
372
+ }
373
+ #word(from) {
374
+ let i = from;
375
+ let foreign;
376
+ for (;;) {
377
+ while (isNamePart(this.#text.charCodeAt(i)))
378
+ i++;
379
+ const point = this.#text.codePointAt(i);
380
+ if (point === undefined || !isNonAsciiLetter(point))
381
+ return { end: i, foreign };
382
+ const written = String.fromCodePoint(point);
383
+ foreign ??= { offset: i, written };
384
+ i += written.length;
385
+ }
386
+ }
387
+ // -------------------------------------------------------------------------
388
+ // Emitting
389
+ // -------------------------------------------------------------------------
390
+ #emit(token) {
391
+ this.#layout.admit(this.#continuing);
392
+ this.#layout.observe(token.kind);
393
+ this.#lineHasToken = true;
394
+ this.#droppedAfterToken = false;
395
+ this.#tokens.push(token);
396
+ }
397
+ /** One newline per statement, never two, and never one before a statement has begun. */
398
+ #emitNewline(span) {
399
+ const last = this.#tokens[this.#tokens.length - 1];
400
+ if (last === undefined || last.kind === 'newline')
401
+ return;
402
+ this.#tokens.push({ kind: 'newline', span, text: '' });
403
+ }
404
+ #span(offset, length) {
405
+ return this.#file.spanAt(offset, length);
406
+ }
407
+ }
408
+ /**
409
+ * Reads a file into tokens, reporting what it cannot read and carrying on.
410
+ *
411
+ * Nothing here throws. One character the language does not have should cost the
412
+ * reader that character and not the rest of the file, so every lexical error is
413
+ * reported against its own span and the scan resumes at the next thing it can
414
+ * recognise.
415
+ */
416
+ export function lex(file, diagnostics) {
417
+ return new Lexer(file, diagnostics).run();
418
+ }
419
+ //# sourceMappingURL=lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.js","sourceRoot":"","sources":["../../../src/core/lex/lexer.ts"],"names":[],"mappings":"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"}