* @brief Parses a `message Name { ... }` block, recursively collecting nested messages. */
| 621 | * @brief Parses a `message Name { ... }` block, recursively collecting nested messages. |
| 622 | */ |
| 623 | bool Parser::parseMessage(const QString& parentQualified, |
| 624 | DataModel::ProtoMessage& out, |
| 625 | ParseError& err, |
| 626 | int depth) |
| 627 | { |
| 628 | if (depth > kMaxMessageNestingDepth) { |
| 629 | err = {m_cur.line, |
| 630 | QObject::tr("Message nesting too deep (limit %1)").arg(kMaxMessageNestingDepth)}; |
| 631 | return false; |
| 632 | } |
| 633 | |
| 634 | if (m_cur.type != Tok::Ident) { |
| 635 | err = {m_cur.line, QObject::tr("Expected message name")}; |
| 636 | return false; |
| 637 | } |
| 638 | out.name = m_cur.text; |
| 639 | out.qualifiedName = |
| 640 | parentQualified.isEmpty() ? out.name : (parentQualified + QLatin1Char('.') + out.name); |
| 641 | advance(); |
| 642 | |
| 643 | if (!expect(Tok::LBrace, QStringLiteral("'{'"), err)) |
| 644 | return false; |
| 645 | |
| 646 | while (m_cur.type != Tok::Eof && m_cur.type != Tok::RBrace) { |
| 647 | if (m_cur.type == Tok::Semi) { |
| 648 | advance(); |
| 649 | continue; |
| 650 | } |
| 651 | |
| 652 | const int kw = tryParseMessageBodyKeyword(out, err, depth); |
| 653 | if (kw < 0) |
| 654 | return false; |
| 655 | |
| 656 | if (kw > 0) |
| 657 | continue; |
| 658 | |
| 659 | if (!parseField(out, err)) |
| 660 | return false; |
| 661 | } |
| 662 | |
| 663 | return expect(Tok::RBrace, QStringLiteral("'}'"), err); |
| 664 | } |
| 665 | |
| 666 | /** |
| 667 | * @brief Returns 1 if the current token started a known body keyword, -1 on parse error, 0 |