Coverage Report

Created: 2025-11-24 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsonnet/core/lexer.h
Line
Count
Source
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
#ifndef JSONNET_LEXER_H
18
#define JSONNET_LEXER_H
19
20
#include <cassert>
21
#include <cstdlib>
22
23
#include <iostream>
24
#include <list>
25
#include <sstream>
26
#include <string>
27
#include <vector>
28
29
#include "static_error.h"
30
#include "unicode.h"
31
32
namespace jsonnet::internal {
33
34
/** Whitespace and comments.
35
 *
36
 * "Fodder" (as in cannon fodder) implies this data is expendable.
37
 */
38
struct FodderElement {
39
    enum Kind {
40
        /** The next token, paragraph, or interstitial should be on a new line.
41
         *
42
         * A single comment string is allowed, which flows before the new line.
43
         *
44
         * The LINE_END fodder specifies the indentation level and vertical spacing before whatever
45
         * comes next.
46
         */
47
        LINE_END,
48
49
        /** A C-style comment that begins and ends on the same line.
50
         *
51
         * If it follows a token (i.e., it is the first fodder element) then it appears after the
52
         * token on the same line.  If it follows another interstitial, it will also flow after it
53
         * on the same line.  If it follows a new line or a paragraph, it is the first thing on the
54
         * following line, after the blank lines and indentation specified by the previous fodder.
55
         *
56
         * There is exactly one comment string.
57
         */
58
        INTERSTITIAL,
59
60
        /** A comment consisting of at least one line.
61
         *
62
         * // and # style commes have exactly one line.  C-style comments can have more than one
63
         * line.
64
         *
65
         * All lines of the comment are indented according to the indentation level of the previous
66
         * new line / paragraph fodder.
67
         *
68
         * The PARAGRAPH fodder specifies the indentation level and vertical spacing before whatever
69
         * comes next.
70
         */
71
        PARAGRAPH,
72
    };
73
    Kind kind;
74
75
    /** How many blank lines (vertical space) before the next fodder / token. */
76
    unsigned blanks;
77
78
    /** How far the next fodder / token should be indented. */
79
    unsigned indent;
80
81
    /** Whatever comments are part of this fodder.
82
     *
83
     * Constraints apply.  See Kind, above.
84
     *
85
     * The strings include any delimiting characters, e.g. // # and C-style comment delimiters but
86
     * not newline characters or indentation.
87
     */
88
    std::vector<std::string> comment;
89
90
    FodderElement(Kind kind, unsigned blanks, unsigned indent,
91
                  const std::vector<std::string> &comment)
92
50.1M
        : kind(kind), blanks(blanks), indent(indent), comment(comment)
93
50.1M
    {
94
50.1M
        assert(kind != LINE_END || comment.size() <= 1);
95
50.1M
        assert(kind != INTERSTITIAL || (blanks == 0 && indent == 0 && comment.size() == 1));
96
50.1M
        assert(kind != PARAGRAPH || comment.size() >= 1);
97
50.1M
    }
98
};
99
100
static inline std::ostream &operator<<(std::ostream &o, const FodderElement &f)
101
0
{
102
0
    switch (f.kind) {
103
0
        case FodderElement::LINE_END:
104
0
            o << "END(" << f.blanks << ", " << f.indent;
105
0
            if (!f.comment.empty()) {
106
0
                o << ", " << f.comment[0];
107
0
            }
108
0
            o << ")";
109
0
            break;
110
0
        case FodderElement::INTERSTITIAL:
111
0
            o << "INT(" << f.blanks << ", " << f.indent << ", " << f.comment[0] << ")";
112
0
            break;
113
0
        case FodderElement::PARAGRAPH:
114
0
            o << "PAR(" << f.blanks << ", " << f.indent << ", " << f.comment[0] << "...)";
115
0
            break;
116
0
    }
117
0
    return o;
118
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::FodderElement const&)
119
120
/** A sequence of fodder elements, typically between two tokens.
121
 *
122
 * A LINE_END is not allowed to follow a PARAGRAPH or a LINE_END. This can be represented by
123
 * replacing the indent of the prior fodder and increasing the number of blank lines if necessary.
124
 * If there was a comment, it can be represented by changing the LINE_END to a paragraph containing
125
 * the same single comment string.
126
 *
127
 * There must be a LINE_END or a PARAGRAPH before a PARAGRAPH.
128
 *
129
 * TODO(sbarzowski) Make it a proper class
130
 */
131
typedef std::vector<FodderElement> Fodder;
132
133
static inline bool fodder_has_clean_endline(const Fodder &fodder)
134
839k
{
135
839k
    return !fodder.empty() && fodder.back().kind != FodderElement::INTERSTITIAL;
136
839k
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
lexer.cpp:jsonnet::internal::fodder_has_clean_endline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Line
Count
Source
134
839k
{
135
839k
    return !fodder.empty() && fodder.back().kind != FodderElement::INTERSTITIAL;
136
839k
}
137
138
/** As a.push_back(elem) but preserves constraints.
139
 *
140
 * See concat_fodder below.
141
 */
142
static inline void fodder_push_back(Fodder &a, const FodderElement &elem)
143
419k
{
144
419k
    if (fodder_has_clean_endline(a) && elem.kind == FodderElement::LINE_END) {
145
0
        if (elem.comment.size() > 0) {
146
            // The line end had a comment, so create a single line paragraph for it.
147
0
            a.emplace_back(FodderElement::PARAGRAPH, elem.blanks, elem.indent, elem.comment);
148
0
        } else {
149
            // Merge it into the previous line end.
150
0
            a.back().indent = elem.indent;
151
0
            a.back().blanks += elem.blanks;
152
0
        }
153
419k
    } else {
154
419k
        if (!fodder_has_clean_endline(a) && elem.kind == FodderElement::PARAGRAPH) {
155
42.9k
            a.emplace_back(FodderElement::LINE_END, 0, elem.indent, std::vector<std::string>());
156
42.9k
        }
157
419k
        a.push_back(elem);
158
419k
    }
159
419k
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
lexer.cpp:jsonnet::internal::fodder_push_back(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, jsonnet::internal::FodderElement const&)
Line
Count
Source
143
419k
{
144
419k
    if (fodder_has_clean_endline(a) && elem.kind == FodderElement::LINE_END) {
145
0
        if (elem.comment.size() > 0) {
146
            // The line end had a comment, so create a single line paragraph for it.
147
0
            a.emplace_back(FodderElement::PARAGRAPH, elem.blanks, elem.indent, elem.comment);
148
0
        } else {
149
            // Merge it into the previous line end.
150
0
            a.back().indent = elem.indent;
151
0
            a.back().blanks += elem.blanks;
152
0
        }
153
419k
    } else {
154
419k
        if (!fodder_has_clean_endline(a) && elem.kind == FodderElement::PARAGRAPH) {
155
42.9k
            a.emplace_back(FodderElement::LINE_END, 0, elem.indent, std::vector<std::string>());
156
42.9k
        }
157
419k
        a.push_back(elem);
158
419k
    }
159
419k
}
160
161
/** As a + b but preserves constraints.
162
 *
163
 * Namely, a LINE_END is not allowed to follow a PARAGRAPH or a LINE_END.
164
 */
165
static inline Fodder concat_fodder(const Fodder &a, const Fodder &b)
166
0
{
167
0
    if (a.size() == 0)
168
0
        return b;
169
0
    if (b.size() == 0)
170
0
        return a;
171
0
    Fodder r = a;
172
    // Carefully add the first element of b.
173
0
    fodder_push_back(r, b[0]);
174
    // Add the rest of b.
175
0
    for (unsigned i = 1; i < b.size(); ++i) {
176
0
        r.push_back(b[i]);
177
0
    }
178
0
    return r;
179
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::concat_fodder(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
180
181
/** Move b to the front of a. */
182
static inline void fodder_move_front(Fodder &a, Fodder &b)
183
0
{
184
0
    a = concat_fodder(b, a);
185
0
    b.clear();
186
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::fodder_move_front(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
187
188
static inline Fodder make_fodder(const FodderElement &elem)
189
0
{
190
0
    Fodder fodder;
191
0
    fodder_push_back(fodder, elem);
192
0
    return fodder;
193
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::make_fodder(jsonnet::internal::FodderElement const&)
194
195
static inline void ensureCleanNewline(Fodder &fodder)
196
0
{
197
0
    if (!fodder_has_clean_endline(fodder)) {
198
0
        fodder_push_back(fodder, FodderElement(FodderElement::Kind::LINE_END, 0, 0, {}));
199
0
    }
200
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::ensureCleanNewline(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> >&)
201
202
static inline int countNewlines(const FodderElement &elem)
203
0
{
204
0
    switch (elem.kind) {
205
0
        case FodderElement::INTERSTITIAL: return 0;
206
0
        case FodderElement::LINE_END: return 1;
207
0
        case FodderElement::PARAGRAPH: return elem.comment.size() + elem.blanks;
208
0
    }
209
0
    std::cerr << "Unknown FodderElement kind" << std::endl;
210
0
    abort();
211
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::countNewlines(jsonnet::internal::FodderElement const&)
212
213
static inline int countNewlines(const Fodder &fodder)
214
0
{
215
0
    int sum = 0;
216
0
    for (const auto &elem : fodder) {
217
0
        sum += countNewlines(elem);
218
0
    }
219
0
    return sum;
220
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::countNewlines(std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
221
222
static inline std::ostream &operator<<(std::ostream &o, const Fodder &fodder)
223
0
{
224
0
    bool first = true;
225
0
    for (const auto &f : fodder) {
226
0
        o << (first ? "[" : ", ");
227
0
        first = false;
228
0
        o << f;
229
0
    }
230
0
    o << (first ? "[]" : "]");
231
0
    return o;
232
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::vector<jsonnet::internal::FodderElement, std::__1::allocator<jsonnet::internal::FodderElement> > const&)
233
234
struct Token {
235
    enum Kind {
236
        // Symbols
237
        BRACE_L,
238
        BRACE_R,
239
        BRACKET_L,
240
        BRACKET_R,
241
        COMMA,
242
        DOLLAR,
243
        DOT,
244
        PAREN_L,
245
        PAREN_R,
246
        SEMICOLON,
247
248
        // Arbitrary length lexemes
249
        IDENTIFIER,
250
        NUMBER,
251
        OPERATOR,
252
        STRING_DOUBLE,
253
        STRING_SINGLE,
254
        STRING_BLOCK,
255
        VERBATIM_STRING_SINGLE,
256
        VERBATIM_STRING_DOUBLE,
257
258
        // Keywords
259
        ASSERT,
260
        ELSE,
261
        ERROR,
262
        FALSE,
263
        FOR,
264
        FUNCTION,
265
        IF,
266
        IMPORT,
267
        IMPORTSTR,
268
        IMPORTBIN,
269
        IN,
270
        LOCAL,
271
        NULL_LIT,
272
        TAILSTRICT,
273
        THEN,
274
        SELF,
275
        SUPER,
276
        TRUE,
277
278
        // A special token that holds line/column information about the end of the file.
279
        END_OF_FILE
280
    } kind;
281
282
    /** Fodder before this token. */
283
    Fodder fodder;
284
285
    /** Content of the token if it wasn't a keyword. */
286
    std::string data;
287
288
    /** If kind == STRING_BLOCK then stores the sequence of whitespace that indented the block. */
289
    std::string stringBlockIndent;
290
291
    /** If kind == STRING_BLOCK then stores the sequence of whitespace that indented the end of
292
     * the block.
293
     *
294
     * This is always fewer whitespace characters than in stringBlockIndent.
295
     */
296
    std::string stringBlockTermIndent;
297
298
    UString data32(void) const
299
119M
    {
300
119M
        return decode_utf8(data);
301
119M
    }
302
303
    LocationRange location;
304
305
    Token(Kind kind, const Fodder &fodder, const std::string &data,
306
          const std::string &string_block_indent, const std::string &string_block_term_indent,
307
          const LocationRange &location)
308
344M
        : kind(kind),
309
344M
          fodder(fodder),
310
344M
          data(data),
311
344M
          stringBlockIndent(string_block_indent),
312
344M
          stringBlockTermIndent(string_block_term_indent),
313
344M
          location(location)
314
344M
    {
315
344M
    }
316
317
0
    Token(Kind kind, const std::string &data = "") : kind(kind), data(data) {}
318
319
    static const char *toString(Kind v)
320
3.44k
    {
321
3.44k
        switch (v) {
322
42
            case BRACE_L: return "\"{\"";
323
118
            case BRACE_R: return "\"}\"";
324
4
            case BRACKET_L: return "\"[\"";
325
339
            case BRACKET_R: return "\"]\"";
326
145
            case COMMA: return "\",\"";
327
74
            case DOLLAR: return "\"$\"";
328
47
            case DOT: return "\".\"";
329
330
0
            case PAREN_L: return "\"(\"";
331
122
            case PAREN_R: return "\")\"";
332
99
            case SEMICOLON: return "\";\"";
333
334
477
            case IDENTIFIER: return "IDENTIFIER";
335
142
            case NUMBER: return "NUMBER";
336
417
            case OPERATOR: return "OPERATOR";
337
54
            case STRING_SINGLE: return "STRING_SINGLE";
338
70
            case STRING_DOUBLE: return "STRING_DOUBLE";
339
11
            case VERBATIM_STRING_SINGLE: return "VERBATIM_STRING_SINGLE";
340
8
            case VERBATIM_STRING_DOUBLE: return "VERBATIM_STRING_DOUBLE";
341
20
            case STRING_BLOCK: return "STRING_BLOCK";
342
343
4
            case ASSERT: return "assert";
344
6
            case ELSE: return "else";
345
0
            case ERROR: return "error";
346
3
            case FALSE: return "false";
347
7
            case FOR: return "for";
348
5
            case FUNCTION: return "function";
349
6
            case IF: return "if";
350
0
            case IMPORT: return "import";
351
1
            case IMPORTSTR: return "importstr";
352
2
            case IMPORTBIN: return "importbin";
353
52
            case IN: return "in";
354
3
            case LOCAL: return "local";
355
1
            case NULL_LIT: return "null";
356
2
            case SELF: return "self";
357
1
            case SUPER: return "super";
358
3
            case TAILSTRICT: return "tailstrict";
359
22
            case THEN: return "then";
360
2
            case TRUE: return "true";
361
362
1.13k
            case END_OF_FILE: return "end of file";
363
0
            default:
364
0
                std::cerr << "INTERNAL ERROR: Unknown token kind: " << v << std::endl;
365
0
                std::abort();
366
3.44k
        }
367
3.44k
    }
368
};
369
370
/** The result of lexing.
371
 *
372
 * Because of the EOF token, this will always contain at least one token.  So element 0 can be used
373
 * to get the filename.
374
 */
375
typedef std::list<Token> Tokens;
376
377
static inline bool operator==(const Token &a, const Token &b)
378
0
{
379
0
    if (a.kind != b.kind)
380
0
        return false;
381
0
    if (a.data != b.data)
382
0
        return false;
383
0
    return true;
384
0
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: parser.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: pass.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::operator==(jsonnet::internal::Token const&, jsonnet::internal::Token const&)
385
386
static inline std::ostream &operator<<(std::ostream &o, Token::Kind v)
387
1.91k
{
388
1.91k
    o << Token::toString(v);
389
1.91k
    return o;
390
1.91k
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
parser.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Line
Count
Source
387
1.91k
{
388
1.91k
    o << Token::toString(v);
389
1.91k
    return o;
390
1.91k
}
Unexecuted instantiation: pass.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: vm.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token::Kind)
391
392
static inline std::ostream &operator<<(std::ostream &o, const Token &v)
393
1.64k
{
394
1.64k
    if (v.data == "") {
395
1.00k
        o << Token::toString(v.kind);
396
1.00k
    } else if (v.kind == Token::OPERATOR) {
397
105
        o << "\"" << v.data << "\"";
398
531
    } else {
399
531
        o << "(" << Token::toString(v.kind) << ", \"" << v.data << "\")";
400
531
    }
401
1.64k
    return o;
402
1.64k
}
Unexecuted instantiation: libjsonnet.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
parser.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Line
Count
Source
393
1.64k
{
394
1.64k
    if (v.data == "") {
395
1.00k
        o << Token::toString(v.kind);
396
1.00k
    } else if (v.kind == Token::OPERATOR) {
397
105
        o << "\"" << v.data << "\"";
398
531
    } else {
399
531
        o << "(" << Token::toString(v.kind) << ", \"" << v.data << "\")";
400
531
    }
401
1.64k
    return o;
402
1.64k
}
Unexecuted instantiation: pass.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: static_analysis.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: string_utils.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: vm.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: desugarer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: formatter.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
Unexecuted instantiation: lexer.cpp:jsonnet::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, jsonnet::internal::Token const&)
403
404
/** IF the given identifier is a keyword, return its kind, otherwise return IDENTIFIER. */
405
Token::Kind lex_get_keyword_kind(const std::string &identifier);
406
407
Tokens jsonnet_lex(const std::string &filename, const char *input);
408
409
std::string jsonnet_unlex(const Tokens &tokens);
410
411
}  // namespace jsonnet::internal
412
413
#endif  // JSONNET_LEXER_H