Coverage Report

Created: 2025-07-23 07:04

/src/jsonnet/core/lexer.h
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
#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
35.7M
        : kind(kind), blanks(blanks), indent(indent), comment(comment)
93
35.7M
    {
94
35.7M
        assert(kind != LINE_END || comment.size() <= 1);
95
35.7M
        assert(kind != INTERSTITIAL || (blanks == 0 && indent == 0 && comment.size() == 1));
96
35.7M
        assert(kind != PARAGRAPH || comment.size() >= 1);
97
35.7M
    }
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
578k
{
135
578k
    return !fodder.empty() && fodder.back().kind != FodderElement::INTERSTITIAL;
136
578k
}
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
578k
{
135
578k
    return !fodder.empty() && fodder.back().kind != FodderElement::INTERSTITIAL;
136
578k
}
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
289k
{
144
289k
    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
289k
    } else {
154
289k
        if (!fodder_has_clean_endline(a) && elem.kind == FodderElement::PARAGRAPH) {
155
37.7k
            a.emplace_back(FodderElement::LINE_END, 0, elem.indent, std::vector<std::string>());
156
37.7k
        }
157
289k
        a.push_back(elem);
158
289k
    }
159
289k
}
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
289k
{
144
289k
    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
289k
    } else {
154
289k
        if (!fodder_has_clean_endline(a) && elem.kind == FodderElement::PARAGRAPH) {
155
37.7k
            a.emplace_back(FodderElement::LINE_END, 0, elem.indent, std::vector<std::string>());
156
37.7k
        }
157
289k
        a.push_back(elem);
158
289k
    }
159
289k
}
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
77.6M
    {
300
77.6M
        return decode_utf8(data);
301
77.6M
    }
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
222M
        : kind(kind),
309
222M
          fodder(fodder),
310
222M
          data(data),
311
222M
          stringBlockIndent(string_block_indent),
312
222M
          stringBlockTermIndent(string_block_term_indent),
313
222M
          location(location)
314
222M
    {
315
222M
    }
316
317
0
    Token(Kind kind, const std::string &data = "") : kind(kind), data(data) {}
318
319
    static const char *toString(Kind v)
320
2.77k
    {
321
2.77k
        switch (v) {
322
34
            case BRACE_L: return "\"{\"";
323
94
            case BRACE_R: return "\"}\"";
324
8
            case BRACKET_L: return "\"[\"";
325
279
            case BRACKET_R: return "\"]\"";
326
117
            case COMMA: return "\",\"";
327
44
            case DOLLAR: return "\"$\"";
328
25
            case DOT: return "\".\"";
329
330
3
            case PAREN_L: return "\"(\"";
331
119
            case PAREN_R: return "\")\"";
332
67
            case SEMICOLON: return "\";\"";
333
334
381
            case IDENTIFIER: return "IDENTIFIER";
335
110
            case NUMBER: return "NUMBER";
336
357
            case OPERATOR: return "OPERATOR";
337
40
            case STRING_SINGLE: return "STRING_SINGLE";
338
40
            case STRING_DOUBLE: return "STRING_DOUBLE";
339
4
            case VERBATIM_STRING_SINGLE: return "VERBATIM_STRING_SINGLE";
340
5
            case VERBATIM_STRING_DOUBLE: return "VERBATIM_STRING_DOUBLE";
341
13
            case STRING_BLOCK: return "STRING_BLOCK";
342
343
4
            case ASSERT: return "assert";
344
4
            case ELSE: return "else";
345
0
            case ERROR: return "error";
346
3
            case FALSE: return "false";
347
6
            case FOR: return "for";
348
2
            case FUNCTION: return "function";
349
7
            case IF: return "if";
350
0
            case IMPORT: return "import";
351
0
            case IMPORTSTR: return "importstr";
352
1
            case IMPORTBIN: return "importbin";
353
36
            case IN: return "in";
354
3
            case LOCAL: return "local";
355
3
            case NULL_LIT: return "null";
356
1
            case SELF: return "self";
357
0
            case SUPER: return "super";
358
3
            case TAILSTRICT: return "tailstrict";
359
20
            case THEN: return "then";
360
2
            case TRUE: return "true";
361
362
936
            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
2.77k
        }
367
2.77k
    }
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.56k
{
388
1.56k
    o << Token::toString(v);
389
1.56k
    return o;
390
1.56k
}
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.56k
{
388
1.56k
    o << Token::toString(v);
389
1.56k
    return o;
390
1.56k
}
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.29k
{
394
1.29k
    if (v.data == "") {
395
818
        o << Token::toString(v.kind);
396
818
    } else if (v.kind == Token::OPERATOR) {
397
89
        o << "\"" << v.data << "\"";
398
390
    } else {
399
390
        o << "(" << Token::toString(v.kind) << ", \"" << v.data << "\")";
400
390
    }
401
1.29k
    return o;
402
1.29k
}
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.29k
{
394
1.29k
    if (v.data == "") {
395
818
        o << Token::toString(v.kind);
396
818
    } else if (v.kind == Token::OPERATOR) {
397
89
        o << "\"" << v.data << "\"";
398
390
    } else {
399
390
        o << "(" << Token::toString(v.kind) << ", \"" << v.data << "\")";
400
390
    }
401
1.29k
    return o;
402
1.29k
}
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