parser.c++ 46.2 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
Kenton Varda's avatar
Kenton Varda committed
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
Kenton Varda's avatar
Kenton Varda committed
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
Kenton Varda's avatar
Kenton Varda committed
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
Kenton Varda's avatar
Kenton Varda committed
21 22

#include "parser.h"
Kenton Varda's avatar
Kenton Varda committed
23
#include "md5.h"
24
#include <capnp/dynamic.h>
25 26 27 28 29
#include <kj/debug.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Kenton Varda's avatar
Kenton Varda committed
30

31 32 33 34 35
#if _WIN32
#include <windows.h>
#undef VOID
#endif

Kenton Varda's avatar
Kenton Varda committed
36 37 38
namespace capnp {
namespace compiler {

39
uint64_t generateRandomId() {
40 41
  uint64_t result;

42 43 44 45 46 47 48 49 50
#if _WIN32
  HCRYPTPROV handle;
  KJ_ASSERT(CryptAcquireContextW(&handle, nullptr, nullptr,
                                 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT));
  KJ_DEFER(KJ_ASSERT(CryptReleaseContext(handle, 0)) {break;});

  KJ_ASSERT(CryptGenRandom(handle, sizeof(result), reinterpret_cast<BYTE*>(&result)));

#else
51 52 53 54 55 56
  int fd;
  KJ_SYSCALL(fd = open("/dev/urandom", O_RDONLY));

  ssize_t n;
  KJ_SYSCALL(n = read(fd, &result, sizeof(result)), "/dev/urandom");
  KJ_ASSERT(n == sizeof(result), "Incomplete read from /dev/urandom.", n);
57
#endif
58

59
  return result | (1ull << 63);
60 61
}

Kenton Varda's avatar
Kenton Varda committed
62 63 64 65 66 67 68 69 70 71
uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) {
  // Compute ID by MD5 hashing the concatenation of the parent ID and the declaration name, and
  // then taking the first 8 bytes.

  kj::byte parentIdBytes[sizeof(uint64_t)];
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    parentIdBytes[i] = (parentId >> (i * 8)) & 0xff;
  }

  Md5 md5;
72
  md5.update(kj::arrayPtr(parentIdBytes, kj::size(parentIdBytes)));
Kenton Varda's avatar
Kenton Varda committed
73 74 75 76 77 78 79 80 81 82 83 84
  md5.update(childName);

  kj::ArrayPtr<const kj::byte> resultBytes = md5.finish();

  uint64_t result = 0;
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    result = (result << 8) | resultBytes[i];
  }

  return result | (1ull << 63);
}

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex) {
  // Compute ID by MD5 hashing the concatenation of the parent ID and the group index, and
  // then taking the first 8 bytes.

  kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t)];
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    bytes[i] = (parentId >> (i * 8)) & 0xff;
  }
  for (uint i = 0; i < sizeof(uint16_t); i++) {
    bytes[sizeof(uint64_t) + i] = (groupIndex >> (i * 8)) & 0xff;
  }

  Md5 md5;
  md5.update(bytes);

  kj::ArrayPtr<const kj::byte> resultBytes = md5.finish();

  uint64_t result = 0;
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    result = (result << 8) | resultBytes[i];
  }

  return result | (1ull << 63);
}

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
uint64_t generateMethodParamsId(uint64_t parentId, uint16_t methodOrdinal, bool isResults) {
  // Compute ID by MD5 hashing the concatenation of the parent ID, the method ordinal, and a
  // boolean indicating whether this is the params or the results, and then taking the first 8
  // bytes.

  kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t) + 1];
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    bytes[i] = (parentId >> (i * 8)) & 0xff;
  }
  for (uint i = 0; i < sizeof(uint16_t); i++) {
    bytes[sizeof(uint64_t) + i] = (methodOrdinal >> (i * 8)) & 0xff;
  }
  bytes[sizeof(bytes) - 1] = isResults;

  Md5 md5;
  md5.update(bytes);

  kj::ArrayPtr<const kj::byte> resultBytes = md5.finish();

  uint64_t result = 0;
  for (uint i = 0; i < sizeof(uint64_t); i++) {
    result = (result << 8) | resultBytes[i];
  }

  return result | (1ull << 63);
}

137
void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
138
               ErrorReporter& errorReporter) {
139 140 141 142 143
  CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);

  kj::Vector<Orphan<Declaration>> decls(statements.size());
  kj::Vector<Orphan<Declaration::AnnotationApplication>> annotations;

144
  auto fileDecl = result.getRoot();
145
  fileDecl.setFile(VOID);
146 147 148 149

  for (auto statement: statements) {
    KJ_IF_MAYBE(decl, parser.parseStatement(statement, parser.getParsers().fileLevelDecl)) {
      Declaration::Builder builder = decl->get();
150 151
      switch (builder.which()) {
        case Declaration::NAKED_ID:
152
          if (fileDecl.getId().isUid()) {
153
            errorReporter.addError(builder.getStartByte(), builder.getEndByte(),
Kenton Varda's avatar
Kenton Varda committed
154
                                   "File can only have one ID.");
155
          } else {
156
            fileDecl.getId().adoptUid(builder.disownNakedId());
157
            if (builder.hasDocComment()) {
158
              fileDecl.adoptDocComment(builder.disownDocComment());
159
            }
160 161
          }
          break;
162 163
        case Declaration::NAKED_ANNOTATION:
          annotations.add(builder.disownNakedAnnotation());
164 165 166 167 168 169 170 171
          break;
        default:
          decls.add(kj::mv(*decl));
          break;
      }
    }
  }

172
  if (fileDecl.getId().which() != Declaration::Id::UID) {
173
    uint64_t id = generateRandomId();
174
    fileDecl.getId().initUid().setValue(id);
175 176
    errorReporter.addError(0, 0,
        kj::str("File does not declare an ID.  I've generated one for you.  Add this line to your "
177
                "file: @0x", kj::hex(id), ";"));
178 179
  }

180
  auto declsBuilder = fileDecl.initNestedDecls(decls.size());
181 182 183 184
  for (size_t i = 0; i < decls.size(); i++) {
    declsBuilder.adoptWithCaveats(i, kj::mv(decls[i]));
  }

185
  auto annotationsBuilder = fileDecl.initAnnotations(annotations.size());
186 187 188 189 190
  for (size_t i = 0; i < annotations.size(); i++) {
    annotationsBuilder.adoptWithCaveats(i, kj::mv(annotations[i]));
  }
}

Kenton Varda's avatar
Kenton Varda committed
191 192 193 194
namespace p = kj::parse;

namespace {

195 196
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
template <typename T>
struct Located {
  T value;
  uint32_t startByte;
  uint32_t endByte;

  template <typename Builder>
  void copyLocationTo(Builder builder) {
    builder.setStartByte(startByte);
    builder.setEndByte(endByte);
  }
  template <typename Builder>
  void copyTo(Builder builder) {
    builder.setValue(value);
    copyLocationTo(builder);
  }
  template <typename Result>
  Orphan<Result> asProto(Orphanage orphanage) {
215
    auto result = orphanage.newOrphan<Result>();
Kenton Varda's avatar
Kenton Varda committed
216 217 218
    copyTo(result.get());
    return result;
  }
Kenton Varda's avatar
Kenton Varda committed
219 220 221 222
  template <typename Other>
  Located<kj::Decay<Other>> rewrap(Other&& other) {
    return Located<Other>(kj::fwd<Other>(other), startByte, endByte);
  }
Kenton Varda's avatar
Kenton Varda committed
223 224 225 226 227 228 229

  Located(const T& value, uint32_t startByte, uint32_t endByte)
      : value(value), startByte(startByte), endByte(endByte) {}
  Located(T&& value, uint32_t startByte, uint32_t endByte)
      : value(kj::mv(value)), startByte(startByte), endByte(endByte) {}
};

230 231
// =======================================================================================

232
template <typename T, Token::Which type, T (Token::Reader::*get)() const>
Kenton Varda's avatar
Kenton Varda committed
233 234
struct MatchTokenType {
  kj::Maybe<Located<T>> operator()(Token::Reader token) const {
235 236
    if (token.which() == type) {
      return Located<T>((token.*get)(), token.getStartByte(), token.getEndByte());
Kenton Varda's avatar
Kenton Varda committed
237 238 239 240 241 242 243 244
    } else {
      return nullptr;
    }
  }
};

#define TOKEN_TYPE_PARSER(type, discrim, getter) \
    p::transformOrReject(p::any, \
245
        MatchTokenType<type, Token::discrim, &Token::Reader::getter>())
Kenton Varda's avatar
Kenton Varda committed
246 247 248

constexpr auto identifier = TOKEN_TYPE_PARSER(Text::Reader, IDENTIFIER, getIdentifier);
constexpr auto stringLiteral = TOKEN_TYPE_PARSER(Text::Reader, STRING_LITERAL, getStringLiteral);
Jason Choy's avatar
Jason Choy committed
249
constexpr auto binaryLiteral = TOKEN_TYPE_PARSER(Data::Reader, BINARY_LITERAL, getBinaryLiteral);
Kenton Varda's avatar
Kenton Varda committed
250 251 252 253 254 255 256 257
constexpr auto integerLiteral = TOKEN_TYPE_PARSER(uint64_t, INTEGER_LITERAL, getIntegerLiteral);
constexpr auto floatLiteral = TOKEN_TYPE_PARSER(double, FLOAT_LITERAL, getFloatLiteral);
constexpr auto operatorToken = TOKEN_TYPE_PARSER(Text::Reader, OPERATOR, getOperator);
constexpr auto rawParenthesizedList =
    TOKEN_TYPE_PARSER(List<List<Token>>::Reader, PARENTHESIZED_LIST, getParenthesizedList);
constexpr auto rawBracketedList =
    TOKEN_TYPE_PARSER(List<List<Token>>::Reader, BRACKETED_LIST, getBracketedList);

258 259
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
class ExactString {
public:
  constexpr ExactString(const char* expected): expected(expected) {}

  kj::Maybe<kj::Tuple<>> operator()(Located<Text::Reader>&& text) const {
    if (text.value == expected) {
      return kj::Tuple<>();
    } else {
      return nullptr;
    }
  }

private:
  const char* expected;
};

constexpr auto keyword(const char* expected)
    -> decltype(p::transformOrReject(identifier, ExactString(expected))) {
  return p::transformOrReject(identifier, ExactString(expected));
}

constexpr auto op(const char* expected)
    -> decltype(p::transformOrReject(operatorToken, ExactString(expected))) {
  return p::transformOrReject(operatorToken, ExactString(expected));
}

286 287
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
288 289 290 291 292
template <typename ItemParser>
class ParseListItems {
  // Transformer that parses all items in the input token sequence list using the given parser.

public:
293
  constexpr ParseListItems(ItemParser&& itemParser, ErrorReporter& errorReporter)
Kenton Varda's avatar
Kenton Varda committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
      : itemParser(p::sequence(kj::fwd<ItemParser>(itemParser), p::endOfInput)),
        errorReporter(errorReporter) {}

  Located<kj::Array<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>> operator()(
      Located<List<List<Token>>::Reader>&& items) const {
    auto result = kj::heapArray<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>(
        items.value.size());
    for (uint i = 0; i < items.value.size(); i++) {
      auto item = items.value[i];
      CapnpParser::ParserInput input(item.begin(), item.end());
      result[i] = itemParser(input);
      if (result[i] == nullptr) {
        // Parsing failed.  Report an error.
        auto best = input.getBest();
        if (best < item.end()) {
          // Report error from the point where parsing failed to the end of the item.
          errorReporter.addError(
Kenton Varda's avatar
Kenton Varda committed
311
              best->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
Kenton Varda's avatar
Kenton Varda committed
312 313 314 315
        } else if (item.size() > 0) {
          // The item is non-empty and the parser consumed all of it before failing.  Report an
          // error for the whole thing.
          errorReporter.addError(
Kenton Varda's avatar
Kenton Varda committed
316
              item.begin()->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
Kenton Varda's avatar
Kenton Varda committed
317 318 319 320
        } else {
          // The item has no content.
          // TODO(cleanup):  We don't actually know the item's location, so we can only report
          //   an error across the whole list.  Fix this.
Kenton Varda's avatar
Kenton Varda committed
321
          errorReporter.addError(items.startByte, items.endByte, "Parse error: Empty list item.");
Kenton Varda's avatar
Kenton Varda committed
322 323 324 325 326 327 328 329 330
        }
      }
    }
    return Located<kj::Array<kj::Maybe<p::OutputType<ItemParser, CapnpParser::ParserInput>>>>(
        kj::mv(result), items.startByte, items.endByte);
  }

private:
  decltype(p::sequence(kj::instance<ItemParser>(), p::endOfInput)) itemParser;
331
  ErrorReporter& errorReporter;
Kenton Varda's avatar
Kenton Varda committed
332 333 334
};

template <typename ItemParser>
335
constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
Kenton Varda's avatar
Kenton Varda committed
336 337 338 339 340 341 342
         transform(rawParenthesizedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter))) {
  return transform(rawParenthesizedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter));
}

template <typename ItemParser>
343
constexpr auto bracketedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
Kenton Varda's avatar
Kenton Varda committed
344 345 346 347 348 349
         transform(rawBracketedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter))) {
  return transform(rawBracketedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter));
}

350 351 352 353 354 355 356 357 358 359 360 361
// =======================================================================================

template <typename T>
Orphan<List<T>> arrayToList(Orphanage& orphanage, kj::Array<Orphan<T>>&& elements) {
  auto result = orphanage.newOrphan<List<T>>(elements.size());
  auto builder = result.get();
  for (size_t i = 0; i < elements.size(); i++) {
    builder.adoptWithCaveats(i, kj::mv(elements[i]));
  }
  return kj::mv(result);
}

362 363
static void initGenericParams(Declaration::Builder builder,
    kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters) {
Kenton Varda's avatar
Kenton Varda committed
364 365 366 367 368 369 370 371 372 373
  KJ_IF_MAYBE(p, genericParameters) {
    auto params = builder.initParameters(p->value.size());
    for (uint i: kj::indices(p->value)) {
      KJ_IF_MAYBE(name, p->value[i]) {
        auto param = params[i];
        param.setName(name->value);
        name->copyLocationTo(param);
      }
    }
  }
374 375 376 377 378 379 380 381 382 383 384 385 386
}

static Declaration::Builder 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) {
  name.copyTo(builder.initName());
  KJ_IF_MAYBE(i, id) {
    builder.getId().adoptUid(kj::mv(*i));
  }

  initGenericParams(builder, kj::mv(genericParameters));
Kenton Varda's avatar
Kenton Varda committed
387

388 389 390 391 392 393 394
  auto list = builder.initAnnotations(annotations.size());
  for (uint i = 0; i < annotations.size(); i++) {
    list.adoptWithCaveats(i, kj::mv(annotations[i]));
  }
  return builder;
}

395
static Declaration::Builder initMemberDecl(
396 397 398 399 400 401 402 403 404 405 406 407
    Declaration::Builder builder, Located<Text::Reader>&& name,
    Orphan<LocatedInteger>&& ordinal,
    kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
  name.copyTo(builder.initName());
  builder.getId().adoptOrdinal(kj::mv(ordinal));
  auto list = builder.initAnnotations(annotations.size());
  for (uint i = 0; i < annotations.size(); i++) {
    list.adoptWithCaveats(i, kj::mv(annotations[i]));
  }
  return builder;
}

Kenton Varda's avatar
Kenton Varda committed
408 409 410 411 412 413 414 415 416
template <typename BuilderType>
void initLocation(kj::parse::Span<List<Token>::Reader::Iterator> location,
                  BuilderType builder) {
  if (location.begin() < location.end()) {
    builder.setStartByte(location.begin()->getStartByte());
    builder.setEndByte((location.end() - 1)->getEndByte());
  }
}

Kenton Varda's avatar
Kenton Varda committed
417 418
}  // namespace

419 420
// =======================================================================================

421
CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterParam)
Kenton Varda's avatar
Kenton Varda committed
422
    : orphanage(orphanageParam), errorReporter(errorReporterParam) {
Kenton Varda's avatar
Kenton Varda committed
423 424 425 426 427
  auto& tupleElement = arena.copy(p::transform(
      p::sequence(p::optional(p::sequence(identifier, op("="))), parsers.expression),
      [this](kj::Maybe<Located<Text::Reader>>&& fieldName, Orphan<Expression>&& fieldValue)
             -> Orphan<Expression::Param> {
        auto result = orphanage.newOrphan<Expression::Param>();
428
        auto builder = result.get();
Kenton Varda's avatar
Kenton Varda committed
429
        KJ_IF_MAYBE(fn, fieldName) {
Kenton Varda's avatar
Kenton Varda committed
430 431 432
          fn->copyTo(builder.initNamed());
        } else {
          builder.setUnnamed();
Kenton Varda's avatar
Kenton Varda committed
433
        }
434 435
        builder.adoptValue(kj::mv(fieldValue));
        return kj::mv(result);
Kenton Varda's avatar
Kenton Varda committed
436 437
      }));

Kenton Varda's avatar
Kenton Varda committed
438 439 440 441 442 443 444 445 446 447 448 449
  auto& tuple = arena.copy<Parser<Located<Orphan<List<Expression::Param>>>>>(
      arena.copy(p::transform(
        parenthesizedList(tupleElement, errorReporter),
        [this](Located<kj::Array<kj::Maybe<Orphan<Expression::Param>>>>&& elements)
               -> Located<Orphan<List<Expression::Param>>> {
          auto result = orphanage.newOrphan<List<Expression::Param>>(elements.value.size());
          auto builder = result.get();
          for (uint i: kj::indices(elements.value)) {
            KJ_IF_MAYBE(e, elements.value[i]) {
              builder.adoptWithCaveats(i, kj::mv(*e));
            } else {
              builder[i].initValue().setUnknown();
450 451
            }
          }
Kenton Varda's avatar
Kenton Varda committed
452 453
          return elements.rewrap(kj::mv(result));
        })));
454

Kenton Varda's avatar
Kenton Varda committed
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
  parsers.expression = arena.copy(p::transform(
      p::sequence(
          // Base expression.
          p::oneOf(
              p::transform(integerLiteral,
                  [this](Located<uint64_t>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setPositiveInt(value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(p::sequence(op("-"), integerLiteral),
                  [this](Located<uint64_t>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setNegativeInt(value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(floatLiteral,
                  [this](Located<double>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setFloat(value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(p::sequence(op("-"), floatLiteral),
                  [this](Located<double>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setFloat(-value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transformWithLocation(p::sequence(op("-"), keyword("inf")),
                  [this](kj::parse::Span<List<Token>::Reader::Iterator> location)
                      -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setFloat(-kj::inf());
                    initLocation(location, builder);
                    return result;
                  }),
              p::transform(stringLiteral,
                  [this](Located<Text::Reader>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setString(value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(binaryLiteral,
                  [this](Located<Data::Reader>&& value) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    builder.setBinary(value.value);
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(bracketedList(parsers.expression, errorReporter),
                  [this](Located<kj::Array<kj::Maybe<Orphan<Expression>>>>&& value)
                      -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    auto listBuilder = builder.initList(value.value.size());
                    for (uint i = 0; i < value.value.size(); i++) {
                      KJ_IF_MAYBE(element, value.value[i]) {
                        listBuilder.adoptWithCaveats(i, kj::mv(*element));
                      }
                    }
                    value.copyLocationTo(builder);
                    return result;
                  }),
              p::transform(tuple,
                  [this](Located<Orphan<List<Expression::Param>>>&& value)
                      -> Orphan<Expression> {
                    auto elements = value.value.get();

                    if (elements.size() == 1 && elements[0].isUnnamed()) {
                      // Single-value tuple is just a value.
                      return elements[0].disownValue();
                    } else {
                      auto result = orphanage.newOrphan<Expression>();
                      auto builder = result.get();
                      builder.adoptTuple(kj::mv(value.value));
                      value.copyLocationTo(builder);
                      return result;
                    }
                  }),
              p::transformWithLocation(p::sequence(keyword("import"), stringLiteral),
                  [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
                         Located<Text::Reader>&& filename) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    initLocation(location, builder);
                    filename.copyTo(builder.initImport());
                    return result;
                  }),
              p::transformWithLocation(p::sequence(op("."), identifier),
                  [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
                         Located<Text::Reader>&& name) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    initLocation(location, builder);
                    name.copyTo(builder.initAbsoluteName());
                    return result;
                  }),
              p::transform(identifier,
                  [this](Located<Text::Reader>&& name) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    name.copyTo(builder.initRelativeName());
                    name.copyLocationTo(builder);
                    return result;
                  })),
          // Suffixes, e.g. ".member" or "(param1, param2)".
          p::many(p::oneOf(
              p::transformWithLocation(p::sequence(op("."), identifier),
                  [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
                         Located<Text::Reader>&& name) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    initLocation(location, builder);
                    name.copyTo(builder.initMember().initName());
                    return result;
                  }),
              p::transform(tuple,
                  [this](Located<Orphan<List<Expression::Param>>>&& params) -> Orphan<Expression> {
                    auto result = orphanage.newOrphan<Expression>();
                    auto builder = result.get();
                    params.copyLocationTo(builder);
                    builder.initApplication().adoptParams(kj::mv(params.value));
                    return result;
                  })))),
      [this](Orphan<Expression>&& base, kj::Array<Orphan<Expression>>&& suffixes)
          -> Orphan<Expression> {
        // Apply all the suffixes to the base expression.
        uint startByte = base.getReader().getStartByte();
        for (auto& suffix: suffixes) {
          auto builder = suffix.get();
          if (builder.isApplication()) {
            builder.getApplication().adoptFunction(kj::mv(base));
          } else if (builder.isMember()) {
            builder.getMember().adoptParent(kj::mv(base));
          } else {
            KJ_FAIL_ASSERT("Unknown suffix?", (uint)builder.which());
603
          }
Kenton Varda's avatar
Kenton Varda committed
604 605
          builder.setStartByte(startByte);
          base = kj::mv(suffix);
606
        }
Kenton Varda's avatar
Kenton Varda committed
607
        return kj::mv(base);
608 609
      }));

Kenton Varda's avatar
Kenton Varda committed
610
  parsers.annotation = arena.copy(p::transform(
Kenton Varda's avatar
Kenton Varda committed
611 612
      p::sequence(op("$"), parsers.expression),
      [this](Orphan<Expression>&& expression)
613 614 615
          -> Orphan<Declaration::AnnotationApplication> {
        auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
        auto builder = result.get();
Kenton Varda's avatar
Kenton Varda committed
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631

        auto exp = expression.get();
        if (exp.isApplication()) {
          // Oops, this annotation specifies the value, but we parsed it as an application on
          // the preceding expression. Pull it back apart.
          auto app = exp.getApplication();
          builder.adoptName(app.disownFunction());
          auto params = app.getParams();
          if (params.size() == 1 && params[0].isUnnamed()) {
            // Params has a single unnamed element, so reduce it to a simple value rather than
            // a tuple.
            builder.getValue().adoptExpression(params[0].disownValue());
          } else {
            // Params is not a single unnamed element, so it's a tuple.
            builder.getValue().initExpression().adoptTuple(app.disownParams());
          }
632
        } else {
Kenton Varda's avatar
Kenton Varda committed
633 634
          // The annotation has no value.
          builder.adoptName(kj::mv(expression));
635 636
          builder.getValue().setNone();
        }
Kenton Varda's avatar
Kenton Varda committed
637

638 639 640 641 642 643 644 645
        return result;
      }));

  parsers.uid = arena.copy(p::transform(
      p::sequence(op("@"), integerLiteral),
      [this](Located<uint64_t>&& value) {
        if (value.value < (1ull << 63)) {
          errorReporter.addError(value.startByte, value.endByte,
Kenton Varda's avatar
Kenton Varda committed
646
              "Invalid ID.  Please generate a new one with 'capnpc -i'.");
647 648 649 650 651 652 653 654 655
        }
        return value.asProto<LocatedInteger>(orphanage);
      }));

  parsers.ordinal = arena.copy(p::transform(
      p::sequence(op("@"), integerLiteral),
      [this](Located<uint64_t>&& value) {
        if (value.value >= 65536) {
          errorReporter.addError(value.startByte, value.endByte,
Kenton Varda's avatar
Kenton Varda committed
656
              "Ordinals cannot be greater than 65535.");
657 658 659 660
        }
        return value.asProto<LocatedInteger>(orphanage);
      }));

Kenton Varda's avatar
Kenton Varda committed
661 662 663
  // -----------------------------------------------------------------

  parsers.usingDecl = arena.copy(p::transform(
664
      p::sequence(keyword("using"), p::optional(p::sequence(identifier, op("="))),
Kenton Varda's avatar
Kenton Varda committed
665 666
                  parsers.expression),
      [this](kj::Maybe<Located<Text::Reader>>&& name, Orphan<Expression>&& target)
667
          -> DeclParserResult {
Kenton Varda's avatar
Kenton Varda committed
668 669
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder = decl.get();
670 671 672
        KJ_IF_MAYBE(n, name) {
          n->copyTo(builder.initName());
        } else {
Kenton Varda's avatar
Kenton Varda committed
673 674 675
          auto targetReader = target.getReader();
          if (targetReader.isMember()) {
            builder.setName(targetReader.getMember().getName());
676
          } else {
Kenton Varda's avatar
Kenton Varda committed
677
            errorReporter.addErrorOn(targetReader,
678 679
                "'using' declaration without '=' must specify a named declaration from a "
                "different scope.");
680 681
          }
        }
Kenton Varda's avatar
Kenton Varda committed
682
        // no id, no annotations for using decl
683
        builder.initUsing().adoptTarget(kj::mv(target));
Kenton Varda's avatar
Kenton Varda committed
684 685
        return DeclParserResult(kj::mv(decl));
      }));
686 687 688

  parsers.constDecl = arena.copy(p::transform(
      p::sequence(keyword("const"), identifier, p::optional(parsers.uid),
Kenton Varda's avatar
Kenton Varda committed
689 690
                  op(":"), parsers.expression,
                  op("="), parsers.expression,
691 692
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
693
             Orphan<Expression>&& type, Orphan<Expression>&& value,
694 695 696
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
697
        auto builder =
Kenton Varda's avatar
Kenton Varda committed
698 699
            initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
                     kj::mv(annotations)).initConst();
700 701 702 703 704 705 706 707 708 709 710 711
        builder.adoptType(kj::mv(type));
        builder.adoptValue(kj::mv(value));
        return DeclParserResult(kj::mv(decl));
      }));

  parsers.enumDecl = arena.copy(p::transform(
      p::sequence(keyword("enum"), identifier, p::optional(parsers.uid),
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
Kenton Varda's avatar
Kenton Varda committed
712
        initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).setEnum();
713 714 715 716 717 718 719 720 721 722
        return DeclParserResult(kj::mv(decl), parsers.enumLevelDecl);
      }));

  parsers.enumerantDecl = arena.copy(p::transform(
      p::sequence(identifier, parsers.ordinal, p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
        initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations))
723
            .setEnumerant();
724 725 726 727 728
        return DeclParserResult(kj::mv(decl));
      }));

  parsers.structDecl = arena.copy(p::transform(
      p::sequence(keyword("struct"), identifier, p::optional(parsers.uid),
Kenton Varda's avatar
Kenton Varda committed
729
                  p::optional(parenthesizedList(identifier, errorReporter)),
730 731
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
732
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
733 734 735
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
Kenton Varda's avatar
Kenton Varda committed
736 737
        initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
                 kj::mv(annotations)).setStruct();
738 739 740 741
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));

  parsers.fieldDecl = arena.copy(p::transform(
Kenton Varda's avatar
Kenton Varda committed
742 743
      p::sequence(identifier, parsers.ordinal, op(":"), parsers.expression,
                  p::optional(p::sequence(op("="), parsers.expression)),
744 745
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
Kenton Varda's avatar
Kenton Varda committed
746
             Orphan<Expression>&& type, kj::Maybe<Orphan<Expression>>&& defaultValue,
747 748 749 750 751
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder =
            initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations))
752
                .initField();
753 754 755 756 757 758 759 760 761
        builder.adoptType(kj::mv(type));
        KJ_IF_MAYBE(val, defaultValue) {
          builder.getDefaultValue().adoptValue(kj::mv(*val));
        } else {
          builder.getDefaultValue().setNone();
        }
        return DeclParserResult(kj::mv(decl));
      }));

762 763 764 765 766 767
  // Parse an ordinal followed by an optional colon, or no ordinal but require a colon.
  auto& ordinalOrColon = arena.copy(p::oneOf(
      p::transform(p::sequence(parsers.ordinal, p::optional(op("!")), p::optional(op(":"))),
          [this](Orphan<LocatedInteger>&& ordinal,
                 kj::Maybe<kj::Tuple<>> exclamation,
                 kj::Maybe<kj::Tuple<>> colon)
768 769
                   -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr);
770 771
          }),
      p::transform(op(":"),
772 773 774
          []() -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(nullptr, false, false);
          })));
775

776
  parsers.unionDecl = arena.copy(p::transform(
777 778
      // The first branch of this oneOf() matches named unions.  The second branch matches unnamed
      // unions and generates dummy values for the parse results.
779 780
      p::oneOf(
          p::sequence(
781 782
              identifier, ordinalOrColon,
              keyword("union"), p::many(parsers.annotation)),
783 784
          p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput),
              [](kj::parse::Span<List<Token>::Reader::Iterator> location) {
785
                return kj::tuple(
786 787
                    Located<Text::Reader>("", location.begin()->getStartByte(),
                                          location.begin()->getEndByte()),
788
                    kj::Maybe<Orphan<LocatedInteger>>(nullptr),
789
                    false, false,
790 791 792
                    kj::Array<Orphan<Declaration::AnnotationApplication>>(nullptr));
              })),
      [this](Located<Text::Reader>&& name,
793
             kj::Maybe<Orphan<LocatedInteger>>&& ordinal,
794
             bool missingExclamation, bool missingColon,
795 796
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
        if (missingExclamation) {
          errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(),
              "As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to "
              "unions. However, removing the number will break binary compatibility. "
              "If this is an old protocol and you need to retain compatibility, please "
              "add an exclamation point after the number to indicate that it is really "
              "needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility "
              "doesn't matter, just remove the @n entirely. Sorry for the inconvenience, "
              "and thanks for being an early adopter!  :)");
        }
        if (missingColon) {
          errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(),
              "As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon "
              "for named unions, e.g. `foo :union {`.");
        }

813
        auto decl = orphanage.newOrphan<Declaration>();
814
        auto builder = decl.get();
815
        name.copyTo(builder.initName());
816 817 818 819 820 821 822 823 824
        KJ_IF_MAYBE(ord, ordinal) {
          builder.getId().adoptOrdinal(kj::mv(*ord));
        } else {
          builder.getId().setUnspecified();
        }
        auto list = builder.initAnnotations(annotations.size());
        for (uint i = 0; i < annotations.size(); i++) {
          list.adoptWithCaveats(i, kj::mv(annotations[i]));
        }
825
        builder.setUnion();
826 827
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));
828

829
  parsers.groupDecl = arena.copy(p::transform(
830
      p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)),
Kenton Varda's avatar
Kenton Varda committed
831 832
      [this](Located<Text::Reader>&& name,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
833 834 835
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder = decl.get();
Kenton Varda's avatar
Kenton Varda committed
836
        name.copyTo(builder.getName());
837 838 839 840
        builder.getId().setUnspecified();
        auto list = builder.initAnnotations(annotations.size());
        for (uint i = 0; i < annotations.size(); i++) {
          list.adoptWithCaveats(i, kj::mv(annotations[i]));
841
        }
842
        builder.setGroup();
843 844 845 846 847
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));

  parsers.interfaceDecl = arena.copy(p::transform(
      p::sequence(keyword("interface"), identifier, p::optional(parsers.uid),
Kenton Varda's avatar
Kenton Varda committed
848
                  p::optional(parenthesizedList(identifier, errorReporter)),
849
                  p::optional(p::sequence(
Kenton Varda's avatar
Kenton Varda committed
850
                      keyword("extends"), parenthesizedList(parsers.expression, errorReporter))),
851 852
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
853
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
854
             kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<Expression>>>>>&& superclasses,
855 856 857
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
858
        auto builder = initDecl(
Kenton Varda's avatar
Kenton Varda committed
859 860
            decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
            kj::mv(annotations)).initInterface();
861 862 863 864 865
        KJ_IF_MAYBE(s, superclasses) {
          auto superclassesBuilder = builder.initSuperclasses(s->value.size());
          for (uint i: kj::indices(s->value)) {
            KJ_IF_MAYBE(superclass, s->value[i]) {
              superclassesBuilder.adoptWithCaveats(i, kj::mv(*superclass));
866 867 868
            }
          }
        }
869 870 871
        return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl);
      }));

872
  parsers.param = arena.copy(p::transformWithLocation(
Kenton Varda's avatar
Kenton Varda committed
873 874
      p::sequence(identifier, op(":"), parsers.expression,
                  p::optional(p::sequence(op("="), parsers.expression)),
875
                  p::many(parsers.annotation)),
876
      [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Kenton Varda's avatar
Kenton Varda committed
877 878
             Located<Text::Reader>&& name, Orphan<Expression>&& type,
             kj::Maybe<Orphan<Expression>>&& defaultValue,
879
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
880 881
                 -> Orphan<Declaration::Param> {
        auto result = orphanage.newOrphan<Declaration::Param>();
882 883
        auto builder = result.get();

884 885
        initLocation(location, builder);

886 887
        name.copyTo(builder.initName());
        builder.adoptType(kj::mv(type));
888
        builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations)));
889 890 891 892 893 894 895 896 897
        KJ_IF_MAYBE(val, defaultValue) {
          builder.getDefaultValue().adoptValue(kj::mv(*val));
        } else {
          builder.getDefaultValue().setNone();
        }

        return kj::mv(result);
      }));

898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
  auto& paramList = arena.copy(p::oneOf(
      p::transform(parenthesizedList(parsers.param, errorReporter),
          [this](Located<kj::Array<kj::Maybe<Orphan<Declaration::Param>>>>&& params)
                -> Orphan<Declaration::ParamList> {
            auto decl = orphanage.newOrphan<Declaration::ParamList>();
            auto builder = decl.get();
            params.copyLocationTo(builder);
            auto listBuilder = builder.initNamedList(params.value.size());
            for (uint i: kj::indices(params.value)) {
              KJ_IF_MAYBE(param, params.value[i]) {
                listBuilder.adoptWithCaveats(i, kj::mv(*param));
              }
            }
            return decl;
          }),
Kenton Varda's avatar
Kenton Varda committed
913 914
      p::transform(parsers.expression,
          [this](Orphan<Expression>&& name) -> Orphan<Declaration::ParamList> {
915 916 917 918 919 920 921 922 923
            auto decl = orphanage.newOrphan<Declaration::ParamList>();
            auto builder = decl.get();
            auto nameReader = name.getReader();
            builder.setStartByte(nameReader.getStartByte());
            builder.setEndByte(nameReader.getEndByte());
            builder.adoptType(kj::mv(name));
            return decl;
          })));

924
  parsers.methodDecl = arena.copy(p::transform(
925 926 927
      p::sequence(identifier, parsers.ordinal,
                  p::optional(bracketedList(identifier, errorReporter)),
                  paramList,
928
                  p::optional(p::sequence(op("->"), paramList)),
929 930
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
931
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParams,
932 933
             Orphan<Declaration::ParamList>&& params,
             kj::Maybe<Orphan<Declaration::ParamList>>&& results,
934 935 936
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
937 938 939 940 941 942
        auto nodeBuilder = initMemberDecl(
            decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations));

        initGenericParams(nodeBuilder, kj::mv(genericParams));

        auto builder = nodeBuilder.initMethod();
943

944
        builder.adoptParams(kj::mv(params));
945

946 947
        KJ_IF_MAYBE(r, results) {
          builder.getResults().adoptExplicit(kj::mv(*r));
948
        } else {
949
          builder.getResults().setNone();
950
        }
951

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
        return DeclParserResult(kj::mv(decl));
      }));

  auto& annotationTarget = arena.copy(p::oneOf(
      identifier,
      p::transformWithLocation(op("*"),
          [this](kj::parse::Span<List<Token>::Reader::Iterator> location) {
            // Hacky...
            return Located<Text::Reader>("*",
                location.begin()->getStartByte(),
                location.begin()->getEndByte());
          })));

  parsers.annotationDecl = arena.copy(p::transform(
      p::sequence(keyword("annotation"), identifier, p::optional(parsers.uid),
                  parenthesizedList(annotationTarget, errorReporter),
Kenton Varda's avatar
Kenton Varda committed
968
                  op(":"), parsers.expression,
969 970 971
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
             Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>&& targets,
Kenton Varda's avatar
Kenton Varda committed
972
             Orphan<Expression>&& type,
973 974 975
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
976
        auto builder =
Kenton Varda's avatar
Kenton Varda committed
977 978
            initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
                     kj::mv(annotations)).initAnnotation();
979 980 981 982 983 984 985 986
        builder.adoptType(kj::mv(type));
        DynamicStruct::Builder dynamicBuilder = builder;
        for (auto& maybeTarget: targets.value) {
          KJ_IF_MAYBE(target, maybeTarget) {
            if (target->value == "*") {
              // Set all.
              if (targets.value.size() > 1) {
                errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
987
                    "Wildcard should not be specified together with other targets.");
988
              }
989

990 991 992
              for (auto field: dynamicBuilder.getSchema().getFields()) {
                if (field.getProto().getName().startsWith("targets")) {
                  dynamicBuilder.set(field, true);
993 994 995 996 997 998
                }
              }
            } else {
              if (target->value.size() == 0 || target->value.size() >= 32 ||
                  target->value[0] < 'a' || target->value[0] > 'z') {
                errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
999
                                       "Not a valid annotation target.");
1000 1001 1002 1003 1004
              } else {
                char buffer[64];
                strcpy(buffer, "targets");
                strcat(buffer, target->value.cStr());
                buffer[strlen("targets")] += 'A' - 'a';
1005 1006
                KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) {
                  if (dynamicBuilder.get(*field).as<bool>()) {
1007
                    errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
1008
                                           "Duplicate target specification.");
1009
                  }
1010
                  dynamicBuilder.set(*field, true);
1011 1012
                } else {
                  errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
1013
                                         "Not a valid annotation target.");
1014 1015 1016 1017 1018
                }
              }
            }
          }
        }
1019 1020 1021 1022 1023 1024 1025 1026
        return DeclParserResult(kj::mv(decl));
      }));

  // -----------------------------------------------------------------

  auto& nakedId = arena.copy(p::transform(parsers.uid,
      [this](Orphan<LocatedInteger>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
1027
        decl.get().adoptNakedId(kj::mv(value));
1028 1029 1030 1031 1032 1033
        return DeclParserResult(kj::mv(decl));
      }));

  auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation,
      [this](Orphan<Declaration::AnnotationApplication>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
1034
        decl.get().adoptNakedAnnotation(kj::mv(value));
1035 1036 1037 1038 1039
        return DeclParserResult(kj::mv(decl));
      }));

  // -----------------------------------------------------------------

1040 1041 1042
  parsers.genericDecl = arena.copy(p::oneOf(
      parsers.usingDecl, parsers.constDecl, parsers.annotationDecl,
      parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl));
1043
  parsers.fileLevelDecl = arena.copy(p::oneOf(
1044 1045 1046
      parsers.genericDecl, nakedId, nakedAnnotation));
  parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl));
  parsers.structLevelDecl = arena.copy(p::oneOf(
1047
      parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl));
1048 1049
  parsers.interfaceLevelDecl = arena.copy(p::oneOf(
      parsers.methodDecl, parsers.genericDecl));
1050 1051
}

1052
CapnpParser::~CapnpParser() noexcept(false) {}
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070

kj::Maybe<Orphan<Declaration>> CapnpParser::parseStatement(
    Statement::Reader statement, const DeclParser& parser) {
  auto fullParser = p::sequence(parser, p::endOfInput);

  auto tokens = statement.getTokens();
  ParserInput parserInput(tokens.begin(), tokens.end());

  KJ_IF_MAYBE(output, fullParser(parserInput)) {
    auto builder = output->decl.get();

    if (statement.hasDocComment()) {
      builder.setDocComment(statement.getDocComment());
    }

    builder.setStartByte(statement.getStartByte());
    builder.setEndByte(statement.getEndByte());

1071 1072
    switch (statement.which()) {
      case Statement::LINE:
1073 1074
        if (output->memberParser != nullptr) {
          errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1075
              "This statement should end with a block, not a semicolon.");
1076 1077 1078
        }
        break;

1079
      case Statement::BLOCK:
1080
        KJ_IF_MAYBE(memberParser, output->memberParser) {
1081
          auto memberStatements = statement.getBlock();
1082 1083 1084 1085 1086 1087 1088 1089 1090
          kj::Vector<Orphan<Declaration>> members(memberStatements.size());
          for (auto memberStatement: memberStatements) {
            KJ_IF_MAYBE(member, parseStatement(memberStatement, *memberParser)) {
              members.add(kj::mv(*member));
            }
          }
          builder.adoptNestedDecls(arrayToList(orphanage, members.releaseAsArray()));
        } else {
          errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1091
              "This statement should end with a semicolon, not a block.");
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
        }
        break;
    }

    return kj::mv(output->decl);

  } else {
    // Parse error.  Figure out where to report it.
    auto best = parserInput.getBest();
    uint32_t bestByte;

    if (best != tokens.end()) {
      bestByte = best->getStartByte();
    } else if (tokens.end() != tokens.begin()) {
      bestByte = (tokens.end() - 1)->getEndByte();
    } else {
1108
      bestByte = statement.getStartByte();
1109 1110
    }

Kenton Varda's avatar
Kenton Varda committed
1111
    errorReporter.addError(bestByte, bestByte, "Parse error.");
1112 1113
    return nullptr;
  }
Kenton Varda's avatar
Kenton Varda committed
1114 1115 1116 1117
}

}  // namespace compiler
}  // namespace capnp