parser.c++ 46.7 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
  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;
                  }),
555 556 557 558 559 560 561 562 563
              p::transformWithLocation(p::sequence(keyword("embed"), 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.initEmbed());
                    return result;
                  }),
Kenton Varda's avatar
Kenton Varda committed
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 603 604 605 606 607 608 609 610 611
              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());
612
          }
Kenton Varda's avatar
Kenton Varda committed
613 614
          builder.setStartByte(startByte);
          base = kj::mv(suffix);
615
        }
Kenton Varda's avatar
Kenton Varda committed
616
        return kj::mv(base);
617 618
      }));

Kenton Varda's avatar
Kenton Varda committed
619
  parsers.annotation = arena.copy(p::transform(
Kenton Varda's avatar
Kenton Varda committed
620 621
      p::sequence(op("$"), parsers.expression),
      [this](Orphan<Expression>&& expression)
622 623 624
          -> Orphan<Declaration::AnnotationApplication> {
        auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
        auto builder = result.get();
Kenton Varda's avatar
Kenton Varda committed
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640

        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());
          }
641
        } else {
Kenton Varda's avatar
Kenton Varda committed
642 643
          // The annotation has no value.
          builder.adoptName(kj::mv(expression));
644 645
          builder.getValue().setNone();
        }
Kenton Varda's avatar
Kenton Varda committed
646

647 648 649 650 651 652 653 654
        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
655
              "Invalid ID.  Please generate a new one with 'capnpc -i'.");
656 657 658 659 660 661 662 663 664
        }
        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
665
              "Ordinals cannot be greater than 65535.");
666 667 668 669
        }
        return value.asProto<LocatedInteger>(orphanage);
      }));

Kenton Varda's avatar
Kenton Varda committed
670 671 672
  // -----------------------------------------------------------------

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

  parsers.constDecl = arena.copy(p::transform(
      p::sequence(keyword("const"), identifier, p::optional(parsers.uid),
Kenton Varda's avatar
Kenton Varda committed
698 699
                  op(":"), parsers.expression,
                  op("="), parsers.expression,
700 701
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
702
             Orphan<Expression>&& type, Orphan<Expression>&& value,
703 704 705
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
706
        auto builder =
Kenton Varda's avatar
Kenton Varda committed
707 708
            initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
                     kj::mv(annotations)).initConst();
709 710 711 712 713 714 715 716 717 718 719 720
        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
721
        initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).setEnum();
722 723 724 725 726 727 728 729 730 731
        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))
732
            .setEnumerant();
733 734 735 736 737
        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
738
                  p::optional(parenthesizedList(identifier, errorReporter)),
739 740
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
741
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
742 743 744
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
Kenton Varda's avatar
Kenton Varda committed
745 746
        initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
                 kj::mv(annotations)).setStruct();
747 748 749 750
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));

  parsers.fieldDecl = arena.copy(p::transform(
Kenton Varda's avatar
Kenton Varda committed
751 752
      p::sequence(identifier, parsers.ordinal, op(":"), parsers.expression,
                  p::optional(p::sequence(op("="), parsers.expression)),
753 754
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
Kenton Varda's avatar
Kenton Varda committed
755
             Orphan<Expression>&& type, kj::Maybe<Orphan<Expression>>&& defaultValue,
756 757 758 759 760
             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))
761
                .initField();
762 763 764 765 766 767 768 769 770
        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));
      }));

771 772 773 774 775 776
  // 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)
777 778
                   -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr);
779 780
          }),
      p::transform(op(":"),
781 782 783
          []() -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(nullptr, false, false);
          })));
784

785
  parsers.unionDecl = arena.copy(p::transform(
786 787
      // The first branch of this oneOf() matches named unions.  The second branch matches unnamed
      // unions and generates dummy values for the parse results.
788 789
      p::oneOf(
          p::sequence(
790 791
              identifier, ordinalOrColon,
              keyword("union"), p::many(parsers.annotation)),
792 793
          p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput),
              [](kj::parse::Span<List<Token>::Reader::Iterator> location) {
794
                return kj::tuple(
795 796
                    Located<Text::Reader>("", location.begin()->getStartByte(),
                                          location.begin()->getEndByte()),
797
                    kj::Maybe<Orphan<LocatedInteger>>(nullptr),
798
                    false, false,
799 800 801
                    kj::Array<Orphan<Declaration::AnnotationApplication>>(nullptr));
              })),
      [this](Located<Text::Reader>&& name,
802
             kj::Maybe<Orphan<LocatedInteger>>&& ordinal,
803
             bool missingExclamation, bool missingColon,
804 805
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
        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 {`.");
        }

822
        auto decl = orphanage.newOrphan<Declaration>();
823
        auto builder = decl.get();
824
        name.copyTo(builder.initName());
825 826 827 828 829 830 831 832 833
        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]));
        }
834
        builder.setUnion();
835 836
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));
837

838
  parsers.groupDecl = arena.copy(p::transform(
839
      p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)),
Kenton Varda's avatar
Kenton Varda committed
840 841
      [this](Located<Text::Reader>&& name,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
842 843 844
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder = decl.get();
Kenton Varda's avatar
Kenton Varda committed
845
        name.copyTo(builder.getName());
846 847 848 849
        builder.getId().setUnspecified();
        auto list = builder.initAnnotations(annotations.size());
        for (uint i = 0; i < annotations.size(); i++) {
          list.adoptWithCaveats(i, kj::mv(annotations[i]));
850
        }
851
        builder.setGroup();
852 853 854 855 856
        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
857
                  p::optional(parenthesizedList(identifier, errorReporter)),
858
                  p::optional(p::sequence(
Kenton Varda's avatar
Kenton Varda committed
859
                      keyword("extends"), parenthesizedList(parsers.expression, errorReporter))),
860 861
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
Kenton Varda's avatar
Kenton Varda committed
862
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
863
             kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<Expression>>>>>&& superclasses,
864 865 866
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
867
        auto builder = initDecl(
Kenton Varda's avatar
Kenton Varda committed
868 869
            decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters),
            kj::mv(annotations)).initInterface();
870 871 872 873 874
        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));
875 876 877
            }
          }
        }
878 879 880
        return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl);
      }));

881
  parsers.param = arena.copy(p::transformWithLocation(
Kenton Varda's avatar
Kenton Varda committed
882 883
      p::sequence(identifier, op(":"), parsers.expression,
                  p::optional(p::sequence(op("="), parsers.expression)),
884
                  p::many(parsers.annotation)),
885
      [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Kenton Varda's avatar
Kenton Varda committed
886 887
             Located<Text::Reader>&& name, Orphan<Expression>&& type,
             kj::Maybe<Orphan<Expression>>&& defaultValue,
888
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
889 890
                 -> Orphan<Declaration::Param> {
        auto result = orphanage.newOrphan<Declaration::Param>();
891 892
        auto builder = result.get();

893 894
        initLocation(location, builder);

895 896
        name.copyTo(builder.initName());
        builder.adoptType(kj::mv(type));
897
        builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations)));
898 899 900 901 902 903 904 905 906
        KJ_IF_MAYBE(val, defaultValue) {
          builder.getDefaultValue().adoptValue(kj::mv(*val));
        } else {
          builder.getDefaultValue().setNone();
        }

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

907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
  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
922 923
      p::transform(parsers.expression,
          [this](Orphan<Expression>&& name) -> Orphan<Declaration::ParamList> {
924 925 926 927 928 929 930 931 932
            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;
          })));

933
  parsers.methodDecl = arena.copy(p::transform(
934 935 936
      p::sequence(identifier, parsers.ordinal,
                  p::optional(bracketedList(identifier, errorReporter)),
                  paramList,
937
                  p::optional(p::sequence(op("->"), paramList)),
938 939
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
940
             kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParams,
941 942
             Orphan<Declaration::ParamList>&& params,
             kj::Maybe<Orphan<Declaration::ParamList>>&& results,
943 944 945
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
946 947 948 949 950 951
        auto nodeBuilder = initMemberDecl(
            decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations));

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

        auto builder = nodeBuilder.initMethod();
952

953
        builder.adoptParams(kj::mv(params));
954

955 956
        KJ_IF_MAYBE(r, results) {
          builder.getResults().adoptExplicit(kj::mv(*r));
957
        } else {
958
          builder.getResults().setNone();
959
        }
960

961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
        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
977
                  op(":"), parsers.expression,
978 979 980
                  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
981
             Orphan<Expression>&& type,
982 983 984
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
985
        auto builder =
Kenton Varda's avatar
Kenton Varda committed
986 987
            initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr,
                     kj::mv(annotations)).initAnnotation();
988 989 990 991 992 993 994 995
        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
996
                    "Wildcard should not be specified together with other targets.");
997
              }
998

999 1000 1001
              for (auto field: dynamicBuilder.getSchema().getFields()) {
                if (field.getProto().getName().startsWith("targets")) {
                  dynamicBuilder.set(field, true);
1002 1003 1004 1005 1006 1007
                }
              }
            } 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
1008
                                       "Not a valid annotation target.");
1009 1010 1011 1012 1013
              } else {
                char buffer[64];
                strcpy(buffer, "targets");
                strcat(buffer, target->value.cStr());
                buffer[strlen("targets")] += 'A' - 'a';
1014 1015
                KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) {
                  if (dynamicBuilder.get(*field).as<bool>()) {
1016
                    errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
1017
                                           "Duplicate target specification.");
1018
                  }
1019
                  dynamicBuilder.set(*field, true);
1020 1021
                } else {
                  errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
1022
                                         "Not a valid annotation target.");
1023 1024 1025 1026 1027
                }
              }
            }
          }
        }
1028 1029 1030 1031 1032 1033 1034 1035
        return DeclParserResult(kj::mv(decl));
      }));

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

  auto& nakedId = arena.copy(p::transform(parsers.uid,
      [this](Orphan<LocatedInteger>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
1036
        decl.get().adoptNakedId(kj::mv(value));
1037 1038 1039 1040 1041 1042
        return DeclParserResult(kj::mv(decl));
      }));

  auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation,
      [this](Orphan<Declaration::AnnotationApplication>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
1043
        decl.get().adoptNakedAnnotation(kj::mv(value));
1044 1045 1046 1047 1048
        return DeclParserResult(kj::mv(decl));
      }));

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

1049 1050 1051
  parsers.genericDecl = arena.copy(p::oneOf(
      parsers.usingDecl, parsers.constDecl, parsers.annotationDecl,
      parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl));
1052
  parsers.fileLevelDecl = arena.copy(p::oneOf(
1053 1054 1055
      parsers.genericDecl, nakedId, nakedAnnotation));
  parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl));
  parsers.structLevelDecl = arena.copy(p::oneOf(
1056
      parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl));
1057 1058
  parsers.interfaceLevelDecl = arena.copy(p::oneOf(
      parsers.methodDecl, parsers.genericDecl));
1059 1060
}

1061
CapnpParser::~CapnpParser() noexcept(false) {}
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079

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());

1080 1081
    switch (statement.which()) {
      case Statement::LINE:
1082 1083
        if (output->memberParser != nullptr) {
          errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1084
              "This statement should end with a block, not a semicolon.");
1085 1086 1087
        }
        break;

1088
      case Statement::BLOCK:
1089
        KJ_IF_MAYBE(memberParser, output->memberParser) {
1090
          auto memberStatements = statement.getBlock();
1091 1092 1093 1094 1095 1096 1097 1098 1099
          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(),
1100
              "This statement should end with a semicolon, not a block.");
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
        }
        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 {
1117
      bestByte = statement.getStartByte();
1118 1119
    }

Kenton Varda's avatar
Kenton Varda committed
1120
    errorReporter.addError(bestByte, bestByte, "Parse error.");
1121 1122
    return nullptr;
  }
Kenton Varda's avatar
Kenton Varda committed
1123 1124 1125 1126
}

}  // namespace compiler
}  // namespace capnp