Coverage Report

Created: 2023-06-07 06:16

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