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