|
@@ -174,8 +174,6 @@ export default class Parser {
|
174
|
174
|
const name = this.eat(TokenTypes.LITERAL);
|
175
|
175
|
if (name instanceof ParserError) return name;
|
176
|
176
|
|
177
|
|
- const rules: AST.Rule[] = [];
|
178
|
|
-
|
179
|
177
|
const openParen = this.eat(TokenTypes.LPAREN);
|
180
|
178
|
if (openParen instanceof ParserError) return openParen;
|
181
|
179
|
|
|
@@ -190,18 +188,21 @@ export default class Parser {
|
190
|
188
|
const closeParen = this.eat(TokenTypes.RPAREN);
|
191
|
189
|
if (closeParen instanceof ParserError) return closeParen;
|
192
|
190
|
|
193
|
|
- while (this.currentToken().type === TokenTypes.PROPERTY) {
|
194
|
|
- const property = this.property();
|
195
|
|
- if (property instanceof ParserError) return property;
|
196
|
|
- const value = this.value();
|
197
|
|
- if (value instanceof ParserError) return value;
|
198
|
|
- rules.push(new AST.Rule(property, value));
|
|
191
|
+ const children: AST.Child[] = [];
|
|
192
|
+ while (
|
|
193
|
+ [TokenTypes.PROPERTY, TokenTypes.LPAREN].includes(
|
|
194
|
+ this.currentToken().type
|
|
195
|
+ )
|
|
196
|
+ ) {
|
|
197
|
+ const child = this.child();
|
|
198
|
+ if (child instanceof ParserError) return child;
|
|
199
|
+ children.push(child);
|
199
|
200
|
}
|
200
|
201
|
|
201
|
202
|
const rParen = this.eat(TokenTypes.RPAREN);
|
202
|
203
|
if (rParen instanceof ParserError) return rParen;
|
203
|
204
|
|
204
|
|
- return new AST.Mixin(name, parameters, rules);
|
|
205
|
+ return new AST.Mixin(name, parameters, children);
|
205
|
206
|
}
|
206
|
207
|
|
207
|
208
|
private application(): AST.Application | ParserError {
|
|
@@ -251,27 +252,9 @@ export default class Parser {
|
251
|
252
|
this.currentToken().type
|
252
|
253
|
)
|
253
|
254
|
) {
|
254
|
|
- if (this.currentToken().type === TokenTypes.PROPERTY) {
|
255
|
|
- const propertyToken = this.eat(TokenTypes.PROPERTY);
|
256
|
|
- if (propertyToken instanceof ParserError) return propertyToken;
|
257
|
|
-
|
258
|
|
- const property = new AST.Property(propertyToken);
|
259
|
|
-
|
260
|
|
- const value = this.value();
|
261
|
|
- if (value instanceof ParserError) return value;
|
262
|
|
-
|
263
|
|
- children.push(new AST.Rule(property, value));
|
264
|
|
- } else if (this.currentToken().type === TokenTypes.LPAREN) {
|
265
|
|
- if (this.nextToken().type === TokenTypes.LITERAL) {
|
266
|
|
- const ruleSet = this.ruleSet(selectors);
|
267
|
|
- if (ruleSet instanceof ParserError) return ruleSet;
|
268
|
|
- children.push(ruleSet);
|
269
|
|
- } else {
|
270
|
|
- const application = this.application();
|
271
|
|
- if (application instanceof ParserError) return application;
|
272
|
|
- children.push(application);
|
273
|
|
- }
|
274
|
|
- }
|
|
255
|
+ const child = this.child(selectors);
|
|
256
|
+ if (child instanceof ParserError) return child;
|
|
257
|
+ children.push(child);
|
275
|
258
|
}
|
276
|
259
|
|
277
|
260
|
const rParen = this.eat(TokenTypes.RPAREN);
|
|
@@ -323,6 +306,35 @@ export default class Parser {
|
323
|
306
|
return new AST.Selector(literal.value, parents);
|
324
|
307
|
}
|
325
|
308
|
|
|
309
|
+ private child(parents: AST.Selector[] = []): AST.Child | ParserError {
|
|
310
|
+ if (this.currentToken().type === TokenTypes.PROPERTY) {
|
|
311
|
+ const property = this.property();
|
|
312
|
+ if (property instanceof ParserError) return property;
|
|
313
|
+
|
|
314
|
+ const value = this.value();
|
|
315
|
+ if (value instanceof ParserError) return value;
|
|
316
|
+
|
|
317
|
+ return new AST.Rule(property, value);
|
|
318
|
+ } else if (this.currentToken().type === TokenTypes.LPAREN) {
|
|
319
|
+ if (this.nextToken().type === TokenTypes.LITERAL) {
|
|
320
|
+ const ruleSet = this.ruleSet(parents);
|
|
321
|
+ if (ruleSet instanceof ParserError) return ruleSet;
|
|
322
|
+ return ruleSet;
|
|
323
|
+ } else if (this.nextToken().type === TokenTypes.FUNCTION_NAME) {
|
|
324
|
+ const application = this.application();
|
|
325
|
+ if (application instanceof ParserError) return application;
|
|
326
|
+ return application;
|
|
327
|
+ }
|
|
328
|
+ }
|
|
329
|
+
|
|
330
|
+ return this.error(
|
|
331
|
+ `Unexpected ${
|
|
332
|
+ this.nextToken().type
|
|
333
|
+ }; expected literal or function/macro application`,
|
|
334
|
+ this.nextToken()
|
|
335
|
+ );
|
|
336
|
+ }
|
|
337
|
+
|
326
|
338
|
private eat(type: TokenTypes): Token | ParserError {
|
327
|
339
|
const token = this.currentToken();
|
328
|
340
|
if (type === token.type) {
|