rooklang 0.0.0-stage → 0.3.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 (314) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -2
  3. package/README.ru.md +178 -0
  4. package/dist/ast/declarations.d.ts +185 -0
  5. package/dist/ast/declarations.js +1 -0
  6. package/dist/ast/expressions.d.ts +201 -0
  7. package/dist/ast/expressions.js +1 -0
  8. package/dist/ast/markup.d.ts +141 -0
  9. package/dist/ast/markup.js +1 -0
  10. package/dist/ast/statements.d.ts +173 -0
  11. package/dist/ast/statements.js +1 -0
  12. package/dist/ast.d.ts +18 -0
  13. package/dist/ast.js +18 -0
  14. package/dist/attrs.d.ts +8 -0
  15. package/dist/attrs.js +23 -0
  16. package/dist/browser.d.ts +30 -0
  17. package/dist/browser.js +36 -0
  18. package/dist/build.d.ts +48 -0
  19. package/dist/build.js +112 -0
  20. package/dist/checker/assignments.d.ts +14 -0
  21. package/dist/checker/assignments.js +197 -0
  22. package/dist/checker/base.d.ts +124 -0
  23. package/dist/checker/base.js +180 -0
  24. package/dist/checker/bigint.d.ts +15 -0
  25. package/dist/checker/bigint.js +85 -0
  26. package/dist/checker/builtins.d.ts +9 -0
  27. package/dist/checker/builtins.js +307 -0
  28. package/dist/checker/bytes.d.ts +11 -0
  29. package/dist/checker/bytes.js +72 -0
  30. package/dist/checker/calls.d.ts +23 -0
  31. package/dist/checker/calls.js +210 -0
  32. package/dist/checker/channel.d.ts +14 -0
  33. package/dist/checker/channel.js +44 -0
  34. package/dist/checker/channels.d.ts +9 -0
  35. package/dist/checker/channels.js +95 -0
  36. package/dist/checker/checker.d.ts +4 -0
  37. package/dist/checker/checker.js +22 -0
  38. package/dist/checker/classes.d.ts +24 -0
  39. package/dist/checker/classes.js +223 -0
  40. package/dist/checker/completion-names.d.ts +11 -0
  41. package/dist/checker/completion-names.js +100 -0
  42. package/dist/checker/completion.d.ts +25 -0
  43. package/dist/checker/completion.js +222 -0
  44. package/dist/checker/component-values.d.ts +11 -0
  45. package/dist/checker/component-values.js +88 -0
  46. package/dist/checker/components.d.ts +37 -0
  47. package/dist/checker/components.js +287 -0
  48. package/dist/checker/context.d.ts +196 -0
  49. package/dist/checker/context.js +35 -0
  50. package/dist/checker/control-flow.d.ts +24 -0
  51. package/dist/checker/control-flow.js +237 -0
  52. package/dist/checker/declarations.d.ts +26 -0
  53. package/dist/checker/declarations.js +259 -0
  54. package/dist/checker/decorator-exports.d.ts +5 -0
  55. package/dist/checker/decorator-exports.js +40 -0
  56. package/dist/checker/decorator-members.d.ts +28 -0
  57. package/dist/checker/decorator-members.js +140 -0
  58. package/dist/checker/decorator-wrappers.d.ts +20 -0
  59. package/dist/checker/decorator-wrappers.js +132 -0
  60. package/dist/checker/decorators.d.ts +28 -0
  61. package/dist/checker/decorators.js +265 -0
  62. package/dist/checker/dom-svg.d.ts +7 -0
  63. package/dist/checker/dom-svg.js +19 -0
  64. package/dist/checker/dom.d.ts +22 -0
  65. package/dist/checker/dom.js +361 -0
  66. package/dist/checker/expressions.d.ts +32 -0
  67. package/dist/checker/expressions.js +244 -0
  68. package/dist/checker/flow.d.ts +18 -0
  69. package/dist/checker/flow.js +134 -0
  70. package/dist/checker/forwarding.d.ts +15 -0
  71. package/dist/checker/forwarding.js +78 -0
  72. package/dist/checker/functions.d.ts +24 -0
  73. package/dist/checker/functions.js +154 -0
  74. package/dist/checker/go-for.d.ts +12 -0
  75. package/dist/checker/go-for.js +93 -0
  76. package/dist/checker/goroutines.d.ts +19 -0
  77. package/dist/checker/goroutines.js +110 -0
  78. package/dist/checker/helpers.d.ts +35 -0
  79. package/dist/checker/helpers.js +162 -0
  80. package/dist/checker/imports.d.ts +7 -0
  81. package/dist/checker/imports.js +83 -0
  82. package/dist/checker/initializers.d.ts +22 -0
  83. package/dist/checker/initializers.js +104 -0
  84. package/dist/checker/iterables.d.ts +5 -0
  85. package/dist/checker/iterables.js +17 -0
  86. package/dist/checker/iterators.d.ts +13 -0
  87. package/dist/checker/iterators.js +95 -0
  88. package/dist/checker/loops.d.ts +10 -0
  89. package/dist/checker/loops.js +82 -0
  90. package/dist/checker/markup.d.ts +28 -0
  91. package/dist/checker/markup.js +220 -0
  92. package/dist/checker/members.d.ts +29 -0
  93. package/dist/checker/members.js +233 -0
  94. package/dist/checker/operators.d.ts +13 -0
  95. package/dist/checker/operators.js +177 -0
  96. package/dist/checker/promise.d.ts +17 -0
  97. package/dist/checker/promise.js +49 -0
  98. package/dist/checker/refs.d.ts +26 -0
  99. package/dist/checker/refs.js +136 -0
  100. package/dist/checker/resolution.d.ts +23 -0
  101. package/dist/checker/resolution.js +173 -0
  102. package/dist/checker/statements.d.ts +28 -0
  103. package/dist/checker/statements.js +212 -0
  104. package/dist/checker/styles.d.ts +14 -0
  105. package/dist/checker/styles.js +49 -0
  106. package/dist/checker/transfer.d.ts +5 -0
  107. package/dist/checker/transfer.js +83 -0
  108. package/dist/checker/types/bytes.d.ts +4 -0
  109. package/dist/checker/types/bytes.js +51 -0
  110. package/dist/checker/types/classes.d.ts +22 -0
  111. package/dist/checker/types/classes.js +93 -0
  112. package/dist/checker/types/constructors.d.ts +27 -0
  113. package/dist/checker/types/constructors.js +129 -0
  114. package/dist/checker/types/generics.d.ts +20 -0
  115. package/dist/checker/types/generics.js +75 -0
  116. package/dist/checker/types/lazy.d.ts +30 -0
  117. package/dist/checker/types/lazy.js +92 -0
  118. package/dist/checker/types/model.d.ts +149 -0
  119. package/dist/checker/types/model.js +15 -0
  120. package/dist/checker/types/params.d.ts +7 -0
  121. package/dist/checker/types/params.js +220 -0
  122. package/dist/checker/types/printing.d.ts +6 -0
  123. package/dist/checker/types/printing.js +109 -0
  124. package/dist/checker/types/relations.d.ts +16 -0
  125. package/dist/checker/types/relations.js +294 -0
  126. package/dist/checker/types.d.ts +9 -0
  127. package/dist/checker/types.js +10 -0
  128. package/dist/cli.d.ts +2 -0
  129. package/dist/cli.js +193 -0
  130. package/dist/codegen/analysis.d.ts +18 -0
  131. package/dist/codegen/analysis.js +144 -0
  132. package/dist/codegen/attributes.d.ts +40 -0
  133. package/dist/codegen/attributes.js +227 -0
  134. package/dist/codegen/calls.d.ts +22 -0
  135. package/dist/codegen/calls.js +106 -0
  136. package/dist/codegen/chan-helpers.d.ts +2 -0
  137. package/dist/codegen/chan-helpers.js +253 -0
  138. package/dist/codegen/component-helpers.d.ts +33 -0
  139. package/dist/codegen/component-helpers.js +18 -0
  140. package/dist/codegen/component-props.d.ts +42 -0
  141. package/dist/codegen/component-props.js +173 -0
  142. package/dist/codegen/component-values.d.ts +27 -0
  143. package/dist/codegen/component-values.js +146 -0
  144. package/dist/codegen/components.d.ts +53 -0
  145. package/dist/codegen/components.js +268 -0
  146. package/dist/codegen/control-flow.d.ts +25 -0
  147. package/dist/codegen/control-flow.js +152 -0
  148. package/dist/codegen/control-statements.d.ts +28 -0
  149. package/dist/codegen/control-statements.js +226 -0
  150. package/dist/codegen/creation.d.ts +31 -0
  151. package/dist/codegen/creation.js +113 -0
  152. package/dist/codegen/early-returns.d.ts +59 -0
  153. package/dist/codegen/early-returns.js +244 -0
  154. package/dist/codegen/element-helpers.d.ts +12 -0
  155. package/dist/codegen/element-helpers.js +54 -0
  156. package/dist/codegen/elements.d.ts +71 -0
  157. package/dist/codegen/elements.js +293 -0
  158. package/dist/codegen/emitter.d.ts +135 -0
  159. package/dist/codegen/emitter.js +296 -0
  160. package/dist/codegen/expressions.d.ts +49 -0
  161. package/dist/codegen/expressions.js +262 -0
  162. package/dist/codegen/functions.d.ts +28 -0
  163. package/dist/codegen/functions.js +170 -0
  164. package/dist/codegen/go-helpers.d.ts +9 -0
  165. package/dist/codegen/go-helpers.js +307 -0
  166. package/dist/codegen/helpers.d.ts +10 -0
  167. package/dist/codegen/helpers.js +356 -0
  168. package/dist/codegen/imported.d.ts +38 -0
  169. package/dist/codegen/imported.js +71 -0
  170. package/dist/codegen/js.d.ts +20 -0
  171. package/dist/codegen/js.js +113 -0
  172. package/dist/codegen/mutations.d.ts +10 -0
  173. package/dist/codegen/mutations.js +102 -0
  174. package/dist/codegen/parallel.d.ts +7 -0
  175. package/dist/codegen/parallel.js +63 -0
  176. package/dist/codegen/reactive.d.ts +95 -0
  177. package/dist/codegen/reactive.js +280 -0
  178. package/dist/codegen/refs.d.ts +62 -0
  179. package/dist/codegen/refs.js +160 -0
  180. package/dist/codegen/select-helpers.d.ts +2 -0
  181. package/dist/codegen/select-helpers.js +135 -0
  182. package/dist/codegen/simple-statements.d.ts +42 -0
  183. package/dist/codegen/simple-statements.js +253 -0
  184. package/dist/codegen/statements.d.ts +22 -0
  185. package/dist/codegen/statements.js +142 -0
  186. package/dist/codegen/styles.d.ts +54 -0
  187. package/dist/codegen/styles.js +157 -0
  188. package/dist/codegen/syntax.d.ts +18 -0
  189. package/dist/codegen/syntax.js +70 -0
  190. package/dist/codegen/thread-helpers.d.ts +2 -0
  191. package/dist/codegen/thread-helpers.js +198 -0
  192. package/dist/codegen/updates.d.ts +51 -0
  193. package/dist/codegen/updates.js +201 -0
  194. package/dist/codegen/web-components.d.ts +20 -0
  195. package/dist/codegen/web-components.js +149 -0
  196. package/dist/compile-file.d.ts +11 -0
  197. package/dist/compile-file.js +24 -0
  198. package/dist/compile.d.ts +53 -0
  199. package/dist/compile.js +187 -0
  200. package/dist/completion.d.ts +10 -0
  201. package/dist/completion.js +134 -0
  202. package/dist/config.d.ts +2 -0
  203. package/dist/config.js +44 -0
  204. package/dist/css/hash.d.ts +1 -0
  205. package/dist/css/hash.js +10 -0
  206. package/dist/css/parse.d.ts +42 -0
  207. package/dist/css/parse.js +138 -0
  208. package/dist/css/print.d.ts +9 -0
  209. package/dist/css/print.js +35 -0
  210. package/dist/css/selectors.d.ts +29 -0
  211. package/dist/css/selectors.js +168 -0
  212. package/dist/declarations.d.ts +3 -0
  213. package/dist/declarations.js +207 -0
  214. package/dist/decorator-copy.d.ts +18 -0
  215. package/dist/decorator-copy.js +158 -0
  216. package/dist/decorators.d.ts +61 -0
  217. package/dist/decorators.js +241 -0
  218. package/dist/diagnostics.d.ts +17 -0
  219. package/dist/diagnostics.js +22 -0
  220. package/dist/go-for.d.ts +26 -0
  221. package/dist/go-for.js +155 -0
  222. package/dist/goroutines.d.ts +37 -0
  223. package/dist/goroutines.js +253 -0
  224. package/dist/html-tag.d.ts +21 -0
  225. package/dist/html-tag.js +103 -0
  226. package/dist/index.d.ts +33 -0
  227. package/dist/index.js +55 -0
  228. package/dist/inline-packages.d.ts +32 -0
  229. package/dist/inline-packages.js +129 -0
  230. package/dist/iterators.d.ts +10 -0
  231. package/dist/iterators.js +33 -0
  232. package/dist/lexer/base.d.ts +24 -0
  233. package/dist/lexer/base.js +87 -0
  234. package/dist/lexer/lexer.d.ts +8 -0
  235. package/dist/lexer/lexer.js +134 -0
  236. package/dist/lexer/literals.d.ts +18 -0
  237. package/dist/lexer/literals.js +203 -0
  238. package/dist/lexer/markup.d.ts +10 -0
  239. package/dist/lexer/markup.js +93 -0
  240. package/dist/lexer/style.d.ts +17 -0
  241. package/dist/lexer/style.js +97 -0
  242. package/dist/lexer/tables.d.ts +53 -0
  243. package/dist/lexer/tables.js +101 -0
  244. package/dist/lexer/token.d.ts +42 -0
  245. package/dist/lexer/token.js +108 -0
  246. package/dist/loader.d.ts +1 -0
  247. package/dist/loader.js +50 -0
  248. package/dist/methods.d.ts +5 -0
  249. package/dist/methods.js +81 -0
  250. package/dist/modules.d.ts +3 -0
  251. package/dist/modules.js +49 -0
  252. package/dist/names.d.ts +23 -0
  253. package/dist/names.js +267 -0
  254. package/dist/parser/base.d.ts +96 -0
  255. package/dist/parser/base.js +202 -0
  256. package/dist/parser/classes.d.ts +8 -0
  257. package/dist/parser/classes.js +164 -0
  258. package/dist/parser/control-flow.d.ts +29 -0
  259. package/dist/parser/control-flow.js +232 -0
  260. package/dist/parser/declarations.d.ts +27 -0
  261. package/dist/parser/declarations.js +238 -0
  262. package/dist/parser/decorators.d.ts +30 -0
  263. package/dist/parser/decorators.js +176 -0
  264. package/dist/parser/expressions.d.ts +15 -0
  265. package/dist/parser/expressions.js +255 -0
  266. package/dist/parser/literals.d.ts +27 -0
  267. package/dist/parser/literals.js +206 -0
  268. package/dist/parser/markup.d.ts +22 -0
  269. package/dist/parser/markup.js +193 -0
  270. package/dist/parser/parser.d.ts +14 -0
  271. package/dist/parser/parser.js +22 -0
  272. package/dist/parser/simple-statements.d.ts +22 -0
  273. package/dist/parser/simple-statements.js +156 -0
  274. package/dist/parser/statements.d.ts +37 -0
  275. package/dist/parser/statements.js +267 -0
  276. package/dist/parser/syntax.d.ts +51 -0
  277. package/dist/parser/syntax.js +173 -0
  278. package/dist/parser/types.d.ts +23 -0
  279. package/dist/parser/types.js +218 -0
  280. package/dist/recursion.d.ts +25 -0
  281. package/dist/recursion.js +170 -0
  282. package/dist/refs.d.ts +49 -0
  283. package/dist/refs.js +210 -0
  284. package/dist/run.d.ts +1 -0
  285. package/dist/run.js +21 -0
  286. package/dist/source.d.ts +15 -0
  287. package/dist/source.js +34 -0
  288. package/dist/style-modules.d.ts +17 -0
  289. package/dist/style-modules.js +49 -0
  290. package/dist/styles.d.ts +36 -0
  291. package/dist/styles.js +160 -0
  292. package/dist/svg.d.ts +8 -0
  293. package/dist/svg.js +77 -0
  294. package/dist/ts-types.d.ts +11 -0
  295. package/dist/ts-types.js +133 -0
  296. package/dist/typed-arrays.d.ts +8 -0
  297. package/dist/typed-arrays.js +43 -0
  298. package/dist/typescript/convert-base.d.ts +42 -0
  299. package/dist/typescript/convert-base.js +135 -0
  300. package/dist/typescript/convert-objects.d.ts +28 -0
  301. package/dist/typescript/convert-objects.js +245 -0
  302. package/dist/typescript/convert.d.ts +14 -0
  303. package/dist/typescript/convert.js +67 -0
  304. package/dist/typescript/importer.d.ts +37 -0
  305. package/dist/typescript/importer.js +152 -0
  306. package/dist/typescript/library.d.ts +23 -0
  307. package/dist/typescript/library.js +81 -0
  308. package/dist/vite.d.ts +11 -0
  309. package/dist/vite.js +86 -0
  310. package/dist/walk-types.d.ts +4 -0
  311. package/dist/walk-types.js +56 -0
  312. package/dist/walk.d.ts +5 -0
  313. package/dist/walk.js +315 -0
  314. package/package.json +104 -4
@@ -0,0 +1,255 @@
1
+ import { BINARY_PRECEDENCE, isBinaryOperator, isUnaryOperator, RESERVED, describe, } from "./syntax.js";
2
+ import { TypeParser } from "./types.js";
3
+ // Expressions: operators with their precedence, member access, calls and indexing.
4
+ export class ExpressionParser extends TypeParser {
5
+ parseExpression() {
6
+ const test = this.parseBinary(1);
7
+ if (!this.accept('?'))
8
+ return test;
9
+ const consequent = this.parseExpression();
10
+ this.expect(':');
11
+ const alternate = this.parseExpression();
12
+ return {
13
+ kind: 'ConditionalExpression',
14
+ test,
15
+ consequent,
16
+ alternate,
17
+ start: test.start,
18
+ end: alternate.end,
19
+ };
20
+ }
21
+ /** Precedence climbing: parses operators that bind at least as tight as `minPrecedence`. */
22
+ parseBinary(minPrecedence) {
23
+ let left = this.parseUnary();
24
+ while (true) {
25
+ const operator = this.peek().kind;
26
+ // `value as Type` binds like a comparison, as in TypeScript.
27
+ if (this.checkWord('as') && minPrecedence <= BINARY_PRECEDENCE['<']) {
28
+ this.next();
29
+ const type = this.parseType();
30
+ left = { kind: 'AsExpression', expression: left, type, start: left.start, end: type.end };
31
+ continue;
32
+ }
33
+ if (!isBinaryOperator(operator))
34
+ return left;
35
+ const precedence = BINARY_PRECEDENCE[operator];
36
+ if (precedence < minPrecedence)
37
+ return left;
38
+ this.next();
39
+ // `**` is right-associative, all other binary operators are left-associative.
40
+ const right = this.parseBinary(operator === '**' ? precedence : precedence + 1);
41
+ left = this.makeBinary(operator, left, right);
42
+ }
43
+ }
44
+ /** Rejects combinations that JS forbids without parentheses, since the output must be valid JS. */
45
+ makeBinary(operator, left, right) {
46
+ if (operator === '??') {
47
+ for (const operand of [left, right]) {
48
+ if (operand.kind === 'BinaryExpression' &&
49
+ (operand.operator === '||' || operand.operator === '&&') &&
50
+ !this.parenthesized.has(operand)) {
51
+ this.error('"??" cannot be mixed with "||" or "&&" without parentheses', operand.start, operand.end);
52
+ }
53
+ }
54
+ }
55
+ if (operator === '**' && left.kind === 'UnaryExpression' && !this.parenthesized.has(left)) {
56
+ this.error('wrap the unary expression in parentheses: "(-a) ** b" or "-(a ** b)"', left.start, left.end);
57
+ }
58
+ return { kind: 'BinaryExpression', operator, left, right, start: left.start, end: right.end };
59
+ }
60
+ parseUnary() {
61
+ const token = this.peek();
62
+ if (isUnaryOperator(token.kind)) {
63
+ const operator = token.kind;
64
+ if (operator === 'await' || operator === '<-') {
65
+ this.requireAsync(operator, token.start, token.end);
66
+ }
67
+ this.next();
68
+ const argument = this.parseUnary();
69
+ return { kind: 'UnaryExpression', operator, argument, start: token.start, end: argument.end };
70
+ }
71
+ if (token.kind === '++' || token.kind === '--') {
72
+ this.fail(`"${token.kind}" must follow the variable: "i${token.kind}"`);
73
+ }
74
+ if (token.kind === 'go') {
75
+ this.next();
76
+ if (this.check('for')) {
77
+ this.fail('"go for" is a statement: it waits for its parts and gives no value');
78
+ }
79
+ const call = this.parsePostfix(this.parsePrimary());
80
+ if (call.kind !== 'CallExpression' || call.optional) {
81
+ this.failAt('"go" needs a call of a function, e.g. "go work(x)"', call.start, call.end);
82
+ }
83
+ return { kind: 'GoExpression', call, start: token.start, end: call.end };
84
+ }
85
+ return this.parsePostfix(this.parsePrimary());
86
+ }
87
+ /** `make([]float64` starts a `make`: an array literal is not followed by a name. */
88
+ isMake() {
89
+ return (this.checkWord('make') &&
90
+ this.peek(1).kind === '(' &&
91
+ this.peek(2).kind === '[' &&
92
+ this.peek(3).kind === ']' &&
93
+ this.peek(4).kind === 'Identifier');
94
+ }
95
+ /** Member access, indexing and calls: `a.b`, `a?.b`, `a[i]`, `a?.[i]`, `f(x)`, `f?.(x)`. */
96
+ parsePostfix(expression) {
97
+ while (true) {
98
+ const start = expression.start;
99
+ if (this.accept('.')) {
100
+ const property = this.parsePropertyName();
101
+ expression = {
102
+ kind: 'MemberExpression',
103
+ object: expression,
104
+ property,
105
+ optional: false,
106
+ ...this.span(start),
107
+ };
108
+ }
109
+ else if (this.accept('?.')) {
110
+ if (this.check('(')) {
111
+ const args = this.parseArguments();
112
+ expression = {
113
+ kind: 'CallExpression',
114
+ callee: expression,
115
+ arguments: args,
116
+ optional: true,
117
+ ...this.span(start),
118
+ };
119
+ }
120
+ else if (this.accept('[')) {
121
+ const index = this.nested(() => this.parseExpression());
122
+ this.expect(']');
123
+ expression = {
124
+ kind: 'IndexExpression',
125
+ object: expression,
126
+ index,
127
+ optional: true,
128
+ ...this.span(start),
129
+ };
130
+ }
131
+ else {
132
+ const property = this.parsePropertyName();
133
+ expression = {
134
+ kind: 'MemberExpression',
135
+ object: expression,
136
+ property,
137
+ optional: true,
138
+ ...this.span(start),
139
+ };
140
+ }
141
+ }
142
+ else if (this.check('(')) {
143
+ const args = this.parseArguments();
144
+ expression = {
145
+ kind: 'CallExpression',
146
+ callee: expression,
147
+ arguments: args,
148
+ optional: false,
149
+ ...this.span(start),
150
+ };
151
+ }
152
+ else if (this.accept('[')) {
153
+ const index = this.nested(() => this.parseExpression());
154
+ this.expect(']');
155
+ expression = {
156
+ kind: 'IndexExpression',
157
+ object: expression,
158
+ index,
159
+ optional: false,
160
+ ...this.span(start),
161
+ };
162
+ }
163
+ else {
164
+ return expression;
165
+ }
166
+ }
167
+ }
168
+ parsePrimary() {
169
+ const token = this.peek();
170
+ const { start, end } = token;
171
+ switch (token.kind) {
172
+ case 'Identifier':
173
+ if (this.peek(1).kind === '=>')
174
+ return this.parseArrowFunction();
175
+ if (this.isDecoratorGet())
176
+ return this.parseDecoratorGet();
177
+ if (this.isMake())
178
+ return this.parseMake();
179
+ this.next();
180
+ return { kind: 'Identifier', name: token.text, start, end };
181
+ case 'Number':
182
+ this.next();
183
+ return { kind: 'NumberLiteral', value: token.value, raw: token.text, start, end };
184
+ case 'BigInt':
185
+ this.next();
186
+ return { kind: 'BigIntLiteral', raw: token.text, start, end };
187
+ case 'String':
188
+ return this.parseStringLiteral();
189
+ case 'Template':
190
+ case 'TemplateHead':
191
+ return this.parseTemplate(token);
192
+ case 'true':
193
+ case 'false':
194
+ this.next();
195
+ return { kind: 'BooleanLiteral', value: token.kind === 'true', start, end };
196
+ case 'null':
197
+ this.next();
198
+ return { kind: 'NullLiteral', start, end };
199
+ case 'this':
200
+ this.next();
201
+ return { kind: 'ThisExpression', start, end };
202
+ case 'super':
203
+ this.next();
204
+ if (!this.check('(') && !this.check('.'))
205
+ this.fail('"super" must be followed by "(" or "."');
206
+ return { kind: 'SuperExpression', start, end };
207
+ case '(':
208
+ return this.isArrowFunctionAhead() ? this.parseArrowFunction() : this.parseParenthesized();
209
+ // `[]byte("text")`: no array literal is followed by a name.
210
+ case '[':
211
+ return this.peek(1).kind === ']' && this.peek(2).kind === 'Identifier'
212
+ ? this.parseConversion()
213
+ : this.parseArrayLiteral();
214
+ case '{':
215
+ if (this.context.noObjectLiteral) {
216
+ this.fail('expected expression, found "{" (wrap object literals in parentheses here)');
217
+ }
218
+ return this.parseObjectLiteral();
219
+ case 'func':
220
+ return this.parseFuncExpression();
221
+ // `chan<number>(10)`: a new channel.
222
+ case 'chan': {
223
+ this.next();
224
+ this.expect('<', '"<": a channel is made as chan<T>(size), e.g. chan<number>(10)');
225
+ const element = this.parseType();
226
+ this.expectTypeClose('">" after the type of the values');
227
+ this.expect('(');
228
+ const size = this.check(')') ? null : this.nested(() => this.parseExpression());
229
+ this.expect(')');
230
+ return { kind: 'ChanExpression', element, size, ...this.span(start) };
231
+ }
232
+ case 'async': {
233
+ this.next();
234
+ const fn = this.check('func')
235
+ ? this.parseFuncExpression(true)
236
+ : (this.check('Identifier') && this.peek(1).kind === '=>') ||
237
+ (this.check('(') && this.isArrowFunctionAhead())
238
+ ? this.parseArrowFunction(true)
239
+ : this.fail('expected a function after "async": "async func(...) { ... }" or "async x => ..."');
240
+ fn.start = start;
241
+ return fn;
242
+ }
243
+ case 'new':
244
+ return this.parseNew();
245
+ case 'JsxTagOpen':
246
+ return this.parseJsxElement();
247
+ case '@':
248
+ return this.parseDecoratorMember();
249
+ default:
250
+ if (RESERVED.has(token.kind))
251
+ this.fail(`"${token.text}" is reserved for future use`);
252
+ return this.fail(`expected expression, found ${describe(token)}`);
253
+ }
254
+ }
255
+ }
@@ -0,0 +1,27 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { type StringToken, type TokenKind } from '../lexer/token.ts';
3
+ import { ExpressionParser } from './expressions.ts';
4
+ export declare abstract class LiteralParser extends ExpressionParser {
5
+ /** Whether the `(` at the current position opens arrow function parameters: `(...) =>`. */
6
+ protected isArrowFunctionAhead(): boolean;
7
+ protected parseArrowFunction(async?: boolean): ast.ArrowFunction;
8
+ protected parseParenthesized(): ast.Expression;
9
+ protected parseFuncExpression(async?: boolean): ast.FuncExpression;
10
+ protected parseNew(): ast.NewExpression;
11
+ protected parseArguments(): (ast.Expression | ast.SpreadElement)[];
12
+ /** An expression or `...spread` in array literals and call arguments. */
13
+ protected parseElement(): ast.Expression | ast.SpreadElement;
14
+ protected parseArrayLiteral(): ast.ArrayLiteral;
15
+ /** `make([]float64, n)` or `make([]float64, n, shared)`. */
16
+ protected parseMake(): ast.MakeExpression;
17
+ /** `[]byte("text")`: a type, then its value in parentheses. */
18
+ protected parseConversion(): ast.ConversionExpression;
19
+ protected parseObjectLiteral(): ast.ObjectLiteral;
20
+ protected parseProperty(): ast.Property | ast.SpreadElement;
21
+ protected parseTemplate(first: StringToken): ast.TemplateLiteral;
22
+ /** Parses `item, item, ...` up to `close`, which is consumed. A trailing comma is allowed. */
23
+ protected parseList<T>(close: TokenKind, parseItem: () => T): T[];
24
+ protected parseIdentifier(what?: string): ast.Identifier;
25
+ /** Names after `.`, object keys and member names, where keywords are allowed too. */
26
+ protected parsePropertyName(what?: string): ast.Identifier;
27
+ }
@@ -0,0 +1,206 @@
1
+ import { isKeyword } from "../lexer/token.js";
2
+ import { ExpressionParser } from "./expressions.js";
3
+ import { FUNCTION_BODY, describe, templateElement } from "./syntax.js";
4
+ // Functions, `new`, literals of arrays, objects and templates, names.
5
+ export class LiteralParser extends ExpressionParser {
6
+ /** Whether the `(` at the current position opens arrow function parameters: `(...) =>`. */
7
+ isArrowFunctionAhead() {
8
+ let depth = 0;
9
+ for (let i = this.pos; i < this.tokens.length; i++) {
10
+ const kind = this.tokens[i].kind;
11
+ if (kind === '(' || kind === '[' || kind === '{') {
12
+ depth++;
13
+ }
14
+ else if (kind === ')' || kind === ']' || kind === '}') {
15
+ depth--;
16
+ if (depth === 0)
17
+ return this.tokens[i + 1]?.kind === '=>';
18
+ }
19
+ else if (kind === 'EOF') {
20
+ return false;
21
+ }
22
+ }
23
+ return false;
24
+ }
25
+ parseArrowFunction(async = false) {
26
+ const start = this.peek().start;
27
+ let params;
28
+ if (this.check('Identifier')) {
29
+ const name = this.parseIdentifier();
30
+ params = [
31
+ {
32
+ kind: 'Parameter',
33
+ name,
34
+ type: null,
35
+ defaultValue: null,
36
+ start: name.start,
37
+ end: name.end,
38
+ },
39
+ ];
40
+ }
41
+ else {
42
+ params = this.parseParams(true);
43
+ }
44
+ this.expect('=>');
45
+ const body = this.withContext({ ...FUNCTION_BODY, inAsync: async }, () => this.check('{') ? this.parseBlock() : this.parseExpression());
46
+ return {
47
+ kind: 'ArrowFunction',
48
+ ...(async ? { async } : {}),
49
+ params,
50
+ body,
51
+ ...this.span(start),
52
+ };
53
+ }
54
+ parseParenthesized() {
55
+ this.expect('(');
56
+ const expression = this.nested(() => this.parseExpression());
57
+ this.expect(')');
58
+ this.parenthesized.add(expression);
59
+ return expression;
60
+ }
61
+ parseFuncExpression(async = false) {
62
+ const start = this.expect('func').start;
63
+ const params = this.parseParams(false);
64
+ const results = this.parseResults();
65
+ const body = this.parseFunctionBody(async);
66
+ return {
67
+ kind: 'FuncExpression',
68
+ ...(async ? { async } : {}),
69
+ params,
70
+ results,
71
+ body,
72
+ ...this.span(start),
73
+ };
74
+ }
75
+ parseNew() {
76
+ const start = this.expect('new').start;
77
+ // The class is a name or a member chain (`new ns.User()`); the parentheses are the arguments.
78
+ let callee = this.parsePrimary();
79
+ while (this.accept('.')) {
80
+ const property = this.parsePropertyName();
81
+ callee = {
82
+ kind: 'MemberExpression',
83
+ object: callee,
84
+ property,
85
+ optional: false,
86
+ ...this.span(callee.start),
87
+ };
88
+ }
89
+ const args = this.check('(') ? this.parseArguments() : [];
90
+ return { kind: 'NewExpression', callee, arguments: args, ...this.span(start) };
91
+ }
92
+ parseArguments() {
93
+ this.expect('(');
94
+ return this.nested(() => this.parseList(')', () => this.parseElement()));
95
+ }
96
+ /** An expression or `...spread` in array literals and call arguments. */
97
+ parseElement() {
98
+ if (!this.check('...'))
99
+ return this.parseExpression();
100
+ const start = this.next().start;
101
+ const argument = this.parseExpression();
102
+ return { kind: 'SpreadElement', argument, ...this.span(start) };
103
+ }
104
+ parseArrayLiteral() {
105
+ const start = this.expect('[').start;
106
+ const elements = this.nested(() => this.parseList(']', () => this.parseElement()));
107
+ return { kind: 'ArrayLiteral', elements, ...this.span(start) };
108
+ }
109
+ /** `make([]float64, n)` or `make([]float64, n, shared)`. */
110
+ parseMake() {
111
+ const start = this.next().start;
112
+ this.expect('(');
113
+ const [type, length, shared] = this.nested(() => {
114
+ const type = this.parseType();
115
+ this.expect(',', '"," and the length: e.g. make([]float64, 100)');
116
+ const length = this.parseExpression();
117
+ let shared = false;
118
+ if (this.accept(',') && !this.check(')')) {
119
+ if (!this.checkWord('shared')) {
120
+ this.fail('the third argument of make is the word shared: make([]float64, n, shared)');
121
+ }
122
+ this.next();
123
+ shared = true;
124
+ this.accept(',');
125
+ }
126
+ return [type, length, shared];
127
+ });
128
+ this.expect(')');
129
+ return { kind: 'MakeExpression', type, length, shared, ...this.span(start) };
130
+ }
131
+ /** `[]byte("text")`: a type, then its value in parentheses. */
132
+ parseConversion() {
133
+ const { start } = this.peek();
134
+ const type = this.parseType();
135
+ this.expect('(', '"(" after the type: e.g. []byte("text") gives the bytes of a string');
136
+ const argument = this.nested(() => this.parseExpression());
137
+ this.expect(')');
138
+ return { kind: 'ConversionExpression', type, argument, ...this.span(start) };
139
+ }
140
+ parseObjectLiteral() {
141
+ const start = this.expect('{').start;
142
+ const properties = this.nested(() => this.parseList('}', () => this.parseProperty()));
143
+ return { kind: 'ObjectLiteral', properties, ...this.span(start) };
144
+ }
145
+ parseProperty() {
146
+ const token = this.peek();
147
+ if (token.kind === '...')
148
+ return this.parseElement();
149
+ const key = token.kind === 'String' ? this.parseStringLiteral() : this.parsePropertyName();
150
+ if (this.accept(':')) {
151
+ const value = this.parseExpression();
152
+ return { kind: 'Property', key, value, shorthand: false, ...this.span(token.start) };
153
+ }
154
+ // Shorthand `{ name }` means `{ name: name }`, so the key must be a plain name.
155
+ if (key.kind !== 'Identifier' || token.kind !== 'Identifier') {
156
+ this.fail(`expected ":" after property name, found ${describe(this.peek())}`);
157
+ }
158
+ return { kind: 'Property', key, value: { ...key }, shorthand: true, ...this.span(token.start) };
159
+ }
160
+ parseTemplate(first) {
161
+ this.next();
162
+ const quasis = [templateElement(first)];
163
+ const expressions = [];
164
+ if (first.kind === 'TemplateHead') {
165
+ while (true) {
166
+ expressions.push(this.nested(() => this.parseExpression()));
167
+ const part = this.peek();
168
+ if (part.kind !== 'TemplateMiddle' && part.kind !== 'TemplateTail') {
169
+ this.fail(`expected "}" to close the template substitution, found ${describe(part)}`);
170
+ }
171
+ this.next();
172
+ quasis.push(templateElement(part));
173
+ if (part.kind === 'TemplateTail')
174
+ break;
175
+ }
176
+ }
177
+ return { kind: 'TemplateLiteral', quasis, expressions, ...this.span(first.start) };
178
+ }
179
+ /** Parses `item, item, ...` up to `close`, which is consumed. A trailing comma is allowed. */
180
+ parseList(close, parseItem) {
181
+ const items = [];
182
+ while (!this.check(close)) {
183
+ items.push(parseItem());
184
+ if (!this.accept(','))
185
+ break;
186
+ }
187
+ this.expect(close);
188
+ return items;
189
+ }
190
+ parseIdentifier(what = 'name') {
191
+ const token = this.peek();
192
+ if (token.kind !== 'Identifier')
193
+ this.fail(`expected ${what}, found ${describe(token)}`);
194
+ this.next();
195
+ return { kind: 'Identifier', name: token.text, start: token.start, end: token.end };
196
+ }
197
+ /** Names after `.`, object keys and member names, where keywords are allowed too. */
198
+ parsePropertyName(what = 'property name') {
199
+ const token = this.peek();
200
+ if (token.kind !== 'Identifier' && !isKeyword(token.kind)) {
201
+ this.fail(`expected ${what}, found ${describe(token)}`);
202
+ }
203
+ this.next();
204
+ return { kind: 'Identifier', name: token.text, start: token.start, end: token.end };
205
+ }
206
+ }
@@ -0,0 +1,22 @@
1
+ import type * as ast from '../ast.ts';
2
+ import { LiteralParser } from './literals.ts';
3
+ export declare abstract class MarkupParser extends LiteralParser {
4
+ /** `<tag attributes>children</tag>`, `<tag ... />` or a fragment `<>children</>`. */
5
+ protected parseJsxElement(): ast.ElementExpression;
6
+ private parseMarkup;
7
+ /** `<section.content />`: a tag with a dot is the value `section.content`. */
8
+ private tagValue;
9
+ protected parseJsxName(what: string): ast.Identifier;
10
+ protected parseJsxAttribute(): ast.JsxAttribute | ast.JsxSpreadAttribute;
11
+ /**
12
+ * The value of an `on*` attribute: a function is the handler itself; anything else is a list of
13
+ * statements to run on the event, e.g. `{count++}` or `{event.preventDefault(); send()}`.
14
+ */
15
+ protected parseEventHandler(): ast.Expression | ast.EventHandler;
16
+ /**
17
+ * `{expression}` or `{if ...}` / `{for ...}` / `{switch ...}` among element children; `null` for
18
+ * `{}` or `{/* comment *\/}`.
19
+ */
20
+ protected parseJsxExpressionContainer(): ast.JsxExpressionContainer | ast.JsxStatementContainer | null;
21
+ protected parseStringLiteral(what?: string): ast.StringLiteral;
22
+ }