1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 #if _WIN32
23 #include <kj/win32-api-version.h>
24 #endif
25 
26 #include "parser.h"
27 #include "type-id.h"
28 #include <capnp/dynamic.h>
29 #include <kj/debug.h>
30 #include <kj/encoding.h>
31 #if !_MSC_VER
32 #include <unistd.h>
33 #endif
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 
38 #if _WIN32
39 #include <windows.h>
40 #include <wincrypt.h>
41 #undef CONST
42 #include <kj/windows-sanity.h>
43 #endif
44 
45 namespace capnp {
46 namespace compiler {
47 
generateRandomId()48 uint64_t generateRandomId() {
49   uint64_t result;
50 
51 #if _WIN32
52   HCRYPTPROV handle;
53   KJ_ASSERT(CryptAcquireContextW(&handle, nullptr, nullptr,
54                                  PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT));
55   KJ_DEFER(KJ_ASSERT(CryptReleaseContext(handle, 0)) {break;});
56 
57   KJ_ASSERT(CryptGenRandom(handle, sizeof(result), reinterpret_cast<BYTE*>(&result)));
58 
59 #else
60   int fd;
61   KJ_SYSCALL(fd = open("/dev/urandom", O_RDONLY));
62 
63   ssize_t n;
64   KJ_SYSCALL(n = read(fd, &result, sizeof(result)), "/dev/urandom");
65   KJ_ASSERT(n == sizeof(result), "Incomplete read from /dev/urandom.", n);
66 #endif
67 
68   return result | (1ull << 63);
69 }
70 
parseFile(List<Statement>::Reader statements,ParsedFile::Builder result,ErrorReporter & errorReporter)71 void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
72                ErrorReporter& errorReporter) {
73   CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);
74 
75   kj::Vector<Orphan<Declaration>> decls(statements.size());
76   kj::Vector<Orphan<Declaration::AnnotationApplication>> annotations;
77 
78   auto fileDecl = result.getRoot();
79   fileDecl.setFile(VOID);
80 
81   for (auto statement: statements) {
82     KJ_IF_MAYBE(decl, parser.parseStatement(statement, parser.getParsers().fileLevelDecl)) {
83       Declaration::Builder builder = decl->get();
84       switch (builder.which()) {
85         case Declaration::NAKED_ID:
86           if (fileDecl.getId().isUid()) {
87             errorReporter.addError(builder.getStartByte(), builder.getEndByte(),
88                                    "File can only have one ID.");
89           } else {
90             fileDecl.getId().adoptUid(builder.disownNakedId());
91             if (builder.hasDocComment()) {
92               fileDecl.adoptDocComment(builder.disownDocComment());
93             }
94           }
95           break;
96         case Declaration::NAKED_ANNOTATION:
97           annotations.add(builder.disownNakedAnnotation());
98           break;
99         default:
100           decls.add(kj::mv(*decl));
101           break;
102       }
103     }
104   }
105 
106   if (fileDecl.getId().which() != Declaration::Id::UID) {
107     // We didn't see an ID. Generate one randomly for now.
108     uint64_t id = generateRandomId();
109     fileDecl.getId().initUid().setValue(id);
110 
111     // Don't report missing ID if there was a parse error, because quite often the parse error
112     // prevents us from parsing the ID even though it is actually there.
113     if (!errorReporter.hadErrors()) {
114       errorReporter.addError(0, 0,
115           kj::str("File does not declare an ID.  I've generated one for you.  Add this line to "
116                   "your file: @0x", kj::hex(id), ";"));
117     }
118   }
119 
120   auto declsBuilder = fileDecl.initNestedDecls(decls.size());
121   for (size_t i = 0; i < decls.size(); i++) {
122     declsBuilder.adoptWithCaveats(i, kj::mv(decls[i]));
123   }
124 
125   auto annotationsBuilder = fileDecl.initAnnotations(annotations.size());
126   for (size_t i = 0; i < annotations.size(); i++) {
127     annotationsBuilder.adoptWithCaveats(i, kj::mv(annotations[i]));
128   }
129 }
130 
131 namespace p = kj::parse;
132 
133 namespace {
134 
135 // =======================================================================================
136 
137 template <typename T>
138 struct Located {
139   T value;
140   uint32_t startByte;
141   uint32_t endByte;
142 
143   template <typename Builder>
copyLocationTocapnp::compiler::__anonbd3fe9d30111::Located144   void copyLocationTo(Builder builder) {
145     builder.setStartByte(startByte);
146     builder.setEndByte(endByte);
147   }
148   template <typename Builder>
copyTocapnp::compiler::__anonbd3fe9d30111::Located149   void copyTo(Builder builder) {
150     builder.setValue(value);
151     copyLocationTo(builder);
152   }
153   template <typename Result>
asProtocapnp::compiler::__anonbd3fe9d30111::Located154   Orphan<Result> asProto(Orphanage orphanage) {
155     auto result = orphanage.newOrphan<Result>();
156     copyTo(result.get());
157     return result;
158   }
159   template <typename Other>
rewrapcapnp::compiler::__anonbd3fe9d30111::Located160   Located<kj::Decay<Other>> rewrap(Other&& other) {
161     return Located<Other>(kj::fwd<Other>(other), startByte, endByte);
162   }
163 
Locatedcapnp::compiler::__anonbd3fe9d30111::Located164   Located(const T& value, uint32_t startByte, uint32_t endByte)
165       : value(value), startByte(startByte), endByte(endByte) {}
Locatedcapnp::compiler::__anonbd3fe9d30111::Located166   Located(T&& value, uint32_t startByte, uint32_t endByte)
167       : value(kj::mv(value)), startByte(startByte), endByte(endByte) {}
168 };
169 
170 // =======================================================================================
171 
172 template <typename T, Token::Which type, T (Token::Reader::*get)() const>
173 struct MatchTokenType {
operator ()capnp::compiler::__anonbd3fe9d30111::MatchTokenType174   kj::Maybe<Located<T>> operator()(Token::Reader token) const {
175     if (token.which() == type) {
176       return Located<T>((token.*get)(), token.getStartByte(), token.getEndByte());
177     } else {
178       return nullptr;
179     }
180   }
181 };
182 
183 #define TOKEN_TYPE_PARSER(type, discrim, getter) \
184     p::transformOrReject(p::any, \
185         MatchTokenType<type, Token::discrim, &Token::Reader::getter>())
186 
187 constexpr auto identifier = TOKEN_TYPE_PARSER(Text::Reader, IDENTIFIER, getIdentifier);
188 constexpr auto stringLiteral = TOKEN_TYPE_PARSER(Text::Reader, STRING_LITERAL, getStringLiteral);
189 constexpr auto binaryLiteral = TOKEN_TYPE_PARSER(Data::Reader, BINARY_LITERAL, getBinaryLiteral);
190 constexpr auto integerLiteral = TOKEN_TYPE_PARSER(uint64_t, INTEGER_LITERAL, getIntegerLiteral);
191 constexpr auto floatLiteral = TOKEN_TYPE_PARSER(double, FLOAT_LITERAL, getFloatLiteral);
192 constexpr auto operatorToken = TOKEN_TYPE_PARSER(Text::Reader, OPERATOR, getOperator);
193 constexpr auto rawParenthesizedList =
194     TOKEN_TYPE_PARSER(List<List<Token>>::Reader, PARENTHESIZED_LIST, getParenthesizedList);
195 constexpr auto rawBracketedList =
196     TOKEN_TYPE_PARSER(List<List<Token>>::Reader, BRACKETED_LIST, getBracketedList);
197 
198 // =======================================================================================
199 
200 class ExactString {
201 public:
ExactString(const char * expected)202   constexpr ExactString(const char* expected): expected(expected) {}
203 
operator ()(Located<Text::Reader> && text) const204   kj::Maybe<kj::Tuple<>> operator()(Located<Text::Reader>&& text) const {
205     if (text.value == expected) {
206       return kj::Tuple<>();
207     } else {
208       return nullptr;
209     }
210   }
211 
212 private:
213   const char* expected;
214 };
215 
keyword(const char * expected)216 constexpr auto keyword(const char* expected)
217     -> decltype(p::transformOrReject(identifier, ExactString(expected))) {
218   return p::transformOrReject(identifier, ExactString(expected));
219 }
220 
op(const char * expected)221 constexpr auto op(const char* expected)
222     -> decltype(p::transformOrReject(operatorToken, ExactString(expected))) {
223   return p::transformOrReject(operatorToken, ExactString(expected));
224 }
225 
226 class LocatedExactString {
227 public:
LocatedExactString(const char * expected)228   constexpr LocatedExactString(const char* expected): expected(expected) {}
229 
operator ()(Located<Text::Reader> && text) const230   kj::Maybe<Located<Text::Reader>> operator()(Located<Text::Reader>&& text) const {
231     if (text.value == expected) {
232       return kj::mv(text);
233     } else {
234       return nullptr;
235     }
236   }
237 
238 private:
239   const char* expected;
240 };
241 
locatedKeyword(const char * expected)242 constexpr auto locatedKeyword(const char* expected)
243     -> decltype(p::transformOrReject(identifier, LocatedExactString(expected))) {
244   return p::transformOrReject(identifier, LocatedExactString(expected));
245 }
246 
247 // =======================================================================================
248 
249 template <typename ItemParser>
250 class ParseListItems {
251   // Transformer that parses all items in the input token sequence list using the given parser.
252 
253 public:
ParseListItems(ItemParser && itemParser,ErrorReporter & errorReporter)254   constexpr ParseListItems(ItemParser&& itemParser, ErrorReporter& errorReporter)
255       : itemParser(p::sequence(kj::fwd<ItemParser>(itemParser), p::endOfInput)),
256         errorReporter(errorReporter) {}
257 
operator ()(Located<List<List<Token>>::Reader> && items) const258   Located<kj::Array<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>> operator()(
259       Located<List<List<Token>>::Reader>&& items) const {
260     auto result = kj::heapArray<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>(
261         items.value.size());
262     for (uint i = 0; i < items.value.size(); i++) {
263       auto item = items.value[i];
264       CapnpParser::ParserInput input(item.begin(), item.end());
265       result[i] = itemParser(input);
266       if (result[i] == nullptr) {
267         // Parsing failed.  Report an error.
268         auto best = input.getBest();
269         if (best < item.end()) {
270           // Report error from the point where parsing failed to the end of the item.
271           errorReporter.addError(
272               best->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
273         } else if (item.size() > 0) {
274           // The item is non-empty and the parser consumed all of it before failing.  Report an
275           // error for the whole thing.
276           errorReporter.addError(
277               item.begin()->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
278         } else {
279           // The item has no content.
280           // TODO(cleanup):  We don't actually know the item's location, so we can only report
281           //   an error across the whole list.  Fix this.
282           errorReporter.addError(items.startByte, items.endByte, "Parse error: Empty list item.");
283         }
284       }
285     }
286     return Located<kj::Array<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>>(
287         kj::mv(result), items.startByte, items.endByte);
288   }
289 
290 private:
291   decltype(p::sequence(kj::instance<ItemParser>(), p::endOfInput)) itemParser;
292   ErrorReporter& errorReporter;
293 };
294 
295 template <typename ItemParser>
parenthesizedList(ItemParser && itemParser,ErrorReporter & errorReporter)296 constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
297          transform(rawParenthesizedList, ParseListItems<ItemParser>(
298              kj::fwd<ItemParser>(itemParser), errorReporter))) {
299   return transform(rawParenthesizedList, ParseListItems<ItemParser>(
300              kj::fwd<ItemParser>(itemParser), errorReporter));
301 }
302 
303 template <typename ItemParser>
bracketedList(ItemParser && itemParser,ErrorReporter & errorReporter)304 constexpr auto bracketedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
305          transform(rawBracketedList, ParseListItems<ItemParser>(
306              kj::fwd<ItemParser>(itemParser), errorReporter))) {
307   return transform(rawBracketedList, ParseListItems<ItemParser>(
308              kj::fwd<ItemParser>(itemParser), errorReporter));
309 }
310 
311 // =======================================================================================
312 
313 template <typename T>
arrayToList(Orphanage & orphanage,kj::Array<Orphan<T>> && elements)314 Orphan<List<T>> arrayToList(Orphanage& orphanage, kj::Array<Orphan<T>>&& elements) {
315   auto result = orphanage.newOrphan<List<T>>(elements.size());
316   auto builder = result.get();
317   for (size_t i = 0; i < elements.size(); i++) {
318     builder.adoptWithCaveats(i, kj::mv(elements[i]));
319   }
320   return kj::mv(result);
321 }
322 
initGenericParams(Declaration::Builder builder,kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>> && genericParameters)323 static void initGenericParams(Declaration::Builder builder,
324     kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters) {
325   KJ_IF_MAYBE(p, genericParameters) {
326     auto params = builder.initParameters(p->value.size());
327     for (uint i: kj::indices(p->value)) {
328       KJ_IF_MAYBE(name, p->value[i]) {
329         auto param = params[i];
330         param.setName(name->value);
331         name->copyLocationTo(param);
332       }
333     }
334   }
335 }
336 
initDecl(Declaration::Builder builder,Located<Text::Reader> && name,kj::Maybe<Orphan<LocatedInteger>> && id,kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>> && genericParameters,kj::Array<Orphan<Declaration::AnnotationApplication>> && annotations)337 static Declaration::Builder initDecl(
338     Declaration::Builder builder, Located<Text::Reader>&& name,
339     kj::Maybe<Orphan<LocatedInteger>>&& id,
340     kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
341     kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
342   name.copyTo(builder.initName());
343   KJ_IF_MAYBE(i, id) {
344     builder.getId().adoptUid(kj::mv(*i));
345   }
346 
347   initGenericParams(builder, kj::mv(genericParameters));
348 
349   auto list = builder.initAnnotations(annotations.size());
350   for (uint i = 0; i < annotations.size(); i++) {
351     list.adoptWithCaveats(i, kj::mv(annotations[i]));
352   }
353   return builder;
354 }
355 
initMemberDecl(Declaration::Builder builder,Located<Text::Reader> && name,Orphan<LocatedInteger> && ordinal,kj::Array<Orphan<Declaration::AnnotationApplication>> && annotations)356 static Declaration::Builder initMemberDecl(
357     Declaration::Builder builder, Located<Text::Reader>&& name,
358     Orphan<LocatedInteger>&& ordinal,
359     kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
360   name.copyTo(builder.initName());
361   builder.getId().adoptOrdinal(kj::mv(ordinal));
362   auto list = builder.initAnnotations(annotations.size());
363   for (uint i = 0; i < annotations.size(); i++) {
364     list.adoptWithCaveats(i, kj::mv(annotations[i]));
365   }
366   return builder;
367 }
368 
369 template <typename BuilderType>
initLocation(kj::parse::Span<typename List<Token>::Reader::Iterator> location,BuilderType builder)370 void initLocation(kj::parse::Span<typename List<Token>::Reader::Iterator> location,
371                   BuilderType builder) {
372   if (location.begin() < location.end()) {
373     builder.setStartByte(location.begin()->getStartByte());
374     builder.setEndByte((location.end() - 1)->getEndByte());
375   }
376 }
377 
378 }  // namespace
379 
380 // =======================================================================================
381 
CapnpParser(Orphanage orphanageParam,ErrorReporter & errorReporterParam)382 CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterParam)
383     : orphanage(orphanageParam), errorReporter(errorReporterParam) {
384   auto& tupleElement = arena.copy(p::transform(
385       p::sequence(p::optional(p::sequence(identifier, op("="))), parsers.expression),
386       [this](kj::Maybe<Located<Text::Reader>>&& fieldName, Orphan<Expression>&& fieldValue)
387              -> Orphan<Expression::Param> {
388         auto result = orphanage.newOrphan<Expression::Param>();
389         auto builder = result.get();
390         KJ_IF_MAYBE(fn, fieldName) {
391           fn->copyTo(builder.initNamed());
392         } else {
393           builder.setUnnamed();
394         }
395         builder.adoptValue(kj::mv(fieldValue));
396         return kj::mv(result);
397       }));
398 
399   auto& tuple = arena.copy<Parser<Located<Orphan<List<Expression::Param>>>>>(
400       arena.copy(p::transform(
401         parenthesizedList(tupleElement, errorReporter),
402         [this](Located<kj::Array<kj::Maybe<Orphan<Expression::Param>>>>&& elements)
403                -> Located<Orphan<List<Expression::Param>>> {
404           auto result = orphanage.newOrphan<List<Expression::Param>>(elements.value.size());
405           auto builder = result.get();
406           for (uint i: kj::indices(elements.value)) {
407             KJ_IF_MAYBE(e, elements.value[i]) {
408               builder.adoptWithCaveats(i, kj::mv(*e));
409             } else {
410               builder[i].initValue().setUnknown();
411             }
412           }
413           return elements.rewrap(kj::mv(result));
414         })));
415 
416   parsers.expression = arena.copy(p::transform(
417       p::sequence(
418           // Base expression.
419           p::oneOf(
420               p::transform(integerLiteral,
421                   [this](Located<uint64_t>&& value) -> Orphan<Expression> {
422                     auto result = orphanage.newOrphan<Expression>();
423                     auto builder = result.get();
424                     builder.setPositiveInt(value.value);
425                     value.copyLocationTo(builder);
426                     return result;
427                   }),
428               p::transform(p::sequence(op("-"), integerLiteral),
429                   [this](Located<uint64_t>&& value) -> Orphan<Expression> {
430                     auto result = orphanage.newOrphan<Expression>();
431                     auto builder = result.get();
432                     builder.setNegativeInt(value.value);
433                     value.copyLocationTo(builder);
434                     return result;
435                   }),
436               p::transform(floatLiteral,
437                   [this](Located<double>&& value) -> Orphan<Expression> {
438                     auto result = orphanage.newOrphan<Expression>();
439                     auto builder = result.get();
440                     builder.setFloat(value.value);
441                     value.copyLocationTo(builder);
442                     return result;
443                   }),
444               p::transform(p::sequence(op("-"), floatLiteral),
445                   [this](Located<double>&& value) -> Orphan<Expression> {
446                     auto result = orphanage.newOrphan<Expression>();
447                     auto builder = result.get();
448                     builder.setFloat(-value.value);
449                     value.copyLocationTo(builder);
450                     return result;
451                   }),
452               p::transformWithLocation(p::sequence(op("-"), keyword("inf")),
453                   [this](kj::parse::Span<List<Token>::Reader::Iterator> location)
454                       -> Orphan<Expression> {
455                     auto result = orphanage.newOrphan<Expression>();
456                     auto builder = result.get();
457                     builder.setFloat(-kj::inf());
458                     initLocation(location, builder);
459                     return result;
460                   }),
461               p::transform(p::oneOrMore(stringLiteral),
462                   [this](kj::Array<Located<Text::Reader>>&& value) -> Orphan<Expression> {
463                     auto result = orphanage.newOrphan<Expression>();
464                     auto builder = result.get();
465                     builder.setString(kj::strArray(
466                         KJ_MAP(part, value) { return part.value; }, ""));
467                     builder.setStartByte(value.front().startByte);
468                     builder.setEndByte(value.back().endByte);
469                     return result;
470                   }),
471               p::transform(binaryLiteral,
472                   [this](Located<Data::Reader>&& value) -> Orphan<Expression> {
473                     auto result = orphanage.newOrphan<Expression>();
474                     auto builder = result.get();
475                     builder.setBinary(value.value);
476                     value.copyLocationTo(builder);
477                     return result;
478                   }),
479               p::transform(bracketedList(parsers.expression, errorReporter),
480                   [this](Located<kj::Array<kj::Maybe<Orphan<Expression>>>>&& value)
481                       -> Orphan<Expression> {
482                     auto result = orphanage.newOrphan<Expression>();
483                     auto builder = result.get();
484                     auto listBuilder = builder.initList(value.value.size());
485                     for (uint i = 0; i < value.value.size(); i++) {
486                       KJ_IF_MAYBE(element, value.value[i]) {
487                         listBuilder.adoptWithCaveats(i, kj::mv(*element));
488                       }
489                     }
490                     value.copyLocationTo(builder);
491                     return result;
492                   }),
493               p::transform(tuple,
494                   [this](Located<Orphan<List<Expression::Param>>>&& value)
495                       -> Orphan<Expression> {
496                     auto elements = value.value.get();
497 
498                     if (elements.size() == 1 && elements[0].isUnnamed()) {
499                       // Single-value tuple is just a value.
500                       return elements[0].disownValue();
501                     } else {
502                       auto result = orphanage.newOrphan<Expression>();
503                       auto builder = result.get();
504                       builder.adoptTuple(kj::mv(value.value));
505                       value.copyLocationTo(builder);
506                       return result;
507                     }
508                   }),
509               p::transformWithLocation(p::sequence(keyword("import"), stringLiteral),
510                   [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
511                          Located<Text::Reader>&& filename) -> Orphan<Expression> {
512                     auto result = orphanage.newOrphan<Expression>();
513                     auto builder = result.get();
514                     initLocation(location, builder);
515                     filename.copyTo(builder.initImport());
516                     return result;
517                   }),
518               p::transformWithLocation(p::sequence(keyword("embed"), stringLiteral),
519                   [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
520                          Located<Text::Reader>&& filename) -> Orphan<Expression> {
521                     auto result = orphanage.newOrphan<Expression>();
522                     auto builder = result.get();
523                     initLocation(location, builder);
524                     filename.copyTo(builder.initEmbed());
525                     return result;
526                   }),
527               p::transformWithLocation(p::sequence(op("."), identifier),
528                   [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
529                          Located<Text::Reader>&& name) -> Orphan<Expression> {
530                     auto result = orphanage.newOrphan<Expression>();
531                     auto builder = result.get();
532                     initLocation(location, builder);
533                     name.copyTo(builder.initAbsoluteName());
534                     return result;
535                   }),
536               p::transform(identifier,
537                   [this](Located<Text::Reader>&& name) -> Orphan<Expression> {
538                     auto result = orphanage.newOrphan<Expression>();
539                     auto builder = result.get();
540                     name.copyTo(builder.initRelativeName());
541                     name.copyLocationTo(builder);
542                     return result;
543                   })),
544           // Suffixes, e.g. ".member" or "(param1, param2)".
545           p::many(p::oneOf(
546               p::transformWithLocation(p::sequence(op("."), identifier),
547                   [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
548                          Located<Text::Reader>&& name) -> Orphan<Expression> {
549                     auto result = orphanage.newOrphan<Expression>();
550                     auto builder = result.get();
551                     initLocation(location, builder);
552                     name.copyTo(builder.initMember().initName());
553                     return result;
554                   }),
555               p::transform(tuple,
556                   [this](Located<Orphan<List<Expression::Param>>>&& params) -> Orphan<Expression> {
557                     auto result = orphanage.newOrphan<Expression>();
558                     auto builder = result.get();
559                     params.copyLocationTo(builder);
560                     builder.initApplication().adoptParams(kj::mv(params.value));
561                     return result;
562                   })))),
563       [](Orphan<Expression>&& base, kj::Array<Orphan<Expression>>&& suffixes)
564           -> Orphan<Expression> {
565         // Apply all the suffixes to the base expression.
566         uint startByte = base.getReader().getStartByte();
567         for (auto& suffix: suffixes) {
568           auto builder = suffix.get();
569           if (builder.isApplication()) {
570             builder.getApplication().adoptFunction(kj::mv(base));
571           } else if (builder.isMember()) {
572             builder.getMember().adoptParent(kj::mv(base));
573           } else {
574             KJ_FAIL_ASSERT("Unknown suffix?", (uint)builder.which());
575           }
576           builder.setStartByte(startByte);
577           base = kj::mv(suffix);
578         }
579         return kj::mv(base);
580       }));
581 
582   parsers.annotation = arena.copy(p::transform(
583       p::sequence(op("$"), parsers.expression),
584       [this](Orphan<Expression>&& expression)
585           -> Orphan<Declaration::AnnotationApplication> {
586         auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
587         auto builder = result.get();
588 
589         auto exp = expression.get();
590         if (exp.isApplication()) {
591           // Oops, this annotation specifies the value, but we parsed it as an application on
592           // the preceding expression. Pull it back apart.
593           auto app = exp.getApplication();
594           builder.adoptName(app.disownFunction());
595           auto params = app.getParams();
596           if (params.size() == 1 && params[0].isUnnamed()) {
597             // Params has a single unnamed element, so reduce it to a simple value rather than
598             // a tuple.
599             builder.getValue().adoptExpression(params[0].disownValue());
600           } else {
601             // Params is not a single unnamed element, so it's a tuple.
602             builder.getValue().initExpression().adoptTuple(app.disownParams());
603           }
604         } else {
605           // The annotation has no value.
606           builder.adoptName(kj::mv(expression));
607           builder.getValue().setNone();
608         }
609 
610         return result;
611       }));
612 
613   parsers.uid = arena.copy(p::transform(
614       p::sequence(op("@"), integerLiteral),
615       [this](Located<uint64_t>&& value) {
616         if (value.value < (1ull << 63)) {
617           errorReporter.addError(value.startByte, value.endByte,
618               "Invalid ID.  Please generate a new one with 'capnpc -i'.");
619         }
620         return value.asProto<LocatedInteger>(orphanage);
621       }));
622 
623   parsers.ordinal = arena.copy(p::transform(
624       p::sequence(op("@"), integerLiteral),
625       [this](Located<uint64_t>&& value) {
626         if (value.value >= 65536) {
627           errorReporter.addError(value.startByte, value.endByte,
628               "Ordinals cannot be greater than 65535.");
629         }
630         return value.asProto<LocatedInteger>(orphanage);
631       }));
632 
633   // -----------------------------------------------------------------
634 
635   parsers.usingDecl = arena.copy(p::transform(
636       p::sequence(keyword("using"), p::optional(p::sequence(identifier, op("="))),
637                   parsers.expression),
638       [this](kj::Maybe<Located<Text::Reader>>&& name, Orphan<Expression>&& target)
639           -> DeclParserResult {
640         auto decl = orphanage.newOrphan<Declaration>();
641         auto builder = decl.get();
642         KJ_IF_MAYBE(n, name) {
643           n->copyTo(builder.initName());
644         } else {
645           auto targetReader = target.getReader();
646           if (targetReader.isMember()) {
647             builder.setName(targetReader.getMember().getName());
648           } else {
649             errorReporter.addErrorOn(targetReader,
650                 "'using' declaration without '=' must specify a named declaration from a "
651                 "different scope.");
652           }
653         }
654         // no id, no annotations for using decl
655         builder.initUsing().adoptTarget(kj::mv(target));
656         return DeclParserResult(kj::mv(decl));
657       }));
658 
659   parsers.constDecl = arena.copy(p::transform(
660       p::sequence(keyword("const"), identifier, p::optional(parsers.uid),
661                   op(":"), parsers.expression,
662                   op("="), parsers.expression,
663                   p::many(parsers.annotation)),
664       [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
665              Orphan<Expression>&& type, Orphan<Expression>&& value,
666              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
667                  -> DeclParserResult {
668         auto decl = orphanage.newOrphan<Declaration>();
669         auto builder =
670             initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
671                      kj::mv(annotations)).initConst();
672         builder.adoptType(kj::mv(type));
673         builder.adoptValue(kj::mv(value));
674         return DeclParserResult(kj::mv(decl));
675       }));
676 
677   parsers.enumDecl = arena.copy(p::transform(
678       p::sequence(keyword("enum"), identifier, p::optional(parsers.uid),
679                   p::many(parsers.annotation)),
680       [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
681              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
682                  -> DeclParserResult {
683         auto decl = orphanage.newOrphan<Declaration>();
684         initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).setEnum();
685         return DeclParserResult(kj::mv(decl), parsers.enumLevelDecl);
686       }));
687 
688   parsers.enumerantDecl = arena.copy(p::transform(
689       p::sequence(identifier, parsers.ordinal, p::many(parsers.annotation)),
690       [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
691              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
692                  -> DeclParserResult {
693         auto decl = orphanage.newOrphan<Declaration>();
694         initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations))
695             .setEnumerant();
696         return DeclParserResult(kj::mv(decl));
697       }));
698 
699   parsers.structDecl = arena.copy(p::transform(
700       p::sequence(keyword("struct"), identifier, p::optional(parsers.uid),
701                   p::optional(parenthesizedList(identifier, errorReporter)),
702                   p::many(parsers.annotation)),
703       [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
704              kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
705              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
706                  -> DeclParserResult {
707         auto decl = orphanage.newOrphan<Declaration>();
708         initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
709                  kj::mv(annotations)).setStruct();
710         return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
711       }));
712 
713   parsers.fieldDecl = arena.copy(p::transform(
714       p::sequence(identifier, parsers.ordinal, op(":"), parsers.expression,
715                   p::optional(p::sequence(op("="), parsers.expression)),
716                   p::many(parsers.annotation)),
717       [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
718              Orphan<Expression>&& type, kj::Maybe<Orphan<Expression>>&& defaultValue,
719              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
720                  -> DeclParserResult {
721         auto decl = orphanage.newOrphan<Declaration>();
722         auto builder =
723             initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations))
724                 .initField();
725         builder.adoptType(kj::mv(type));
726         KJ_IF_MAYBE(val, defaultValue) {
727           builder.getDefaultValue().adoptValue(kj::mv(*val));
728         } else {
729           builder.getDefaultValue().setNone();
730         }
731         return DeclParserResult(kj::mv(decl));
732       }));
733 
734   // Parse an ordinal followed by an optional colon, or no ordinal but require a colon.
735   auto& ordinalOrColon = arena.copy(p::oneOf(
736       p::transform(p::sequence(parsers.ordinal, p::optional(op("!")), p::optional(op(":"))),
737           [](Orphan<LocatedInteger>&& ordinal,
738                  kj::Maybe<kj::Tuple<>> exclamation,
739                  kj::Maybe<kj::Tuple<>> colon)
740                    -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
741             return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr);
742           }),
743       p::transform(op(":"),
744           []() -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
745             return kj::tuple(nullptr, false, false);
746           })));
747 
748   parsers.unionDecl = arena.copy(p::transform(
749       // The first branch of this oneOf() matches named unions.  The second branch matches unnamed
750       // unions and generates dummy values for the parse results.
751       p::oneOf(
752           p::sequence(
753               identifier, ordinalOrColon,
754               keyword("union"), p::many(parsers.annotation)),
755           p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput),
756               [](kj::parse::Span<List<Token>::Reader::Iterator> location) {
757                 return kj::tuple(
758                     Located<Text::Reader>("", location.begin()->getStartByte(),
759                                           location.begin()->getEndByte()),
760                     kj::Maybe<Orphan<LocatedInteger>>(nullptr),
761                     false, false,
762                     kj::Array<Orphan<Declaration::AnnotationApplication>>(nullptr));
763               })),
764       [this](Located<Text::Reader>&& name,
765              kj::Maybe<Orphan<LocatedInteger>>&& ordinal,
766              bool missingExclamation, bool missingColon,
767              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
768                  -> DeclParserResult {
769         if (missingExclamation) {
770           errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(),
771               "As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to "
772               "unions. However, removing the number will break binary compatibility. "
773               "If this is an old protocol and you need to retain compatibility, please "
774               "add an exclamation point after the number to indicate that it is really "
775               "needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility "
776               "doesn't matter, just remove the @n entirely. Sorry for the inconvenience, "
777               "and thanks for being an early adopter!  :)");
778         }
779         if (missingColon) {
780           errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(),
781               "As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon "
782               "for named unions, e.g. `foo :union {`.");
783         }
784 
785         auto decl = orphanage.newOrphan<Declaration>();
786         auto builder = decl.get();
787         name.copyTo(builder.initName());
788         KJ_IF_MAYBE(ord, ordinal) {
789           builder.getId().adoptOrdinal(kj::mv(*ord));
790         } else {
791           builder.getId().setUnspecified();
792         }
793         auto list = builder.initAnnotations(annotations.size());
794         for (uint i = 0; i < annotations.size(); i++) {
795           list.adoptWithCaveats(i, kj::mv(annotations[i]));
796         }
797         builder.setUnion();
798         return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
799       }));
800 
801   parsers.groupDecl = arena.copy(p::transform(
802       p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)),
803       [this](Located<Text::Reader>&& name,
804              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
805                  -> DeclParserResult {
806         auto decl = orphanage.newOrphan<Declaration>();
807         auto builder = decl.get();
808         name.copyTo(builder.getName());
809         builder.getId().setUnspecified();
810         auto list = builder.initAnnotations(annotations.size());
811         for (uint i = 0; i < annotations.size(); i++) {
812           list.adoptWithCaveats(i, kj::mv(annotations[i]));
813         }
814         builder.setGroup();
815         return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
816       }));
817 
818   parsers.interfaceDecl = arena.copy(p::transform(
819       p::sequence(keyword("interface"), identifier, p::optional(parsers.uid),
820                   p::optional(parenthesizedList(identifier, errorReporter)),
821                   p::optional(p::sequence(
822                       keyword("extends"), parenthesizedList(parsers.expression, errorReporter))),
823                   p::many(parsers.annotation)),
824       [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
825              kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
826              kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<Expression>>>>>&& superclasses,
827              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
828                  -> DeclParserResult {
829         auto decl = orphanage.newOrphan<Declaration>();
830         auto builder = initDecl(
831             decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
832             kj::mv(annotations)).initInterface();
833         KJ_IF_MAYBE(s, superclasses) {
834           auto superclassesBuilder = builder.initSuperclasses(s->value.size());
835           for (uint i: kj::indices(s->value)) {
836             KJ_IF_MAYBE(superclass, s->value[i]) {
837               superclassesBuilder.adoptWithCaveats(i, kj::mv(*superclass));
838             }
839           }
840         }
841         return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl);
842       }));
843 
844   parsers.param = arena.copy(p::transformWithLocation(
845       p::sequence(identifier, op(":"), parsers.expression,
846                   p::optional(p::sequence(op("="), parsers.expression)),
847                   p::many(parsers.annotation)),
848       [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
849              Located<Text::Reader>&& name, Orphan<Expression>&& type,
850              kj::Maybe<Orphan<Expression>>&& defaultValue,
851              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
852                  -> Orphan<Declaration::Param> {
853         auto result = orphanage.newOrphan<Declaration::Param>();
854         auto builder = result.get();
855 
856         initLocation(location, builder);
857 
858         name.copyTo(builder.initName());
859         builder.adoptType(kj::mv(type));
860         builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations)));
861         KJ_IF_MAYBE(val, defaultValue) {
862           builder.getDefaultValue().adoptValue(kj::mv(*val));
863         } else {
864           builder.getDefaultValue().setNone();
865         }
866 
867         return kj::mv(result);
868       }));
869 
870   auto& paramList = arena.copy(p::oneOf(
871       p::transform(parenthesizedList(parsers.param, errorReporter),
872           [this](Located<kj::Array<kj::Maybe<Orphan<Declaration::Param>>>>&& params)
873                 -> Orphan<Declaration::ParamList> {
874             auto decl = orphanage.newOrphan<Declaration::ParamList>();
875             auto builder = decl.get();
876             params.copyLocationTo(builder);
877             auto listBuilder = builder.initNamedList(params.value.size());
878             for (uint i: kj::indices(params.value)) {
879               KJ_IF_MAYBE(param, params.value[i]) {
880                 listBuilder.adoptWithCaveats(i, kj::mv(*param));
881               }
882             }
883             return decl;
884           }),
885       p::transform(locatedKeyword("stream"),
886           [this](Located<Text::Reader>&& kw) -> Orphan<Declaration::ParamList> {
887             auto decl = orphanage.newOrphan<Declaration::ParamList>();
888             auto builder = decl.get();
889             kw.copyLocationTo(builder);
890             builder.setStream();
891             return decl;
892           }),
893       p::transform(parsers.expression,
894           [this](Orphan<Expression>&& name) -> Orphan<Declaration::ParamList> {
895             auto decl = orphanage.newOrphan<Declaration::ParamList>();
896             auto builder = decl.get();
897             auto nameReader = name.getReader();
898             builder.setStartByte(nameReader.getStartByte());
899             builder.setEndByte(nameReader.getEndByte());
900             builder.adoptType(kj::mv(name));
901             return decl;
902           })));
903 
904   parsers.methodDecl = arena.copy(p::transform(
905       p::sequence(identifier, parsers.ordinal,
906                   p::optional(bracketedList(identifier, errorReporter)),
907                   paramList,
908                   p::optional(p::sequence(op("->"), paramList)),
909                   p::many(parsers.annotation)),
910       [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
911              kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParams,
912              Orphan<Declaration::ParamList>&& params,
913              kj::Maybe<Orphan<Declaration::ParamList>>&& results,
914              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
915                  -> DeclParserResult {
916         auto decl = orphanage.newOrphan<Declaration>();
917         auto nodeBuilder = initMemberDecl(
918             decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations));
919 
920         initGenericParams(nodeBuilder, kj::mv(genericParams));
921 
922         auto builder = nodeBuilder.initMethod();
923 
924         builder.adoptParams(kj::mv(params));
925 
926         KJ_IF_MAYBE(r, results) {
927           builder.getResults().adoptExplicit(kj::mv(*r));
928         } else {
929           builder.getResults().setNone();
930         }
931 
932         return DeclParserResult(kj::mv(decl));
933       }));
934 
935   auto& annotationTarget = arena.copy(p::oneOf(
936       identifier,
937       p::transformWithLocation(op("*"),
938           [](kj::parse::Span<List<Token>::Reader::Iterator> location) {
939             // Hacky...
940             return Located<Text::Reader>("*",
941                 location.begin()->getStartByte(),
942                 location.begin()->getEndByte());
943           })));
944 
945   parsers.annotationDecl = arena.copy(p::transform(
946       p::sequence(keyword("annotation"), identifier, p::optional(parsers.uid),
947                   parenthesizedList(annotationTarget, errorReporter),
948                   op(":"), parsers.expression,
949                   p::many(parsers.annotation)),
950       [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
951              Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>&& targets,
952              Orphan<Expression>&& type,
953              kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
954                  -> DeclParserResult {
955         auto decl = orphanage.newOrphan<Declaration>();
956         auto builder =
957             initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
958                      kj::mv(annotations)).initAnnotation();
959         builder.adoptType(kj::mv(type));
960         DynamicStruct::Builder dynamicBuilder = builder;
961         for (auto& maybeTarget: targets.value) {
962           KJ_IF_MAYBE(target, maybeTarget) {
963             if (target->value == "*") {
964               // Set all.
965               if (targets.value.size() > 1) {
966                 errorReporter.addError(target->startByte, target->endByte,
967                     "Wildcard should not be specified together with other targets.");
968               }
969 
970               for (auto field: dynamicBuilder.getSchema().getFields()) {
971                 if (field.getProto().getName().startsWith("targets")) {
972                   dynamicBuilder.set(field, true);
973                 }
974               }
975             } else {
976               if (target->value.size() == 0 || target->value.size() >= 32 ||
977                   target->value[0] < 'a' || target->value[0] > 'z') {
978                 errorReporter.addError(target->startByte, target->endByte,
979                                        "Not a valid annotation target.");
980               } else {
981                 char buffer[64];
982                 strcpy(buffer, "targets");
983                 strcat(buffer, target->value.cStr());
984                 buffer[strlen("targets")] += 'A' - 'a';
985                 KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) {
986                   if (dynamicBuilder.get(*field).as<bool>()) {
987                     errorReporter.addError(target->startByte, target->endByte,
988                                            "Duplicate target specification.");
989                   }
990                   dynamicBuilder.set(*field, true);
991                 } else {
992                   errorReporter.addError(target->startByte, target->endByte,
993                                          "Not a valid annotation target.");
994                 }
995               }
996             }
997           }
998         }
999         return DeclParserResult(kj::mv(decl));
1000       }));
1001 
1002   // -----------------------------------------------------------------
1003 
1004   auto& nakedId = arena.copy(p::transform(parsers.uid,
1005       [this](Orphan<LocatedInteger>&& value) -> DeclParserResult {
1006         auto decl = orphanage.newOrphan<Declaration>();
1007         decl.get().adoptNakedId(kj::mv(value));
1008         return DeclParserResult(kj::mv(decl));
1009       }));
1010 
1011   auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation,
1012       [this](Orphan<Declaration::AnnotationApplication>&& value) -> DeclParserResult {
1013         auto decl = orphanage.newOrphan<Declaration>();
1014         decl.get().adoptNakedAnnotation(kj::mv(value));
1015         return DeclParserResult(kj::mv(decl));
1016       }));
1017 
1018   // -----------------------------------------------------------------
1019 
1020   parsers.genericDecl = arena.copy(p::oneOf(
1021       parsers.usingDecl, parsers.constDecl, parsers.annotationDecl,
1022       parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl));
1023   parsers.fileLevelDecl = arena.copy(p::oneOf(
1024       parsers.genericDecl, nakedId, nakedAnnotation));
1025   parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl));
1026   parsers.structLevelDecl = arena.copy(p::oneOf(
1027       parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl));
1028   parsers.interfaceLevelDecl = arena.copy(p::oneOf(
1029       parsers.methodDecl, parsers.genericDecl));
1030 }
1031 
~CapnpParser()1032 CapnpParser::~CapnpParser() noexcept(false) {}
1033 
parseStatement(Statement::Reader statement,const DeclParser & parser)1034 kj::Maybe<Orphan<Declaration>> CapnpParser::parseStatement(
1035     Statement::Reader statement, const DeclParser& parser) {
1036   auto fullParser = p::sequence(parser, p::endOfInput);
1037 
1038   auto tokens = statement.getTokens();
1039   ParserInput parserInput(tokens.begin(), tokens.end());
1040 
1041   KJ_IF_MAYBE(output, fullParser(parserInput)) {
1042     auto builder = output->decl.get();
1043 
1044     if (statement.hasDocComment()) {
1045       builder.setDocComment(statement.getDocComment());
1046     }
1047 
1048     builder.setStartByte(statement.getStartByte());
1049     builder.setEndByte(statement.getEndByte());
1050 
1051     switch (statement.which()) {
1052       case Statement::LINE:
1053         if (output->memberParser != nullptr) {
1054           errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1055               "This statement should end with a block, not a semicolon.");
1056         }
1057         break;
1058 
1059       case Statement::BLOCK:
1060         KJ_IF_MAYBE(memberParser, output->memberParser) {
1061           auto memberStatements = statement.getBlock();
1062           kj::Vector<Orphan<Declaration>> members(memberStatements.size());
1063           for (auto memberStatement: memberStatements) {
1064             KJ_IF_MAYBE(member, parseStatement(memberStatement, *memberParser)) {
1065               members.add(kj::mv(*member));
1066             }
1067           }
1068           builder.adoptNestedDecls(arrayToList(orphanage, members.releaseAsArray()));
1069         } else {
1070           errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1071               "This statement should end with a semicolon, not a block.");
1072         }
1073         break;
1074     }
1075 
1076     return kj::mv(output->decl);
1077 
1078   } else {
1079     // Parse error.  Figure out where to report it.
1080     auto best = parserInput.getBest();
1081     uint32_t bestByte;
1082 
1083     if (best != tokens.end()) {
1084       bestByte = best->getStartByte();
1085     } else if (tokens.end() != tokens.begin()) {
1086       bestByte = (tokens.end() - 1)->getEndByte();
1087     } else {
1088       bestByte = statement.getStartByte();
1089     }
1090 
1091     errorReporter.addError(bestByte, bestByte, "Parse error.");
1092     return nullptr;
1093   }
1094 }
1095 
1096 // =======================================================================================
1097 
1098 static const char HEXDIGITS[] = "0123456789abcdef";
1099 
stringLiteralStringTree(kj::StringPtr chars)1100 static kj::StringTree stringLiteralStringTree(kj::StringPtr chars) {
1101   return kj::strTree('"', kj::encodeCEscape(chars), '"');
1102 }
1103 
binaryLiteralStringTree(Data::Reader data)1104 static kj::StringTree binaryLiteralStringTree(Data::Reader data) {
1105   kj::Vector<char> escaped(data.size() * 3);
1106 
1107   for (byte b: data) {
1108     escaped.add(HEXDIGITS[b % 16]);
1109     escaped.add(HEXDIGITS[b / 16]);
1110     escaped.add(' ');
1111   }
1112 
1113   escaped.removeLast();
1114   return kj::strTree("0x\"", escaped, '"');
1115 }
1116 
1117 static kj::StringTree expressionStringTree(Expression::Reader exp);
1118 
tupleLiteral(List<Expression::Param>::Reader params)1119 static kj::StringTree tupleLiteral(List<Expression::Param>::Reader params) {
1120   auto parts = kj::heapArrayBuilder<kj::StringTree>(params.size());
1121   for (auto param: params) {
1122     auto part = expressionStringTree(param.getValue());
1123     if (param.isNamed()) {
1124       part = kj::strTree(param.getNamed().getValue(), " = ", kj::mv(part));
1125     }
1126     parts.add(kj::mv(part));
1127   }
1128   return kj::strTree("( ", kj::StringTree(parts.finish(), ", "), " )");
1129 }
1130 
expressionStringTree(Expression::Reader exp)1131 static kj::StringTree expressionStringTree(Expression::Reader exp) {
1132   switch (exp.which()) {
1133     case Expression::UNKNOWN:
1134       return kj::strTree("<parse error>");
1135     case Expression::POSITIVE_INT:
1136       return kj::strTree(exp.getPositiveInt());
1137     case Expression::NEGATIVE_INT:
1138       return kj::strTree('-', exp.getNegativeInt());
1139     case Expression::FLOAT:
1140       return kj::strTree(exp.getFloat());
1141     case Expression::STRING:
1142       return stringLiteralStringTree(exp.getString());
1143     case Expression::BINARY:
1144       return binaryLiteralStringTree(exp.getBinary());
1145     case Expression::RELATIVE_NAME:
1146       return kj::strTree(exp.getRelativeName().getValue());
1147     case Expression::ABSOLUTE_NAME:
1148       return kj::strTree('.', exp.getAbsoluteName().getValue());
1149     case Expression::IMPORT:
1150       return kj::strTree("import ", stringLiteralStringTree(exp.getImport().getValue()));
1151     case Expression::EMBED:
1152       return kj::strTree("embed ", stringLiteralStringTree(exp.getEmbed().getValue()));
1153 
1154     case Expression::LIST: {
1155       auto list = exp.getList();
1156       auto parts = kj::heapArrayBuilder<kj::StringTree>(list.size());
1157       for (auto element: list) {
1158         parts.add(expressionStringTree(element));
1159       }
1160       return kj::strTree("[ ", kj::StringTree(parts.finish(), ", "), " ]");
1161     }
1162 
1163     case Expression::TUPLE:
1164       return tupleLiteral(exp.getTuple());
1165 
1166     case Expression::APPLICATION: {
1167       auto app = exp.getApplication();
1168       return kj::strTree(expressionStringTree(app.getFunction()),
1169                          '(', tupleLiteral(app.getParams()), ')');
1170     }
1171 
1172     case Expression::MEMBER: {
1173       auto member = exp.getMember();
1174       return kj::strTree(expressionStringTree(member.getParent()), '.',
1175                          member.getName().getValue());
1176     }
1177   }
1178 
1179   KJ_UNREACHABLE;
1180 }
1181 
expressionString(Expression::Reader name)1182 kj::String expressionString(Expression::Reader name) {
1183   return expressionStringTree(name).flatten();
1184 }
1185 
1186 }  // namespace compiler
1187 }  // namespace capnp
1188