* @brief Parses a single field declaration inside a message body. */
| 540 | * @brief Parses a single field declaration inside a message body. |
| 541 | */ |
| 542 | bool Parser::parseField(DataModel::ProtoMessage& msg, ParseError& err) |
| 543 | { |
| 544 | DataModel::ProtoField f; |
| 545 | |
| 546 | if (m_cur.type == Tok::Ident |
| 547 | && (m_cur.text == QLatin1String("repeated") || m_cur.text == QLatin1String("optional") |
| 548 | || m_cur.text == QLatin1String("required"))) { |
| 549 | f.repeated = (m_cur.text == QLatin1String("repeated")); |
| 550 | advance(); |
| 551 | } |
| 552 | |
| 553 | if (m_cur.type != Tok::Ident) { |
| 554 | err = {m_cur.line, QObject::tr("Expected field type, got '%1'").arg(m_cur.text)}; |
| 555 | return false; |
| 556 | } |
| 557 | |
| 558 | QString typeName = m_cur.text; |
| 559 | advance(); |
| 560 | while (m_cur.type == Tok::Dot) { |
| 561 | typeName += QLatin1Char('.'); |
| 562 | advance(); |
| 563 | if (m_cur.type == Tok::Ident) { |
| 564 | typeName += m_cur.text; |
| 565 | advance(); |
| 566 | } |
| 567 | } |
| 568 | |
| 569 | f.scalar = classifyScalar(typeName); |
| 570 | f.typeRef = typeName; |
| 571 | |
| 572 | if (m_cur.type != Tok::Ident) { |
| 573 | err = {m_cur.line, QObject::tr("Expected field name after type")}; |
| 574 | return false; |
| 575 | } |
| 576 | f.name = m_cur.text; |
| 577 | advance(); |
| 578 | |
| 579 | if (!expect(Tok::Eq, QStringLiteral("'='"), err)) |
| 580 | return false; |
| 581 | |
| 582 | if (m_cur.type != Tok::IntLit) { |
| 583 | err = {m_cur.line, QObject::tr("Expected field tag number")}; |
| 584 | return false; |
| 585 | } |
| 586 | if (!parseFieldTag(f.tag, err)) |
| 587 | return false; |
| 588 | |
| 589 | advance(); |
| 590 | |
| 591 | skipOptionList(); |
| 592 | |
| 593 | if (!expect(Tok::Semi, QStringLiteral("';'"), err)) |
| 594 | return false; |
| 595 | |
| 596 | msg.fields.append(f); |
| 597 | return true; |
| 598 | } |
| 599 |
nothing calls this directly
no test coverage detected