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,17 @@
1
+ import type { IfStatement } from '../ast/index.js';
2
+ import type { Cursor } from './cursor.js';
3
+ /**
4
+ * `if`, `else if` and `else`, language.md 10.2.
5
+ *
6
+ * The branches are kept beside each other rather than nested, because `else if`
7
+ * is two words on one line and does not increase indentation, so a reader sees
8
+ * one statement with several arms and every pass over the tree should see the
9
+ * same thing.
10
+ *
11
+ * An `else` pairs with the `if` at its own indentation. The lexer has already
12
+ * closed the blocks between them, so the `else` that arrives here is the one
13
+ * that belongs to this `if`; what is left to check is that the two line up, and
14
+ * OS1016 when they do not.
15
+ */
16
+ export declare function parseIfStatement(cursor: Cursor): IfStatement;
17
+ //# sourceMappingURL=branches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branches.d.ts","sourceRoot":"","sources":["../../../src/core/parse/branches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CA0B5D"}
@@ -0,0 +1,66 @@
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
+ * `if`, `else if` and `else`, language.md 10.2.
8
+ *
9
+ * The branches are kept beside each other rather than nested, because `else if`
10
+ * is two words on one line and does not increase indentation, so a reader sees
11
+ * one statement with several arms and every pass over the tree should see the
12
+ * same thing.
13
+ *
14
+ * An `else` pairs with the `if` at its own indentation. The lexer has already
15
+ * closed the blocks between them, so the `else` that arrives here is the one
16
+ * that belongs to this `if`; what is left to check is that the two line up, and
17
+ * OS1016 when they do not.
18
+ */
19
+ export function parseIfStatement(cursor) {
20
+ const keyword = cursor.token;
21
+ cursor.noteIf(keyword.span.column);
22
+ const branches = [parseBranch(cursor, 'if', keyword.span)];
23
+ let elseBranch;
24
+ let end = branches[0]?.span ?? keyword.span;
25
+ while (cursor.at('else')) {
26
+ const word = cursor.token;
27
+ pairWithIf(cursor, word, keyword);
28
+ cursor.advance();
29
+ if (cursor.at('if')) {
30
+ const branch = parseBranch(cursor, 'else if', word.span);
31
+ branches.push(branch);
32
+ end = branch.span;
33
+ continue;
34
+ }
35
+ elseBranch = parseElse(cursor, word);
36
+ end = elseBranch.span;
37
+ break;
38
+ }
39
+ return makeNode('ifStatement', spanning(keyword.span, end), { branches, elseBranch });
40
+ }
41
+ /** One `if` or `else if` header and the block under it. */
42
+ function parseBranch(cursor, header, start) {
43
+ cursor.beginStatement();
44
+ const keyword = cursor.advance();
45
+ const condition = parseCondition(cursor);
46
+ finishStatement(cursor);
47
+ const body = parseBlock(cursor, header, spanning(start, keyword.span));
48
+ return makeNode('ifBranch', spanning(start, body.span), { condition, body });
49
+ }
50
+ function parseElse(cursor, word) {
51
+ cursor.beginStatement();
52
+ // Nothing may follow `else` on its line: there is no statement separator to
53
+ // end a one line body with, so a body is written indented underneath.
54
+ finishStatement(cursor);
55
+ const body = parseBlock(cursor, 'else', word.span);
56
+ return makeNode('elseBranch', spanning(word.span, body.span), { body });
57
+ }
58
+ function pairWithIf(cursor, word, keyword) {
59
+ if (word.span.column === keyword.span.column)
60
+ return;
61
+ cursor.report('OS1016', word.span, {
62
+ found: word.span.column - 1,
63
+ expected: keyword.span.column - 1,
64
+ });
65
+ }
66
+ //# sourceMappingURL=branches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branches.js","sourceRoot":"","sources":["../../../src/core/parse/branches.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import type { DiagnosticCode, DiagnosticValues } from '../catalogue/index.js';
2
+ import type { DiagnosticSink } from '../diagnostics/index.js';
3
+ import type { SourceFile } from '../source/index.js';
4
+ import type { Span } from '../span/index.js';
5
+ import type { Token, TokenKind } from '../tokens/index.js';
6
+ /**
7
+ * What a diagnostic calls a token when it has to quote one.
8
+ *
9
+ * A layout token carries no text, and a message that quoted one would quote
10
+ * nothing at all, so each is named by what a reader would call it.
11
+ */
12
+ export declare function describeToken(token: Token): string;
13
+ export declare class Cursor {
14
+ #private;
15
+ readonly file: SourceFile;
16
+ constructor(file: SourceFile, tokens: readonly Token[], sink: DiagnosticSink);
17
+ /** An index into the stream, which a loop compares to prove it made progress. */
18
+ get position(): number;
19
+ get token(): Token;
20
+ get kind(): TokenKind;
21
+ peek(ahead?: number): Token;
22
+ at(kind: TokenKind): boolean;
23
+ atStatementEnd(): boolean;
24
+ advance(): Token;
25
+ take(kind: TokenKind): Token | undefined;
26
+ /** The last token consumed, for a node that has to end where one ended. */
27
+ previous(): Token;
28
+ /**
29
+ * The token before this one, when it is one a reader wrote.
30
+ *
31
+ * OS1022 names the token the statement ran out after, which is the one to the
32
+ * left of the hole. At the start of a line there is no such token, and the
33
+ * caller names the one it is looking at instead.
34
+ */
35
+ previousMeaningful(): Token | undefined;
36
+ /**
37
+ * What the reader wrote across a span.
38
+ *
39
+ * A diagnostic that has to quote a piece of a program quotes the source
40
+ * rather than rebuilding it from the tree. `a.b` put back together out of a
41
+ * member node is a reconstruction, and one that differs from the page by so
42
+ * much as a space sends the reader looking for something they did not write.
43
+ */
44
+ textOf(span: Span): string;
45
+ /** An empty span where something should have been written and was not. */
46
+ holeSpan(): Span;
47
+ report<Code extends DiagnosticCode>(code: Code, span: Span, values: DiagnosticValues[Code]): void;
48
+ /**
49
+ * Whether this statement has already been reported on.
50
+ *
51
+ * One mistake is one diagnostic. A statement that has been reported on has
52
+ * nothing more to say about its own leftovers, so the second message about
53
+ * the same mistake is suppressed rather than the reader being left to work
54
+ * out which of the two to believe.
55
+ */
56
+ get reportedHere(): boolean;
57
+ /**
58
+ * A token where the grammar had one exact thing in mind, OS1018.
59
+ *
60
+ * The catalogue has no code for "a closing bracket belongs here", so the one
61
+ * it does have is used for all of them: OS1018 states what is true, that the
62
+ * token was not expected where it sits, and its fix names the two things that
63
+ * are usually wrong, a missing operator or a line that lost its newline.
64
+ */
65
+ unexpected(token: Token): void;
66
+ /**
67
+ * Whether one more level of expression nesting is within the ceiling.
68
+ *
69
+ * Refusing abandons the statement rather than only this level, because a
70
+ * parser that unwound from here would report the brackets it never reached
71
+ * the closers of, one per level, all of them about the expression that was
72
+ * already too deep.
73
+ */
74
+ deeper(span: Span): boolean;
75
+ shallower(): void;
76
+ /**
77
+ * The same ceiling for blocks, counted across statements rather than within
78
+ * one, because a block's depth is the file's shape and not a line's.
79
+ *
80
+ * A refusal here costs the block and not the statement: the caller skips the
81
+ * whole of it, so there is nothing left inside to report on twice.
82
+ */
83
+ openBlock(span: Span): boolean;
84
+ closeBlock(): void;
85
+ beginStatement(): void;
86
+ /**
87
+ * The first statement in the file, which is the line OS1021 names when a
88
+ * version declaration turns up below it.
89
+ */
90
+ noteStatement(line: number): void;
91
+ get firstStatementLine(): number | undefined;
92
+ /** Where the most recent `if` sat, which is what OS1016 pairs an `else` against. */
93
+ noteIf(column: number): void;
94
+ get nearestIfColumn(): number;
95
+ /**
96
+ * Whether a loop body is being read, which is the whole of OS1009.
97
+ *
98
+ * It is a count on the cursor rather than an argument threaded through every
99
+ * rule, because the one question `break` asks is whether any loop is open,
100
+ * and a function body cannot be inside one: functions are top level only.
101
+ */
102
+ enterLoop(): void;
103
+ leaveLoop(): void;
104
+ get insideLoop(): boolean;
105
+ /** To the end of this line, taking the newline, and no further. */
106
+ skipToEndOfLine(): void;
107
+ /**
108
+ * The whole statement, including a block written under it.
109
+ *
110
+ * This is the boundary to recover at when the line itself was not understood.
111
+ * A header the parser could not read still has its body indented beneath it,
112
+ * and reading that body as though it stood at the outer level would report
113
+ * every line of it.
114
+ */
115
+ skipStatement(): void;
116
+ /** A block, and the blocks inside it, when no statement can hold it. */
117
+ skipBlockBody(): void;
118
+ }
119
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/core/parse/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAyC3D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAYlD;AAED,qBAAa,MAAM;;IACjB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;gBAcd,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc;IAU5E,iFAAiF;IACjF,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,KAAK,IAAI,KAAK,CAEjB;IAED,IAAI,IAAI,IAAI,SAAS,CAEpB;IAED,IAAI,CAAC,KAAK,SAAI,GAAG,KAAK;IAItB,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAI5B,cAAc,IAAI,OAAO;IAIzB,OAAO,IAAI,KAAK;IAMhB,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS;IAIxC,2EAA2E;IAC3E,QAAQ,IAAI,KAAK;IAIjB;;;;;;OAMG;IACH,kBAAkB,IAAI,KAAK,GAAG,SAAS;IAKvC;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAI1B,0EAA0E;IAC1E,QAAQ,IAAI,IAAI;IAehB,MAAM,CAAC,IAAI,SAAS,cAAc,EAChC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAC7B,IAAI;IAUP;;;;;;;OAOG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAI9B;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAc3B,SAAS,IAAI,IAAI;IAIjB;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAa9B,UAAU,IAAI,IAAI;IAQlB,cAAc,IAAI,IAAI;IAMtB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIjC,IAAI,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAE3C;IAED,oFAAoF;IACpF,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI5B,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;;;;;OAMG;IACH,SAAS,IAAI,IAAI;IAIjB,SAAS,IAAI,IAAI;IAIjB,IAAI,UAAU,IAAI,OAAO,CAExB;IAMD,mEAAmE;IACnE,eAAe,IAAI,IAAI;IAUvB;;;;;;;OAOG;IACH,aAAa,IAAI,IAAI;IAKrB,wEAAwE;IACxE,aAAa,IAAI,IAAI;CAStB"}
@@ -0,0 +1,305 @@
1
+ import { endOffset } from '../span/index.js';
2
+ /**
3
+ * The parser's place in the token stream, and the three things every rule of
4
+ * the grammar needs that are not grammar: where it is, how it reports, and how
5
+ * it gets out of trouble.
6
+ *
7
+ * Recovery lives here rather than in each rule because it has to be the same
8
+ * everywhere. A trader with three mistakes in a file wants three diagnostics,
9
+ * so no rule throws and no rule gives up on the file: it reports, skips to the
10
+ * next boundary the language guarantees, and carries on. The boundaries are the
11
+ * lexer's own layout tokens, which is what makes the skip reliable rather than
12
+ * a guess: a statement ends at a `newline`, and a block is bracketed by an
13
+ * `indent` and a `dedent`.
14
+ */
15
+ /**
16
+ * The ceiling on source nesting, OS5005.
17
+ *
18
+ * Its purpose is a bounded stack: the parser descends one frame per level of
19
+ * brackets, and generated source is the usual way a file reaches a depth no
20
+ * person writes. The specification names no number, so this one is the
21
+ * compiler's, and it is far above anything written by hand: the deepest
22
+ * expression in the example scripts nests four.
23
+ */
24
+ const MAX_NESTING = 128;
25
+ /** The tokens that end a statement. None of them is ever part of one. */
26
+ const STATEMENT_END = new Set([
27
+ 'newline',
28
+ 'dedent',
29
+ 'endOfFile',
30
+ ]);
31
+ const LAYOUT = new Set([
32
+ 'newline',
33
+ 'indent',
34
+ 'dedent',
35
+ 'endOfFile',
36
+ ]);
37
+ /**
38
+ * What a diagnostic calls a token when it has to quote one.
39
+ *
40
+ * A layout token carries no text, and a message that quoted one would quote
41
+ * nothing at all, so each is named by what a reader would call it.
42
+ */
43
+ export function describeToken(token) {
44
+ switch (token.kind) {
45
+ case 'newline':
46
+ return 'the end of the line';
47
+ case 'endOfFile':
48
+ return 'the end of the file';
49
+ case 'indent':
50
+ case 'dedent':
51
+ return 'the change of indentation';
52
+ default:
53
+ return token.text;
54
+ }
55
+ }
56
+ export class Cursor {
57
+ file;
58
+ #tokens;
59
+ #sink;
60
+ #at = 0;
61
+ /** Diagnostics reported since this statement began. See `reportedHere`. */
62
+ #reported = 0;
63
+ #expressions = 0;
64
+ #blocks = 0;
65
+ #abandoned = false;
66
+ #firstStatementLine;
67
+ #ifColumn;
68
+ #loops = 0;
69
+ constructor(file, tokens, sink) {
70
+ this.file = file;
71
+ this.#tokens = tokens;
72
+ this.#sink = sink;
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // Where it is
76
+ // ---------------------------------------------------------------------------
77
+ /** An index into the stream, which a loop compares to prove it made progress. */
78
+ get position() {
79
+ return this.#at;
80
+ }
81
+ get token() {
82
+ return this.#tokenAt(this.#at);
83
+ }
84
+ get kind() {
85
+ return this.token.kind;
86
+ }
87
+ peek(ahead = 1) {
88
+ return this.#tokenAt(this.#at + ahead);
89
+ }
90
+ at(kind) {
91
+ return this.token.kind === kind;
92
+ }
93
+ atStatementEnd() {
94
+ return STATEMENT_END.has(this.token.kind);
95
+ }
96
+ advance() {
97
+ const token = this.token;
98
+ if (this.#at < this.#tokens.length - 1)
99
+ this.#at += 1;
100
+ return token;
101
+ }
102
+ take(kind) {
103
+ return this.at(kind) ? this.advance() : undefined;
104
+ }
105
+ /** The last token consumed, for a node that has to end where one ended. */
106
+ previous() {
107
+ return this.#tokenAt(this.#at - 1);
108
+ }
109
+ /**
110
+ * The token before this one, when it is one a reader wrote.
111
+ *
112
+ * OS1022 names the token the statement ran out after, which is the one to the
113
+ * left of the hole. At the start of a line there is no such token, and the
114
+ * caller names the one it is looking at instead.
115
+ */
116
+ previousMeaningful() {
117
+ const before = this.#tokenAt(this.#at - 1);
118
+ return this.#at > 0 && !LAYOUT.has(before.kind) ? before : undefined;
119
+ }
120
+ /**
121
+ * What the reader wrote across a span.
122
+ *
123
+ * A diagnostic that has to quote a piece of a program quotes the source
124
+ * rather than rebuilding it from the tree. `a.b` put back together out of a
125
+ * member node is a reconstruction, and one that differs from the page by so
126
+ * much as a space sends the reader looking for something they did not write.
127
+ */
128
+ textOf(span) {
129
+ return this.file.text.slice(span.offset, endOffset(span));
130
+ }
131
+ /** An empty span where something should have been written and was not. */
132
+ holeSpan() {
133
+ return this.file.spanAt(this.token.span.offset, 0);
134
+ }
135
+ #tokenAt(index) {
136
+ const clamped = Math.min(Math.max(index, 0), this.#tokens.length - 1);
137
+ // The stream always ends with an end of file token, so there is no empty
138
+ // case here to invent a token for.
139
+ return this.#tokens[clamped];
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // How it reports
143
+ // ---------------------------------------------------------------------------
144
+ report(code, span, values) {
145
+ // An abandoned statement has said what it has to say. Everything an
146
+ // unwinding parser would report after it is about the same mistake, and a
147
+ // file that reports two hundred unclosed brackets for one expression that
148
+ // was too deep has told the reader nothing.
149
+ if (this.#abandoned)
150
+ return;
151
+ this.#reported += 1;
152
+ this.#sink.report(code, span, values);
153
+ }
154
+ /**
155
+ * Whether this statement has already been reported on.
156
+ *
157
+ * One mistake is one diagnostic. A statement that has been reported on has
158
+ * nothing more to say about its own leftovers, so the second message about
159
+ * the same mistake is suppressed rather than the reader being left to work
160
+ * out which of the two to believe.
161
+ */
162
+ get reportedHere() {
163
+ return this.#reported > 0;
164
+ }
165
+ /**
166
+ * A token where the grammar had one exact thing in mind, OS1018.
167
+ *
168
+ * The catalogue has no code for "a closing bracket belongs here", so the one
169
+ * it does have is used for all of them: OS1018 states what is true, that the
170
+ * token was not expected where it sits, and its fix names the two things that
171
+ * are usually wrong, a missing operator or a line that lost its newline.
172
+ */
173
+ unexpected(token) {
174
+ this.report('OS1018', token.span, { token: describeToken(token) });
175
+ }
176
+ /**
177
+ * Whether one more level of expression nesting is within the ceiling.
178
+ *
179
+ * Refusing abandons the statement rather than only this level, because a
180
+ * parser that unwound from here would report the brackets it never reached
181
+ * the closers of, one per level, all of them about the expression that was
182
+ * already too deep.
183
+ */
184
+ deeper(span) {
185
+ if (this.#expressions >= MAX_NESTING) {
186
+ this.report('OS5005', span, {
187
+ construct: 'An expression',
188
+ found: this.#expressions + 1,
189
+ max: MAX_NESTING,
190
+ });
191
+ this.#abandoned = true;
192
+ return false;
193
+ }
194
+ this.#expressions += 1;
195
+ return true;
196
+ }
197
+ shallower() {
198
+ this.#expressions -= 1;
199
+ }
200
+ /**
201
+ * The same ceiling for blocks, counted across statements rather than within
202
+ * one, because a block's depth is the file's shape and not a line's.
203
+ *
204
+ * A refusal here costs the block and not the statement: the caller skips the
205
+ * whole of it, so there is nothing left inside to report on twice.
206
+ */
207
+ openBlock(span) {
208
+ if (this.#blocks >= MAX_NESTING) {
209
+ this.report('OS5005', span, {
210
+ construct: 'A block',
211
+ found: this.#blocks + 1,
212
+ max: MAX_NESTING,
213
+ });
214
+ return false;
215
+ }
216
+ this.#blocks += 1;
217
+ return true;
218
+ }
219
+ closeBlock() {
220
+ this.#blocks -= 1;
221
+ }
222
+ // ---------------------------------------------------------------------------
223
+ // The file as a whole
224
+ // ---------------------------------------------------------------------------
225
+ beginStatement() {
226
+ this.#reported = 0;
227
+ this.#expressions = 0;
228
+ this.#abandoned = false;
229
+ }
230
+ /**
231
+ * The first statement in the file, which is the line OS1021 names when a
232
+ * version declaration turns up below it.
233
+ */
234
+ noteStatement(line) {
235
+ this.#firstStatementLine ??= line;
236
+ }
237
+ get firstStatementLine() {
238
+ return this.#firstStatementLine;
239
+ }
240
+ /** Where the most recent `if` sat, which is what OS1016 pairs an `else` against. */
241
+ noteIf(column) {
242
+ this.#ifColumn = column;
243
+ }
244
+ get nearestIfColumn() {
245
+ return this.#ifColumn ?? 1;
246
+ }
247
+ /**
248
+ * Whether a loop body is being read, which is the whole of OS1009.
249
+ *
250
+ * It is a count on the cursor rather than an argument threaded through every
251
+ * rule, because the one question `break` asks is whether any loop is open,
252
+ * and a function body cannot be inside one: functions are top level only.
253
+ */
254
+ enterLoop() {
255
+ this.#loops += 1;
256
+ }
257
+ leaveLoop() {
258
+ this.#loops -= 1;
259
+ }
260
+ get insideLoop() {
261
+ return this.#loops > 0;
262
+ }
263
+ // ---------------------------------------------------------------------------
264
+ // How it gets out of trouble
265
+ // ---------------------------------------------------------------------------
266
+ /** To the end of this line, taking the newline, and no further. */
267
+ skipToEndOfLine() {
268
+ const before = this.#at;
269
+ while (!this.atStatementEnd())
270
+ this.advance();
271
+ if (this.take('newline') !== undefined)
272
+ return;
273
+ // A skip that consumed nothing leaves the loop that called it where it
274
+ // began, and a compiler that hangs on a malformed file is worse than one
275
+ // that gives up on it.
276
+ if (this.#at === before && !this.at('endOfFile'))
277
+ this.advance();
278
+ }
279
+ /**
280
+ * The whole statement, including a block written under it.
281
+ *
282
+ * This is the boundary to recover at when the line itself was not understood.
283
+ * A header the parser could not read still has its body indented beneath it,
284
+ * and reading that body as though it stood at the outer level would report
285
+ * every line of it.
286
+ */
287
+ skipStatement() {
288
+ this.skipToEndOfLine();
289
+ this.skipBlockBody();
290
+ }
291
+ /** A block, and the blocks inside it, when no statement can hold it. */
292
+ skipBlockBody() {
293
+ if (!this.at('indent'))
294
+ return;
295
+ let depth = 0;
296
+ do {
297
+ if (this.at('indent'))
298
+ depth += 1;
299
+ else if (this.at('dedent'))
300
+ depth -= 1;
301
+ this.advance();
302
+ } while (depth > 0 && !this.at('endOfFile'));
303
+ }
304
+ }
305
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/core/parse/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { Argument, Expression } from '../ast/index.js';
2
+ import type { Span } from '../span/index.js';
3
+ import type { Token, TokenKind } from '../tokens/index.js';
4
+ import type { Cursor } from './cursor.js';
5
+ /**
6
+ * Whether an expression can begin here, which is what tells one argument from
7
+ * the next and what keeps a list from reading a closing bracket as an item.
8
+ *
9
+ * A reserved word a reader meant as a name begins one too, because `parsePrimary`
10
+ * reads it as the name it was meant to be rather than leaving it where it sits.
11
+ */
12
+ export declare function startsExpression(kind: TokenKind): boolean;
13
+ interface List<Item> {
14
+ readonly items: readonly Item[];
15
+ /** Where the list ended, so the node around it can reach its closing bracket. */
16
+ readonly end: Span;
17
+ }
18
+ export declare function parseExpression(cursor: Cursor): Expression;
19
+ /**
20
+ * An expression in a position where a value is being tested rather than stored.
21
+ *
22
+ * `if x = 5` is the one typo the language is shaped to catch: assignment is a
23
+ * statement and never an expression (10.1), so there is no reading of the line
24
+ * that compiles, and OS1006 can name the fix instead of a type error arriving
25
+ * three stages later. The `==` is built as though the fix had been applied, so
26
+ * the rest of the file still checks.
27
+ */
28
+ export declare function parseCondition(cursor: Cursor): Expression;
29
+ /**
30
+ * A comma separated list inside brackets: an argument list or an array literal.
31
+ *
32
+ * The two shapes are one function because their recovery is the same and has to
33
+ * stay the same: a missing comma is OS1014 and the list carries on, and a list
34
+ * that runs to the end of the line without a closer is the bracket's own error
35
+ * rather than one per item.
36
+ */
37
+ export declare function parseBracketedList<Item>(cursor: Cursor, open: Token, parseItem: (cursor: Cursor) => Item): List<Item>;
38
+ /**
39
+ * The closing bracket, or the two ways it can be missing.
40
+ *
41
+ * OS1012 is reported at the opening bracket rather than at the end of the file,
42
+ * because an open bracket continues the statement onto every following line
43
+ * (3.11) and the mistake is where the bracket was opened.
44
+ */
45
+ export declare function closeBracket(cursor: Cursor, open: Token): Span;
46
+ /**
47
+ * The hole a rule leaves where an expression was required.
48
+ *
49
+ * The span is empty and sits where the expression should have been, so it never
50
+ * takes a caret meant for its neighbour, and everything downstream still has a
51
+ * tree to walk over a file that is being typed.
52
+ */
53
+ export declare function missingExpression(cursor: Cursor): Expression;
54
+ /** An argument list, for the three statements that are a call in all but name. */
55
+ export declare function parseArgumentList(cursor: Cursor, open: Token): List<Argument>;
56
+ export {};
57
+ //# sourceMappingURL=expressions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressions.d.ts","sourceRoot":"","sources":["../../../src/core/parse/expressions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,QAAQ,EAER,UAAU,EAEX,MAAM,iBAAiB,CAAC;AAOzB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAuC1C;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAEzD;AAED,UAAU,IAAI,CAAC,IAAI;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAK1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAYzD;AAiOD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,KAAK,EACX,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAClC,IAAI,CAAC,IAAI,CAAC,CAuCZ;AAMD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAmB9D;AAUD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAE5D;AAUD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAE7E"}