handle_decl_name_and_params.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/lex/token_index.h"
  5. #include "toolchain/parse/context.h"
  6. #include "toolchain/parse/handle.h"
  7. namespace Carbon::Parse {
  8. // Adds a leaf node for the name, and updates the state stack for parameter
  9. // handling.
  10. static auto HandleName(Context& context, Context::State state,
  11. Lex::TokenIndex name_token,
  12. NodeKind not_before_params_kind,
  13. NodeKind not_before_params_qualifier_kind,
  14. NodeKind before_params_kind) -> void {
  15. switch (context.PositionKind()) {
  16. case Lex::TokenKind::Period:
  17. context.AddLeafNode(not_before_params_kind, name_token);
  18. context.AddNode(not_before_params_qualifier_kind,
  19. context.ConsumeChecked(Lex::TokenKind::Period),
  20. state.has_error);
  21. context.PushState(StateKind::DeclNameAndParams);
  22. break;
  23. case Lex::TokenKind::OpenSquareBracket:
  24. context.AddLeafNode(before_params_kind, name_token);
  25. state.kind = StateKind::DeclNameAndParamsAfterImplicit;
  26. context.PushState(state);
  27. context.PushState(StateKind::PatternListAsImplicit);
  28. break;
  29. case Lex::TokenKind::OpenParen:
  30. context.AddLeafNode(before_params_kind, name_token);
  31. state.kind = StateKind::DeclNameAndParamsAfterParams;
  32. context.PushState(state);
  33. context.PushState(StateKind::PatternListAsExplicit);
  34. break;
  35. default:
  36. context.AddLeafNode(not_before_params_kind, name_token);
  37. break;
  38. }
  39. }
  40. auto HandleDeclNameAndParams(Context& context) -> void {
  41. auto state = context.PopState();
  42. if (auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier)) {
  43. HandleName(context, state, *identifier,
  44. NodeKind::IdentifierNameNotBeforeParams,
  45. NodeKind::IdentifierNameQualifierWithoutParams,
  46. NodeKind::IdentifierNameBeforeParams);
  47. return;
  48. }
  49. if (auto keyword = context.ConsumeIf(Lex::TokenKind::Destroy)) {
  50. HandleName(context, state, *keyword, NodeKind::KeywordNameNotBeforeParams,
  51. NodeKind::KeywordNameQualifierWithoutParams,
  52. NodeKind::KeywordNameBeforeParams);
  53. return;
  54. }
  55. Lex::TokenIndex token = *context.position();
  56. if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
  57. // The end of file is an unhelpful diagnostic location. Instead, use the
  58. // introducer token.
  59. token = state.token;
  60. }
  61. if (state.token == *context.position()) {
  62. CARBON_DIAGNOSTIC(ExpectedDeclNameAfterPeriod, Error,
  63. "`.` should be followed by a name");
  64. context.emitter().Emit(token, ExpectedDeclNameAfterPeriod);
  65. } else {
  66. CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
  67. "`{0}` introducer should be followed by a name",
  68. Lex::TokenKind);
  69. context.emitter().Emit(token, ExpectedDeclName,
  70. context.tokens().GetKind(state.token));
  71. }
  72. context.ReturnErrorOnState();
  73. context.AddInvalidParse(*context.position());
  74. }
  75. auto HandleDeclNameAndParamsAfterImplicit(Context& context) -> void {
  76. auto state = context.PopState();
  77. state.kind = StateKind::DeclNameAndParamsAfterParams;
  78. context.PushState(state);
  79. if (!context.PositionIs(Lex::TokenKind::OpenParen)) {
  80. return;
  81. }
  82. context.PushState(StateKind::PatternListAsExplicit);
  83. }
  84. auto HandleDeclNameAndParamsAfterParams(Context& context) -> void {
  85. auto state = context.PopState();
  86. if (auto period = context.ConsumeIf(Lex::TokenKind::Period)) {
  87. auto start_kind = context.tree().node_kind(NodeId(state.subtree_start));
  88. auto node_kind = start_kind == NodeKind::IdentifierNameBeforeParams
  89. ? NodeKind::IdentifierNameQualifierWithParams
  90. : NodeKind::KeywordNameQualifierWithParams;
  91. context.AddNode(node_kind, *period, state.has_error);
  92. context.PushState(StateKind::DeclNameAndParams);
  93. }
  94. }
  95. } // namespace Carbon::Parse