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.
- package/LICENSE +201 -0
- package/NOTICE +12 -0
- package/README.md +255 -0
- package/dist/core/ast/annotations.d.ts +56 -0
- package/dist/core/ast/annotations.d.ts.map +1 -0
- package/dist/core/ast/annotations.js +27 -0
- package/dist/core/ast/annotations.js.map +1 -0
- package/dist/core/ast/build.d.ts +25 -0
- package/dist/core/ast/build.d.ts.map +1 -0
- package/dist/core/ast/build.js +26 -0
- package/dist/core/ast/build.js.map +1 -0
- package/dist/core/ast/children.d.ts +15 -0
- package/dist/core/ast/children.d.ts.map +1 -0
- package/dist/core/ast/children.js +103 -0
- package/dist/core/ast/children.js.map +1 -0
- package/dist/core/ast/expressions.d.ts +178 -0
- package/dist/core/ast/expressions.d.ts.map +1 -0
- package/dist/core/ast/expressions.js +50 -0
- package/dist/core/ast/expressions.js.map +1 -0
- package/dist/core/ast/header.d.ts +50 -0
- package/dist/core/ast/header.d.ts.map +1 -0
- package/dist/core/ast/header.js +2 -0
- package/dist/core/ast/header.js.map +1 -0
- package/dist/core/ast/index.d.ts +30 -0
- package/dist/core/ast/index.d.ts.map +1 -0
- package/dist/core/ast/index.js +21 -0
- package/dist/core/ast/index.js.map +1 -0
- package/dist/core/ast/name.d.ts +24 -0
- package/dist/core/ast/name.d.ts.map +1 -0
- package/dist/core/ast/name.js +2 -0
- package/dist/core/ast/name.js.map +1 -0
- package/dist/core/ast/node.d.ts +34 -0
- package/dist/core/ast/node.d.ts.map +1 -0
- package/dist/core/ast/node.js +70 -0
- package/dist/core/ast/node.js.map +1 -0
- package/dist/core/ast/script.d.ts +57 -0
- package/dist/core/ast/script.d.ts.map +1 -0
- package/dist/core/ast/script.js +2 -0
- package/dist/core/ast/script.js.map +1 -0
- package/dist/core/ast/statements.d.ts +161 -0
- package/dist/core/ast/statements.d.ts.map +1 -0
- package/dist/core/ast/statements.js +10 -0
- package/dist/core/ast/statements.js.map +1 -0
- package/dist/core/ast/walk.d.ts +39 -0
- package/dist/core/ast/walk.d.ts.map +1 -0
- package/dist/core/ast/walk.js +54 -0
- package/dist/core/ast/walk.js.map +1 -0
- package/dist/core/catalogue/catalogue.generated.d.ts +1590 -0
- package/dist/core/catalogue/catalogue.generated.d.ts.map +1 -0
- package/dist/core/catalogue/catalogue.generated.js +162 -0
- package/dist/core/catalogue/catalogue.generated.js.map +1 -0
- package/dist/core/catalogue/index.d.ts +15 -0
- package/dist/core/catalogue/index.d.ts.map +1 -0
- package/dist/core/catalogue/index.js +4 -0
- package/dist/core/catalogue/index.js.map +1 -0
- package/dist/core/catalogue/lookup.d.ts +14 -0
- package/dist/core/catalogue/lookup.d.ts.map +1 -0
- package/dist/core/catalogue/lookup.js +19 -0
- package/dist/core/catalogue/lookup.js.map +1 -0
- package/dist/core/catalogue/template.d.ts +15 -0
- package/dist/core/catalogue/template.d.ts.map +1 -0
- package/dist/core/catalogue/template.js +33 -0
- package/dist/core/catalogue/template.js.map +1 -0
- package/dist/core/catalogue/types.d.ts +34 -0
- package/dist/core/catalogue/types.d.ts.map +1 -0
- package/dist/core/catalogue/types.js +6 -0
- package/dist/core/catalogue/types.js.map +1 -0
- package/dist/core/catalogue/values.generated.d.ts +565 -0
- package/dist/core/catalogue/values.generated.d.ts.map +1 -0
- package/dist/core/catalogue/values.generated.js +6 -0
- package/dist/core/catalogue/values.generated.js.map +1 -0
- package/dist/core/diagnostics/collector.d.ts +46 -0
- package/dist/core/diagnostics/collector.d.ts.map +1 -0
- package/dist/core/diagnostics/collector.js +55 -0
- package/dist/core/diagnostics/collector.js.map +1 -0
- package/dist/core/diagnostics/diagnostic.d.ts +40 -0
- package/dist/core/diagnostics/diagnostic.d.ts.map +1 -0
- package/dist/core/diagnostics/diagnostic.js +29 -0
- package/dist/core/diagnostics/diagnostic.js.map +1 -0
- package/dist/core/diagnostics/index.d.ts +12 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -0
- package/dist/core/diagnostics/index.js +3 -0
- package/dist/core/diagnostics/index.js.map +1 -0
- package/dist/core/index.d.ts +28 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +22 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lex/blocks.d.ts +51 -0
- package/dist/core/lex/blocks.d.ts.map +1 -0
- package/dist/core/lex/blocks.js +56 -0
- package/dist/core/lex/blocks.js.map +1 -0
- package/dist/core/lex/characters.d.ts +38 -0
- package/dist/core/lex/characters.d.ts.map +1 -0
- package/dist/core/lex/characters.js +50 -0
- package/dist/core/lex/characters.js.map +1 -0
- package/dist/core/lex/comments.d.ts +50 -0
- package/dist/core/lex/comments.d.ts.map +1 -0
- package/dist/core/lex/comments.js +64 -0
- package/dist/core/lex/comments.js.map +1 -0
- package/dist/core/lex/index.d.ts +12 -0
- package/dist/core/lex/index.d.ts.map +1 -0
- package/dist/core/lex/index.js +12 -0
- package/dist/core/lex/index.js.map +1 -0
- package/dist/core/lex/layout.d.ts +40 -0
- package/dist/core/lex/layout.d.ts.map +1 -0
- package/dist/core/lex/layout.js +143 -0
- package/dist/core/lex/layout.js.map +1 -0
- package/dist/core/lex/lexer.d.ts +13 -0
- package/dist/core/lex/lexer.d.ts.map +1 -0
- package/dist/core/lex/lexer.js +419 -0
- package/dist/core/lex/lexer.js.map +1 -0
- package/dist/core/lex/numbers.d.ts +22 -0
- package/dist/core/lex/numbers.d.ts.map +1 -0
- package/dist/core/lex/numbers.js +58 -0
- package/dist/core/lex/numbers.js.map +1 -0
- package/dist/core/lex/statements.d.ts +24 -0
- package/dist/core/lex/statements.d.ts.map +1 -0
- package/dist/core/lex/statements.js +90 -0
- package/dist/core/lex/statements.js.map +1 -0
- package/dist/core/lex/strings.d.ts +27 -0
- package/dist/core/lex/strings.d.ts.map +1 -0
- package/dist/core/lex/strings.js +92 -0
- package/dist/core/lex/strings.js.map +1 -0
- package/dist/core/lex/unexpected.d.ts +31 -0
- package/dist/core/lex/unexpected.d.ts.map +1 -0
- package/dist/core/lex/unexpected.js +114 -0
- package/dist/core/lex/unexpected.js.map +1 -0
- package/dist/core/parse/annotations.d.ts +4 -0
- package/dist/core/parse/annotations.d.ts.map +1 -0
- package/dist/core/parse/annotations.js +49 -0
- package/dist/core/parse/annotations.js.map +1 -0
- package/dist/core/parse/blocks.d.ts +18 -0
- package/dist/core/parse/blocks.d.ts.map +1 -0
- package/dist/core/parse/blocks.js +47 -0
- package/dist/core/parse/blocks.js.map +1 -0
- package/dist/core/parse/branches.d.ts +17 -0
- package/dist/core/parse/branches.d.ts.map +1 -0
- package/dist/core/parse/branches.js +66 -0
- package/dist/core/parse/branches.js.map +1 -0
- package/dist/core/parse/cursor.d.ts +119 -0
- package/dist/core/parse/cursor.d.ts.map +1 -0
- package/dist/core/parse/cursor.js +305 -0
- package/dist/core/parse/cursor.js.map +1 -0
- package/dist/core/parse/expressions.d.ts +57 -0
- package/dist/core/parse/expressions.d.ts.map +1 -0
- package/dist/core/parse/expressions.js +373 -0
- package/dist/core/parse/expressions.js.map +1 -0
- package/dist/core/parse/functions.d.ts +16 -0
- package/dist/core/parse/functions.d.ts.map +1 -0
- package/dist/core/parse/functions.js +92 -0
- package/dist/core/parse/functions.js.map +1 -0
- package/dist/core/parse/index.d.ts +13 -0
- package/dist/core/parse/index.d.ts.map +1 -0
- package/dist/core/parse/index.js +13 -0
- package/dist/core/parse/index.js.map +1 -0
- package/dist/core/parse/loops.d.ts +13 -0
- package/dist/core/parse/loops.d.ts.map +1 -0
- package/dist/core/parse/loops.js +78 -0
- package/dist/core/parse/loops.js.map +1 -0
- package/dist/core/parse/names.d.ts +34 -0
- package/dist/core/parse/names.d.ts.map +1 -0
- package/dist/core/parse/names.js +122 -0
- package/dist/core/parse/names.js.map +1 -0
- package/dist/core/parse/script.d.ts +23 -0
- package/dist/core/parse/script.d.ts.map +1 -0
- package/dist/core/parse/script.js +55 -0
- package/dist/core/parse/script.js.map +1 -0
- package/dist/core/parse/statements.d.ts +14 -0
- package/dist/core/parse/statements.d.ts.map +1 -0
- package/dist/core/parse/statements.js +292 -0
- package/dist/core/parse/statements.js.map +1 -0
- package/dist/core/parse/switches.d.ts +16 -0
- package/dist/core/parse/switches.d.ts.map +1 -0
- package/dist/core/parse/switches.js +98 -0
- package/dist/core/parse/switches.js.map +1 -0
- package/dist/core/render/index.d.ts +10 -0
- package/dist/core/render/index.d.ts.map +1 -0
- package/dist/core/render/index.js +10 -0
- package/dist/core/render/index.js.map +1 -0
- package/dist/core/render/terminal.d.ts +11 -0
- package/dist/core/render/terminal.d.ts.map +1 -0
- package/dist/core/render/terminal.js +51 -0
- package/dist/core/render/terminal.js.map +1 -0
- package/dist/core/source/index.d.ts +7 -0
- package/dist/core/source/index.d.ts.map +1 -0
- package/dist/core/source/index.js +2 -0
- package/dist/core/source/index.js.map +1 -0
- package/dist/core/source/source.d.ts +41 -0
- package/dist/core/source/source.d.ts.map +1 -0
- package/dist/core/source/source.js +67 -0
- package/dist/core/source/source.js.map +1 -0
- package/dist/core/span/index.d.ts +3 -0
- package/dist/core/span/index.d.ts.map +1 -0
- package/dist/core/span/index.js +2 -0
- package/dist/core/span/index.js.map +1 -0
- package/dist/core/span/span.d.ts +67 -0
- package/dist/core/span/span.d.ts.map +1 -0
- package/dist/core/span/span.js +27 -0
- package/dist/core/span/span.js.map +1 -0
- package/dist/core/tokens/index.d.ts +8 -0
- package/dist/core/tokens/index.d.ts.map +1 -0
- package/dist/core/tokens/index.js +2 -0
- package/dist/core/tokens/index.js.map +1 -0
- package/dist/core/tokens/kind.d.ts +53 -0
- package/dist/core/tokens/kind.d.ts.map +1 -0
- package/dist/core/tokens/kind.js +94 -0
- package/dist/core/tokens/kind.js.map +1 -0
- package/dist/core/tokens/token.d.ts +36 -0
- package/dist/core/tokens/token.d.ts.map +1 -0
- package/dist/core/tokens/token.js +2 -0
- package/dist/core/tokens/token.js.map +1 -0
- package/package.json +52 -0
- package/spec/README.md +48 -0
- package/spec/errors.json +3204 -0
- package/src/core/ast/annotations.ts +68 -0
- package/src/core/ast/build.ts +35 -0
- package/src/core/ast/children.ts +110 -0
- package/src/core/ast/expressions.ts +254 -0
- package/src/core/ast/header.ts +53 -0
- package/src/core/ast/index.ts +102 -0
- package/src/core/ast/name.ts +24 -0
- package/src/core/ast/node.ts +120 -0
- package/src/core/ast/script.ts +60 -0
- package/src/core/ast/statements.ts +193 -0
- package/src/core/ast/walk.ts +67 -0
- package/src/core/catalogue/catalogue.generated.ts +171 -0
- package/src/core/catalogue/index.ts +20 -0
- package/src/core/catalogue/lookup.ts +23 -0
- package/src/core/catalogue/template.ts +38 -0
- package/src/core/catalogue/types.ts +37 -0
- package/src/core/catalogue/values.generated.ts +160 -0
- package/src/core/diagnostics/collector.ts +87 -0
- package/src/core/diagnostics/diagnostic.ts +72 -0
- package/src/core/diagnostics/index.ts +12 -0
- package/src/core/index.ts +146 -0
- package/src/core/lex/blocks.ts +92 -0
- package/src/core/lex/characters.ts +56 -0
- package/src/core/lex/comments.ts +75 -0
- package/src/core/lex/index.ts +11 -0
- package/src/core/lex/layout.ts +188 -0
- package/src/core/lex/lexer.ts +486 -0
- package/src/core/lex/numbers.ts +77 -0
- package/src/core/lex/statements.ts +94 -0
- package/src/core/lex/strings.ts +119 -0
- package/src/core/lex/unexpected.ts +125 -0
- package/src/core/parse/annotations.ts +60 -0
- package/src/core/parse/blocks.ts +52 -0
- package/src/core/parse/branches.ts +77 -0
- package/src/core/parse/cursor.ts +348 -0
- package/src/core/parse/expressions.ts +441 -0
- package/src/core/parse/functions.ts +109 -0
- package/src/core/parse/index.ts +12 -0
- package/src/core/parse/loops.ts +97 -0
- package/src/core/parse/names.ts +135 -0
- package/src/core/parse/script.ts +64 -0
- package/src/core/parse/statements.ts +329 -0
- package/src/core/parse/switches.ts +105 -0
- package/src/core/render/index.ts +9 -0
- package/src/core/render/terminal.ts +62 -0
- package/src/core/source/index.ts +6 -0
- package/src/core/source/source.ts +102 -0
- package/src/core/span/index.ts +2 -0
- package/src/core/span/span.ts +84 -0
- package/src/core/tokens/index.ts +15 -0
- package/src/core/tokens/kind.ts +123 -0
- package/src/core/tokens/token.ts +39 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { COMPARISON_OPERATORS, EQUALITY_OPERATORS, UNARY_OPERATORS, makeNode, } from '../ast/index.js';
|
|
2
|
+
import { spanning } from '../span/index.js';
|
|
3
|
+
import { describeToken } from './cursor.js';
|
|
4
|
+
import { atLabel, isMeantAsAName, takeLabel, takeMember, takeName } from './names.js';
|
|
5
|
+
/**
|
|
6
|
+
* The expression grammar, which is the precedence table of language.md 9.1 read
|
|
7
|
+
* from the bottom up.
|
|
8
|
+
*
|
|
9
|
+
* One function per level, in the order the table lists them, so the table can
|
|
10
|
+
* be checked against this file line by line. Precedence ends up in the shape of
|
|
11
|
+
* the tree rather than in a field, which is why nothing downstream ever has to
|
|
12
|
+
* know that `*` binds tighter than `+`.
|
|
13
|
+
*
|
|
14
|
+
* Two levels are deliberately not loops. Comparison and equality take at most
|
|
15
|
+
* one operator, because `a < b < c` has two plausible readings and the language
|
|
16
|
+
* refuses both (9.3). They are written as loops all the same, so that the
|
|
17
|
+
* second operator is reported as OS1008 with a caret on it and the expression
|
|
18
|
+
* still builds, rather than the parser stopping at a shape it cannot hold.
|
|
19
|
+
*/
|
|
20
|
+
const ADDITIVE = ['+', '-'];
|
|
21
|
+
const MULTIPLICATIVE = ['*', '/', '%'];
|
|
22
|
+
/** The tokens an expression can begin with, which is what tells two arguments apart. */
|
|
23
|
+
const STARTS_EXPRESSION = new Set([
|
|
24
|
+
'numberLiteral',
|
|
25
|
+
'stringLiteral',
|
|
26
|
+
'hexColor',
|
|
27
|
+
'identifier',
|
|
28
|
+
'true',
|
|
29
|
+
'false',
|
|
30
|
+
'none',
|
|
31
|
+
'(',
|
|
32
|
+
'[',
|
|
33
|
+
'-',
|
|
34
|
+
'+',
|
|
35
|
+
'not',
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Whether an expression can begin here, which is what tells one argument from
|
|
39
|
+
* the next and what keeps a list from reading a closing bracket as an item.
|
|
40
|
+
*
|
|
41
|
+
* A reserved word a reader meant as a name begins one too, because `parsePrimary`
|
|
42
|
+
* reads it as the name it was meant to be rather than leaving it where it sits.
|
|
43
|
+
*/
|
|
44
|
+
export function startsExpression(kind) {
|
|
45
|
+
return STARTS_EXPRESSION.has(kind) || isMeantAsAName(kind);
|
|
46
|
+
}
|
|
47
|
+
export function parseExpression(cursor) {
|
|
48
|
+
if (!cursor.deeper(cursor.token.span))
|
|
49
|
+
return missingExpression(cursor);
|
|
50
|
+
const expression = parseTernary(cursor);
|
|
51
|
+
cursor.shallower();
|
|
52
|
+
return expression;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* An expression in a position where a value is being tested rather than stored.
|
|
56
|
+
*
|
|
57
|
+
* `if x = 5` is the one typo the language is shaped to catch: assignment is a
|
|
58
|
+
* statement and never an expression (10.1), so there is no reading of the line
|
|
59
|
+
* that compiles, and OS1006 can name the fix instead of a type error arriving
|
|
60
|
+
* three stages later. The `==` is built as though the fix had been applied, so
|
|
61
|
+
* the rest of the file still checks.
|
|
62
|
+
*/
|
|
63
|
+
export function parseCondition(cursor) {
|
|
64
|
+
const condition = parseExpression(cursor);
|
|
65
|
+
const assign = cursor.take('=');
|
|
66
|
+
if (assign === undefined)
|
|
67
|
+
return condition;
|
|
68
|
+
cursor.report('OS1006', assign.span, {});
|
|
69
|
+
const right = parseExpression(cursor);
|
|
70
|
+
return makeNode('binary', spanning(condition.span, right.span), {
|
|
71
|
+
operator: '==',
|
|
72
|
+
left: condition,
|
|
73
|
+
right,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function parseTernary(cursor) {
|
|
77
|
+
const condition = parseOr(cursor);
|
|
78
|
+
const question = cursor.take('?');
|
|
79
|
+
if (question === undefined)
|
|
80
|
+
return condition;
|
|
81
|
+
const whenTrue = parseExpression(cursor);
|
|
82
|
+
if (cursor.take(':') === undefined) {
|
|
83
|
+
cursor.report('OS1015', question.span, {});
|
|
84
|
+
const hole = missingExpression(cursor);
|
|
85
|
+
return makeNode('ternary', spanning(condition.span, whenTrue.span), {
|
|
86
|
+
condition,
|
|
87
|
+
whenTrue,
|
|
88
|
+
whenFalse: hole,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Right associative (9.1): the false arm takes the rest of the line, so
|
|
92
|
+
// `x > 0 ? "up" : x < 0 ? "down" : "flat"` nests to the right.
|
|
93
|
+
const whenFalse = parseExpression(cursor);
|
|
94
|
+
return makeNode('ternary', spanning(condition.span, whenFalse.span), {
|
|
95
|
+
condition,
|
|
96
|
+
whenTrue,
|
|
97
|
+
whenFalse,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function parseOr(cursor) {
|
|
101
|
+
let left = parseAnd(cursor);
|
|
102
|
+
while (cursor.take('or') !== undefined) {
|
|
103
|
+
const right = parseAnd(cursor);
|
|
104
|
+
left = makeNode('binary', spanning(left.span, right.span), { operator: 'or', left, right });
|
|
105
|
+
}
|
|
106
|
+
return left;
|
|
107
|
+
}
|
|
108
|
+
function parseAnd(cursor) {
|
|
109
|
+
let left = parseEquality(cursor);
|
|
110
|
+
while (cursor.take('and') !== undefined) {
|
|
111
|
+
const right = parseEquality(cursor);
|
|
112
|
+
left = makeNode('binary', spanning(left.span, right.span), { operator: 'and', left, right });
|
|
113
|
+
}
|
|
114
|
+
return left;
|
|
115
|
+
}
|
|
116
|
+
function parseEquality(cursor) {
|
|
117
|
+
return parseUnchainable(cursor, EQUALITY_OPERATORS, parseComparison);
|
|
118
|
+
}
|
|
119
|
+
function parseComparison(cursor) {
|
|
120
|
+
return parseUnchainable(cursor, COMPARISON_OPERATORS, parseAdditive);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A level that takes at most one operator, and says so when it is given two.
|
|
124
|
+
*
|
|
125
|
+
* The chain is folded to the left after the report so that the tree holds
|
|
126
|
+
* everything the reader wrote. A parser that stopped here would leave the rest
|
|
127
|
+
* of the line unparsed, and the reader would fix the chain only to be told
|
|
128
|
+
* about the next mistake on the same line one compile later.
|
|
129
|
+
*/
|
|
130
|
+
function parseUnchainable(cursor, operators, next) {
|
|
131
|
+
let left = next(cursor);
|
|
132
|
+
let first;
|
|
133
|
+
let chained = false;
|
|
134
|
+
for (;;) {
|
|
135
|
+
const operator = operatorAt(cursor, operators);
|
|
136
|
+
if (operator === undefined)
|
|
137
|
+
return left;
|
|
138
|
+
const token = cursor.advance();
|
|
139
|
+
if (first !== undefined && !chained) {
|
|
140
|
+
chained = true;
|
|
141
|
+
cursor.report('OS1008', token.span, { op1: first, op2: operator });
|
|
142
|
+
}
|
|
143
|
+
first ??= operator;
|
|
144
|
+
const right = next(cursor);
|
|
145
|
+
left = makeNode('binary', spanning(left.span, right.span), { operator, left, right });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function parseAdditive(cursor) {
|
|
149
|
+
return parseLeftAssociative(cursor, ADDITIVE, parseMultiplicative);
|
|
150
|
+
}
|
|
151
|
+
function parseMultiplicative(cursor) {
|
|
152
|
+
return parseLeftAssociative(cursor, MULTIPLICATIVE, parseUnary);
|
|
153
|
+
}
|
|
154
|
+
function parseLeftAssociative(cursor, operators, next) {
|
|
155
|
+
let left = next(cursor);
|
|
156
|
+
for (;;) {
|
|
157
|
+
const operator = operatorAt(cursor, operators);
|
|
158
|
+
if (operator === undefined)
|
|
159
|
+
return left;
|
|
160
|
+
cursor.advance();
|
|
161
|
+
const right = next(cursor);
|
|
162
|
+
left = makeNode('binary', spanning(left.span, right.span), { operator, left, right });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Unary minus, plus and `not`, right associative.
|
|
167
|
+
*
|
|
168
|
+
* Section 19 writes this level as taking at most one operator. The prose wins:
|
|
169
|
+
* 9.1 calls it right associative, so `not not ready` and `- -x` are shapes the
|
|
170
|
+
* tree can hold and the checker can have an opinion about.
|
|
171
|
+
*/
|
|
172
|
+
function parseUnary(cursor) {
|
|
173
|
+
const operator = operatorAt(cursor, UNARY_OPERATORS);
|
|
174
|
+
if (operator === undefined)
|
|
175
|
+
return parsePostfix(cursor);
|
|
176
|
+
const token = cursor.advance();
|
|
177
|
+
if (!cursor.deeper(token.span))
|
|
178
|
+
return missingExpression(cursor);
|
|
179
|
+
const operand = parseUnary(cursor);
|
|
180
|
+
cursor.shallower();
|
|
181
|
+
return makeNode('unary', spanning(token.span, operand.span), { operator, operand });
|
|
182
|
+
}
|
|
183
|
+
/** A call, a history or element read, and a member, applied left to right. */
|
|
184
|
+
function parsePostfix(cursor) {
|
|
185
|
+
let target = parsePrimary(cursor);
|
|
186
|
+
for (;;) {
|
|
187
|
+
const before = cursor.position;
|
|
188
|
+
if (cursor.at('(')) {
|
|
189
|
+
const open = cursor.advance();
|
|
190
|
+
const args = parseBracketedList(cursor, open, parseArgument);
|
|
191
|
+
target = makeNode('call', spanning(target.span, args.end), {
|
|
192
|
+
callee: target,
|
|
193
|
+
args: args.items,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else if (cursor.at('[')) {
|
|
197
|
+
const open = cursor.advance();
|
|
198
|
+
const index = parseExpression(cursor);
|
|
199
|
+
const end = closeBracket(cursor, open);
|
|
200
|
+
target = makeNode('index', spanning(target.span, end), { target, index });
|
|
201
|
+
}
|
|
202
|
+
else if (cursor.at('.')) {
|
|
203
|
+
cursor.advance();
|
|
204
|
+
const member = takeMember(cursor);
|
|
205
|
+
target = makeNode('member', spanning(target.span, member.span), { object: target, member });
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
return target;
|
|
209
|
+
}
|
|
210
|
+
if (cursor.position === before)
|
|
211
|
+
return target;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function parsePrimary(cursor) {
|
|
215
|
+
const token = cursor.token;
|
|
216
|
+
switch (token.kind) {
|
|
217
|
+
case 'numberLiteral':
|
|
218
|
+
cursor.advance();
|
|
219
|
+
return makeNode('numberLiteral', token.span, { value: token.value });
|
|
220
|
+
case 'stringLiteral':
|
|
221
|
+
cursor.advance();
|
|
222
|
+
return makeNode('stringLiteral', token.span, { value: token.value });
|
|
223
|
+
case 'true':
|
|
224
|
+
case 'false':
|
|
225
|
+
cursor.advance();
|
|
226
|
+
return makeNode('booleanLiteral', token.span, { value: token.kind === 'true' });
|
|
227
|
+
case 'none':
|
|
228
|
+
cursor.advance();
|
|
229
|
+
return makeNode('noneLiteral', token.span, {});
|
|
230
|
+
// Only `#rrggbb` and `#rrggbbaa`. A named colour is an ordinary global
|
|
231
|
+
// (3.8), so `aqua` arrives here as an identifier and leaves as a reference.
|
|
232
|
+
case 'hexColor':
|
|
233
|
+
cursor.advance();
|
|
234
|
+
return makeNode('colorLiteral', token.span, { text: token.text });
|
|
235
|
+
case 'identifier':
|
|
236
|
+
cursor.advance();
|
|
237
|
+
return makeNode('nameReference', token.span, { name: token.text });
|
|
238
|
+
case '(': {
|
|
239
|
+
cursor.advance();
|
|
240
|
+
const inner = parseExpression(cursor);
|
|
241
|
+
const end = closeBracket(cursor, token);
|
|
242
|
+
return makeNode('grouping', spanning(token.span, end), { expression: inner });
|
|
243
|
+
}
|
|
244
|
+
case '[': {
|
|
245
|
+
cursor.advance();
|
|
246
|
+
const elements = parseBracketedList(cursor, token, parseExpression);
|
|
247
|
+
return makeNode('arrayLiteral', spanning(token.span, elements.end), {
|
|
248
|
+
elements: elements.items,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
default:
|
|
252
|
+
// A reserved word where a value belongs is the name the reader meant, and
|
|
253
|
+
// OS1019 says the language has taken the word. The word is taken here as
|
|
254
|
+
// well as reported on: a rule that reports and then consumes nothing
|
|
255
|
+
// leaves the list and the bracket above it looking at the token it could
|
|
256
|
+
// not read, and the next thing the reader is told is that a bracket they
|
|
257
|
+
// plainly closed was never closed.
|
|
258
|
+
if (isMeantAsAName(token.kind)) {
|
|
259
|
+
const name = takeName(cursor);
|
|
260
|
+
return makeNode('nameReference', name.span, { name: name.text });
|
|
261
|
+
}
|
|
262
|
+
return expressionExpected(cursor);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** One argument, with the label of a named one when there is a label. */
|
|
266
|
+
function parseArgument(cursor) {
|
|
267
|
+
if (!atLabel(cursor)) {
|
|
268
|
+
const bare = parseExpression(cursor);
|
|
269
|
+
return makeNode('argument', bare.span, { label: undefined, value: bare });
|
|
270
|
+
}
|
|
271
|
+
const label = takeLabel(cursor);
|
|
272
|
+
cursor.advance();
|
|
273
|
+
const value = parseExpression(cursor);
|
|
274
|
+
return makeNode('argument', spanning(label.span, value.span), { label, value });
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* A comma separated list inside brackets: an argument list or an array literal.
|
|
278
|
+
*
|
|
279
|
+
* The two shapes are one function because their recovery is the same and has to
|
|
280
|
+
* stay the same: a missing comma is OS1014 and the list carries on, and a list
|
|
281
|
+
* that runs to the end of the line without a closer is the bracket's own error
|
|
282
|
+
* rather than one per item.
|
|
283
|
+
*/
|
|
284
|
+
export function parseBracketedList(cursor, open, parseItem) {
|
|
285
|
+
const items = [];
|
|
286
|
+
for (;;) {
|
|
287
|
+
if (atListEnd(cursor))
|
|
288
|
+
break;
|
|
289
|
+
const before = cursor.position;
|
|
290
|
+
items.push(parseItem(cursor));
|
|
291
|
+
const comma = cursor.take(',');
|
|
292
|
+
if (comma !== undefined) {
|
|
293
|
+
if (!atListEnd(cursor))
|
|
294
|
+
continue;
|
|
295
|
+
// A comma promises another item (3.11 continues the line for one), so a
|
|
296
|
+
// list that ends on one has lost it rather than written an empty slot.
|
|
297
|
+
cursor.report('OS1022', cursor.holeSpan(), { token: describeToken(comma) });
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
if (atListEnd(cursor))
|
|
301
|
+
break;
|
|
302
|
+
// The item read nothing, so it has reported its own hole and the token it
|
|
303
|
+
// could not read is still here. Taking it carries the list on to the item
|
|
304
|
+
// after it and, more importantly, to the closing bracket: a list that
|
|
305
|
+
// stopped here would hand the bracket a token that is not a closer, and the
|
|
306
|
+
// reader would be told the bracket was never closed on a line that closes
|
|
307
|
+
// it.
|
|
308
|
+
if (cursor.position === before) {
|
|
309
|
+
cursor.advance();
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
// What follows could not have begun a second item, so this is the closing
|
|
313
|
+
// bracket's mistake and not a missing comma.
|
|
314
|
+
if (!startsExpression(cursor.kind))
|
|
315
|
+
break;
|
|
316
|
+
cursor.report('OS1014', cursor.token.span, { token: describeToken(cursor.token) });
|
|
317
|
+
}
|
|
318
|
+
return { items, end: closeBracket(cursor, open) };
|
|
319
|
+
}
|
|
320
|
+
function atListEnd(cursor) {
|
|
321
|
+
return cursor.at(')') || cursor.at(']') || cursor.atStatementEnd();
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* The closing bracket, or the two ways it can be missing.
|
|
325
|
+
*
|
|
326
|
+
* OS1012 is reported at the opening bracket rather than at the end of the file,
|
|
327
|
+
* because an open bracket continues the statement onto every following line
|
|
328
|
+
* (3.11) and the mistake is where the bracket was opened.
|
|
329
|
+
*/
|
|
330
|
+
export function closeBracket(cursor, open) {
|
|
331
|
+
const expected = open.kind === '(' ? ')' : ']';
|
|
332
|
+
const closer = cursor.take(expected);
|
|
333
|
+
if (closer !== undefined)
|
|
334
|
+
return closer.span;
|
|
335
|
+
if (cursor.at(')') || cursor.at(']')) {
|
|
336
|
+
const found = cursor.advance();
|
|
337
|
+
cursor.report('OS1013', found.span, {
|
|
338
|
+
found: found.text,
|
|
339
|
+
expected,
|
|
340
|
+
opener: open.text,
|
|
341
|
+
line: open.span.line,
|
|
342
|
+
});
|
|
343
|
+
return found.span;
|
|
344
|
+
}
|
|
345
|
+
cursor.report('OS1012', open.span, { bracket: open.text, line: open.span.line });
|
|
346
|
+
return cursor.previous().span;
|
|
347
|
+
}
|
|
348
|
+
function expressionExpected(cursor) {
|
|
349
|
+
const hole = cursor.holeSpan();
|
|
350
|
+
cursor.report('OS1022', hole, {
|
|
351
|
+
token: describeToken(cursor.previousMeaningful() ?? cursor.token),
|
|
352
|
+
});
|
|
353
|
+
return makeNode('missingExpression', hole, {});
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The hole a rule leaves where an expression was required.
|
|
357
|
+
*
|
|
358
|
+
* The span is empty and sits where the expression should have been, so it never
|
|
359
|
+
* takes a caret meant for its neighbour, and everything downstream still has a
|
|
360
|
+
* tree to walk over a file that is being typed.
|
|
361
|
+
*/
|
|
362
|
+
export function missingExpression(cursor) {
|
|
363
|
+
return makeNode('missingExpression', cursor.holeSpan(), {});
|
|
364
|
+
}
|
|
365
|
+
function operatorAt(cursor, operators) {
|
|
366
|
+
const kind = cursor.kind;
|
|
367
|
+
return operators.includes(kind) ? kind : undefined;
|
|
368
|
+
}
|
|
369
|
+
/** An argument list, for the three statements that are a call in all but name. */
|
|
370
|
+
export function parseArgumentList(cursor, open) {
|
|
371
|
+
return parseBracketedList(cursor, open, parseArgument);
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=expressions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expressions.js","sourceRoot":"","sources":["../../../src/core/parse/expressions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FunctionDeclaration } from '../ast/index.js';
|
|
2
|
+
import type { Cursor } from './cursor.js';
|
|
3
|
+
/**
|
|
4
|
+
* `fn name(parameters) => body`, language.md 11.1.
|
|
5
|
+
*
|
|
6
|
+
* The body is an expression when it is written after the `=>` on one line, and
|
|
7
|
+
* a block when the `=>` ends the line. Both forms exist because the one line
|
|
8
|
+
* form needs the implicit return and an early exit needs the explicit one.
|
|
9
|
+
*
|
|
10
|
+
* The `=>` is two tokens. Section 3.12 does not list it among the punctuation,
|
|
11
|
+
* so it arrives as an `=` and a `>` that touch, and touching is what tells it
|
|
12
|
+
* from a comparison: the lexer suppresses its continuation rule for that exact
|
|
13
|
+
* pair, and the same adjacency test is what matches it here.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseFunctionDeclaration(cursor: Cursor): FunctionDeclaration;
|
|
16
|
+
//# sourceMappingURL=functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/core/parse/functions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,mBAAmB,EAAmB,MAAM,iBAAiB,CAAC;AAM/F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAsB5E"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { makeNode } from '../ast/index.js';
|
|
2
|
+
import { spanning } from '../span/index.js';
|
|
3
|
+
import { parseTypeAnnotation } from './annotations.js';
|
|
4
|
+
import { parseBlock } from './blocks.js';
|
|
5
|
+
import { parseBracketedList, parseExpression } from './expressions.js';
|
|
6
|
+
import { takeName } from './names.js';
|
|
7
|
+
import { finishStatement } from './statements.js';
|
|
8
|
+
/**
|
|
9
|
+
* `fn name(parameters) => body`, language.md 11.1.
|
|
10
|
+
*
|
|
11
|
+
* The body is an expression when it is written after the `=>` on one line, and
|
|
12
|
+
* a block when the `=>` ends the line. Both forms exist because the one line
|
|
13
|
+
* form needs the implicit return and an early exit needs the explicit one.
|
|
14
|
+
*
|
|
15
|
+
* The `=>` is two tokens. Section 3.12 does not list it among the punctuation,
|
|
16
|
+
* so it arrives as an `=` and a `>` that touch, and touching is what tells it
|
|
17
|
+
* from a comparison: the lexer suppresses its continuation rule for that exact
|
|
18
|
+
* pair, and the same adjacency test is what matches it here.
|
|
19
|
+
*/
|
|
20
|
+
export function parseFunctionDeclaration(cursor) {
|
|
21
|
+
const keyword = cursor.advance();
|
|
22
|
+
const name = takeName(cursor);
|
|
23
|
+
const open = cursor.take('(');
|
|
24
|
+
if (open === undefined)
|
|
25
|
+
cursor.unexpected(cursor.token);
|
|
26
|
+
const parameters = open === undefined ? [] : parseBracketedList(cursor, open, parseParameter).items;
|
|
27
|
+
const arrow = takeArrow(cursor);
|
|
28
|
+
if (arrow === undefined) {
|
|
29
|
+
return declaration(keyword, name, parameters, headerWithNoArrow(cursor, keyword));
|
|
30
|
+
}
|
|
31
|
+
if (!cursor.atStatementEnd()) {
|
|
32
|
+
const body = parseExpression(cursor);
|
|
33
|
+
finishStatement(cursor);
|
|
34
|
+
return declaration(keyword, name, parameters, body);
|
|
35
|
+
}
|
|
36
|
+
finishStatement(cursor);
|
|
37
|
+
return declaration(keyword, name, parameters, parseBlock(cursor, 'fn', keyword.span));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A parameter, which is an ordinary identifier and not a label.
|
|
41
|
+
*
|
|
42
|
+
* `fn f(color = red)` is OS1019, and `plot(v, "V", color = aqua)` is not: the
|
|
43
|
+
* body of a function refers to its parameters, and nothing ever refers to a
|
|
44
|
+
* label (language.md 3.4). `takeName` is the whole of that difference.
|
|
45
|
+
*/
|
|
46
|
+
function parseParameter(cursor) {
|
|
47
|
+
const name = takeName(cursor);
|
|
48
|
+
const annotation = cursor.take(':') !== undefined ? parseTypeAnnotation(cursor) : undefined;
|
|
49
|
+
const defaultValue = cursor.take('=') !== undefined ? parseExpression(cursor) : undefined;
|
|
50
|
+
const end = defaultValue?.span ?? annotation?.span ?? name.span;
|
|
51
|
+
return makeNode('parameter', spanning(name.span, end), { name, annotation, defaultValue });
|
|
52
|
+
}
|
|
53
|
+
/** The `=>` of 11.1: an `=` and a `>` written against each other. */
|
|
54
|
+
function takeArrow(cursor) {
|
|
55
|
+
const equals = cursor.token;
|
|
56
|
+
const greater = cursor.peek();
|
|
57
|
+
if (equals.kind !== '=' || greater.kind !== '>')
|
|
58
|
+
return undefined;
|
|
59
|
+
if (equals.span.offset + equals.span.length !== greater.span.offset)
|
|
60
|
+
return undefined;
|
|
61
|
+
cursor.advance();
|
|
62
|
+
return cursor.advance();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A header with no `=>`, which the catalogue has no code of its own for.
|
|
66
|
+
*
|
|
67
|
+
* What is reported is what is true. A token sitting where the arrow belongs is
|
|
68
|
+
* OS1018, whose fix names the operator that was meant to join the two halves. A
|
|
69
|
+
* header that simply ends is OS1010, because that is what it now is: a header
|
|
70
|
+
* with no body, since without the arrow the lexer opened no block under it.
|
|
71
|
+
*/
|
|
72
|
+
function headerWithNoArrow(cursor, keyword) {
|
|
73
|
+
if (!cursor.atStatementEnd()) {
|
|
74
|
+
cursor.unexpected(cursor.token);
|
|
75
|
+
const body = parseExpression(cursor);
|
|
76
|
+
finishStatement(cursor);
|
|
77
|
+
return body;
|
|
78
|
+
}
|
|
79
|
+
cursor.report('OS1010', keyword.span, { header: 'fn' });
|
|
80
|
+
finishStatement(cursor);
|
|
81
|
+
if (cursor.at('indent'))
|
|
82
|
+
return parseBlock(cursor, 'fn', keyword.span);
|
|
83
|
+
return makeNode('block', cursor.holeSpan(), { statements: [] });
|
|
84
|
+
}
|
|
85
|
+
function declaration(keyword, name, parameters, body) {
|
|
86
|
+
return makeNode('functionDeclaration', spanning(keyword.span, body.span), {
|
|
87
|
+
name,
|
|
88
|
+
parameters,
|
|
89
|
+
body,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/core/parse/functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The parser: tokens to a syntax tree, and a diagnostic for anything the
|
|
3
|
+
* grammar does not have a shape for.
|
|
4
|
+
*
|
|
5
|
+
* The whole of language.md section 19 lives behind this door, with the prose of
|
|
6
|
+
* sections 9 to 13 winning wherever the two disagree. What comes out is a tree
|
|
7
|
+
* for every file, including a file with mistakes in it: a parse error costs the
|
|
8
|
+
* statement it is on and nothing else, so an editor asking about a half typed
|
|
9
|
+
* line still gets a tree, and a compile reports every mistake in a file rather
|
|
10
|
+
* than the first one.
|
|
11
|
+
*/
|
|
12
|
+
export { parse, parseTokens } from './script.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/parse/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The parser: tokens to a syntax tree, and a diagnostic for anything the
|
|
3
|
+
* grammar does not have a shape for.
|
|
4
|
+
*
|
|
5
|
+
* The whole of language.md section 19 lives behind this door, with the prose of
|
|
6
|
+
* sections 9 to 13 winning wherever the two disagree. What comes out is a tree
|
|
7
|
+
* for every file, including a file with mistakes in it: a parse error costs the
|
|
8
|
+
* statement it is on and nothing else, so an editor asking about a half typed
|
|
9
|
+
* line still gets a tree, and a compile reports every mistake in a file rather
|
|
10
|
+
* than the first one.
|
|
11
|
+
*/
|
|
12
|
+
export { parse, parseTokens } from './script.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/parse/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ForInStatement, ForRangeStatement, WhileStatement } from '../ast/index.js';
|
|
2
|
+
import type { Cursor } from './cursor.js';
|
|
3
|
+
/**
|
|
4
|
+
* `for` and `while`, language.md 10.3 and 10.4.
|
|
5
|
+
*
|
|
6
|
+
* There are two loop forms and no third, so a header that is neither is OS1020
|
|
7
|
+
* rather than a cascade of smaller complaints: the message names the two shapes
|
|
8
|
+
* that exist, which is the only thing the reader needs. The body is read either
|
|
9
|
+
* way, so the lines under a header that was not understood are still checked.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseForStatement(cursor: Cursor): ForRangeStatement | ForInStatement;
|
|
12
|
+
export declare function parseWhileStatement(cursor: Cursor): WhileStatement;
|
|
13
|
+
//# sourceMappingURL=loops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loops.d.ts","sourceRoot":"","sources":["../../../src/core/parse/loops.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAK5G,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C;;;;;;;GAOG;AAEH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,cAAc,CA8BpF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAKlE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { makeNode } from '../ast/index.js';
|
|
2
|
+
import { spanning } from '../span/index.js';
|
|
3
|
+
import { parseBlock } from './blocks.js';
|
|
4
|
+
import { describeToken } from './cursor.js';
|
|
5
|
+
import { missingExpression, parseCondition, parseExpression } from './expressions.js';
|
|
6
|
+
import { takeName } from './names.js';
|
|
7
|
+
import { finishStatement } from './statements.js';
|
|
8
|
+
/**
|
|
9
|
+
* `for` and `while`, language.md 10.3 and 10.4.
|
|
10
|
+
*
|
|
11
|
+
* There are two loop forms and no third, so a header that is neither is OS1020
|
|
12
|
+
* rather than a cascade of smaller complaints: the message names the two shapes
|
|
13
|
+
* that exist, which is the only thing the reader needs. The body is read either
|
|
14
|
+
* way, so the lines under a header that was not understood are still checked.
|
|
15
|
+
*/
|
|
16
|
+
export function parseForStatement(cursor) {
|
|
17
|
+
const keyword = cursor.advance();
|
|
18
|
+
const variable = takeName(cursor);
|
|
19
|
+
if (cursor.take('in') !== undefined) {
|
|
20
|
+
const iterable = parseExpression(cursor);
|
|
21
|
+
const body = readBody(cursor, keyword);
|
|
22
|
+
return makeNode('forInStatement', spanning(keyword.span, body.span), {
|
|
23
|
+
variable,
|
|
24
|
+
iterable,
|
|
25
|
+
body,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (cursor.take('=') === undefined) {
|
|
29
|
+
incompleteHeader(cursor);
|
|
30
|
+
return range(cursor, keyword, variable, missingExpression(cursor), missingExpression(cursor));
|
|
31
|
+
}
|
|
32
|
+
const from = parseExpression(cursor);
|
|
33
|
+
if (cursor.take('to') === undefined) {
|
|
34
|
+
incompleteHeader(cursor);
|
|
35
|
+
return range(cursor, keyword, variable, from, missingExpression(cursor));
|
|
36
|
+
}
|
|
37
|
+
const to = parseExpression(cursor);
|
|
38
|
+
// A missing `step` is one rather than a node the reader did not write, so
|
|
39
|
+
// OS3004 on a step of zero always has a span to point at (10.3).
|
|
40
|
+
const step = cursor.take('step') !== undefined ? parseExpression(cursor) : undefined;
|
|
41
|
+
return range(cursor, keyword, variable, from, to, step);
|
|
42
|
+
}
|
|
43
|
+
export function parseWhileStatement(cursor) {
|
|
44
|
+
const keyword = cursor.advance();
|
|
45
|
+
const condition = parseCondition(cursor);
|
|
46
|
+
const body = readBody(cursor, keyword);
|
|
47
|
+
return makeNode('whileStatement', spanning(keyword.span, body.span), { condition, body });
|
|
48
|
+
}
|
|
49
|
+
function range(cursor, keyword, variable, from, to, step) {
|
|
50
|
+
const body = readBody(cursor, keyword);
|
|
51
|
+
return makeNode('forRangeStatement', spanning(keyword.span, body.span), {
|
|
52
|
+
variable,
|
|
53
|
+
from,
|
|
54
|
+
to,
|
|
55
|
+
step,
|
|
56
|
+
body,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The block under a loop header, with the loop counted while it is read.
|
|
61
|
+
*
|
|
62
|
+
* The count is what `break` and `continue` ask about, so it has to go up before
|
|
63
|
+
* the body is parsed and down after it, including on the paths where the header
|
|
64
|
+
* itself was not understood: a `break` inside a broken `for` is still inside a
|
|
65
|
+
* loop, and reporting OS1009 on it would be a second complaint about the first
|
|
66
|
+
* mistake.
|
|
67
|
+
*/
|
|
68
|
+
function readBody(cursor, keyword) {
|
|
69
|
+
finishStatement(cursor);
|
|
70
|
+
cursor.enterLoop();
|
|
71
|
+
const body = parseBlock(cursor, keyword.text, keyword.span);
|
|
72
|
+
cursor.leaveLoop();
|
|
73
|
+
return body;
|
|
74
|
+
}
|
|
75
|
+
function incompleteHeader(cursor) {
|
|
76
|
+
cursor.report('OS1020', cursor.token.span, { token: describeToken(cursor.token) });
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=loops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loops.js","sourceRoot":"","sources":["../../../src/core/parse/loops.ts"],"names":[],"mappings":"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"}
|