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