Coverage Report

Created: 2022-03-15 07:22

/src/jsonnet/core/parser.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright 2015 Google Inc. All rights reserved.
3
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7
8
    http://www.apache.org/licenses/LICENSE-2.0
9
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16
17
#include <cassert>
18
#include <cmath>
19
#include <cstdlib>
20
21
#include <iomanip>
22
#include <list>
23
#include <memory>
24
#include <set>
25
#include <sstream>
26
#include <string>
27
28
#include "ast.h"
29
#include "desugarer.h"
30
#include "lexer.h"
31
#include "parser.h"
32
#include "static_error.h"
33
34
std::string jsonnet_unparse_number(double v)
35
2.64M
{
36
2.64M
    std::stringstream ss;
37
2.64M
    if (v == floor(v)) {
38
2.63M
        ss << std::fixed << std::setprecision(0) << v;
39
2.63M
    } else {
40
        // See "What Every Computer Scientist Should Know About Floating-Point Arithmetic"
41
        // Theorem 15
42
        // https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
43
5.70k
        ss << std::setprecision(17);
44
5.70k
        ss << v;
45
5.70k
    }
46
2.64M
    return ss.str();
47
2.64M
}
48
49
namespace {
50
51
static const Fodder EMPTY_FODDER;
52
53
static bool op_is_unary(const std::string &op, UnaryOp &uop)
54
385k
{
55
385k
    auto it = unary_map.find(op);
56
385k
    if (it == unary_map.end())
57
14
        return false;
58
385k
    uop = it->second;
59
385k
    return true;
60
385k
}
61
62
static bool op_is_binary(const std::string &op, BinaryOp &bop)
63
973k
{
64
973k
    auto it = binary_map.find(op);
65
973k
    if (it == binary_map.end())
66
15
        return false;
67
972k
    bop = it->second;
68
972k
    return true;
69
973k
}
70
71
LocationRange span(const Token &begin)
72
6.38M
{
73
6.38M
    return LocationRange(begin.location.file, begin.location.begin, begin.location.end);
74
6.38M
}
75
76
LocationRange span(const Token &begin, const Token &end)
77
1.02M
{
78
1.02M
    return LocationRange(begin.location.file, begin.location.begin, end.location.end);
79
1.02M
}
80
81
LocationRange span(const Token &begin, AST *end)
82
1.22M
{
83
1.22M
    return LocationRange(begin.location.file, begin.location.begin, end->location.end);
84
1.22M
}
85
86
/** Holds state while parsing a given token list.
87
 */
88
class Parser {
89
    // The private member functions are utilities for dealing with the token stream.
90
91
    StaticError unexpected(const Token &tok, const std::string &while_)
92
29
    {
93
29
        std::stringstream ss;
94
29
        ss << "unexpected: " << tok.kind << " while " << while_;
95
29
        return StaticError(tok.location, ss.str());
96
29
    }
97
98
    Token pop(void)
99
16.0M
    {
100
16.0M
        Token tok = peek();
101
16.0M
        tokens.pop_front();
102
16.0M
        return tok;
103
16.0M
    }
104
105
    void push(Token tok)
106
0
    {
107
0
        tokens.push_front(tok);
108
0
    }
109
110
    const Token &peek(void)
111
55.0M
    {
112
55.0M
        return tokens.front();
113
55.0M
    }
114
115
    /** Only call this is peek() is not an EOF token. */
116
    Token doublePeek(void)
117
1.02M
    {
118
1.02M
        Tokens::iterator it = tokens.begin();  // First one.
119
1.02M
        it++;                                  // Now pointing at the second one.
120
1.02M
        return *(it);
121
1.02M
    }
122
123
    Token popExpect(Token::Kind k, const char *data = nullptr)
124
985k
    {
125
985k
        Token tok = pop();
126
985k
        if (tok.kind != k) {
127
2
            std::stringstream ss;
128
2
            ss << "expected token " << k << " but got " << tok;
129
2
            throw StaticError(tok.location, ss.str());
130
2
        }
131
985k
        if (data != nullptr && tok.data != data) {
132
0
            std::stringstream ss;
133
0
            ss << "expected operator " << data << " but got " << tok.data;
134
0
            throw StaticError(tok.location, ss.str());
135
0
        }
136
985k
        return tok;
137
985k
    }
138
139
    std::list<Token> &tokens;
140
    Allocator *alloc;
141
142
   public:
143
865
    Parser(Tokens &tokens, Allocator *alloc) : tokens(tokens), alloc(alloc) {}
144
145
    /** Parse a comma-separated list of expressions.
146
     *
147
     * Allows an optional ending comma.
148
     * \param exprs Expressions added here.
149
     * \param end The token that ends the list (e.g. ] or )).
150
     * \param element_kind Used in error messages when a comma was not found.
151
     * \returns The last token (the one that matched parameter end).
152
     */
153
    Token parseArgs(ArgParams &args, const std::string &element_kind, bool &got_comma)
154
470k
    {
155
470k
        got_comma = false;
156
470k
        bool first = true;
157
1.90M
        do {
158
1.90M
            Token next = peek();
159
1.90M
            if (next.kind == Token::PAREN_R) {
160
                // got_comma can be true or false here.
161
470k
                return pop();
162
470k
            }
163
1.43M
            if (!first && !got_comma) {
164
5
                std::stringstream ss;
165
5
                ss << "expected a comma before next " << element_kind << ".";
166
5
                throw StaticError(next.location, ss.str());
167
5
            }
168
            // Either id=expr or id or expr, but note that expr could be id==1 so this needs
169
            // look-ahead.
170
1.43M
            Fodder id_fodder;
171
1.43M
            const Identifier *id = nullptr;
172
1.43M
            Fodder eq_fodder;
173
1.43M
            if (peek().kind == Token::IDENTIFIER) {
174
1.02M
                Token maybe_eq = doublePeek();
175
1.02M
                if (maybe_eq.kind == Token::OPERATOR && maybe_eq.data == "=") {
176
9.42k
                    id_fodder = peek().fodder;
177
9.42k
                    id = alloc->makeIdentifier(peek().data32());
178
9.42k
                    eq_fodder = maybe_eq.fodder;
179
9.42k
                    pop();  // id
180
9.42k
                    pop();  // eq
181
9.42k
                }
182
1.02M
            }
183
1.43M
            AST *expr = parse(MAX_PRECEDENCE);
184
1.43M
            got_comma = false;
185
1.43M
            first = false;
186
1.43M
            Fodder comma_fodder;
187
1.43M
            if (peek().kind == Token::COMMA) {
188
963k
                Token comma = pop();
189
963k
                comma_fodder = comma.fodder;
190
963k
                got_comma = true;
191
963k
            }
192
1.43M
            args.emplace_back(id_fodder, id, eq_fodder, expr, comma_fodder);
193
1.43M
        } while (true);
194
470k
    }
195
196
    ArgParams parseParams(const std::string &element_kind, bool &got_comma, Fodder &close_fodder)
197
108k
    {
198
108k
        ArgParams params;
199
108k
        Token paren_r = parseArgs(params, element_kind, got_comma);
200
201
        // Check they're all identifiers
202
        // parseArgs returns f(x) with x as an expression.  Convert it here.
203
258k
        for (auto &p : params) {
204
258k
            if (p.id == nullptr) {
205
250k
                if (p.expr->type != AST_VAR) {
206
0
                    throw StaticError(p.expr->location, "could not parse parameter here.");
207
0
                }
208
250k
                auto *pv = static_cast<Var *>(p.expr);
209
250k
                p.id = pv->id;
210
250k
                p.idFodder = pv->openFodder;
211
250k
                p.expr = nullptr;
212
250k
            }
213
258k
        }
214
215
108k
        close_fodder = paren_r.fodder;
216
217
108k
        return params;
218
108k
    }
219
220
    Token parseBind(Local::Binds &binds)
221
116k
    {
222
116k
        Token var_id = popExpect(Token::IDENTIFIER);
223
116k
        auto *id = alloc->makeIdentifier(var_id.data32());
224
116k
        for (const auto &bind : binds) {
225
16.4k
            if (bind.var == id)
226
0
                throw StaticError(var_id.location, "duplicate local var: " + var_id.data);
227
16.4k
        }
228
116k
        bool is_function = false;
229
116k
        ArgParams params;
230
116k
        bool trailing_comma = false;
231
116k
        Fodder fodder_l, fodder_r;
232
116k
        if (peek().kind == Token::PAREN_L) {
233
34.8k
            Token paren_l = pop();
234
34.8k
            fodder_l = paren_l.fodder;
235
34.8k
            params = parseParams("function parameter", trailing_comma, fodder_r);
236
34.8k
            is_function = true;
237
34.8k
        }
238
116k
        Token eq = popExpect(Token::OPERATOR, "=");
239
116k
        AST *body = parse(MAX_PRECEDENCE);
240
116k
        Token delim = pop();
241
116k
        binds.emplace_back(var_id.fodder,
242
116k
                           id,
243
116k
                           eq.fodder,
244
116k
                           body,
245
116k
                           is_function,
246
116k
                           fodder_l,
247
116k
                           params,
248
116k
                           trailing_comma,
249
116k
                           fodder_r,
250
116k
                           delim.fodder);
251
116k
        return delim;
252
116k
    }
253
254
    Token parseObjectRemainder(AST *&obj, const Token &tok)
255
138k
    {
256
138k
        ObjectFields fields;
257
138k
        std::set<std::string> literal_fields;  // For duplicate fields detection.
258
138k
        std::set<const Identifier *> binds;    // For duplicate locals detection.
259
260
138k
        bool got_comma = false;
261
138k
        bool first = true;
262
138k
        Token next = pop();
263
264
566k
        do {
265
566k
            if (next.kind == Token::BRACE_R) {
266
136k
                obj = alloc->make<Object>(
267
136k
                    span(tok, next), tok.fodder, fields, got_comma, next.fodder);
268
136k
                return next;
269
270
430k
            } else if (next.kind == Token::FOR) {
271
                // It's a comprehension
272
1.88k
                unsigned num_fields = 0;
273
1.88k
                unsigned num_asserts = 0;
274
1.88k
                const ObjectField *field_ptr = nullptr;
275
1.88k
                for (const auto &field : fields) {
276
1.88k
                    if (field.kind == ObjectField::LOCAL)
277
0
                        continue;
278
1.88k
                    if (field.kind == ObjectField::ASSERT) {
279
0
                        num_asserts++;
280
0
                        continue;
281
0
                    }
282
1.88k
                    field_ptr = &field;
283
1.88k
                    num_fields++;
284
1.88k
                }
285
1.88k
                if (num_asserts > 0) {
286
0
                    auto msg = "object comprehension cannot have asserts.";
287
0
                    throw StaticError(next.location, msg);
288
0
                }
289
1.88k
                if (num_fields != 1) {
290
0
                    auto msg = "object comprehension can only have one field.";
291
0
                    throw StaticError(next.location, msg);
292
0
                }
293
1.88k
                const ObjectField &field = *field_ptr;
294
295
1.88k
                if (field.hide != ObjectField::INHERIT) {
296
0
                    auto msg = "object comprehensions cannot have hidden fields.";
297
0
                    throw StaticError(next.location, msg);
298
0
                }
299
300
1.88k
                if (field.kind != ObjectField::FIELD_EXPR) {
301
0
                    auto msg = "object comprehensions can only have [e] fields.";
302
0
                    throw StaticError(next.location, msg);
303
0
                }
304
305
1.88k
                std::vector<ComprehensionSpec> specs;
306
1.88k
                Token last = parseComprehensionSpecs(Token::BRACE_R, next.fodder, specs);
307
1.88k
                obj = alloc->make<ObjectComprehension>(
308
1.88k
                    span(tok, last), tok.fodder, fields, got_comma, specs, last.fodder);
309
310
1.88k
                return last;
311
1.88k
            }
312
313
428k
            if (!got_comma && !first)
314
0
                throw StaticError(next.location, "expected a comma before next field.");
315
316
428k
            first = false;
317
428k
            got_comma = false;
318
319
428k
            switch (next.kind) {
320
2.76k
                case Token::BRACKET_L:
321
126k
                case Token::IDENTIFIER:
322
128k
                case Token::STRING_DOUBLE:
323
128k
                case Token::STRING_SINGLE:
324
130k
                case Token::STRING_BLOCK:
325
130k
                case Token::VERBATIM_STRING_DOUBLE:
326
130k
                case Token::VERBATIM_STRING_SINGLE: {
327
130k
                    ObjectField::Kind kind;
328
130k
                    AST *expr1 = nullptr;
329
130k
                    const Identifier *id = nullptr;
330
130k
                    Fodder fodder1, fodder2;
331
130k
                    LocationRange idLocation;
332
130k
                    if (next.kind == Token::IDENTIFIER) {
333
123k
                        fodder1 = next.fodder;
334
123k
                        kind = ObjectField::FIELD_ID;
335
123k
                        id = alloc->makeIdentifier(next.data32());
336
123k
                        idLocation = next.location;
337
123k
                    } else if (next.kind == Token::STRING_DOUBLE) {
338
1.76k
                        kind = ObjectField::FIELD_STR;
339
1.76k
                        expr1 = alloc->make<LiteralString>(next.location,
340
1.76k
                                                           next.fodder,
341
1.76k
                                                           next.data32(),
342
1.76k
                                                           LiteralString::DOUBLE,
343
1.76k
                                                           "",
344
1.76k
                                                           "");
345
4.46k
                    } else if (next.kind == Token::STRING_SINGLE) {
346
0
                        kind = ObjectField::FIELD_STR;
347
0
                        expr1 = alloc->make<LiteralString>(next.location,
348
0
                                                           next.fodder,
349
0
                                                           next.data32(),
350
0
                                                           LiteralString::SINGLE,
351
0
                                                           "",
352
0
                                                           "");
353
4.46k
                    } else if (next.kind == Token::STRING_BLOCK) {
354
1.70k
                        kind = ObjectField::FIELD_STR;
355
1.70k
                        expr1 = alloc->make<LiteralString>(next.location,
356
1.70k
                                                           next.fodder,
357
1.70k
                                                           next.data32(),
358
1.70k
                                                           LiteralString::BLOCK,
359
1.70k
                                                           next.stringBlockIndent,
360
1.70k
                                                           next.stringBlockTermIndent);
361
2.76k
                    } else if (next.kind == Token::VERBATIM_STRING_SINGLE) {
362
0
                        kind = ObjectField::FIELD_STR;
363
0
                        expr1 = alloc->make<LiteralString>(next.location,
364
0
                                                           next.fodder,
365
0
                                                           next.data32(),
366
0
                                                           LiteralString::VERBATIM_SINGLE,
367
0
                                                           "",
368
0
                                                           "");
369
2.76k
                    } else if (next.kind == Token::VERBATIM_STRING_DOUBLE) {
370
0
                        kind = ObjectField::FIELD_STR;
371
0
                        expr1 = alloc->make<LiteralString>(next.location,
372
0
                                                           next.fodder,
373
0
                                                           next.data32(),
374
0
                                                           LiteralString::VERBATIM_DOUBLE,
375
0
                                                           "",
376
0
                                                           "");
377
2.76k
                    } else {
378
2.76k
                        kind = ObjectField::FIELD_EXPR;
379
2.76k
                        fodder1 = next.fodder;
380
2.76k
                        expr1 = parse(MAX_PRECEDENCE);
381
2.76k
                        Token bracket_r = popExpect(Token::BRACKET_R);
382
2.76k
                        fodder2 = bracket_r.fodder;
383
2.76k
                    }
384
385
130k
                    bool is_method = false;
386
130k
                    bool meth_comma = false;
387
130k
                    ArgParams params;
388
130k
                    Fodder fodder_l;
389
130k
                    Fodder fodder_r;
390
130k
                    if (peek().kind == Token::PAREN_L) {
391
64.1k
                        Token paren_l = pop();
392
64.1k
                        fodder_l = paren_l.fodder;
393
64.1k
                        params = parseParams("method parameter", meth_comma, fodder_r);
394
64.1k
                        is_method = true;
395
64.1k
                    }
396
397
130k
                    bool plus_sugar = false;
398
399
130k
                    Token op = popExpect(Token::OPERATOR);
400
130k
                    const char *od = op.data.c_str();
401
130k
                    if (*od == '+') {
402
14.6k
                        plus_sugar = true;
403
14.6k
                        od++;
404
14.6k
                    }
405
130k
                    unsigned colons = 0;
406
304k
                    for (; *od != '\0'; ++od) {
407
174k
                        if (*od != ':') {
408
1
                            throw StaticError(
409
1
                                next.location,
410
1
                                "expected one of :, ::, :::, +:, +::, +:::, got: " + op.data);
411
1
                        }
412
174k
                        ++colons;
413
174k
                    }
414
130k
                    ObjectField::Hide field_hide;
415
130k
                    switch (colons) {
416
85.9k
                        case 1: field_hide = ObjectField::INHERIT; break;
417
418
44.2k
                        case 2: field_hide = ObjectField::HIDDEN; break;
419
420
0
                        case 3: field_hide = ObjectField::VISIBLE; break;
421
422
0
                        default:
423
0
                            throw StaticError(
424
0
                                next.location,
425
0
                                "expected one of :, ::, :::, +:, +::, +:::, got: " + op.data);
426
130k
                    }
427
428
                    // Basic checks for invalid Jsonnet code.
429
130k
                    if (is_method && plus_sugar) {
430
0
                        throw StaticError(next.location,
431
0
                                          "cannot use +: syntax sugar in a method: " + next.data);
432
0
                    }
433
130k
                    if (kind != ObjectField::FIELD_EXPR) {
434
127k
                        if (!literal_fields.insert(next.data).second) {
435
0
                            throw StaticError(next.location, "duplicate field: " + next.data);
436
0
                        }
437
127k
                    }
438
439
130k
                    AST *body = parse(MAX_PRECEDENCE);
440
441
130k
                    Fodder comma_fodder;
442
130k
                    next = pop();
443
130k
                    if (next.kind == Token::COMMA) {
444
77.6k
                        comma_fodder = next.fodder;
445
77.6k
                        next = pop();
446
77.6k
                        got_comma = true;
447
77.6k
                    }
448
130k
                    fields.emplace_back(kind,
449
130k
                                        fodder1,
450
130k
                                        fodder2,
451
130k
                                        fodder_l,
452
130k
                                        fodder_r,
453
130k
                                        field_hide,
454
130k
                                        plus_sugar,
455
130k
                                        is_method,
456
130k
                                        expr1,
457
130k
                                        id,
458
130k
                                        idLocation,
459
130k
                                        params,
460
130k
                                        meth_comma,
461
130k
                                        op.fodder,
462
130k
                                        body,
463
130k
                                        nullptr,
464
130k
                                        comma_fodder);
465
130k
                } break;
466
467
2.35k
                case Token::LOCAL: {
468
2.35k
                    Fodder local_fodder = next.fodder;
469
2.35k
                    Token var_id = popExpect(Token::IDENTIFIER);
470
2.35k
                    auto *id = alloc->makeIdentifier(var_id.data32());
471
472
2.35k
                    if (binds.find(id) != binds.end()) {
473
0
                        throw StaticError(var_id.location, "duplicate local var: " + var_id.data);
474
0
                    }
475
2.35k
                    bool is_method = false;
476
2.35k
                    bool func_comma = false;
477
2.35k
                    ArgParams params;
478
2.35k
                    Fodder paren_l_fodder;
479
2.35k
                    Fodder paren_r_fodder;
480
2.35k
                    if (peek().kind == Token::PAREN_L) {
481
471
                        Token paren_l = pop();
482
471
                        paren_l_fodder = paren_l.fodder;
483
471
                        is_method = true;
484
471
                        params = parseParams("function parameter", func_comma, paren_r_fodder);
485
471
                    }
486
2.35k
                    Token eq = popExpect(Token::OPERATOR, "=");
487
2.35k
                    AST *body = parse(MAX_PRECEDENCE);
488
2.35k
                    binds.insert(id);
489
490
2.35k
                    Fodder comma_fodder;
491
2.35k
                    next = pop();
492
2.35k
                    if (next.kind == Token::COMMA) {
493
2.35k
                        comma_fodder = next.fodder;
494
2.35k
                        next = pop();
495
2.35k
                        got_comma = true;
496
2.35k
                    }
497
2.35k
                    fields.push_back(ObjectField::Local(local_fodder,
498
2.35k
                                                        var_id.fodder,
499
2.35k
                                                        paren_l_fodder,
500
2.35k
                                                        paren_r_fodder,
501
2.35k
                                                        is_method,
502
2.35k
                                                        id,
503
2.35k
                                                        params,
504
2.35k
                                                        func_comma,
505
2.35k
                                                        eq.fodder,
506
2.35k
                                                        body,
507
2.35k
                                                        comma_fodder));
508
509
2.35k
                } break;
510
511
295k
                case Token::ASSERT: {
512
295k
                    Fodder assert_fodder = next.fodder;
513
295k
                    AST *cond = parse(MAX_PRECEDENCE);
514
295k
                    AST *msg = nullptr;
515
295k
                    Fodder colon_fodder;
516
295k
                    if (peek().kind == Token::OPERATOR && peek().data == ":") {
517
2
                        Token colon = pop();
518
2
                        colon_fodder = colon.fodder;
519
2
                        msg = parse(MAX_PRECEDENCE);
520
2
                    }
521
522
295k
                    Fodder comma_fodder;
523
295k
                    next = pop();
524
295k
                    if (next.kind == Token::COMMA) {
525
295k
                        comma_fodder = next.fodder;
526
295k
                        next = pop();
527
295k
                        got_comma = true;
528
295k
                    }
529
295k
                    fields.push_back(
530
295k
                        ObjectField::Assert(assert_fodder, cond, colon_fodder, msg, comma_fodder));
531
295k
                } break;
532
533
14
                default: throw unexpected(next, "parsing field definition");
534
428k
            }
535
536
428k
        } while (true);
537
138k
    }
538
539
    /** parses for x in expr for y in expr if expr for z in expr ... */
540
    Token parseComprehensionSpecs(Token::Kind end, Fodder for_fodder,
541
                                  std::vector<ComprehensionSpec> &specs)
542
14.6k
    {
543
15.5k
        while (true) {
544
15.5k
            LocationRange l;
545
15.5k
            Token id_token = popExpect(Token::IDENTIFIER);
546
15.5k
            const Identifier *id = alloc->makeIdentifier(id_token.data32());
547
15.5k
            Token in_token = popExpect(Token::IN);
548
15.5k
            AST *arr = parse(MAX_PRECEDENCE);
549
15.5k
            specs.emplace_back(
550
15.5k
                ComprehensionSpec::FOR, for_fodder, id_token.fodder, id, in_token.fodder, arr);
551
552
15.5k
            Token maybe_if = pop();
553
18.3k
            for (; maybe_if.kind == Token::IF; maybe_if = pop()) {
554
2.82k
                AST *cond = parse(MAX_PRECEDENCE);
555
2.82k
                specs.emplace_back(
556
2.82k
                    ComprehensionSpec::IF, maybe_if.fodder, Fodder{}, nullptr, Fodder{}, cond);
557
2.82k
            }
558
15.5k
            if (maybe_if.kind == end) {
559
14.6k
                return maybe_if;
560
14.6k
            }
561
943
            if (maybe_if.kind != Token::FOR) {
562
0
                std::stringstream ss;
563
0
                ss << "expected for, if or " << end << " after for clause, got: " << maybe_if;
564
0
                throw StaticError(maybe_if.location, ss.str());
565
0
            }
566
943
            for_fodder = maybe_if.fodder;
567
943
        }
568
14.6k
    }
569
570
    AST *parseTerminalBracketsOrUnary(void)
571
6.96M
    {
572
6.96M
        Token tok = pop();
573
6.96M
        switch (tok.kind) {
574
0
            case Token::ASSERT:
575
0
            case Token::BRACE_R:
576
0
            case Token::BRACKET_R:
577
4
            case Token::COMMA:
578
4
            case Token::DOT:
579
4
            case Token::ELSE:
580
4
            case Token::ERROR:
581
4
            case Token::FOR:
582
4
            case Token::FUNCTION:
583
4
            case Token::IF:
584
4
            case Token::IN:
585
4
            case Token::IMPORT:
586
4
            case Token::IMPORTSTR:
587
4
            case Token::LOCAL:
588
4
            case Token::PAREN_R:
589
4
            case Token::SEMICOLON:
590
4
            case Token::TAILSTRICT:
591
4
            case Token::THEN: throw unexpected(tok, "parsing terminal");
592
593
19
            case Token::END_OF_FILE: throw StaticError(tok.location, "unexpected end of file.");
594
595
385k
            case Token::OPERATOR: {
596
385k
                UnaryOp uop;
597
385k
                if (!op_is_unary(tok.data, uop)) {
598
14
                    std::stringstream ss;
599
14
                    ss << "not a unary operator: " << tok.data;
600
14
                    throw StaticError(tok.location, ss.str());
601
14
                }
602
385k
                AST *expr = parse(UNARY_PRECEDENCE);
603
385k
                return alloc->make<Unary>(span(tok, expr), tok.fodder, uop, expr);
604
385k
            }
605
96.7k
            case Token::BRACE_L: {
606
96.7k
                AST *obj;
607
96.7k
                parseObjectRemainder(obj, tok);
608
96.7k
                return obj;
609
385k
            }
610
611
73.1k
            case Token::BRACKET_L: {
612
73.1k
                Token next = peek();
613
73.1k
                if (next.kind == Token::BRACKET_R) {
614
14.6k
                    Token bracket_r = pop();
615
14.6k
                    return alloc->make<Array>(
616
14.6k
                        span(tok, next), tok.fodder, Array::Elements{}, false, bracket_r.fodder);
617
14.6k
                }
618
58.4k
                AST *first = parse(MAX_PRECEDENCE);
619
58.4k
                bool got_comma = false;
620
58.4k
                Fodder comma_fodder;
621
58.4k
                next = peek();
622
58.4k
                if (!got_comma && next.kind == Token::COMMA) {
623
6.69k
                    Token comma = pop();
624
6.69k
                    comma_fodder = comma.fodder;
625
6.69k
                    next = peek();
626
6.69k
                    got_comma = true;
627
6.69k
                }
628
629
58.4k
                if (next.kind == Token::FOR) {
630
                    // It's a comprehension
631
12.7k
                    Token for_token = pop();
632
12.7k
                    std::vector<ComprehensionSpec> specs;
633
12.7k
                    Token last = parseComprehensionSpecs(Token::BRACKET_R, for_token.fodder, specs);
634
12.7k
                    return alloc->make<ArrayComprehension>(span(tok, last),
635
12.7k
                                                           tok.fodder,
636
12.7k
                                                           first,
637
12.7k
                                                           comma_fodder,
638
12.7k
                                                           got_comma,
639
12.7k
                                                           specs,
640
12.7k
                                                           last.fodder);
641
12.7k
                }
642
643
                // Not a comprehension: It can have more elements.
644
45.7k
                Array::Elements elements;
645
45.7k
                elements.emplace_back(first, comma_fodder);
646
3.60M
                do {
647
3.60M
                    if (next.kind == Token::BRACKET_R) {
648
45.6k
                        Token bracket_r = pop();
649
45.6k
                        return alloc->make<Array>(
650
45.6k
                            span(tok, next), tok.fodder, elements, got_comma, bracket_r.fodder);
651
45.6k
                    }
652
3.56M
                    if (!got_comma) {
653
34
                        std::stringstream ss;
654
34
                        ss << "expected a comma before next array element.";
655
34
                        throw StaticError(next.location, ss.str());
656
34
                    }
657
3.56M
                    AST *expr = parse(MAX_PRECEDENCE);
658
3.56M
                    comma_fodder.clear();
659
3.56M
                    got_comma = false;
660
3.56M
                    next = peek();
661
3.56M
                    if (next.kind == Token::COMMA) {
662
3.55M
                        Token comma = pop();
663
3.55M
                        comma_fodder = comma.fodder;
664
3.55M
                        next = peek();
665
3.55M
                        got_comma = true;
666
3.55M
                    }
667
3.56M
                    elements.emplace_back(expr, comma_fodder);
668
3.56M
                } while (true);
669
45.7k
            }
670
671
22.6k
            case Token::PAREN_L: {
672
22.6k
                auto *inner = parse(MAX_PRECEDENCE);
673
22.6k
                Token close = popExpect(Token::PAREN_R);
674
22.6k
                return alloc->make<Parens>(span(tok, close), tok.fodder, inner, close.fodder);
675
45.7k
            }
676
677
            // Literals
678
4.03M
            case Token::NUMBER: return alloc->make<LiteralNumber>(span(tok), tok.fodder, tok.data);
679
680
546k
            case Token::STRING_SINGLE:
681
546k
                return alloc->make<LiteralString>(
682
546k
                    span(tok), tok.fodder, tok.data32(), LiteralString::SINGLE, "", "");
683
3.37k
            case Token::STRING_DOUBLE:
684
3.37k
                return alloc->make<LiteralString>(
685
3.37k
                    span(tok), tok.fodder, tok.data32(), LiteralString::DOUBLE, "", "");
686
0
            case Token::STRING_BLOCK:
687
0
                return alloc->make<LiteralString>(span(tok),
688
0
                                                  tok.fodder,
689
0
                                                  tok.data32(),
690
0
                                                  LiteralString::BLOCK,
691
0
                                                  tok.stringBlockIndent,
692
0
                                                  tok.stringBlockTermIndent);
693
100
            case Token::VERBATIM_STRING_SINGLE:
694
100
                return alloc->make<LiteralString>(
695
100
                    span(tok), tok.fodder, tok.data32(), LiteralString::VERBATIM_SINGLE, "", "");
696
0
            case Token::VERBATIM_STRING_DOUBLE:
697
0
                return alloc->make<LiteralString>(
698
0
                    span(tok), tok.fodder, tok.data32(), LiteralString::VERBATIM_DOUBLE, "", "");
699
700
23.0k
            case Token::FALSE: return alloc->make<LiteralBoolean>(span(tok), tok.fodder, false);
701
702
16.9k
            case Token::TRUE: return alloc->make<LiteralBoolean>(span(tok), tok.fodder, true);
703
704
11.2k
            case Token::NULL_LIT: return alloc->make<LiteralNull>(span(tok), tok.fodder);
705
706
            // Variables
707
12.9k
            case Token::DOLLAR: return alloc->make<Dollar>(span(tok), tok.fodder);
708
709
1.72M
            case Token::IDENTIFIER:
710
1.72M
                return alloc->make<Var>(span(tok), tok.fodder, alloc->makeIdentifier(tok.data32()));
711
712
3.11k
            case Token::SELF: return alloc->make<Self>(span(tok), tok.fodder);
713
714
588
            case Token::SUPER: {
715
588
                Token next = pop();
716
588
                AST *index = nullptr;
717
588
                const Identifier *id = nullptr;
718
588
                Fodder id_fodder;
719
588
                switch (next.kind) {
720
0
                    case Token::DOT: {
721
0
                        Token field_id = popExpect(Token::IDENTIFIER);
722
0
                        id_fodder = field_id.fodder;
723
0
                        id = alloc->makeIdentifier(field_id.data32());
724
0
                    } break;
725
588
                    case Token::BRACKET_L: {
726
588
                        index = parse(MAX_PRECEDENCE);
727
588
                        Token bracket_r = popExpect(Token::BRACKET_R);
728
588
                        id_fodder = bracket_r.fodder;  // Not id_fodder, but use the same var.
729
588
                    } break;
730
0
                    default: throw StaticError(tok.location, "expected . or [ after super.");
731
588
                }
732
588
                return alloc->make<SuperIndex>(
733
588
                    span(tok), tok.fodder, next.fodder, index, id_fodder, id);
734
588
            }
735
6.96M
        }
736
737
0
        std::cerr << "INTERNAL ERROR: Unknown tok kind: " << tok.kind << std::endl;
738
0
        std::abort();
739
0
        return nullptr;  // Quiet, compiler.
740
6.96M
    }
741
742
    // If the first token makes it clear that we will parsing a greedy construct, then return the
743
    // AST.  Otherwise, return nullptr.  Greedy constructs are those that consume as many tokens
744
    // as possible on the right hand side, because they have no closing token.
745
    AST *maybeParseGreedy(void)
746
7.27M
    {
747
        // Allocate this on the heap to control stack growth.
748
7.27M
        std::unique_ptr<Token> begin_(new Token(peek()));
749
7.27M
        const Token &begin = *begin_;
750
751
7.27M
        switch (begin.kind) {
752
            // These cases have effectively MAX_PRECEDENCE as the first
753
            // call to parse will parse them.
754
19.3k
            case Token::ASSERT: {
755
19.3k
                pop();
756
19.3k
                AST *cond = parse(MAX_PRECEDENCE);
757
19.3k
                Fodder colonFodder;
758
19.3k
                AST *msg = nullptr;
759
19.3k
                if (peek().kind == Token::OPERATOR && peek().data == ":") {
760
17.8k
                    Token colon = pop();
761
17.8k
                    colonFodder = colon.fodder;
762
17.8k
                    msg = parse(MAX_PRECEDENCE);
763
17.8k
                }
764
19.3k
                Token semicolon = popExpect(Token::SEMICOLON);
765
19.3k
                AST *rest = parse(MAX_PRECEDENCE);
766
19.3k
                return alloc->make<Assert>(span(begin, rest),
767
19.3k
                                           begin.fodder,
768
19.3k
                                           cond,
769
19.3k
                                           colonFodder,
770
19.3k
                                           msg,
771
19.3k
                                           semicolon.fodder,
772
19.3k
                                           rest);
773
0
            }
774
775
29.0k
            case Token::ERROR: {
776
29.0k
                pop();
777
29.0k
                AST *expr = parse(MAX_PRECEDENCE);
778
29.0k
                return alloc->make<Error>(span(begin, expr), begin.fodder, expr);
779
0
            }
780
781
147k
            case Token::IF: {
782
147k
                pop();
783
147k
                AST *cond = parse(MAX_PRECEDENCE);
784
147k
                Token then = popExpect(Token::THEN);
785
147k
                AST *branch_true = parse(MAX_PRECEDENCE);
786
147k
                if (peek().kind == Token::ELSE) {
787
146k
                    Token else_ = pop();
788
146k
                    AST *branch_false = parse(MAX_PRECEDENCE);
789
146k
                    return alloc->make<Conditional>(span(begin, branch_false),
790
146k
                                                    begin.fodder,
791
146k
                                                    cond,
792
146k
                                                    then.fodder,
793
146k
                                                    branch_true,
794
146k
                                                    else_.fodder,
795
146k
                                                    branch_false);
796
146k
                }
797
1.88k
                return alloc->make<Conditional>(span(begin, branch_true),
798
1.88k
                                                begin.fodder,
799
1.88k
                                                cond,
800
1.88k
                                                then.fodder,
801
1.88k
                                                branch_true,
802
1.88k
                                                Fodder{},
803
1.88k
                                                nullptr);
804
147k
            }
805
806
9.42k
            case Token::FUNCTION: {
807
9.42k
                pop();  // Still available in 'begin'.
808
9.42k
                Token paren_l = pop();
809
9.42k
                if (paren_l.kind == Token::PAREN_L) {
810
9.42k
                    std::vector<AST *> params_asts;
811
9.42k
                    bool got_comma;
812
9.42k
                    Fodder paren_r_fodder;
813
9.42k
                    ArgParams params = parseParams("function parameter", got_comma, paren_r_fodder);
814
9.42k
                    AST *body = parse(MAX_PRECEDENCE);
815
9.42k
                    return alloc->make<Function>(span(begin, body),
816
9.42k
                                                 begin.fodder,
817
9.42k
                                                 paren_l.fodder,
818
9.42k
                                                 params,
819
9.42k
                                                 got_comma,
820
9.42k
                                                 paren_r_fodder,
821
9.42k
                                                 body);
822
9.42k
                } else {
823
0
                    std::stringstream ss;
824
0
                    ss << "expected ( but got " << paren_l;
825
0
                    throw StaticError(paren_l.location, ss.str());
826
0
                }
827
9.42k
            }
828
829
20
            case Token::IMPORT: {
830
20
                pop();
831
20
                AST *body = parse(MAX_PRECEDENCE);
832
20
                if (body->type == AST_LITERAL_STRING) {
833
20
                    auto *lit = static_cast<LiteralString *>(body);
834
20
                    if (lit->tokenKind == LiteralString::BLOCK) {
835
0
                        throw StaticError(lit->location,
836
0
                                          "Cannot use text blocks in import statements.");
837
0
                    }
838
20
                    return alloc->make<Import>(span(begin, body), begin.fodder, lit);
839
20
                } else {
840
0
                    std::stringstream ss;
841
0
                    ss << "computed imports are not allowed.";
842
0
                    throw StaticError(body->location, ss.str());
843
0
                }
844
20
            }
845
846
0
            case Token::IMPORTSTR: {
847
0
                pop();
848
0
                AST *body = parse(MAX_PRECEDENCE);
849
0
                if (body->type == AST_LITERAL_STRING) {
850
0
                    auto *lit = static_cast<LiteralString *>(body);
851
0
                    if (lit->tokenKind == LiteralString::BLOCK) {
852
0
                        throw StaticError(lit->location,
853
0
                                          "Cannot use text blocks in import statements.");
854
0
                    }
855
0
                    return alloc->make<Importstr>(span(begin, body), begin.fodder, lit);
856
0
                } else {
857
0
                    std::stringstream ss;
858
0
                    ss << "computed imports are not allowed.";
859
0
                    throw StaticError(body->location, ss.str());
860
0
                }
861
0
            }
862
863
110k
            case Token::LOCAL: {
864
110k
                pop();
865
110k
                Local::Binds binds;
866
116k
                do {
867
116k
                    Token delim = parseBind(binds);
868
116k
                    if (delim.kind != Token::SEMICOLON && delim.kind != Token::COMMA) {
869
1
                        std::stringstream ss;
870
1
                        ss << "expected , or ; but got " << delim;
871
1
                        throw StaticError(delim.location, ss.str());
872
1
                    }
873
116k
                    if (delim.kind == Token::SEMICOLON)
874
110k
                        break;
875
116k
                } while (true);
876
110k
                AST *body = parse(MAX_PRECEDENCE);
877
110k
                return alloc->make<Local>(span(begin, body), begin.fodder, binds, body);
878
110k
            }
879
880
6.96M
            default:
881
6.96M
            return nullptr;
882
7.27M
        }
883
7.27M
    }
884
885
    // Parse a general expression.
886
    //
887
    // Consume infix tokens up to (but not including) max_precedence, then stop.
888
    AST *parse(unsigned max_precedence)
889
7.27M
    {
890
7.27M
        AST *ast = maybeParseGreedy();
891
        // There cannot be an operator after a greedy parse.
892
7.27M
        if (ast != nullptr) return ast;
893
894
        // If we get here, we could be parsing an infix construct.
895
896
        // Allocate this on the heap to control stack growth.
897
6.96M
        std::unique_ptr<Token> begin_(new Token(peek()));
898
6.96M
        const Token &begin = *begin_;
899
900
6.96M
        AST *lhs = parseTerminalBracketsOrUnary();
901
902
6.96M
        return parseInfix(lhs, begin, max_precedence);
903
7.27M
    }
904
905
    AST *parseInfix(AST *lhs, const Token &begin, unsigned max_precedence)
906
6.96M
    {
907
8.28M
        while (true) {
908
909
8.28M
            BinaryOp bop = BOP_PLUS;
910
8.28M
            unsigned op_precedence = 0;
911
912
8.28M
            switch (peek().kind) {
913
                // Logical / arithmetic binary operator.
914
62
                case Token::IN:
915
1.01M
                case Token::OPERATOR:
916
                    // These occur if the outer statement was an assert or array slice.
917
                    // Either way, we terminate the parsing here.
918
1.01M
                    if (peek().data == ":" || peek().data == "::") {
919
37.6k
                        return lhs;
920
37.6k
                    }
921
973k
                    if (!op_is_binary(peek().data, bop)) {
922
15
                        std::stringstream ss;
923
15
                        ss << "not a binary operator: " << peek().data;
924
15
                        throw StaticError(peek().location, ss.str());
925
15
                    }
926
972k
                    op_precedence = precedence_map[bop];
927
972k
                    break;
928
929
                // Index, Apply
930
316k
                case Token::DOT:
931
393k
                case Token::BRACKET_L:
932
754k
                case Token::PAREN_L:
933
796k
                case Token::BRACE_L:
934
796k
                    op_precedence = APPLY_PRECEDENCE;
935
796k
                    break;
936
937
6.47M
                default: 
938
                    // This happens when we reach EOF or the terminating token of an outer context.
939
6.47M
                    return lhs;
940
8.28M
            }
941
942
            // If higher precedence than the outer recursive call, let that handle it.
943
1.76M
            if (op_precedence >= max_precedence)
944
450k
                return lhs;
945
946
1.31M
            Token op = pop();
947
948
1.31M
            switch (op.kind) {
949
76.3k
                case Token::BRACKET_L: {
950
76.3k
                    bool is_slice;
951
76.3k
                    AST *first = nullptr;
952
76.3k
                    Fodder second_fodder;
953
76.3k
                    AST *second = nullptr;
954
76.3k
                    Fodder third_fodder;
955
76.3k
                    AST *third = nullptr;
956
957
76.3k
                    if (peek().kind == Token::BRACKET_R)
958
0
                        throw unexpected(pop(), "parsing index");
959
960
76.3k
                    if (peek().data != ":" && peek().data != "::") {
961
75.4k
                        first = parse(MAX_PRECEDENCE);
962
75.4k
                    }
963
964
76.3k
                    if (peek().kind == Token::OPERATOR && peek().data == "::") {
965
                        // Handle ::
966
0
                        is_slice = true;
967
0
                        Token joined = pop();
968
0
                        second_fodder = joined.fodder;
969
970
0
                        if (peek().kind != Token::BRACKET_R)
971
0
                            third = parse(MAX_PRECEDENCE);
972
973
76.3k
                    } else if (peek().kind != Token::BRACKET_R) {
974
8.50k
                        is_slice = true;
975
8.50k
                        Token delim = pop();
976
8.50k
                        if (delim.data != ":")
977
1
                            throw unexpected(delim, "parsing slice");
978
979
8.50k
                        second_fodder = delim.fodder;
980
981
8.50k
                        if (peek().data != ":" && peek().kind != Token::BRACKET_R)
982
3.79k
                            second = parse(MAX_PRECEDENCE);
983
984
8.50k
                        if (peek().kind != Token::BRACKET_R) {
985
481
                            Token delim = pop();
986
481
                            if (delim.data != ":")
987
10
                                throw unexpected(delim, "parsing slice");
988
989
471
                            third_fodder = delim.fodder;
990
991
471
                            if (peek().kind != Token::BRACKET_R)
992
471
                                third = parse(MAX_PRECEDENCE);
993
471
                        }
994
67.8k
                    } else {
995
67.8k
                        is_slice = false;
996
67.8k
                    }
997
76.3k
                    Token end = popExpect(Token::BRACKET_R);
998
76.3k
                    lhs = alloc->make<Index>(span(begin, end),
999
76.3k
                                             EMPTY_FODDER,
1000
76.3k
                                             lhs,
1001
76.3k
                                             op.fodder,
1002
76.3k
                                             is_slice,
1003
76.3k
                                             first,
1004
76.3k
                                             second_fodder,
1005
76.3k
                                             second,
1006
76.3k
                                             third_fodder,
1007
76.3k
                                             third,
1008
76.3k
                                             end.fodder);
1009
76.3k
                    break;
1010
76.3k
                }
1011
316k
                case Token::DOT: {
1012
316k
                    Token field_id = popExpect(Token::IDENTIFIER);
1013
316k
                    const Identifier *id = alloc->makeIdentifier(field_id.data32());
1014
316k
                    lhs = alloc->make<Index>(span(begin, field_id),
1015
316k
                                             EMPTY_FODDER,
1016
316k
                                             lhs,
1017
316k
                                             op.fodder,
1018
316k
                                             field_id.fodder,
1019
316k
                                             id);
1020
316k
                    break;
1021
76.3k
                }
1022
361k
                case Token::PAREN_L: {
1023
361k
                    ArgParams args;
1024
361k
                    bool got_comma;
1025
361k
                    Token end = parseArgs(args, "function argument", got_comma);
1026
361k
                    bool got_named = false;
1027
878k
                    for (const auto& arg : args) {
1028
878k
                        if (arg.id != nullptr) {
1029
1.41k
                            got_named = true;
1030
877k
                        } else {
1031
877k
                            if (got_named) {
1032
0
                                throw StaticError(arg.expr->location, "Positional argument after a named argument is not allowed");
1033
0
                            }
1034
877k
                        }
1035
878k
                    }
1036
361k
                    bool tailstrict = false;
1037
361k
                    Fodder tailstrict_fodder;
1038
361k
                    if (peek().kind == Token::TAILSTRICT) {
1039
18.8k
                        Token tailstrict_token = pop();
1040
18.8k
                        tailstrict_fodder = tailstrict_token.fodder;
1041
18.8k
                        tailstrict = true;
1042
18.8k
                    }
1043
361k
                    lhs = alloc->make<Apply>(span(begin, end),
1044
361k
                                             EMPTY_FODDER,
1045
361k
                                             lhs,
1046
361k
                                             op.fodder,
1047
361k
                                             args,
1048
361k
                                             got_comma,
1049
361k
                                             end.fodder,
1050
361k
                                             tailstrict_fodder,
1051
361k
                                             tailstrict);
1052
361k
                    break;
1053
361k
                }
1054
41.5k
                case Token::BRACE_L: {
1055
41.5k
                    AST *obj;
1056
41.5k
                    Token end = parseObjectRemainder(obj, op);
1057
41.5k
                    lhs = alloc->make<ApplyBrace>(span(begin, end), EMPTY_FODDER, lhs, obj);
1058
41.5k
                    break;
1059
361k
                }
1060
1061
42
                case Token::IN: {
1062
42
                    if (peek().kind == Token::SUPER) {
1063
0
                        Token super = pop();
1064
0
                        lhs = alloc->make<InSuper>(
1065
0
                            span(begin, super), EMPTY_FODDER, lhs, op.fodder, super.fodder);
1066
42
                    } else {
1067
42
                        AST *rhs = parse(op_precedence);
1068
42
                        lhs = alloc->make<Binary>(
1069
42
                            span(begin, rhs), EMPTY_FODDER, lhs, op.fodder, bop, rhs);
1070
42
                    }
1071
42
                    break;
1072
361k
                }
1073
1074
522k
                case Token::OPERATOR: {
1075
522k
                    AST *rhs = parse(op_precedence);
1076
522k
                    lhs = alloc->make<Binary>(
1077
522k
                        span(begin, rhs), EMPTY_FODDER, lhs, op.fodder, bop, rhs);
1078
522k
                    break;
1079
361k
                }
1080
1081
0
                default: {
1082
0
                    std::cerr << "Should not be here." << std::endl;
1083
0
                    abort();
1084
361k
                }
1085
1.31M
            }
1086
1.31M
        }
1087
1088
        // (1 & ((1 + (1 * 1)) + 1)) & 1
1089
        //
1090
        //
1091
1092
/*
1093
        // Allocate this on the heap to control stack growth.
1094
        std::unique_ptr<Token> begin_(new Token(peek()));
1095
        const Token &begin = *begin_;
1096
*/
1097
6.96M
    }
1098
};
1099
1100
}  // namespace
1101
1102
AST *jsonnet_parse(Allocator *alloc, Tokens &tokens)
1103
865
{
1104
865
    Parser parser(tokens, alloc);
1105
865
    AST *expr = parser.parse(MAX_PRECEDENCE);
1106
865
    if (tokens.front().kind != Token::END_OF_FILE) {
1107
8
        std::stringstream ss;
1108
8
        ss << "did not expect: " << tokens.front();
1109
8
        throw StaticError(tokens.front().location, ss.str());
1110
8
    }
1111
1112
857
    return expr;
1113
865
}