1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #include "tools/cddl/parse.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <unistd.h>
8*3f982cf4SFabien Sanglard
9*3f982cf4SFabien Sanglard #include <algorithm>
10*3f982cf4SFabien Sanglard #include <iostream>
11*3f982cf4SFabien Sanglard #include <memory>
12*3f982cf4SFabien Sanglard #include <sstream>
13*3f982cf4SFabien Sanglard #include <utility>
14*3f982cf4SFabien Sanglard #include <vector>
15*3f982cf4SFabien Sanglard
16*3f982cf4SFabien Sanglard #include "absl/strings/ascii.h"
17*3f982cf4SFabien Sanglard #include "absl/strings/match.h"
18*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
19*3f982cf4SFabien Sanglard #include "tools/cddl/logging.h"
20*3f982cf4SFabien Sanglard
21*3f982cf4SFabien Sanglard static_assert(sizeof(absl::string_view::size_type) == sizeof(size_t),
22*3f982cf4SFabien Sanglard "We assume string_view's size_type is the same as size_t. If "
23*3f982cf4SFabien Sanglard "not, the following file needs to be refactored");
24*3f982cf4SFabien Sanglard
25*3f982cf4SFabien Sanglard // All of the parsing methods in this file that operate on Parser are named
26*3f982cf4SFabien Sanglard // either Parse* or Skip* and are named according to the CDDL grammar in
27*3f982cf4SFabien Sanglard // grammar.abnf. Similarly, methods like ParseMemberKey1 attempt to parse the
28*3f982cf4SFabien Sanglard // first choice in the memberkey rule.
29*3f982cf4SFabien Sanglard struct Parser {
30*3f982cf4SFabien Sanglard Parser(const Parser&) = delete;
31*3f982cf4SFabien Sanglard Parser& operator=(const Parser&) = delete;
32*3f982cf4SFabien Sanglard
33*3f982cf4SFabien Sanglard const char* data;
34*3f982cf4SFabien Sanglard std::vector<std::unique_ptr<AstNode>> nodes;
35*3f982cf4SFabien Sanglard };
36*3f982cf4SFabien Sanglard
AddNode(Parser * p,AstNode::Type type,absl::string_view text,AstNode * children=nullptr)37*3f982cf4SFabien Sanglard AstNode* AddNode(Parser* p,
38*3f982cf4SFabien Sanglard AstNode::Type type,
39*3f982cf4SFabien Sanglard absl::string_view text,
40*3f982cf4SFabien Sanglard AstNode* children = nullptr) {
41*3f982cf4SFabien Sanglard p->nodes.emplace_back(new AstNode);
42*3f982cf4SFabien Sanglard AstNode* node = p->nodes.back().get();
43*3f982cf4SFabien Sanglard node->children = children;
44*3f982cf4SFabien Sanglard node->sibling = nullptr;
45*3f982cf4SFabien Sanglard node->type = type;
46*3f982cf4SFabien Sanglard node->text = std::string(text);
47*3f982cf4SFabien Sanglard return node;
48*3f982cf4SFabien Sanglard }
49*3f982cf4SFabien Sanglard
IsBinaryDigit(char x)50*3f982cf4SFabien Sanglard bool IsBinaryDigit(char x) {
51*3f982cf4SFabien Sanglard return '0' == x || x == '1';
52*3f982cf4SFabien Sanglard }
53*3f982cf4SFabien Sanglard
54*3f982cf4SFabien Sanglard // Determines if the given character matches regex '[a-zA-Z@_$]'.
IsExtendedAlpha(char x)55*3f982cf4SFabien Sanglard bool IsExtendedAlpha(char x) {
56*3f982cf4SFabien Sanglard return absl::ascii_isalpha(x) || x == '@' || x == '_' || x == '$';
57*3f982cf4SFabien Sanglard }
58*3f982cf4SFabien Sanglard
IsNewline(char x)59*3f982cf4SFabien Sanglard bool IsNewline(char x) {
60*3f982cf4SFabien Sanglard return x == '\r' || x == '\n';
61*3f982cf4SFabien Sanglard }
62*3f982cf4SFabien Sanglard
IsWhitespaceOrSemicolon(char c)63*3f982cf4SFabien Sanglard bool IsWhitespaceOrSemicolon(char c) {
64*3f982cf4SFabien Sanglard return c == ' ' || c == ';' || c == '\r' || c == '\n';
65*3f982cf4SFabien Sanglard }
66*3f982cf4SFabien Sanglard
SkipNewline(absl::string_view view)67*3f982cf4SFabien Sanglard absl::string_view SkipNewline(absl::string_view view) {
68*3f982cf4SFabien Sanglard size_t index = 0;
69*3f982cf4SFabien Sanglard while (IsNewline(view[index])) {
70*3f982cf4SFabien Sanglard ++index;
71*3f982cf4SFabien Sanglard }
72*3f982cf4SFabien Sanglard
73*3f982cf4SFabien Sanglard return view.substr(index);
74*3f982cf4SFabien Sanglard }
75*3f982cf4SFabien Sanglard
76*3f982cf4SFabien Sanglard // Skips over a comment that makes up the remainder of the current line.
SkipComment(absl::string_view view)77*3f982cf4SFabien Sanglard absl::string_view SkipComment(absl::string_view view) {
78*3f982cf4SFabien Sanglard size_t index = 0;
79*3f982cf4SFabien Sanglard if (view[index] == ';') {
80*3f982cf4SFabien Sanglard ++index;
81*3f982cf4SFabien Sanglard while (!IsNewline(view[index]) && index < view.length()) {
82*3f982cf4SFabien Sanglard CHECK(absl::ascii_isprint(view[index]));
83*3f982cf4SFabien Sanglard ++index;
84*3f982cf4SFabien Sanglard }
85*3f982cf4SFabien Sanglard
86*3f982cf4SFabien Sanglard while (IsNewline(view[index])) {
87*3f982cf4SFabien Sanglard ++index;
88*3f982cf4SFabien Sanglard }
89*3f982cf4SFabien Sanglard }
90*3f982cf4SFabien Sanglard
91*3f982cf4SFabien Sanglard return view.substr(index);
92*3f982cf4SFabien Sanglard }
93*3f982cf4SFabien Sanglard
SkipWhitespace(Parser * p,bool skip_comments=true)94*3f982cf4SFabien Sanglard void SkipWhitespace(Parser* p, bool skip_comments = true) {
95*3f982cf4SFabien Sanglard if (!skip_comments) {
96*3f982cf4SFabien Sanglard p->data = absl::StripLeadingAsciiWhitespace(p->data).data();
97*3f982cf4SFabien Sanglard return;
98*3f982cf4SFabien Sanglard }
99*3f982cf4SFabien Sanglard
100*3f982cf4SFabien Sanglard absl::string_view view = p->data;
101*3f982cf4SFabien Sanglard absl::string_view new_view;
102*3f982cf4SFabien Sanglard
103*3f982cf4SFabien Sanglard while (true) {
104*3f982cf4SFabien Sanglard new_view = SkipComment(view);
105*3f982cf4SFabien Sanglard if (new_view.data() == view.data()) {
106*3f982cf4SFabien Sanglard new_view = absl::StripLeadingAsciiWhitespace(view);
107*3f982cf4SFabien Sanglard }
108*3f982cf4SFabien Sanglard
109*3f982cf4SFabien Sanglard if (new_view == view) {
110*3f982cf4SFabien Sanglard break;
111*3f982cf4SFabien Sanglard }
112*3f982cf4SFabien Sanglard
113*3f982cf4SFabien Sanglard view = new_view;
114*3f982cf4SFabien Sanglard }
115*3f982cf4SFabien Sanglard
116*3f982cf4SFabien Sanglard p->data = new_view.data();
117*3f982cf4SFabien Sanglard }
118*3f982cf4SFabien Sanglard
TrySkipNewline(Parser * p)119*3f982cf4SFabien Sanglard bool TrySkipNewline(Parser* p) {
120*3f982cf4SFabien Sanglard auto* new_view = SkipNewline(p->data).data();
121*3f982cf4SFabien Sanglard bool is_changed = p->data == new_view;
122*3f982cf4SFabien Sanglard p->data = new_view;
123*3f982cf4SFabien Sanglard return is_changed;
124*3f982cf4SFabien Sanglard }
125*3f982cf4SFabien Sanglard
TrySkipCharacter(Parser * p,char c)126*3f982cf4SFabien Sanglard bool TrySkipCharacter(Parser* p, char c) {
127*3f982cf4SFabien Sanglard if (p->data[0] == c) {
128*3f982cf4SFabien Sanglard p->data++;
129*3f982cf4SFabien Sanglard return true;
130*3f982cf4SFabien Sanglard }
131*3f982cf4SFabien Sanglard
132*3f982cf4SFabien Sanglard return false;
133*3f982cf4SFabien Sanglard }
134*3f982cf4SFabien Sanglard
135*3f982cf4SFabien Sanglard enum class AssignType {
136*3f982cf4SFabien Sanglard kInvalid = -1,
137*3f982cf4SFabien Sanglard kAssign,
138*3f982cf4SFabien Sanglard kAssignT,
139*3f982cf4SFabien Sanglard kAssignG,
140*3f982cf4SFabien Sanglard };
141*3f982cf4SFabien Sanglard
ParseAssignmentType(Parser * p)142*3f982cf4SFabien Sanglard AssignType ParseAssignmentType(Parser* p) {
143*3f982cf4SFabien Sanglard const char* it = p->data;
144*3f982cf4SFabien Sanglard if (it[0] == '=') {
145*3f982cf4SFabien Sanglard p->data = it + 1;
146*3f982cf4SFabien Sanglard return AssignType::kAssign;
147*3f982cf4SFabien Sanglard } else if (it[0] == '/') {
148*3f982cf4SFabien Sanglard ++it;
149*3f982cf4SFabien Sanglard if (it[0] == '/' && it[1] == '=') {
150*3f982cf4SFabien Sanglard p->data = it + 2;
151*3f982cf4SFabien Sanglard return AssignType::kAssignG;
152*3f982cf4SFabien Sanglard } else if (it[0] == '=') {
153*3f982cf4SFabien Sanglard p->data = it + 1;
154*3f982cf4SFabien Sanglard return AssignType::kAssignT;
155*3f982cf4SFabien Sanglard }
156*3f982cf4SFabien Sanglard }
157*3f982cf4SFabien Sanglard return AssignType::kInvalid;
158*3f982cf4SFabien Sanglard }
159*3f982cf4SFabien Sanglard
160*3f982cf4SFabien Sanglard AstNode* ParseType1(Parser* p);
161*3f982cf4SFabien Sanglard AstNode* ParseType(Parser* p, bool skip_comments = true);
162*3f982cf4SFabien Sanglard AstNode* ParseId(Parser* p);
163*3f982cf4SFabien Sanglard
SkipUint(Parser * p)164*3f982cf4SFabien Sanglard void SkipUint(Parser* p) {
165*3f982cf4SFabien Sanglard absl::string_view view = p->data;
166*3f982cf4SFabien Sanglard
167*3f982cf4SFabien Sanglard bool is_binary = false;
168*3f982cf4SFabien Sanglard size_t index = 0;
169*3f982cf4SFabien Sanglard if (absl::StartsWith(view, "0b")) {
170*3f982cf4SFabien Sanglard is_binary = true;
171*3f982cf4SFabien Sanglard index = 2;
172*3f982cf4SFabien Sanglard } else if (absl::StartsWith(view, "0x")) {
173*3f982cf4SFabien Sanglard index = 2;
174*3f982cf4SFabien Sanglard }
175*3f982cf4SFabien Sanglard
176*3f982cf4SFabien Sanglard while (index < view.length() && absl::ascii_isdigit(view[index])) {
177*3f982cf4SFabien Sanglard if (is_binary) {
178*3f982cf4SFabien Sanglard CHECK(IsBinaryDigit(view[index]));
179*3f982cf4SFabien Sanglard }
180*3f982cf4SFabien Sanglard
181*3f982cf4SFabien Sanglard ++index;
182*3f982cf4SFabien Sanglard }
183*3f982cf4SFabien Sanglard
184*3f982cf4SFabien Sanglard p->data = view.substr(index).data();
185*3f982cf4SFabien Sanglard }
186*3f982cf4SFabien Sanglard
ParseNumber(Parser * p)187*3f982cf4SFabien Sanglard AstNode* ParseNumber(Parser* p) {
188*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
189*3f982cf4SFabien Sanglard if (!absl::ascii_isdigit(p_speculative.data[0]) &&
190*3f982cf4SFabien Sanglard p_speculative.data[0] != '-') {
191*3f982cf4SFabien Sanglard // TODO(btolsch): Add support for hexfloat, fraction, exponent.
192*3f982cf4SFabien Sanglard return nullptr;
193*3f982cf4SFabien Sanglard }
194*3f982cf4SFabien Sanglard if (p_speculative.data[0] == '-') {
195*3f982cf4SFabien Sanglard ++p_speculative.data;
196*3f982cf4SFabien Sanglard }
197*3f982cf4SFabien Sanglard
198*3f982cf4SFabien Sanglard SkipUint(&p_speculative);
199*3f982cf4SFabien Sanglard
200*3f982cf4SFabien Sanglard AstNode* node =
201*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kNumber,
202*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data));
203*3f982cf4SFabien Sanglard p->data = p_speculative.data;
204*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
205*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
206*3f982cf4SFabien Sanglard return node;
207*3f982cf4SFabien Sanglard }
208*3f982cf4SFabien Sanglard
ParseText(Parser * p)209*3f982cf4SFabien Sanglard AstNode* ParseText(Parser* p) {
210*3f982cf4SFabien Sanglard return nullptr;
211*3f982cf4SFabien Sanglard }
212*3f982cf4SFabien Sanglard
ParseBytes(Parser * p)213*3f982cf4SFabien Sanglard AstNode* ParseBytes(Parser* p) {
214*3f982cf4SFabien Sanglard return nullptr;
215*3f982cf4SFabien Sanglard }
216*3f982cf4SFabien Sanglard
217*3f982cf4SFabien Sanglard // Returns whether |c| could be the first character in a valid "value" string.
218*3f982cf4SFabien Sanglard // This is not a guarantee however, since 'h' and 'b' could also indicate the
219*3f982cf4SFabien Sanglard // start of an ID, but value needs to be tried first.
IsValue(char c)220*3f982cf4SFabien Sanglard bool IsValue(char c) {
221*3f982cf4SFabien Sanglard return (c == '-' || absl::ascii_isdigit(c) || // FIRST(number)
222*3f982cf4SFabien Sanglard c == '"' || // FIRST(text)
223*3f982cf4SFabien Sanglard c == '\'' || c == 'h' || c == 'b'); // FIRST(bytes)
224*3f982cf4SFabien Sanglard }
225*3f982cf4SFabien Sanglard
ParseValue(Parser * p)226*3f982cf4SFabien Sanglard AstNode* ParseValue(Parser* p) {
227*3f982cf4SFabien Sanglard AstNode* node = ParseNumber(p);
228*3f982cf4SFabien Sanglard if (!node) {
229*3f982cf4SFabien Sanglard node = ParseText(p);
230*3f982cf4SFabien Sanglard }
231*3f982cf4SFabien Sanglard if (!node) {
232*3f982cf4SFabien Sanglard ParseBytes(p);
233*3f982cf4SFabien Sanglard }
234*3f982cf4SFabien Sanglard return node;
235*3f982cf4SFabien Sanglard }
236*3f982cf4SFabien Sanglard
237*3f982cf4SFabien Sanglard // Determines whether an occurrence operator (such as '*' or '?') prefacing
238*3f982cf4SFabien Sanglard // the group definition occurs before the next whitespace character, and
239*3f982cf4SFabien Sanglard // creates a new Occurrence node if so.
ParseOccur(Parser * p)240*3f982cf4SFabien Sanglard AstNode* ParseOccur(Parser* p) {
241*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
242*3f982cf4SFabien Sanglard
243*3f982cf4SFabien Sanglard if (*p_speculative.data == '?' || *p_speculative.data == '+') {
244*3f982cf4SFabien Sanglard p_speculative.data++;
245*3f982cf4SFabien Sanglard } else {
246*3f982cf4SFabien Sanglard SkipUint(&p_speculative);
247*3f982cf4SFabien Sanglard if (*p_speculative.data++ != '*') {
248*3f982cf4SFabien Sanglard return nullptr;
249*3f982cf4SFabien Sanglard }
250*3f982cf4SFabien Sanglard SkipUint(&p_speculative);
251*3f982cf4SFabien Sanglard }
252*3f982cf4SFabien Sanglard
253*3f982cf4SFabien Sanglard AstNode* node =
254*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kOccur,
255*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data));
256*3f982cf4SFabien Sanglard p->data = p_speculative.data;
257*3f982cf4SFabien Sanglard return node;
258*3f982cf4SFabien Sanglard }
259*3f982cf4SFabien Sanglard
ParseTypeKeyFromComment(Parser * p)260*3f982cf4SFabien Sanglard absl::optional<std::string> ParseTypeKeyFromComment(Parser* p) {
261*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
262*3f982cf4SFabien Sanglard if (!TrySkipCharacter(&p_speculative, ';')) {
263*3f982cf4SFabien Sanglard return absl::nullopt;
264*3f982cf4SFabien Sanglard }
265*3f982cf4SFabien Sanglard
266*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
267*3f982cf4SFabien Sanglard const char kTypeKeyPrefix[] = "type key";
268*3f982cf4SFabien Sanglard if (!absl::StartsWith(p_speculative.data, kTypeKeyPrefix)) {
269*3f982cf4SFabien Sanglard return absl::nullopt;
270*3f982cf4SFabien Sanglard }
271*3f982cf4SFabien Sanglard p_speculative.data += strlen(kTypeKeyPrefix);
272*3f982cf4SFabien Sanglard
273*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
274*3f982cf4SFabien Sanglard Parser p_speculative2{p_speculative.data};
275*3f982cf4SFabien Sanglard for (; absl::ascii_isdigit(p_speculative2.data[0]); p_speculative2.data++) {
276*3f982cf4SFabien Sanglard }
277*3f982cf4SFabien Sanglard auto result = absl::string_view(p_speculative.data,
278*3f982cf4SFabien Sanglard p_speculative2.data - p_speculative.data);
279*3f982cf4SFabien Sanglard p->data = p_speculative2.data;
280*3f982cf4SFabien Sanglard return std::string(result.data()).substr(0, result.length());
281*3f982cf4SFabien Sanglard }
282*3f982cf4SFabien Sanglard
ParseMemberKeyFromComment(Parser * p)283*3f982cf4SFabien Sanglard AstNode* ParseMemberKeyFromComment(Parser* p) {
284*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
285*3f982cf4SFabien Sanglard if (!TrySkipCharacter(&p_speculative, ';')) {
286*3f982cf4SFabien Sanglard return nullptr;
287*3f982cf4SFabien Sanglard }
288*3f982cf4SFabien Sanglard
289*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
290*3f982cf4SFabien Sanglard
291*3f982cf4SFabien Sanglard AstNode* value = ParseId(&p_speculative);
292*3f982cf4SFabien Sanglard if (!value) {
293*3f982cf4SFabien Sanglard return nullptr;
294*3f982cf4SFabien Sanglard }
295*3f982cf4SFabien Sanglard
296*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
297*3f982cf4SFabien Sanglard if (!TrySkipNewline(&p_speculative)) {
298*3f982cf4SFabien Sanglard return nullptr;
299*3f982cf4SFabien Sanglard }
300*3f982cf4SFabien Sanglard
301*3f982cf4SFabien Sanglard AstNode* node = AddNode(p, AstNode::Type::kMemberKey, value->text, value);
302*3f982cf4SFabien Sanglard p->data = p_speculative.data;
303*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
304*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
305*3f982cf4SFabien Sanglard
306*3f982cf4SFabien Sanglard return node;
307*3f982cf4SFabien Sanglard }
308*3f982cf4SFabien Sanglard
ParseMemberKey1(Parser * p)309*3f982cf4SFabien Sanglard AstNode* ParseMemberKey1(Parser* p) {
310*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
311*3f982cf4SFabien Sanglard if (!ParseType1(&p_speculative)) {
312*3f982cf4SFabien Sanglard return nullptr;
313*3f982cf4SFabien Sanglard }
314*3f982cf4SFabien Sanglard
315*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
316*3f982cf4SFabien Sanglard
317*3f982cf4SFabien Sanglard if (*p_speculative.data++ != '=' || *p_speculative.data++ != '>') {
318*3f982cf4SFabien Sanglard return nullptr;
319*3f982cf4SFabien Sanglard }
320*3f982cf4SFabien Sanglard AstNode* node =
321*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kMemberKey,
322*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data));
323*3f982cf4SFabien Sanglard p->data = p_speculative.data;
324*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
325*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
326*3f982cf4SFabien Sanglard return node;
327*3f982cf4SFabien Sanglard }
328*3f982cf4SFabien Sanglard
ParseMemberKey2(Parser * p)329*3f982cf4SFabien Sanglard AstNode* ParseMemberKey2(Parser* p) {
330*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
331*3f982cf4SFabien Sanglard AstNode* id = ParseId(&p_speculative);
332*3f982cf4SFabien Sanglard if (!id) {
333*3f982cf4SFabien Sanglard return nullptr;
334*3f982cf4SFabien Sanglard }
335*3f982cf4SFabien Sanglard
336*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
337*3f982cf4SFabien Sanglard
338*3f982cf4SFabien Sanglard if (*p_speculative.data++ != ':') {
339*3f982cf4SFabien Sanglard return nullptr;
340*3f982cf4SFabien Sanglard }
341*3f982cf4SFabien Sanglard
342*3f982cf4SFabien Sanglard AstNode* node =
343*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kMemberKey,
344*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data), id);
345*3f982cf4SFabien Sanglard p->data = p_speculative.data;
346*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
347*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
348*3f982cf4SFabien Sanglard return node;
349*3f982cf4SFabien Sanglard }
350*3f982cf4SFabien Sanglard
ParseMemberKey3(Parser * p)351*3f982cf4SFabien Sanglard AstNode* ParseMemberKey3(Parser* p) {
352*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
353*3f982cf4SFabien Sanglard AstNode* value = ParseValue(&p_speculative);
354*3f982cf4SFabien Sanglard if (!value) {
355*3f982cf4SFabien Sanglard return nullptr;
356*3f982cf4SFabien Sanglard }
357*3f982cf4SFabien Sanglard
358*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
359*3f982cf4SFabien Sanglard
360*3f982cf4SFabien Sanglard if (*p_speculative.data++ != ':') {
361*3f982cf4SFabien Sanglard return nullptr;
362*3f982cf4SFabien Sanglard }
363*3f982cf4SFabien Sanglard AstNode* node =
364*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kMemberKey,
365*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data), value);
366*3f982cf4SFabien Sanglard p->data = p_speculative.data;
367*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
368*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
369*3f982cf4SFabien Sanglard return node;
370*3f982cf4SFabien Sanglard }
371*3f982cf4SFabien Sanglard
372*3f982cf4SFabien Sanglard // Iteratively tries all valid member key formats, retuning a Node representing
373*3f982cf4SFabien Sanglard // the member key if found or nullptr if not.
ParseMemberKey(Parser * p)374*3f982cf4SFabien Sanglard AstNode* ParseMemberKey(Parser* p) {
375*3f982cf4SFabien Sanglard AstNode* node = ParseMemberKey1(p);
376*3f982cf4SFabien Sanglard if (!node) {
377*3f982cf4SFabien Sanglard node = ParseMemberKey2(p);
378*3f982cf4SFabien Sanglard }
379*3f982cf4SFabien Sanglard if (!node) {
380*3f982cf4SFabien Sanglard node = ParseMemberKey3(p);
381*3f982cf4SFabien Sanglard }
382*3f982cf4SFabien Sanglard return node;
383*3f982cf4SFabien Sanglard }
384*3f982cf4SFabien Sanglard
385*3f982cf4SFabien Sanglard AstNode* ParseGroupEntry(Parser* p);
386*3f982cf4SFabien Sanglard
SkipOptionalComma(Parser * p)387*3f982cf4SFabien Sanglard bool SkipOptionalComma(Parser* p) {
388*3f982cf4SFabien Sanglard SkipWhitespace(p);
389*3f982cf4SFabien Sanglard if (p->data[0] == ',') {
390*3f982cf4SFabien Sanglard ++p->data;
391*3f982cf4SFabien Sanglard SkipWhitespace(p);
392*3f982cf4SFabien Sanglard }
393*3f982cf4SFabien Sanglard return true;
394*3f982cf4SFabien Sanglard }
395*3f982cf4SFabien Sanglard
396*3f982cf4SFabien Sanglard // Parse the group contained inside of other brackets. Since the brackets around
397*3f982cf4SFabien Sanglard // the group are optional inside of other brackets, we can't directly call
398*3f982cf4SFabien Sanglard // ParseGroupEntry(...) and instead need this wrapper around it.
ParseGroupChoice(Parser * p)399*3f982cf4SFabien Sanglard AstNode* ParseGroupChoice(Parser* p) {
400*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
401*3f982cf4SFabien Sanglard AstNode* tail = nullptr;
402*3f982cf4SFabien Sanglard AstNode* group_node =
403*3f982cf4SFabien Sanglard AddNode(&p_speculative, AstNode::Type::kGrpchoice, absl::string_view());
404*3f982cf4SFabien Sanglard const char* group_node_text = p_speculative.data;
405*3f982cf4SFabien Sanglard while (true) {
406*3f982cf4SFabien Sanglard const char* orig = p_speculative.data;
407*3f982cf4SFabien Sanglard AstNode* group_entry = ParseGroupEntry(&p_speculative);
408*3f982cf4SFabien Sanglard if (!group_entry) {
409*3f982cf4SFabien Sanglard p_speculative.data = orig;
410*3f982cf4SFabien Sanglard if (!group_node->children) {
411*3f982cf4SFabien Sanglard return nullptr;
412*3f982cf4SFabien Sanglard }
413*3f982cf4SFabien Sanglard group_node->text =
414*3f982cf4SFabien Sanglard std::string(group_node_text, p_speculative.data - group_node_text);
415*3f982cf4SFabien Sanglard p->data = p_speculative.data;
416*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
417*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
418*3f982cf4SFabien Sanglard return group_node;
419*3f982cf4SFabien Sanglard }
420*3f982cf4SFabien Sanglard if (!group_node->children) {
421*3f982cf4SFabien Sanglard group_node->children = group_entry;
422*3f982cf4SFabien Sanglard }
423*3f982cf4SFabien Sanglard if (tail) {
424*3f982cf4SFabien Sanglard tail->sibling = group_entry;
425*3f982cf4SFabien Sanglard }
426*3f982cf4SFabien Sanglard tail = group_entry;
427*3f982cf4SFabien Sanglard if (!SkipOptionalComma(&p_speculative)) {
428*3f982cf4SFabien Sanglard return nullptr;
429*3f982cf4SFabien Sanglard }
430*3f982cf4SFabien Sanglard }
431*3f982cf4SFabien Sanglard }
432*3f982cf4SFabien Sanglard
ParseGroup(Parser * p)433*3f982cf4SFabien Sanglard AstNode* ParseGroup(Parser* p) {
434*3f982cf4SFabien Sanglard const char* orig = p->data;
435*3f982cf4SFabien Sanglard AstNode* group_choice = ParseGroupChoice(p);
436*3f982cf4SFabien Sanglard if (!group_choice) {
437*3f982cf4SFabien Sanglard return nullptr;
438*3f982cf4SFabien Sanglard }
439*3f982cf4SFabien Sanglard return AddNode(p, AstNode::Type::kGroup,
440*3f982cf4SFabien Sanglard absl::string_view(orig, p->data - orig), group_choice);
441*3f982cf4SFabien Sanglard }
442*3f982cf4SFabien Sanglard
443*3f982cf4SFabien Sanglard // Parse optional range operator .. (inlcusive) or ... (exclusive)
444*3f982cf4SFabien Sanglard // ABNF rule: rangeop = "..." / ".."
ParseRangeop(Parser * p)445*3f982cf4SFabien Sanglard AstNode* ParseRangeop(Parser* p) {
446*3f982cf4SFabien Sanglard absl::string_view view(p->data);
447*3f982cf4SFabien Sanglard if (absl::StartsWith(view, "...")) {
448*3f982cf4SFabien Sanglard // rangeop ...
449*3f982cf4SFabien Sanglard p->data += 3;
450*3f982cf4SFabien Sanglard return AddNode(p, AstNode::Type::kRangeop, view.substr(0, 3));
451*3f982cf4SFabien Sanglard } else if (absl::StartsWith(view, "..")) {
452*3f982cf4SFabien Sanglard // rangeop ..
453*3f982cf4SFabien Sanglard p->data += 2;
454*3f982cf4SFabien Sanglard return AddNode(p, AstNode::Type::kRangeop, view.substr(0, 2));
455*3f982cf4SFabien Sanglard }
456*3f982cf4SFabien Sanglard return nullptr;
457*3f982cf4SFabien Sanglard }
458*3f982cf4SFabien Sanglard
459*3f982cf4SFabien Sanglard // Parse optional control operator .id
460*3f982cf4SFabien Sanglard // ABNF rule: ctlop = "." id
ParseCtlop(Parser * p)461*3f982cf4SFabien Sanglard AstNode* ParseCtlop(Parser* p) {
462*3f982cf4SFabien Sanglard absl::string_view view(p->data);
463*3f982cf4SFabien Sanglard if (!absl::StartsWith(view, ".")) {
464*3f982cf4SFabien Sanglard return nullptr;
465*3f982cf4SFabien Sanglard }
466*3f982cf4SFabien Sanglard ++p->data;
467*3f982cf4SFabien Sanglard AstNode* id = ParseId(p);
468*3f982cf4SFabien Sanglard if (!id) {
469*3f982cf4SFabien Sanglard return nullptr;
470*3f982cf4SFabien Sanglard }
471*3f982cf4SFabien Sanglard return AddNode(p, AstNode::Type::kCtlop,
472*3f982cf4SFabien Sanglard view.substr(0, p->data - view.begin()), id);
473*3f982cf4SFabien Sanglard }
474*3f982cf4SFabien Sanglard
ParseType2(Parser * p)475*3f982cf4SFabien Sanglard AstNode* ParseType2(Parser* p) {
476*3f982cf4SFabien Sanglard const char* orig = p->data;
477*3f982cf4SFabien Sanglard const char* it = p->data;
478*3f982cf4SFabien Sanglard AstNode* node = AddNode(p, AstNode::Type::kType2, absl::string_view());
479*3f982cf4SFabien Sanglard if (IsValue(it[0])) {
480*3f982cf4SFabien Sanglard AstNode* value = ParseValue(p);
481*3f982cf4SFabien Sanglard if (!value) {
482*3f982cf4SFabien Sanglard if (it[0] == 'h' || it[0] == 'b') {
483*3f982cf4SFabien Sanglard AstNode* id = ParseId(p);
484*3f982cf4SFabien Sanglard if (!id) {
485*3f982cf4SFabien Sanglard return nullptr;
486*3f982cf4SFabien Sanglard }
487*3f982cf4SFabien Sanglard id->type = AstNode::Type::kTypename;
488*3f982cf4SFabien Sanglard node->children = id;
489*3f982cf4SFabien Sanglard } else {
490*3f982cf4SFabien Sanglard return nullptr;
491*3f982cf4SFabien Sanglard }
492*3f982cf4SFabien Sanglard } else {
493*3f982cf4SFabien Sanglard node->children = value;
494*3f982cf4SFabien Sanglard }
495*3f982cf4SFabien Sanglard } else if (IsExtendedAlpha(it[0])) {
496*3f982cf4SFabien Sanglard AstNode* id = ParseId(p);
497*3f982cf4SFabien Sanglard if (!id) {
498*3f982cf4SFabien Sanglard return nullptr;
499*3f982cf4SFabien Sanglard }
500*3f982cf4SFabien Sanglard if (p->data[0] == '<') {
501*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to use a generic argument, "
502*3f982cf4SFabien Sanglard "which we don't support"
503*3f982cf4SFabien Sanglard << std::endl;
504*3f982cf4SFabien Sanglard return nullptr;
505*3f982cf4SFabien Sanglard }
506*3f982cf4SFabien Sanglard id->type = AstNode::Type::kTypename;
507*3f982cf4SFabien Sanglard node->children = id;
508*3f982cf4SFabien Sanglard } else if (it[0] == '(') {
509*3f982cf4SFabien Sanglard p->data = it + 1;
510*3f982cf4SFabien Sanglard SkipWhitespace(p);
511*3f982cf4SFabien Sanglard if (p->data[0] == ')') {
512*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to provide an empty Type (), "
513*3f982cf4SFabien Sanglard "which we don't support"
514*3f982cf4SFabien Sanglard << std::endl;
515*3f982cf4SFabien Sanglard return nullptr;
516*3f982cf4SFabien Sanglard }
517*3f982cf4SFabien Sanglard AstNode* type = ParseType(p);
518*3f982cf4SFabien Sanglard if (!type) {
519*3f982cf4SFabien Sanglard return nullptr;
520*3f982cf4SFabien Sanglard }
521*3f982cf4SFabien Sanglard SkipWhitespace(p);
522*3f982cf4SFabien Sanglard if (p->data[0] != ')') {
523*3f982cf4SFabien Sanglard return nullptr;
524*3f982cf4SFabien Sanglard }
525*3f982cf4SFabien Sanglard ++p->data;
526*3f982cf4SFabien Sanglard node->children = type;
527*3f982cf4SFabien Sanglard } else if (it[0] == '{') {
528*3f982cf4SFabien Sanglard p->data = it + 1;
529*3f982cf4SFabien Sanglard SkipWhitespace(p);
530*3f982cf4SFabien Sanglard if (p->data[0] == '}') {
531*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to provide an empty Group {}, "
532*3f982cf4SFabien Sanglard "which we don't support"
533*3f982cf4SFabien Sanglard << std::endl;
534*3f982cf4SFabien Sanglard return nullptr;
535*3f982cf4SFabien Sanglard }
536*3f982cf4SFabien Sanglard AstNode* group = ParseGroup(p);
537*3f982cf4SFabien Sanglard if (!group) {
538*3f982cf4SFabien Sanglard return nullptr;
539*3f982cf4SFabien Sanglard }
540*3f982cf4SFabien Sanglard SkipWhitespace(p);
541*3f982cf4SFabien Sanglard if (p->data[0] != '}') {
542*3f982cf4SFabien Sanglard return nullptr;
543*3f982cf4SFabien Sanglard }
544*3f982cf4SFabien Sanglard ++p->data;
545*3f982cf4SFabien Sanglard node->children = group;
546*3f982cf4SFabien Sanglard } else if (it[0] == '[') {
547*3f982cf4SFabien Sanglard p->data = it + 1;
548*3f982cf4SFabien Sanglard SkipWhitespace(p);
549*3f982cf4SFabien Sanglard AstNode* group = ParseGroup(p);
550*3f982cf4SFabien Sanglard if (!group) {
551*3f982cf4SFabien Sanglard return nullptr;
552*3f982cf4SFabien Sanglard }
553*3f982cf4SFabien Sanglard SkipWhitespace(p);
554*3f982cf4SFabien Sanglard if (p->data[0] != ']') {
555*3f982cf4SFabien Sanglard return nullptr;
556*3f982cf4SFabien Sanglard }
557*3f982cf4SFabien Sanglard ++p->data;
558*3f982cf4SFabien Sanglard node->children = group;
559*3f982cf4SFabien Sanglard } else if (it[0] == '~') {
560*3f982cf4SFabien Sanglard p->data = it + 1;
561*3f982cf4SFabien Sanglard SkipWhitespace(p);
562*3f982cf4SFabien Sanglard if (!ParseId(p)) {
563*3f982cf4SFabien Sanglard return nullptr;
564*3f982cf4SFabien Sanglard }
565*3f982cf4SFabien Sanglard if (p->data[0] == '<') {
566*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to use a generic argument, "
567*3f982cf4SFabien Sanglard "which we don't support"
568*3f982cf4SFabien Sanglard << std::endl;
569*3f982cf4SFabien Sanglard return nullptr;
570*3f982cf4SFabien Sanglard }
571*3f982cf4SFabien Sanglard } else if (it[0] == '&') {
572*3f982cf4SFabien Sanglard p->data = it + 1;
573*3f982cf4SFabien Sanglard SkipWhitespace(p);
574*3f982cf4SFabien Sanglard if (p->data[0] == '(') {
575*3f982cf4SFabien Sanglard ++p->data;
576*3f982cf4SFabien Sanglard SkipWhitespace(p);
577*3f982cf4SFabien Sanglard if (p->data[0] == ')') {
578*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to provide an empty Type &(),"
579*3f982cf4SFabien Sanglard " which we don't support"
580*3f982cf4SFabien Sanglard << std::endl;
581*3f982cf4SFabien Sanglard return nullptr;
582*3f982cf4SFabien Sanglard }
583*3f982cf4SFabien Sanglard AstNode* group = ParseGroup(p);
584*3f982cf4SFabien Sanglard if (!group) {
585*3f982cf4SFabien Sanglard return nullptr;
586*3f982cf4SFabien Sanglard }
587*3f982cf4SFabien Sanglard SkipWhitespace(p);
588*3f982cf4SFabien Sanglard if (p->data[0] != ')') {
589*3f982cf4SFabien Sanglard return nullptr;
590*3f982cf4SFabien Sanglard }
591*3f982cf4SFabien Sanglard ++p->data;
592*3f982cf4SFabien Sanglard node->children = group;
593*3f982cf4SFabien Sanglard } else {
594*3f982cf4SFabien Sanglard AstNode* id = ParseId(p);
595*3f982cf4SFabien Sanglard if (id) {
596*3f982cf4SFabien Sanglard if (p->data[0] == '<') {
597*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to use a generic argument, "
598*3f982cf4SFabien Sanglard "which we don't support"
599*3f982cf4SFabien Sanglard << std::endl;
600*3f982cf4SFabien Sanglard return nullptr;
601*3f982cf4SFabien Sanglard }
602*3f982cf4SFabien Sanglard id->type = AstNode::Type::kGroupname;
603*3f982cf4SFabien Sanglard node->children = id;
604*3f982cf4SFabien Sanglard } else {
605*3f982cf4SFabien Sanglard return nullptr;
606*3f982cf4SFabien Sanglard }
607*3f982cf4SFabien Sanglard }
608*3f982cf4SFabien Sanglard } else if (it[0] == '#') {
609*3f982cf4SFabien Sanglard ++it;
610*3f982cf4SFabien Sanglard if (it[0] == '6') {
611*3f982cf4SFabien Sanglard ++it;
612*3f982cf4SFabien Sanglard if (it[0] == '.') {
613*3f982cf4SFabien Sanglard p->data = it + 1;
614*3f982cf4SFabien Sanglard SkipUint(p);
615*3f982cf4SFabien Sanglard it = p->data;
616*3f982cf4SFabien Sanglard }
617*3f982cf4SFabien Sanglard if (it[0] != '(') {
618*3f982cf4SFabien Sanglard return nullptr;
619*3f982cf4SFabien Sanglard }
620*3f982cf4SFabien Sanglard p->data = ++it;
621*3f982cf4SFabien Sanglard SkipWhitespace(p);
622*3f982cf4SFabien Sanglard AstNode* type = ParseType(p);
623*3f982cf4SFabien Sanglard if (!type) {
624*3f982cf4SFabien Sanglard return nullptr;
625*3f982cf4SFabien Sanglard }
626*3f982cf4SFabien Sanglard SkipWhitespace(p);
627*3f982cf4SFabien Sanglard if (p->data[0] != ')') {
628*3f982cf4SFabien Sanglard return nullptr;
629*3f982cf4SFabien Sanglard }
630*3f982cf4SFabien Sanglard ++p->data;
631*3f982cf4SFabien Sanglard node->children = type;
632*3f982cf4SFabien Sanglard } else if (absl::ascii_isdigit(it[0])) {
633*3f982cf4SFabien Sanglard std::cerr << "# MAJOR unimplemented" << std::endl;
634*3f982cf4SFabien Sanglard return nullptr;
635*3f982cf4SFabien Sanglard } else {
636*3f982cf4SFabien Sanglard p->data = it;
637*3f982cf4SFabien Sanglard }
638*3f982cf4SFabien Sanglard } else {
639*3f982cf4SFabien Sanglard return nullptr;
640*3f982cf4SFabien Sanglard }
641*3f982cf4SFabien Sanglard node->text = std::string(orig, p->data - orig);
642*3f982cf4SFabien Sanglard return node;
643*3f982cf4SFabien Sanglard }
644*3f982cf4SFabien Sanglard
ParseType1(Parser * p)645*3f982cf4SFabien Sanglard AstNode* ParseType1(Parser* p) {
646*3f982cf4SFabien Sanglard const char* orig = p->data;
647*3f982cf4SFabien Sanglard AstNode* type2 = ParseType2(p);
648*3f982cf4SFabien Sanglard if (!type2) {
649*3f982cf4SFabien Sanglard return nullptr;
650*3f982cf4SFabien Sanglard }
651*3f982cf4SFabien Sanglard SkipWhitespace(p, false);
652*3f982cf4SFabien Sanglard AstNode* rangeop_or_ctlop = ParseRangeop(p);
653*3f982cf4SFabien Sanglard if (!rangeop_or_ctlop) {
654*3f982cf4SFabien Sanglard rangeop_or_ctlop = ParseCtlop(p);
655*3f982cf4SFabien Sanglard }
656*3f982cf4SFabien Sanglard if (rangeop_or_ctlop) {
657*3f982cf4SFabien Sanglard SkipWhitespace(p, false);
658*3f982cf4SFabien Sanglard AstNode* param = ParseType2(p);
659*3f982cf4SFabien Sanglard if (!param) {
660*3f982cf4SFabien Sanglard return nullptr;
661*3f982cf4SFabien Sanglard }
662*3f982cf4SFabien Sanglard type2->sibling = rangeop_or_ctlop;
663*3f982cf4SFabien Sanglard rangeop_or_ctlop->sibling = param;
664*3f982cf4SFabien Sanglard }
665*3f982cf4SFabien Sanglard return AddNode(p, AstNode::Type::kType1,
666*3f982cf4SFabien Sanglard absl::string_view(orig, p->data - orig), type2);
667*3f982cf4SFabien Sanglard }
668*3f982cf4SFabien Sanglard
669*3f982cf4SFabien Sanglard // Different valid types for a call are specified as type1 / type2, so we split
670*3f982cf4SFabien Sanglard // at the '/' character and process each allowed type separately.
ParseType(Parser * p,bool skip_comments)671*3f982cf4SFabien Sanglard AstNode* ParseType(Parser* p, bool skip_comments) {
672*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
673*3f982cf4SFabien Sanglard
674*3f982cf4SFabien Sanglard // Parse all allowed types into a linked list starting in type1's sibling ptr.
675*3f982cf4SFabien Sanglard AstNode* type1 = ParseType1(&p_speculative);
676*3f982cf4SFabien Sanglard if (!type1) {
677*3f982cf4SFabien Sanglard return nullptr;
678*3f982cf4SFabien Sanglard }
679*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, skip_comments);
680*3f982cf4SFabien Sanglard
681*3f982cf4SFabien Sanglard AstNode* tail = type1;
682*3f982cf4SFabien Sanglard while (*p_speculative.data == '/') {
683*3f982cf4SFabien Sanglard ++p_speculative.data;
684*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, skip_comments);
685*3f982cf4SFabien Sanglard
686*3f982cf4SFabien Sanglard AstNode* next_type1 = ParseType1(&p_speculative);
687*3f982cf4SFabien Sanglard if (!next_type1) {
688*3f982cf4SFabien Sanglard return nullptr;
689*3f982cf4SFabien Sanglard }
690*3f982cf4SFabien Sanglard tail->sibling = next_type1;
691*3f982cf4SFabien Sanglard tail = next_type1;
692*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, skip_comments);
693*3f982cf4SFabien Sanglard }
694*3f982cf4SFabien Sanglard
695*3f982cf4SFabien Sanglard // Create a new AstNode with all parsed types.
696*3f982cf4SFabien Sanglard AstNode* node =
697*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kType,
698*3f982cf4SFabien Sanglard absl::string_view(p->data, p_speculative.data - p->data), type1);
699*3f982cf4SFabien Sanglard p->data = p_speculative.data;
700*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
701*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
702*3f982cf4SFabien Sanglard return node;
703*3f982cf4SFabien Sanglard }
704*3f982cf4SFabien Sanglard
ParseId(Parser * p)705*3f982cf4SFabien Sanglard AstNode* ParseId(Parser* p) {
706*3f982cf4SFabien Sanglard const char* id = p->data;
707*3f982cf4SFabien Sanglard
708*3f982cf4SFabien Sanglard // If the id doesnt start with a valid name character, return null.
709*3f982cf4SFabien Sanglard if (!IsExtendedAlpha(id[0])) {
710*3f982cf4SFabien Sanglard return nullptr;
711*3f982cf4SFabien Sanglard }
712*3f982cf4SFabien Sanglard
713*3f982cf4SFabien Sanglard // Read through the name character by character and make sure it's valid.
714*3f982cf4SFabien Sanglard const char* it = id + 1;
715*3f982cf4SFabien Sanglard while (true) {
716*3f982cf4SFabien Sanglard if (it[0] == '-' || it[0] == '.') {
717*3f982cf4SFabien Sanglard ++it;
718*3f982cf4SFabien Sanglard if (!IsExtendedAlpha(it[0]) && !absl::ascii_isdigit(it[0])) {
719*3f982cf4SFabien Sanglard return nullptr;
720*3f982cf4SFabien Sanglard }
721*3f982cf4SFabien Sanglard ++it;
722*3f982cf4SFabien Sanglard } else if (IsExtendedAlpha(it[0]) || absl::ascii_isdigit(it[0])) {
723*3f982cf4SFabien Sanglard ++it;
724*3f982cf4SFabien Sanglard } else {
725*3f982cf4SFabien Sanglard break;
726*3f982cf4SFabien Sanglard }
727*3f982cf4SFabien Sanglard }
728*3f982cf4SFabien Sanglard
729*3f982cf4SFabien Sanglard // Create and return a new node with the parsed data.
730*3f982cf4SFabien Sanglard AstNode* node =
731*3f982cf4SFabien Sanglard AddNode(p, AstNode::Type::kId, absl::string_view(p->data, it - p->data));
732*3f982cf4SFabien Sanglard p->data = it;
733*3f982cf4SFabien Sanglard return node;
734*3f982cf4SFabien Sanglard }
735*3f982cf4SFabien Sanglard
UpdateNodesForGroupEntry(Parser * p,Parser * p_speculative,AstNode * occur,AstNode * member_key,AstNode * type)736*3f982cf4SFabien Sanglard AstNode* UpdateNodesForGroupEntry(Parser* p,
737*3f982cf4SFabien Sanglard Parser* p_speculative,
738*3f982cf4SFabien Sanglard AstNode* occur,
739*3f982cf4SFabien Sanglard AstNode* member_key,
740*3f982cf4SFabien Sanglard AstNode* type) {
741*3f982cf4SFabien Sanglard AstNode* node = AddNode(p, AstNode::Type::kGrpent, absl::string_view());
742*3f982cf4SFabien Sanglard if (occur) {
743*3f982cf4SFabien Sanglard node->children = occur;
744*3f982cf4SFabien Sanglard if (member_key) {
745*3f982cf4SFabien Sanglard occur->sibling = member_key;
746*3f982cf4SFabien Sanglard member_key->sibling = type;
747*3f982cf4SFabien Sanglard } else {
748*3f982cf4SFabien Sanglard occur->sibling = type;
749*3f982cf4SFabien Sanglard }
750*3f982cf4SFabien Sanglard } else if (member_key) {
751*3f982cf4SFabien Sanglard node->children = member_key;
752*3f982cf4SFabien Sanglard member_key->sibling = type;
753*3f982cf4SFabien Sanglard } else {
754*3f982cf4SFabien Sanglard node->children = type;
755*3f982cf4SFabien Sanglard }
756*3f982cf4SFabien Sanglard node->text = std::string(p->data, p_speculative->data - p->data);
757*3f982cf4SFabien Sanglard p->data = p_speculative->data;
758*3f982cf4SFabien Sanglard std::move(p_speculative->nodes.begin(), p_speculative->nodes.end(),
759*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
760*3f982cf4SFabien Sanglard return node;
761*3f982cf4SFabien Sanglard }
762*3f982cf4SFabien Sanglard
763*3f982cf4SFabien Sanglard // Parse a group entry of form <id_num>: <type> ; <name>
ParseGroupEntryWithNameInComment(Parser * p)764*3f982cf4SFabien Sanglard AstNode* ParseGroupEntryWithNameInComment(Parser* p) {
765*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
766*3f982cf4SFabien Sanglard AstNode* occur = ParseOccur(&p_speculative);
767*3f982cf4SFabien Sanglard if (occur) {
768*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
769*3f982cf4SFabien Sanglard }
770*3f982cf4SFabien Sanglard AstNode* member_key_num = ParseValue(&p_speculative);
771*3f982cf4SFabien Sanglard if (!member_key_num) {
772*3f982cf4SFabien Sanglard return nullptr;
773*3f982cf4SFabien Sanglard }
774*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
775*3f982cf4SFabien Sanglard if (*p_speculative.data++ != ':') {
776*3f982cf4SFabien Sanglard return nullptr;
777*3f982cf4SFabien Sanglard }
778*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
779*3f982cf4SFabien Sanglard AstNode* type = ParseType(&p_speculative, false);
780*3f982cf4SFabien Sanglard if (!type) {
781*3f982cf4SFabien Sanglard return nullptr;
782*3f982cf4SFabien Sanglard }
783*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative, false);
784*3f982cf4SFabien Sanglard AstNode* member_key = ParseMemberKeyFromComment(&p_speculative);
785*3f982cf4SFabien Sanglard if (!member_key) {
786*3f982cf4SFabien Sanglard return nullptr;
787*3f982cf4SFabien Sanglard }
788*3f982cf4SFabien Sanglard
789*3f982cf4SFabien Sanglard member_key->integer_member_key_text = member_key_num->text;
790*3f982cf4SFabien Sanglard
791*3f982cf4SFabien Sanglard return UpdateNodesForGroupEntry(p, &p_speculative, occur, member_key, type);
792*3f982cf4SFabien Sanglard }
793*3f982cf4SFabien Sanglard
ParseGroupEntryWithNameAsId(Parser * p)794*3f982cf4SFabien Sanglard AstNode* ParseGroupEntryWithNameAsId(Parser* p) {
795*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
796*3f982cf4SFabien Sanglard AstNode* occur = ParseOccur(&p_speculative);
797*3f982cf4SFabien Sanglard if (occur) {
798*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
799*3f982cf4SFabien Sanglard }
800*3f982cf4SFabien Sanglard AstNode* member_key = ParseMemberKey(&p_speculative);
801*3f982cf4SFabien Sanglard if (member_key) {
802*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
803*3f982cf4SFabien Sanglard }
804*3f982cf4SFabien Sanglard AstNode* type = ParseType(&p_speculative);
805*3f982cf4SFabien Sanglard if (!type) {
806*3f982cf4SFabien Sanglard return nullptr;
807*3f982cf4SFabien Sanglard }
808*3f982cf4SFabien Sanglard return UpdateNodesForGroupEntry(p, &p_speculative, occur, member_key, type);
809*3f982cf4SFabien Sanglard }
810*3f982cf4SFabien Sanglard
811*3f982cf4SFabien Sanglard // NOTE: This should probably never be hit, why is it in the grammar?
ParseGroupEntryWithGroupReference(Parser * p)812*3f982cf4SFabien Sanglard AstNode* ParseGroupEntryWithGroupReference(Parser* p) {
813*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
814*3f982cf4SFabien Sanglard
815*3f982cf4SFabien Sanglard // Check for an occurance indicator ('?', '*', "+") before the sub-group
816*3f982cf4SFabien Sanglard // definition.
817*3f982cf4SFabien Sanglard AstNode* occur = ParseOccur(&p_speculative);
818*3f982cf4SFabien Sanglard if (occur) {
819*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
820*3f982cf4SFabien Sanglard }
821*3f982cf4SFabien Sanglard
822*3f982cf4SFabien Sanglard // Parse the ID of the sub-group.
823*3f982cf4SFabien Sanglard AstNode* id = ParseId(&p_speculative);
824*3f982cf4SFabien Sanglard if (!id) {
825*3f982cf4SFabien Sanglard return nullptr;
826*3f982cf4SFabien Sanglard }
827*3f982cf4SFabien Sanglard id->type = AstNode::Type::kGroupname;
828*3f982cf4SFabien Sanglard if (*p_speculative.data == '<') {
829*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to use a generic argument, "
830*3f982cf4SFabien Sanglard "which we don't support"
831*3f982cf4SFabien Sanglard << std::endl;
832*3f982cf4SFabien Sanglard return nullptr;
833*3f982cf4SFabien Sanglard }
834*3f982cf4SFabien Sanglard
835*3f982cf4SFabien Sanglard // Create a new node containing this sub-group reference.
836*3f982cf4SFabien Sanglard AstNode* node = AddNode(p, AstNode::Type::kGrpent, absl::string_view());
837*3f982cf4SFabien Sanglard if (occur) {
838*3f982cf4SFabien Sanglard occur->sibling = id;
839*3f982cf4SFabien Sanglard node->children = occur;
840*3f982cf4SFabien Sanglard } else {
841*3f982cf4SFabien Sanglard node->children = id;
842*3f982cf4SFabien Sanglard }
843*3f982cf4SFabien Sanglard node->text = std::string(p->data, p_speculative.data - p->data);
844*3f982cf4SFabien Sanglard p->data = p_speculative.data;
845*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
846*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
847*3f982cf4SFabien Sanglard return node;
848*3f982cf4SFabien Sanglard }
849*3f982cf4SFabien Sanglard
850*3f982cf4SFabien Sanglard // Recursively parse a group entry that's an inline-defined group of the form
851*3f982cf4SFabien Sanglard // '(...<some contents>...)'.
ParseGroupEntryWithInlineGroupDefinition(Parser * p)852*3f982cf4SFabien Sanglard AstNode* ParseGroupEntryWithInlineGroupDefinition(Parser* p) {
853*3f982cf4SFabien Sanglard Parser p_speculative{p->data};
854*3f982cf4SFabien Sanglard AstNode* occur = ParseOccur(&p_speculative);
855*3f982cf4SFabien Sanglard if (occur) {
856*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
857*3f982cf4SFabien Sanglard }
858*3f982cf4SFabien Sanglard if (*p_speculative.data != '(') {
859*3f982cf4SFabien Sanglard return nullptr;
860*3f982cf4SFabien Sanglard }
861*3f982cf4SFabien Sanglard ++p_speculative.data;
862*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
863*3f982cf4SFabien Sanglard AstNode* group = ParseGroup(&p_speculative); // Recursive call here.
864*3f982cf4SFabien Sanglard if (!group) {
865*3f982cf4SFabien Sanglard return nullptr;
866*3f982cf4SFabien Sanglard }
867*3f982cf4SFabien Sanglard
868*3f982cf4SFabien Sanglard SkipWhitespace(&p_speculative);
869*3f982cf4SFabien Sanglard if (*p_speculative.data != ')') {
870*3f982cf4SFabien Sanglard return nullptr;
871*3f982cf4SFabien Sanglard }
872*3f982cf4SFabien Sanglard ++p_speculative.data;
873*3f982cf4SFabien Sanglard AstNode* node = AddNode(p, AstNode::Type::kGrpent, absl::string_view());
874*3f982cf4SFabien Sanglard if (occur) {
875*3f982cf4SFabien Sanglard node->children = occur;
876*3f982cf4SFabien Sanglard occur->sibling = group;
877*3f982cf4SFabien Sanglard } else {
878*3f982cf4SFabien Sanglard node->children = group;
879*3f982cf4SFabien Sanglard }
880*3f982cf4SFabien Sanglard node->text = std::string(p->data, p_speculative.data - p->data);
881*3f982cf4SFabien Sanglard p->data = p_speculative.data;
882*3f982cf4SFabien Sanglard std::move(p_speculative.nodes.begin(), p_speculative.nodes.end(),
883*3f982cf4SFabien Sanglard std::back_inserter(p->nodes));
884*3f982cf4SFabien Sanglard return node;
885*3f982cf4SFabien Sanglard }
886*3f982cf4SFabien Sanglard
887*3f982cf4SFabien Sanglard // Recursively parse the group assignemnt.
ParseGroupEntry(Parser * p)888*3f982cf4SFabien Sanglard AstNode* ParseGroupEntry(Parser* p) {
889*3f982cf4SFabien Sanglard // Parse a group entry of form '#: type ; name'
890*3f982cf4SFabien Sanglard AstNode* node = ParseGroupEntryWithNameInComment(p);
891*3f982cf4SFabien Sanglard
892*3f982cf4SFabien Sanglard // Parse a group entry of form 'id: type'.
893*3f982cf4SFabien Sanglard if (!node) {
894*3f982cf4SFabien Sanglard node = ParseGroupEntryWithNameAsId(p);
895*3f982cf4SFabien Sanglard }
896*3f982cf4SFabien Sanglard
897*3f982cf4SFabien Sanglard // Parse a group entry of form 'subgroupName'.
898*3f982cf4SFabien Sanglard if (!node) {
899*3f982cf4SFabien Sanglard node = ParseGroupEntryWithGroupReference(p);
900*3f982cf4SFabien Sanglard }
901*3f982cf4SFabien Sanglard
902*3f982cf4SFabien Sanglard // Parse a group entry of the form: '(' <some contents> ')'.
903*3f982cf4SFabien Sanglard // NOTE: This is the method hit during the top-level group parsing, and the
904*3f982cf4SFabien Sanglard // recursive call occurs inside this method.
905*3f982cf4SFabien Sanglard if (!node) {
906*3f982cf4SFabien Sanglard node = ParseGroupEntryWithInlineGroupDefinition(p);
907*3f982cf4SFabien Sanglard }
908*3f982cf4SFabien Sanglard
909*3f982cf4SFabien Sanglard // Return the results of the recursive call.
910*3f982cf4SFabien Sanglard return node;
911*3f982cf4SFabien Sanglard }
912*3f982cf4SFabien Sanglard
ParseRule(Parser * p)913*3f982cf4SFabien Sanglard AstNode* ParseRule(Parser* p) {
914*3f982cf4SFabien Sanglard const char* start = p->data;
915*3f982cf4SFabien Sanglard
916*3f982cf4SFabien Sanglard // Parse the type key, if it's present
917*3f982cf4SFabien Sanglard absl::optional<std::string> type_key = ParseTypeKeyFromComment(p);
918*3f982cf4SFabien Sanglard SkipWhitespace(p);
919*3f982cf4SFabien Sanglard
920*3f982cf4SFabien Sanglard // Use the parser to extract the id and data.
921*3f982cf4SFabien Sanglard AstNode* id = ParseId(p);
922*3f982cf4SFabien Sanglard if (!id) {
923*3f982cf4SFabien Sanglard Logger::Error("No id found!");
924*3f982cf4SFabien Sanglard return nullptr;
925*3f982cf4SFabien Sanglard }
926*3f982cf4SFabien Sanglard if (p->data[0] == '<') {
927*3f982cf4SFabien Sanglard std::cerr << "It looks like you're trying to use a generic parameter, "
928*3f982cf4SFabien Sanglard "which we don't support"
929*3f982cf4SFabien Sanglard << std::endl;
930*3f982cf4SFabien Sanglard return nullptr;
931*3f982cf4SFabien Sanglard }
932*3f982cf4SFabien Sanglard
933*3f982cf4SFabien Sanglard // Determine the type of assignment being done to this variable name (ie '=').
934*3f982cf4SFabien Sanglard SkipWhitespace(p);
935*3f982cf4SFabien Sanglard const char* assign_start = p->data;
936*3f982cf4SFabien Sanglard AssignType assign_type = ParseAssignmentType(p);
937*3f982cf4SFabien Sanglard if (assign_type != AssignType::kAssign) {
938*3f982cf4SFabien Sanglard Logger::Error("No assignment operator found! assign_type: %d", assign_type);
939*3f982cf4SFabien Sanglard return nullptr;
940*3f982cf4SFabien Sanglard }
941*3f982cf4SFabien Sanglard AstNode* assign_node = AddNode(
942*3f982cf4SFabien Sanglard p,
943*3f982cf4SFabien Sanglard (assign_type == AssignType::kAssign)
944*3f982cf4SFabien Sanglard ? AstNode::Type::kAssign
945*3f982cf4SFabien Sanglard : (assign_type == AssignType::kAssignT) ? AstNode::Type::kAssignT
946*3f982cf4SFabien Sanglard : AstNode::Type::kAssignG,
947*3f982cf4SFabien Sanglard absl::string_view(assign_start, p->data - assign_start));
948*3f982cf4SFabien Sanglard id->sibling = assign_node;
949*3f982cf4SFabien Sanglard
950*3f982cf4SFabien Sanglard // Parse the object type being assigned.
951*3f982cf4SFabien Sanglard SkipWhitespace(p);
952*3f982cf4SFabien Sanglard AstNode* type = ParseType(p, false); // Try to parse it as a type.
953*3f982cf4SFabien Sanglard id->type = AstNode::Type::kTypename;
954*3f982cf4SFabien Sanglard if (!type) { // If it's not a type, try and parse it as a group.
955*3f982cf4SFabien Sanglard type = ParseGroupEntry(p);
956*3f982cf4SFabien Sanglard id->type = AstNode::Type::kGroupname;
957*3f982cf4SFabien Sanglard }
958*3f982cf4SFabien Sanglard if (!type) { // if it's not a type or a group, exit as failure.
959*3f982cf4SFabien Sanglard Logger::Error("No node type found!");
960*3f982cf4SFabien Sanglard return nullptr;
961*3f982cf4SFabien Sanglard }
962*3f982cf4SFabien Sanglard assign_node->sibling = type;
963*3f982cf4SFabien Sanglard SkipWhitespace(p, false);
964*3f982cf4SFabien Sanglard
965*3f982cf4SFabien Sanglard // Return the results.
966*3f982cf4SFabien Sanglard auto rule_node = AddNode(p, AstNode::Type::kRule,
967*3f982cf4SFabien Sanglard absl::string_view(start, p->data - start), id);
968*3f982cf4SFabien Sanglard rule_node->type_key = type_key;
969*3f982cf4SFabien Sanglard return rule_node;
970*3f982cf4SFabien Sanglard }
971*3f982cf4SFabien Sanglard
972*3f982cf4SFabien Sanglard // Iteratively parse the CDDL spec into a tree structure.
ParseCddl(absl::string_view data)973*3f982cf4SFabien Sanglard ParseResult ParseCddl(absl::string_view data) {
974*3f982cf4SFabien Sanglard if (data[0] == 0) {
975*3f982cf4SFabien Sanglard return {nullptr, {}};
976*3f982cf4SFabien Sanglard }
977*3f982cf4SFabien Sanglard Parser p{data.data()};
978*3f982cf4SFabien Sanglard
979*3f982cf4SFabien Sanglard SkipWhitespace(&p);
980*3f982cf4SFabien Sanglard AstNode* root = nullptr;
981*3f982cf4SFabien Sanglard AstNode* tail = nullptr;
982*3f982cf4SFabien Sanglard do {
983*3f982cf4SFabien Sanglard AstNode* next = ParseRule(&p);
984*3f982cf4SFabien Sanglard if (!next) {
985*3f982cf4SFabien Sanglard Logger::Error("Failed to parse next node. Failed starting at: '%s'",
986*3f982cf4SFabien Sanglard p.data);
987*3f982cf4SFabien Sanglard return {nullptr, {}};
988*3f982cf4SFabien Sanglard } else {
989*3f982cf4SFabien Sanglard Logger::Log("Processed text \"%s\" into node: ", next->text);
990*3f982cf4SFabien Sanglard DumpAst(next);
991*3f982cf4SFabien Sanglard }
992*3f982cf4SFabien Sanglard
993*3f982cf4SFabien Sanglard if (!root) {
994*3f982cf4SFabien Sanglard root = next;
995*3f982cf4SFabien Sanglard }
996*3f982cf4SFabien Sanglard if (tail) {
997*3f982cf4SFabien Sanglard tail->sibling = next;
998*3f982cf4SFabien Sanglard }
999*3f982cf4SFabien Sanglard tail = next;
1000*3f982cf4SFabien Sanglard } while (p.data[0]);
1001*3f982cf4SFabien Sanglard return {root, std::move(p.nodes)};
1002*3f982cf4SFabien Sanglard }
1003*3f982cf4SFabien Sanglard
1004*3f982cf4SFabien Sanglard // Recursively print out the AstNode graph.
DumpAst(AstNode * node,int indent_level)1005*3f982cf4SFabien Sanglard void DumpAst(AstNode* node, int indent_level) {
1006*3f982cf4SFabien Sanglard while (node) {
1007*3f982cf4SFabien Sanglard // Prefix with '-'s so the levels of the graph are clear.
1008*3f982cf4SFabien Sanglard std::string node_text = "";
1009*3f982cf4SFabien Sanglard for (int i = 0; i <= indent_level; ++i) {
1010*3f982cf4SFabien Sanglard node_text += "--";
1011*3f982cf4SFabien Sanglard }
1012*3f982cf4SFabien Sanglard
1013*3f982cf4SFabien Sanglard // Print the type.
1014*3f982cf4SFabien Sanglard switch (node->type) {
1015*3f982cf4SFabien Sanglard case AstNode::Type::kRule:
1016*3f982cf4SFabien Sanglard node_text += "kRule";
1017*3f982cf4SFabien Sanglard break;
1018*3f982cf4SFabien Sanglard case AstNode::Type::kTypename:
1019*3f982cf4SFabien Sanglard node_text += "kTypename";
1020*3f982cf4SFabien Sanglard break;
1021*3f982cf4SFabien Sanglard case AstNode::Type::kGroupname:
1022*3f982cf4SFabien Sanglard node_text += "kGroupname";
1023*3f982cf4SFabien Sanglard break;
1024*3f982cf4SFabien Sanglard case AstNode::Type::kAssign:
1025*3f982cf4SFabien Sanglard node_text += "kAssign";
1026*3f982cf4SFabien Sanglard break;
1027*3f982cf4SFabien Sanglard case AstNode::Type::kAssignT:
1028*3f982cf4SFabien Sanglard node_text += "kAssignT";
1029*3f982cf4SFabien Sanglard break;
1030*3f982cf4SFabien Sanglard case AstNode::Type::kAssignG:
1031*3f982cf4SFabien Sanglard node_text += "kAssignG";
1032*3f982cf4SFabien Sanglard break;
1033*3f982cf4SFabien Sanglard case AstNode::Type::kType:
1034*3f982cf4SFabien Sanglard node_text += "kType";
1035*3f982cf4SFabien Sanglard break;
1036*3f982cf4SFabien Sanglard case AstNode::Type::kGrpent:
1037*3f982cf4SFabien Sanglard node_text += "kGrpent";
1038*3f982cf4SFabien Sanglard break;
1039*3f982cf4SFabien Sanglard case AstNode::Type::kType1:
1040*3f982cf4SFabien Sanglard node_text += "kType1";
1041*3f982cf4SFabien Sanglard break;
1042*3f982cf4SFabien Sanglard case AstNode::Type::kType2:
1043*3f982cf4SFabien Sanglard node_text += "kType2";
1044*3f982cf4SFabien Sanglard break;
1045*3f982cf4SFabien Sanglard case AstNode::Type::kValue:
1046*3f982cf4SFabien Sanglard node_text += "kValue";
1047*3f982cf4SFabien Sanglard break;
1048*3f982cf4SFabien Sanglard case AstNode::Type::kGroup:
1049*3f982cf4SFabien Sanglard node_text += "kGroup";
1050*3f982cf4SFabien Sanglard break;
1051*3f982cf4SFabien Sanglard case AstNode::Type::kUint:
1052*3f982cf4SFabien Sanglard node_text += "kUint";
1053*3f982cf4SFabien Sanglard break;
1054*3f982cf4SFabien Sanglard case AstNode::Type::kDigit:
1055*3f982cf4SFabien Sanglard node_text += "kDigit";
1056*3f982cf4SFabien Sanglard break;
1057*3f982cf4SFabien Sanglard case AstNode::Type::kRangeop:
1058*3f982cf4SFabien Sanglard node_text += "kRangeop";
1059*3f982cf4SFabien Sanglard break;
1060*3f982cf4SFabien Sanglard case AstNode::Type::kCtlop:
1061*3f982cf4SFabien Sanglard node_text += "kCtlop";
1062*3f982cf4SFabien Sanglard break;
1063*3f982cf4SFabien Sanglard case AstNode::Type::kGrpchoice:
1064*3f982cf4SFabien Sanglard node_text += "kGrpchoice";
1065*3f982cf4SFabien Sanglard break;
1066*3f982cf4SFabien Sanglard case AstNode::Type::kOccur:
1067*3f982cf4SFabien Sanglard node_text += "kOccur";
1068*3f982cf4SFabien Sanglard break;
1069*3f982cf4SFabien Sanglard case AstNode::Type::kMemberKey:
1070*3f982cf4SFabien Sanglard node_text += "kMemberKey";
1071*3f982cf4SFabien Sanglard break;
1072*3f982cf4SFabien Sanglard case AstNode::Type::kId:
1073*3f982cf4SFabien Sanglard node_text += "kId";
1074*3f982cf4SFabien Sanglard break;
1075*3f982cf4SFabien Sanglard case AstNode::Type::kNumber:
1076*3f982cf4SFabien Sanglard node_text += "kNumber";
1077*3f982cf4SFabien Sanglard break;
1078*3f982cf4SFabien Sanglard case AstNode::Type::kText:
1079*3f982cf4SFabien Sanglard node_text += "kText";
1080*3f982cf4SFabien Sanglard break;
1081*3f982cf4SFabien Sanglard case AstNode::Type::kBytes:
1082*3f982cf4SFabien Sanglard node_text += "kBytes";
1083*3f982cf4SFabien Sanglard break;
1084*3f982cf4SFabien Sanglard case AstNode::Type::kOther:
1085*3f982cf4SFabien Sanglard node_text += "kOther";
1086*3f982cf4SFabien Sanglard break;
1087*3f982cf4SFabien Sanglard }
1088*3f982cf4SFabien Sanglard if (node->type_key != absl::nullopt) {
1089*3f982cf4SFabien Sanglard node_text += " (type key=\"" + node->type_key.value() + "\")";
1090*3f982cf4SFabien Sanglard }
1091*3f982cf4SFabien Sanglard node_text += ": ";
1092*3f982cf4SFabien Sanglard
1093*3f982cf4SFabien Sanglard // Print the contents.
1094*3f982cf4SFabien Sanglard int size = static_cast<int>(node->text.size());
1095*3f982cf4SFabien Sanglard absl::string_view text = node->text.data();
1096*3f982cf4SFabien Sanglard for (int i = 0; i < size; ++i) {
1097*3f982cf4SFabien Sanglard if (text[i] == ' ' || text[i] == '\n') {
1098*3f982cf4SFabien Sanglard node_text += " ";
1099*3f982cf4SFabien Sanglard while (i < size - 1 && (text[i + 1] == ' ' || text[i + 1] == '\n')) {
1100*3f982cf4SFabien Sanglard ++i;
1101*3f982cf4SFabien Sanglard }
1102*3f982cf4SFabien Sanglard continue;
1103*3f982cf4SFabien Sanglard } else {
1104*3f982cf4SFabien Sanglard node_text += text[i];
1105*3f982cf4SFabien Sanglard }
1106*3f982cf4SFabien Sanglard }
1107*3f982cf4SFabien Sanglard Logger::Log(node_text);
1108*3f982cf4SFabien Sanglard
1109*3f982cf4SFabien Sanglard // Recursively print children then iteratively print siblings.
1110*3f982cf4SFabien Sanglard DumpAst(node->children, indent_level + 1);
1111*3f982cf4SFabien Sanglard node = node->sibling;
1112*3f982cf4SFabien Sanglard }
1113*3f982cf4SFabien Sanglard }
1114