parser.c++ 44.4 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "parser.h"
Kenton Varda's avatar
Kenton Varda committed
25
#include "md5.h"
26
#include <capnp/dynamic.h>
27 28 29 30 31
#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
32
#include <limits>
Kenton Varda's avatar
Kenton Varda committed
33 34 35 36

namespace capnp {
namespace compiler {

37
uint64_t generateRandomId() {
38 39 40 41 42 43 44 45 46
  uint64_t result;

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

47
  return result | (1ull << 63);
48 49
}

Kenton Varda's avatar
Kenton Varda committed
50 51 52 53 54 55 56 57 58 59
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;
60
  md5.update(kj::arrayPtr(parentIdBytes, kj::size(parentIdBytes)));
Kenton Varda's avatar
Kenton Varda committed
61 62 63 64 65 66 67 68 69 70 71 72
  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);
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
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);
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
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);
}

125
void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
126
               const ErrorReporter& errorReporter) {
127 128 129 130 131
  CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);

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

132
  auto fileDecl = result.getRoot();
133
  fileDecl.setFile(VOID);
134 135 136 137

  for (auto statement: statements) {
    KJ_IF_MAYBE(decl, parser.parseStatement(statement, parser.getParsers().fileLevelDecl)) {
      Declaration::Builder builder = decl->get();
138 139
      switch (builder.which()) {
        case Declaration::NAKED_ID:
140
          if (fileDecl.getId().isUid()) {
141
            errorReporter.addError(builder.getStartByte(), builder.getEndByte(),
Kenton Varda's avatar
Kenton Varda committed
142
                                   "File can only have one ID.");
143
          } else {
144
            fileDecl.getId().adoptUid(builder.disownNakedId());
145
            if (builder.hasDocComment()) {
146
              fileDecl.adoptDocComment(builder.disownDocComment());
147
            }
148 149
          }
          break;
150 151
        case Declaration::NAKED_ANNOTATION:
          annotations.add(builder.disownNakedAnnotation());
152 153 154 155 156 157 158 159
          break;
        default:
          decls.add(kj::mv(*decl));
          break;
      }
    }
  }

160
  if (fileDecl.getId().which() != Declaration::Id::UID) {
161
    uint64_t id = generateRandomId();
162
    fileDecl.getId().initUid().setValue(id);
163 164
    errorReporter.addError(0, 0,
        kj::str("File does not declare an ID.  I've generated one for you.  Add this line to your "
165
                "file: @0x", kj::hex(id), ";"));
166 167
  }

168
  auto declsBuilder = fileDecl.initNestedDecls(decls.size());
169 170 171 172
  for (size_t i = 0; i < decls.size(); i++) {
    declsBuilder.adoptWithCaveats(i, kj::mv(decls[i]));
  }

173
  auto annotationsBuilder = fileDecl.initAnnotations(annotations.size());
174 175 176 177 178
  for (size_t i = 0; i < annotations.size(); i++) {
    annotationsBuilder.adoptWithCaveats(i, kj::mv(annotations[i]));
  }
}

Kenton Varda's avatar
Kenton Varda committed
179 180 181 182
namespace p = kj::parse;

namespace {

183 184
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
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) {
203
    auto result = orphanage.newOrphan<Result>();
Kenton Varda's avatar
Kenton Varda committed
204 205 206 207 208 209 210 211 212 213
    copyTo(result.get());
    return result;
  }

  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) {}
};

214 215
// =======================================================================================

216
template <typename T, Token::Which type, T (Token::Reader::*get)() const>
Kenton Varda's avatar
Kenton Varda committed
217 218
struct MatchTokenType {
  kj::Maybe<Located<T>> operator()(Token::Reader token) const {
219 220
    if (token.which() == type) {
      return Located<T>((token.*get)(), token.getStartByte(), token.getEndByte());
Kenton Varda's avatar
Kenton Varda committed
221 222 223 224 225 226 227 228
    } else {
      return nullptr;
    }
  }
};

#define TOKEN_TYPE_PARSER(type, discrim, getter) \
    p::transformOrReject(p::any, \
229
        MatchTokenType<type, Token::discrim, &Token::Reader::getter>())
Kenton Varda's avatar
Kenton Varda committed
230 231 232 233 234 235 236 237 238 239 240

constexpr auto identifier = TOKEN_TYPE_PARSER(Text::Reader, IDENTIFIER, getIdentifier);
constexpr auto stringLiteral = TOKEN_TYPE_PARSER(Text::Reader, STRING_LITERAL, getStringLiteral);
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);

241 242
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
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));
}

269 270
// =======================================================================================

Kenton Varda's avatar
Kenton Varda committed
271 272 273 274 275
template <typename ItemParser>
class ParseListItems {
  // Transformer that parses all items in the input token sequence list using the given parser.

public:
276
  constexpr ParseListItems(ItemParser&& itemParser, const ErrorReporter& errorReporter)
Kenton Varda's avatar
Kenton Varda committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
      : 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
294
              best->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
Kenton Varda's avatar
Kenton Varda committed
295 296 297 298
        } 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
299
              item.begin()->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error.");
Kenton Varda's avatar
Kenton Varda committed
300 301 302 303
        } 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
304
          errorReporter.addError(items.startByte, items.endByte, "Parse error: Empty list item.");
Kenton Varda's avatar
Kenton Varda committed
305 306 307 308 309 310 311 312 313
        }
      }
    }
    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;
314
  const ErrorReporter& errorReporter;
Kenton Varda's avatar
Kenton Varda committed
315 316 317
};

template <typename ItemParser>
318 319
constexpr auto parenthesizedList(ItemParser&& itemParser,
                                 const ErrorReporter& errorReporter) -> decltype(
Kenton Varda's avatar
Kenton Varda committed
320 321 322 323 324 325 326
         transform(rawParenthesizedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter))) {
  return transform(rawParenthesizedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter));
}

template <typename ItemParser>
327 328
constexpr auto bracketedList(ItemParser&& itemParser,
                             const ErrorReporter& errorReporter) -> decltype(
Kenton Varda's avatar
Kenton Varda committed
329 330 331 332 333 334
         transform(rawBracketedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter))) {
  return transform(rawBracketedList, ParseListItems<ItemParser>(
             kj::fwd<ItemParser>(itemParser), errorReporter));
}

335 336 337 338 339 340 341 342 343 344 345 346
// =======================================================================================

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

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
inline Declaration::Builder initDecl(
    Declaration::Builder builder, Located<Text::Reader>&& name,
    kj::Maybe<Orphan<LocatedInteger>>&& id,
    kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
  name.copyTo(builder.initName());
  KJ_IF_MAYBE(i, id) {
    builder.getId().adoptUid(kj::mv(*i));
  }
  auto list = builder.initAnnotations(annotations.size());
  for (uint i = 0; i < annotations.size(); i++) {
    list.adoptWithCaveats(i, kj::mv(annotations[i]));
  }
  return builder;
}

inline Declaration::Builder initMemberDecl(
    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
375 376 377 378 379 380 381 382 383
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
384 385
}  // namespace

386 387
// =======================================================================================

388
CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorReporterParam)
Kenton Varda's avatar
Kenton Varda committed
389
    : orphanage(orphanageParam), errorReporter(errorReporterParam) {
390
  parsers.declName = arena.copy(p::transformWithLocation(
Kenton Varda's avatar
Kenton Varda committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
      p::sequence(
          p::oneOf(
              p::transform(p::sequence(keyword("import"), stringLiteral),
                  [this](Located<Text::Reader>&& filename) -> Orphan<DeclName> {
                    auto result = orphanage.newOrphan<DeclName>();
                    filename.copyTo(result.get().getBase().initImportName());
                    return result;
                  }),
              p::transform(p::sequence(op("."), identifier),
                  [this](Located<Text::Reader>&& filename) -> Orphan<DeclName> {
                    auto result = orphanage.newOrphan<DeclName>();
                    filename.copyTo(result.get().getBase().initAbsoluteName());
                    return result;
                  }),
              p::transform(identifier,
                  [this](Located<Text::Reader>&& filename) -> Orphan<DeclName> {
                    auto result = orphanage.newOrphan<DeclName>();
                    filename.copyTo(result.get().getBase().initRelativeName());
                    return result;
                  })),
          p::many(p::sequence(op("."), identifier))),
412 413
      [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
             Orphan<DeclName>&& result, kj::Array<Located<Text::Reader>>&& memberPath)
Kenton Varda's avatar
Kenton Varda committed
414
          -> Orphan<DeclName> {
415 416
        auto builder = result.get();
        auto pathBuilder = builder.initMemberPath(memberPath.size());
Kenton Varda's avatar
Kenton Varda committed
417
        for (size_t i = 0; i < memberPath.size(); i++) {
418
          memberPath[i].copyTo(pathBuilder[i]);
Kenton Varda's avatar
Kenton Varda committed
419
        }
420
        initLocation(location, builder);
Kenton Varda's avatar
Kenton Varda committed
421 422 423
        return kj::mv(result);
      }));

Kenton Varda's avatar
Kenton Varda committed
424
  parsers.typeExpression = arena.copy(p::transformWithLocation(
Kenton Varda's avatar
Kenton Varda committed
425 426
      p::sequence(parsers.declName, p::optional(
          parenthesizedList(parsers.typeExpression, errorReporter))),
Kenton Varda's avatar
Kenton Varda committed
427 428
      [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
             Orphan<DeclName>&& name,
Kenton Varda's avatar
Kenton Varda committed
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
             kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<TypeExpression>>>>>&& params)
             -> Orphan<TypeExpression> {
        auto result = orphanage.newOrphan<TypeExpression>();
        auto builder = result.get();
        builder.adoptName(kj::mv(name));
        KJ_IF_MAYBE(p, params) {
          auto paramsBuilder = builder.initParams(p->value.size());
          for (uint i = 0; i < p->value.size(); i++) {
            KJ_IF_MAYBE(param, p->value[i]) {
              paramsBuilder.adoptWithCaveats(i, kj::mv(*param));
            } else {
              // param failed to parse
              paramsBuilder[i].initName().getBase().initAbsoluteName().setValue("Void");
            }
          }
        }
Kenton Varda's avatar
Kenton Varda committed
445
        initLocation(location, builder);
Kenton Varda's avatar
Kenton Varda committed
446 447 448
        return result;
      }));

449 450 451
  // Parser for a "name = value" pair.  Also matches "name = unionMember(value)",
  // "unionMember(value)" (unnamed union), and just "value" (which is not actually a valid field
  // assigment, but simplifies the parser for parenthesizedValueExpression).
Kenton Varda's avatar
Kenton Varda committed
452
  auto& fieldAssignment = arena.copy(p::transform(
453 454
      p::sequence(p::optional(p::sequence(identifier, op("="))), parsers.valueExpression),
      [this](kj::Maybe<Located<Text::Reader>>&& fieldName, Orphan<ValueExpression>&& fieldValue)
455
             -> Orphan<ValueExpression::FieldAssignment> {
456 457
        auto result = orphanage.newOrphan<ValueExpression::FieldAssignment>();
        auto builder = result.get();
Kenton Varda's avatar
Kenton Varda committed
458 459 460
        KJ_IF_MAYBE(fn, fieldName) {
          fn->copyTo(builder.initFieldName());
        }
461 462
        builder.adoptValue(kj::mv(fieldValue));
        return kj::mv(result);
Kenton Varda's avatar
Kenton Varda committed
463 464
      }));

465 466 467 468 469 470
  parsers.parenthesizedValueExpression = arena.copy(p::transform(
      parenthesizedList(fieldAssignment, errorReporter),
      [this](Located<kj::Array<kj::Maybe<Orphan<ValueExpression::FieldAssignment>>>>&& value)
          -> Orphan<ValueExpression> {
        if (value.value.size() == 1) {
          KJ_IF_MAYBE(firstVal, value.value[0]) {
471
            auto reader = firstVal->getReader();
472 473
            if (reader.getFieldName().getValue().size() == 0) {
              // There is only one value and it isn't an assignment, therefore the value is
474 475 476 477 478 479 480
              // not a struct.
              return firstVal->get().disownValue();
            }
          } else {
            // There is only one value and it failed to parse.
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
481
            builder.setUnknown();
482 483 484 485 486 487 488 489 490 491 492 493
            value.copyLocationTo(builder);
            return result;
          }
        }

        // If we get here, the parentheses appear to contain a list of field assignments, meaning
        // the value is a struct.

        auto result = orphanage.newOrphan<ValueExpression>();
        auto builder = result.get();
        value.copyLocationTo(builder);

494
        auto structBuilder = builder.initStruct(value.value.size());
495 496
        for (uint i = 0; i < value.value.size(); i++) {
          KJ_IF_MAYBE(field, value.value[i]) {
497
            auto reader = field->getReader();
498
            if (reader.getFieldName().getValue().size() > 0) {
499 500
              structBuilder.adoptWithCaveats(i, kj::mv(*field));
            } else {
501
              errorReporter.addErrorOn(reader.getValue(), "Missing field name.");
502 503 504 505 506 507 508
            }
          }
        }

        return result;
      }));

Kenton Varda's avatar
Kenton Varda committed
509 510 511 512 513
  parsers.valueExpression = arena.copy(p::oneOf(
      p::transform(integerLiteral,
          [this](Located<uint64_t>&& value) -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
514
            builder.setPositiveInt(value.value);
Kenton Varda's avatar
Kenton Varda committed
515 516 517 518 519 520 521
            value.copyLocationTo(builder);
            return result;
          }),
      p::transform(p::sequence(op("-"), integerLiteral),
          [this](Located<uint64_t>&& value) -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
522
            builder.setNegativeInt(value.value);
Kenton Varda's avatar
Kenton Varda committed
523 524 525 526 527 528 529
            value.copyLocationTo(builder);
            return result;
          }),
      p::transform(floatLiteral,
          [this](Located<double>&& value) -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
530
            builder.setFloat(value.value);
Kenton Varda's avatar
Kenton Varda committed
531 532 533 534 535 536 537
            value.copyLocationTo(builder);
            return result;
          }),
      p::transform(p::sequence(op("-"), floatLiteral),
          [this](Located<double>&& value) -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
538
            builder.setFloat(-value.value);
Kenton Varda's avatar
Kenton Varda committed
539 540 541
            value.copyLocationTo(builder);
            return result;
          }),
Kenton Varda's avatar
Kenton Varda committed
542 543 544 545 546
      p::transformWithLocation(p::sequence(op("-"), keyword("inf")),
          [this](kj::parse::Span<List<Token>::Reader::Iterator> location)
              -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
547
            builder.setFloat(-std::numeric_limits<double>::infinity());
Kenton Varda's avatar
Kenton Varda committed
548 549 550
            initLocation(location, builder);
            return result;
          }),
Kenton Varda's avatar
Kenton Varda committed
551 552 553 554
      p::transform(stringLiteral,
          [this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
555
            builder.setString(value.value);
Kenton Varda's avatar
Kenton Varda committed
556 557 558
            value.copyLocationTo(builder);
            return result;
          }),
Kenton Varda's avatar
Kenton Varda committed
559 560 561
      p::transformWithLocation(parsers.declName,
          [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
                 Orphan<DeclName>&& value) -> Orphan<ValueExpression> {
Kenton Varda's avatar
Kenton Varda committed
562 563
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
564
            builder.adoptName(kj::mv(value));
Kenton Varda's avatar
Kenton Varda committed
565
            initLocation(location, builder);
Kenton Varda's avatar
Kenton Varda committed
566 567 568 569 570 571 572
            return result;
          }),
      p::transform(bracketedList(parsers.valueExpression, errorReporter),
          [this](Located<kj::Array<kj::Maybe<Orphan<ValueExpression>>>>&& value)
              -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
573
            auto listBuilder = builder.initList(value.value.size());
Kenton Varda's avatar
Kenton Varda committed
574 575 576 577 578 579 580 581 582 583 584 585 586
            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(parenthesizedList(fieldAssignment, errorReporter),
          [this](Located<kj::Array<kj::Maybe<Orphan<ValueExpression::FieldAssignment>>>>&& value)
              -> Orphan<ValueExpression> {
            auto result = orphanage.newOrphan<ValueExpression>();
            auto builder = result.get();
587
            auto structBuilder = builder.initStruct(value.value.size());
Kenton Varda's avatar
Kenton Varda committed
588 589
            for (uint i = 0; i < value.value.size(); i++) {
              KJ_IF_MAYBE(field, value.value[i]) {
590
                auto reader = field->get();
591
                if (reader.getFieldName().getValue().size() > 0) {
Kenton Varda's avatar
Kenton Varda committed
592 593 594 595
                  structBuilder.adoptWithCaveats(i, kj::mv(*field));
                } else {
                  auto fieldValue = field->get().getValue();
                  errorReporter.addError(fieldValue.getStartByte(), fieldValue.getEndByte(),
Kenton Varda's avatar
Kenton Varda committed
596
                                         "Missing field name.");
Kenton Varda's avatar
Kenton Varda committed
597 598 599 600 601 602 603 604
                }
              }
            }
            value.copyLocationTo(builder);
            return result;
          })
      ));

Kenton Varda's avatar
Kenton Varda committed
605
  parsers.annotation = arena.copy(p::transform(
606
      p::sequence(op("$"), parsers.declName, p::optional(parsers.parenthesizedValueExpression)),
Kenton Varda's avatar
Kenton Varda committed
607
      [this](Orphan<DeclName>&& name, kj::Maybe<Orphan<ValueExpression>>&& value)
608 609 610 611
          -> Orphan<Declaration::AnnotationApplication> {
        auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
        auto builder = result.get();
        builder.adoptName(kj::mv(name));
612 613 614 615 616
        KJ_IF_MAYBE(v, value) {
          builder.getValue().adoptExpression(kj::mv(*v));
        } else {
          builder.getValue().setNone();
        }
617 618 619 620 621 622 623 624
        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
625
              "Invalid ID.  Please generate a new one with 'capnpc -i'.");
626 627 628 629 630 631 632 633 634
        }
        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
635
              "Ordinals cannot be greater than 65535.");
636 637 638 639
        }
        return value.asProto<LocatedInteger>(orphanage);
      }));

Kenton Varda's avatar
Kenton Varda committed
640 641 642
  // -----------------------------------------------------------------

  parsers.usingDecl = arena.copy(p::transform(
643 644 645 646
      p::sequence(keyword("using"), p::optional(p::sequence(identifier, op("="))),
                  parsers.declName),
      [this](kj::Maybe<Located<Text::Reader>>&& name, Orphan<DeclName>&& target)
          -> DeclParserResult {
Kenton Varda's avatar
Kenton Varda committed
647 648
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder = decl.get();
649 650 651 652 653 654 655 656 657 658 659
        KJ_IF_MAYBE(n, name) {
          n->copyTo(builder.initName());
        } else {
          auto targetPath = target.getReader().getMemberPath();
          if (targetPath.size() == 0) {
            errorReporter.addErrorOn(
                target.getReader(), "'using' declaration without '=' must use a qualified path.");
          } else {
            builder.setName(targetPath[targetPath.size() - 1]);
          }
        }
Kenton Varda's avatar
Kenton Varda committed
660
        // no id, no annotations for using decl
661
        builder.initUsing().adoptTarget(kj::mv(target));
Kenton Varda's avatar
Kenton Varda committed
662 663
        return DeclParserResult(kj::mv(decl));
      }));
664 665 666 667 668 669 670 671 672 673 674

  parsers.constDecl = arena.copy(p::transform(
      p::sequence(keyword("const"), identifier, p::optional(parsers.uid),
                  op(":"), parsers.typeExpression,
                  op("="), parsers.valueExpression,
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
             Orphan<TypeExpression>&& type, Orphan<ValueExpression>&& value,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
675 676
        auto builder =
            initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(annotations)).initConst();
677 678 679 680 681 682 683 684 685 686 687 688
        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>();
689
        initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(annotations)).setEnum();
690 691 692 693 694 695 696 697 698 699
        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))
700
            .setEnumerant();
701 702 703 704 705 706 707 708 709 710
        return DeclParserResult(kj::mv(decl));
      }));

  parsers.structDecl = arena.copy(p::transform(
      p::sequence(keyword("struct"), 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>();
711
        initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(annotations)).setStruct();
712 713 714 715 716 717 718 719 720 721 722 723 724 725
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));

  parsers.fieldDecl = arena.copy(p::transform(
      p::sequence(identifier, parsers.ordinal, op(":"), parsers.typeExpression,
                  p::optional(p::sequence(op("="), parsers.valueExpression)),
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
             Orphan<TypeExpression>&& type, kj::Maybe<Orphan<ValueExpression>>&& defaultValue,
             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))
726
                .initField();
727 728 729 730 731 732 733 734 735
        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));
      }));

736 737 738 739 740 741
  // 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)
742 743
                   -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr);
744 745
          }),
      p::transform(op(":"),
746 747 748
          []() -> kj::Tuple<kj::Maybe<Orphan<LocatedInteger>>, bool, bool> {
            return kj::tuple(nullptr, false, false);
          })));
749

750
  parsers.unionDecl = arena.copy(p::transform(
751 752
      // The first branch of this oneOf() matches named unions.  The second branch matches unnamed
      // unions and generates dummy values for the parse results.
753 754
      p::oneOf(
          p::sequence(
755 756
              identifier, ordinalOrColon,
              keyword("union"), p::many(parsers.annotation)),
757 758
          p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput),
              [](kj::parse::Span<List<Token>::Reader::Iterator> location) {
759
                return kj::tuple(
760 761
                    Located<Text::Reader>("", location.begin()->getStartByte(),
                                          location.begin()->getEndByte()),
762
                    kj::Maybe<Orphan<LocatedInteger>>(nullptr),
763
                    false, false,
764 765 766
                    kj::Array<Orphan<Declaration::AnnotationApplication>>(nullptr));
              })),
      [this](Located<Text::Reader>&& name,
767
             kj::Maybe<Orphan<LocatedInteger>>&& ordinal,
768
             bool missingExclamation, bool missingColon,
769 770
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
        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 {`.");
        }

787
        auto decl = orphanage.newOrphan<Declaration>();
788
        auto builder = decl.get();
789
        name.copyTo(builder.initName());
790 791 792 793 794 795 796 797 798
        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]));
        }
799
        builder.setUnion();
800 801
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));
802

803
  parsers.groupDecl = arena.copy(p::transform(
804
      p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)),
Kenton Varda's avatar
Kenton Varda committed
805 806
      [this](Located<Text::Reader>&& name,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
807 808 809
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
        auto builder = decl.get();
Kenton Varda's avatar
Kenton Varda committed
810
        name.copyTo(builder.getName());
811 812 813 814
        builder.getId().setUnspecified();
        auto list = builder.initAnnotations(annotations.size());
        for (uint i = 0; i < annotations.size(); i++) {
          list.adoptWithCaveats(i, kj::mv(annotations[i]));
815
        }
816
        builder.setGroup();
817 818 819 820 821
        return DeclParserResult(kj::mv(decl), parsers.structLevelDecl);
      }));

  parsers.interfaceDecl = arena.copy(p::transform(
      p::sequence(keyword("interface"), identifier, p::optional(parsers.uid),
822 823
                  p::optional(p::sequence(
                      keyword("extends"), parenthesizedList(parsers.declName, errorReporter))),
824 825
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
826
             kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<DeclName>>>>>&& extends,
827 828 829
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
830 831 832 833 834 835 836 837 838 839
        auto builder = initDecl(
            decl.get(), kj::mv(name), kj::mv(id), kj::mv(annotations)).initInterface();
        KJ_IF_MAYBE(e, extends) {
          auto extendsBuilder = builder.initExtends(e->value.size());
          for (uint i: kj::indices(e->value)) {
            KJ_IF_MAYBE(extend, e->value[i]) {
              extendsBuilder.adoptWithCaveats(i, kj::mv(*extend));
            }
          }
        }
840 841 842
        return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl);
      }));

843
  parsers.param = arena.copy(p::transformWithLocation(
844 845 846
      p::sequence(identifier, op(":"), parsers.typeExpression,
                  p::optional(p::sequence(op("="), parsers.valueExpression)),
                  p::many(parsers.annotation)),
847 848
      [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
             Located<Text::Reader>&& name, Orphan<TypeExpression>&& type,
849 850
             kj::Maybe<Orphan<ValueExpression>>&& defaultValue,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
851 852
                 -> Orphan<Declaration::Param> {
        auto result = orphanage.newOrphan<Declaration::Param>();
853 854
        auto builder = result.get();

855 856
        initLocation(location, builder);

857 858
        name.copyTo(builder.initName());
        builder.adoptType(kj::mv(type));
859
        builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations)));
860 861 862 863 864 865 866 867 868
        KJ_IF_MAYBE(val, defaultValue) {
          builder.getDefaultValue().adoptValue(kj::mv(*val));
        } else {
          builder.getDefaultValue().setNone();
        }

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

869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
  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;
          }),
      p::transform(parsers.declName,
          [this](Orphan<DeclName>&& name) -> Orphan<Declaration::ParamList> {
            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;
          })));

895
  parsers.methodDecl = arena.copy(p::transform(
896 897
      p::sequence(identifier, parsers.ordinal, paramList,
                  p::optional(p::sequence(op("->"), paramList)),
898 899
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
900 901
             Orphan<Declaration::ParamList>&& params,
             kj::Maybe<Orphan<Declaration::ParamList>>&& results,
902 903 904 905 906
             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))
907
                .initMethod();
908

909
        builder.adoptParams(kj::mv(params));
910

911 912
        KJ_IF_MAYBE(r, results) {
          builder.getResults().adoptExplicit(kj::mv(*r));
913
        } else {
914
          builder.getResults().setNone();
915
        }
916

917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
        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),
                  op(":"), parsers.typeExpression,
                  p::many(parsers.annotation)),
      [this](Located<Text::Reader>&& name, kj::Maybe<Orphan<LocatedInteger>>&& id,
             Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>&& targets,
             Orphan<TypeExpression>&& type,
             kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
                 -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
941 942
        auto builder =
            initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(annotations)).initAnnotation();
943 944 945 946 947 948 949 950
        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
951
                    "Wildcard should not be specified together with other targets.");
952
              }
953

954 955 956
              for (auto field: dynamicBuilder.getSchema().getFields()) {
                if (field.getProto().getName().startsWith("targets")) {
                  dynamicBuilder.set(field, true);
957 958 959 960 961 962
                }
              }
            } 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
963
                                       "Not a valid annotation target.");
964 965 966 967 968
              } else {
                char buffer[64];
                strcpy(buffer, "targets");
                strcat(buffer, target->value.cStr());
                buffer[strlen("targets")] += 'A' - 'a';
969 970
                KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) {
                  if (dynamicBuilder.get(*field).as<bool>()) {
971
                    errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
972
                                           "Duplicate target specification.");
973
                  }
974
                  dynamicBuilder.set(*field, true);
975 976
                } else {
                  errorReporter.addError(target->startByte, target->endByte,
Kenton Varda's avatar
Kenton Varda committed
977
                                         "Not a valid annotation target.");
978 979 980 981 982
                }
              }
            }
          }
        }
983 984 985 986 987 988 989 990
        return DeclParserResult(kj::mv(decl));
      }));

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

  auto& nakedId = arena.copy(p::transform(parsers.uid,
      [this](Orphan<LocatedInteger>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
991
        decl.get().adoptNakedId(kj::mv(value));
992 993 994 995 996 997
        return DeclParserResult(kj::mv(decl));
      }));

  auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation,
      [this](Orphan<Declaration::AnnotationApplication>&& value) -> DeclParserResult {
        auto decl = orphanage.newOrphan<Declaration>();
998
        decl.get().adoptNakedAnnotation(kj::mv(value));
999 1000 1001 1002 1003
        return DeclParserResult(kj::mv(decl));
      }));

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

1004 1005 1006
  parsers.genericDecl = arena.copy(p::oneOf(
      parsers.usingDecl, parsers.constDecl, parsers.annotationDecl,
      parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl));
1007
  parsers.fileLevelDecl = arena.copy(p::oneOf(
1008 1009 1010
      parsers.genericDecl, nakedId, nakedAnnotation));
  parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl));
  parsers.structLevelDecl = arena.copy(p::oneOf(
1011
      parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl));
1012 1013
  parsers.interfaceLevelDecl = arena.copy(p::oneOf(
      parsers.methodDecl, parsers.genericDecl));
1014 1015
}

1016
CapnpParser::~CapnpParser() noexcept(false) {}
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034

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

1035 1036
    switch (statement.which()) {
      case Statement::LINE:
1037 1038
        if (output->memberParser != nullptr) {
          errorReporter.addError(statement.getStartByte(), statement.getEndByte(),
1039
              "This statement should end with a block, not a semicolon.");
1040 1041 1042
        }
        break;

1043
      case Statement::BLOCK:
1044
        KJ_IF_MAYBE(memberParser, output->memberParser) {
1045
          auto memberStatements = statement.getBlock();
1046 1047 1048 1049 1050 1051 1052 1053 1054
          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(),
1055
              "This statement should end with a semicolon, not a block.");
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
        }
        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 {
1072
      bestByte = statement.getStartByte();
1073 1074
    }

Kenton Varda's avatar
Kenton Varda committed
1075
    errorReporter.addError(bestByte, bestByte, "Parse error.");
1076 1077
    return nullptr;
  }
Kenton Varda's avatar
Kenton Varda committed
1078 1079 1080 1081
}

}  // namespace compiler
}  // namespace capnp