handle_binding_pattern.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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/parse/context.h"
  5. namespace Carbon::Parse {
  6. // Handles BindingPatternAs(ImplicitParam|FunctionParam|Variable|Let).
  7. static auto HandleBindingPattern(Context& context,
  8. Context::BindingPatternKind pattern_kind)
  9. -> void {
  10. auto state = context.PopState();
  11. // Parameters may have keywords prefixing the pattern. They become the parent
  12. // for the full BindingPattern.
  13. if (pattern_kind != Context::BindingPatternKind::Variable) {
  14. context.ConsumeIfBindingPatternKeyword(Lex::TokenKind::Template,
  15. State::BindingPatternTemplate,
  16. state.subtree_start);
  17. context.ConsumeIfBindingPatternKeyword(Lex::TokenKind::Addr,
  18. State::BindingPatternAddress,
  19. state.subtree_start);
  20. }
  21. // Handle an invalid pattern introducer for parameters and variables.
  22. auto on_error = [&]() {
  23. switch (pattern_kind) {
  24. case Context::BindingPatternKind::ImplicitParam:
  25. case Context::BindingPatternKind::Param: {
  26. CARBON_DIAGNOSTIC(ExpectedParamName, Error,
  27. "Expected parameter declaration.");
  28. context.emitter().Emit(*context.position(), ExpectedParamName);
  29. break;
  30. }
  31. case Context::BindingPatternKind::Variable: {
  32. CARBON_DIAGNOSTIC(ExpectedVariableName, Error,
  33. "Expected pattern in `var` declaration.");
  34. context.emitter().Emit(*context.position(), ExpectedVariableName);
  35. break;
  36. }
  37. case Context::BindingPatternKind::Let: {
  38. CARBON_DIAGNOSTIC(ExpectedLetBindingName, Error,
  39. "Expected pattern in `let` declaration.");
  40. context.emitter().Emit(*context.position(), ExpectedLetBindingName);
  41. break;
  42. }
  43. }
  44. // Add a placeholder for the type.
  45. context.AddLeafNode(NodeKind::InvalidParse, *context.position(),
  46. /*has_error=*/true);
  47. state.state = State::BindingPatternFinishAsRegular;
  48. state.has_error = true;
  49. context.PushState(state);
  50. };
  51. // The first item should be an identifier or `self`.
  52. bool has_name = false;
  53. if (auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier)) {
  54. context.AddLeafNode(NodeKind::Name, *identifier);
  55. has_name = true;
  56. } else if (auto self =
  57. context.ConsumeIf(Lex::TokenKind::SelfValueIdentifier)) {
  58. // Checking will validate the `self` is only declared in the implicit
  59. // parameter list of a function.
  60. context.AddLeafNode(NodeKind::SelfValueName, *self);
  61. has_name = true;
  62. }
  63. if (!has_name) {
  64. // Add a placeholder for the name.
  65. context.AddLeafNode(NodeKind::Name, *context.position(),
  66. /*has_error=*/true);
  67. on_error();
  68. return;
  69. }
  70. if (auto kind = context.PositionKind();
  71. kind == Lex::TokenKind::Colon || kind == Lex::TokenKind::ColonExclaim) {
  72. state.state = kind == Lex::TokenKind::Colon
  73. ? State::BindingPatternFinishAsRegular
  74. : State::BindingPatternFinishAsGeneric;
  75. // Use the `:` or `:!` for the root node.
  76. state.token = context.Consume();
  77. context.PushState(state);
  78. context.PushStateForExpr(PrecedenceGroup::ForType());
  79. } else {
  80. on_error();
  81. return;
  82. }
  83. }
  84. auto HandleBindingPatternAsImplicitParam(Context& context) -> void {
  85. HandleBindingPattern(context, Context::BindingPatternKind::ImplicitParam);
  86. }
  87. auto HandleBindingPatternAsParam(Context& context) -> void {
  88. HandleBindingPattern(context, Context::BindingPatternKind::Param);
  89. }
  90. auto HandleBindingPatternAsVariable(Context& context) -> void {
  91. HandleBindingPattern(context, Context::BindingPatternKind::Variable);
  92. }
  93. auto HandleBindingPatternAsLet(Context& context) -> void {
  94. HandleBindingPattern(context, Context::BindingPatternKind::Let);
  95. }
  96. // Handles BindingPatternFinishAs(Generic|Regular).
  97. static auto HandleBindingPatternFinish(Context& context, NodeKind node_kind)
  98. -> void {
  99. auto state = context.PopState();
  100. context.AddNode(node_kind, state.token, state.subtree_start, state.has_error);
  101. // Propagate errors to the parent state so that they can take different
  102. // actions on invalid patterns.
  103. if (state.has_error) {
  104. context.ReturnErrorOnState();
  105. }
  106. }
  107. auto HandleBindingPatternFinishAsGeneric(Context& context) -> void {
  108. HandleBindingPatternFinish(context, NodeKind::GenericBindingPattern);
  109. }
  110. auto HandleBindingPatternFinishAsRegular(Context& context) -> void {
  111. HandleBindingPatternFinish(context, NodeKind::BindingPattern);
  112. }
  113. auto HandleBindingPatternAddress(Context& context) -> void {
  114. auto state = context.PopState();
  115. context.AddNode(NodeKind::Address, state.token, state.subtree_start,
  116. state.has_error);
  117. // If an error was encountered, propagate it while adding a node.
  118. if (state.has_error) {
  119. context.ReturnErrorOnState();
  120. }
  121. }
  122. auto HandleBindingPatternTemplate(Context& context) -> void {
  123. auto state = context.PopState();
  124. context.AddNode(NodeKind::Template, state.token, state.subtree_start,
  125. state.has_error);
  126. // If an error was encountered, propagate it while adding a node.
  127. if (state.has_error) {
  128. context.ReturnErrorOnState();
  129. }
  130. }
  131. } // namespace Carbon::Parse