handle_decl_name_and_params.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. Lex::TokenIndex token = *context.position();
  50. if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
  51. // The end of file is an unhelpful diagnostic location. Instead, use the
  52. // introducer token.
  53. token = state.token;
  54. }
  55. if (state.token == *context.position()) {
  56. CARBON_DIAGNOSTIC(ExpectedDeclNameAfterPeriod, Error,
  57. "`.` should be followed by a name");
  58. context.emitter().Emit(token, ExpectedDeclNameAfterPeriod);
  59. } else {
  60. CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
  61. "`{0}` introducer should be followed by a name",
  62. Lex::TokenKind);
  63. context.emitter().Emit(token, ExpectedDeclName,
  64. context.tokens().GetKind(state.token));
  65. }
  66. context.ReturnErrorOnState();
  67. context.AddInvalidParse(*context.position());
  68. }
  69. auto HandleDeclNameAndParamsAfterImplicit(Context& context) -> void {
  70. auto state = context.PopState();
  71. state.kind = StateKind::DeclNameAndParamsAfterParams;
  72. context.PushState(state);
  73. if (!context.PositionIs(Lex::TokenKind::OpenParen)) {
  74. return;
  75. }
  76. context.PushState(StateKind::PatternListAsExplicit);
  77. }
  78. auto HandleDeclNameAndParamsAfterParams(Context& context) -> void {
  79. auto state = context.PopState();
  80. if (auto period = context.ConsumeIf(Lex::TokenKind::Period)) {
  81. CARBON_CHECK(context.tree().node_kind(NodeId(state.subtree_start)) ==
  82. NodeKind::IdentifierNameBeforeParams);
  83. context.AddNode(NodeKind::IdentifierNameQualifierWithParams, *period,
  84. state.has_error);
  85. context.PushState(StateKind::DeclNameAndParams);
  86. }
  87. }
  88. } // namespace Carbon::Parse