pure-dango 1.8.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.
@@ -0,0 +1,157 @@
1
+ import {parseErrors} from "../../runtime/errors";
2
+ import {peek, next, parseExpression, OPERATORS} from "./main";
3
+
4
+ // returns true at closing parentheses, question marks, colons, and commas
5
+ export const stoppingCheck = (token : BaseToken, stopAtComma : boolean) : boolean =>
6
+ {
7
+ if (!token)
8
+ return true;
9
+
10
+ if (token.value === ")")
11
+ return true;
12
+
13
+ if (token.value === "?")
14
+ return true;
15
+
16
+ if (token.value === ":")
17
+ return true;
18
+
19
+ if (stopAtComma && token.value === ",")
20
+ return true;
21
+
22
+ return false;
23
+ };
24
+
25
+ const attachProperty = (node : ParserToken, token : BaseToken, tokens : Tokens, state : State) : ParserToken =>
26
+ {
27
+ next(tokens, state); // eat .
28
+ const property : BaseToken | null = next(tokens, state);
29
+ if (!property ||
30
+ !(property.type === "Identifier" || property.type === "Literal" || property.type === "StringLiteral")
31
+ )
32
+ throw new parseErrors.UnexpectedTokenError(property?.value, property?.row!, property?.column!);
33
+
34
+ if (peek(tokens, state)?.value === "(")
35
+ {
36
+ next(tokens, state); // eat (
37
+ const args = [];
38
+
39
+ while (peek(tokens, state) && peek(tokens, state).value !== ")")
40
+ {
41
+ if (peek(tokens, state)?.value === "...")
42
+ {
43
+ next(tokens, state);
44
+ const expression = parseExpression(tokens, 0, state, true);
45
+ args.push
46
+ (
47
+ {
48
+ type : "SpreadElement",
49
+ argument : expression,
50
+ row : token.row,
51
+ column : token.column
52
+ }
53
+ );
54
+ }
55
+ else
56
+ {
57
+ const argument = parseExpression(tokens, 0, state, true);
58
+ if (argument)
59
+ args.push(argument);
60
+ }
61
+
62
+ if (peek(tokens, state)?.value === ",")
63
+ next(tokens, state);
64
+ }
65
+
66
+ if (!peek(tokens, state) || peek(tokens, state).value !== ")")
67
+ throw new parseErrors.MissingTokenError(")", token.row, token.column);
68
+ next(tokens, state); // eat )
69
+
70
+ return {
71
+ type : "MethodCall",
72
+ object : node,
73
+ property : property.value,
74
+ args,
75
+ row : token.row,
76
+ column : token.column
77
+ };
78
+ }
79
+ else
80
+ {
81
+ return {
82
+ type : "MemberExpression",
83
+ object : node,
84
+ property : property.value,
85
+ row : token.row,
86
+ column : token.column
87
+ };
88
+ }
89
+ }
90
+
91
+ const attachAccess = (node : ParserToken, token : BaseToken, tokens : Tokens, state : State) : ParserToken =>
92
+ {
93
+ next(tokens, state); // eat [
94
+ const index = parseExpression(tokens, 0, state)!;
95
+
96
+ if (!peek(tokens, state) || peek(tokens, state).value !== "]")
97
+ throw new parseErrors.MissingTokenError("]", token.row, token.column);
98
+ next(tokens, state); // eat ]
99
+
100
+ return {
101
+ type : "ArrayAccess",
102
+ object : node,
103
+ index,
104
+ row : token.row,
105
+ column : token.column
106
+ }
107
+ }
108
+
109
+ // attaches parents to node
110
+ export const attach = (node : ParserToken, tokens : Tokens, state : State, stopAtComma : boolean) : ParserToken =>
111
+ {
112
+ let lastOperator : string | null = null;
113
+
114
+ while (true)
115
+ {
116
+ const token = peek(tokens, state);
117
+ if (stoppingCheck(token, stopAtComma))
118
+ break;
119
+
120
+ if (token.value === ".")
121
+ {
122
+ node = attachProperty(node, token, tokens, state);
123
+ continue;
124
+ }
125
+
126
+ if (token.value === "[")
127
+ {
128
+ node = attachAccess(node, token, tokens, state);
129
+ continue;
130
+ }
131
+
132
+ const info = OPERATORS[token.value];
133
+ if (!info || info.type !== "unary" || !(info.fix === "postfix" || info.fix === "both"))
134
+ break;
135
+
136
+ if ((lastOperator === "++" || lastOperator === "--") && (token.value === "++" || token.value === "--"))
137
+ throw new parseErrors.ChainedIncDecError(token.row, token.column);
138
+
139
+ if (node.type !== "VariableReference" && node.type !== "ArrayAccess" && node.type !== "MemberExpression")
140
+ throw new parseErrors.InvalidPostfixError(token.value, node.type, node.value, node.row, node.column);
141
+
142
+ const operator = next(tokens, state)!;
143
+
144
+ node =
145
+ {
146
+ type : "PostfixUnaryExpression",
147
+ operator : operator.value,
148
+ argument : node,
149
+ row : operator.row,
150
+ column : operator.column
151
+ };
152
+
153
+ lastOperator = operator.value;
154
+ }
155
+
156
+ return node;
157
+ }