handle_pattern_list.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. #include "toolchain/parse/handle.h"
  6. namespace Carbon::Parse {
  7. // Handles PatternListElementAs(Tuple|Explicit|Implicit).
  8. static auto HandlePatternListElement(Context& context, StateKind pattern_state,
  9. StateKind finish_state_kind) -> void {
  10. auto state = context.PopState();
  11. context.PushStateForPattern(finish_state_kind, state.in_var_pattern,
  12. state.in_unused_pattern,
  13. state.ambient_precedence);
  14. context.PushStateForPattern(pattern_state, state.in_var_pattern,
  15. state.in_unused_pattern,
  16. state.ambient_precedence);
  17. }
  18. auto HandlePatternListElementAsTuple(Context& context) -> void {
  19. HandlePatternListElement(context, StateKind::Pattern,
  20. StateKind::PatternListElementFinishAsTuple);
  21. }
  22. auto HandlePatternListElementAsExplicit(Context& context) -> void {
  23. HandlePatternListElement(context, StateKind::Pattern,
  24. StateKind::PatternListElementFinishAsExplicit);
  25. }
  26. auto HandlePatternListElementAsImplicit(Context& context) -> void {
  27. HandlePatternListElement(context, StateKind::Pattern,
  28. StateKind::PatternListElementFinishAsImplicit);
  29. }
  30. // Handles PatternListElementFinishAs(Tuple|Explicit|Implicit).
  31. static auto HandlePatternListElementFinish(Context& context,
  32. Lex::TokenKind close_token,
  33. StateKind param_state_kind) -> void {
  34. auto state = context.PopState();
  35. if (state.has_error) {
  36. context.ReturnErrorOnState();
  37. }
  38. auto list_token_kind = context.ConsumeListToken(NodeKind::PatternListComma,
  39. close_token, state.has_error);
  40. // If we have a comma, the parent is now a tuple pattern not a parenthesized
  41. // pattern.
  42. if (list_token_kind != Context::ListTokenKind::Close &&
  43. param_state_kind == StateKind::PatternListElementAsTuple) {
  44. auto parent_state = context.PopState();
  45. CARBON_CHECK(parent_state.kind == StateKind::PatternListFinishAsTuple ||
  46. parent_state.kind == StateKind::PatternListFinishAsParen);
  47. context.PushState(parent_state, StateKind::PatternListFinishAsTuple);
  48. }
  49. if (list_token_kind == Context::ListTokenKind::Comma) {
  50. context.PushStateForPattern(param_state_kind, state.in_var_pattern,
  51. state.in_unused_pattern,
  52. state.ambient_precedence);
  53. }
  54. }
  55. auto HandlePatternListElementFinishAsTuple(Context& context) -> void {
  56. HandlePatternListElementFinish(context, Lex::TokenKind::CloseParen,
  57. StateKind::PatternListElementAsTuple);
  58. }
  59. auto HandlePatternListElementFinishAsExplicit(Context& context) -> void {
  60. HandlePatternListElementFinish(context, Lex::TokenKind::CloseParen,
  61. StateKind::PatternListElementAsExplicit);
  62. }
  63. auto HandlePatternListElementFinishAsImplicit(Context& context) -> void {
  64. HandlePatternListElementFinish(context, Lex::TokenKind::CloseSquareBracket,
  65. StateKind::PatternListElementAsImplicit);
  66. }
  67. // Handles PatternListAs(Tuple|Explicit|Implicit).
  68. static auto HandlePatternList(Context& context, NodeKind node_kind,
  69. Lex::TokenKind open_token_kind,
  70. Lex::TokenKind close_token_kind,
  71. StateKind param_state,
  72. StateKind finish_state_empty,
  73. StateKind finish_state_nonempty) -> void {
  74. auto state = context.PopState();
  75. auto open_token = context.ConsumeChecked(open_token_kind);
  76. bool empty = context.PositionIs(close_token_kind);
  77. context.PushStateForPattern(
  78. empty ? finish_state_empty : finish_state_nonempty, state.in_var_pattern,
  79. state.in_unused_pattern, state.ambient_precedence);
  80. context.AddLeafNode(node_kind, open_token);
  81. if (!empty) {
  82. context.PushStateForPattern(param_state, state.in_var_pattern,
  83. state.in_unused_pattern,
  84. PrecedenceGroup::ForTopLevelExpr());
  85. }
  86. }
  87. auto HandlePatternListAsTuple(Context& context) -> void {
  88. // If the list is nonempty, use PatternListFinishAsParen as the parent. This
  89. // will be replaced by PatternListFinishAsTuple if we see a comma.
  90. HandlePatternList(
  91. context, NodeKind::TuplePatternStart, Lex::TokenKind::OpenParen,
  92. Lex::TokenKind::CloseParen, StateKind::PatternListElementAsTuple,
  93. StateKind::PatternListFinishAsTuple, StateKind::PatternListFinishAsParen);
  94. }
  95. auto HandlePatternListAsExplicit(Context& context) -> void {
  96. HandlePatternList(context, NodeKind::ExplicitParamListStart,
  97. Lex::TokenKind::OpenParen, Lex::TokenKind::CloseParen,
  98. StateKind::PatternListElementAsExplicit,
  99. StateKind::PatternListFinishAsExplicit,
  100. StateKind::PatternListFinishAsExplicit);
  101. }
  102. auto HandlePatternListAsImplicit(Context& context) -> void {
  103. HandlePatternList(context, NodeKind::ImplicitParamListStart,
  104. Lex::TokenKind::OpenSquareBracket,
  105. Lex::TokenKind::CloseSquareBracket,
  106. StateKind::PatternListElementAsImplicit,
  107. StateKind::PatternListFinishAsImplicit,
  108. StateKind::PatternListFinishAsImplicit);
  109. }
  110. // Handles PatternListFinishAs(Paren|Tuple|Explicit|Implicit).
  111. static auto HandlePatternListFinish(Context& context, NodeKind node_kind,
  112. Lex::TokenKind token_kind) -> void {
  113. auto state = context.PopState();
  114. context.AddNode(node_kind, context.ConsumeChecked(token_kind),
  115. state.has_error);
  116. }
  117. auto HandlePatternListFinishAsParen(Context& context) -> void {
  118. HandlePatternListFinish(context, NodeKind::ParenPattern,
  119. Lex::TokenKind::CloseParen);
  120. }
  121. auto HandlePatternListFinishAsTuple(Context& context) -> void {
  122. HandlePatternListFinish(context, NodeKind::TuplePattern,
  123. Lex::TokenKind::CloseParen);
  124. }
  125. auto HandlePatternListFinishAsExplicit(Context& context) -> void {
  126. HandlePatternListFinish(context, NodeKind::ExplicitParamList,
  127. Lex::TokenKind::CloseParen);
  128. }
  129. auto HandlePatternListFinishAsImplicit(Context& context) -> void {
  130. HandlePatternListFinish(context, NodeKind::ImplicitParamList,
  131. Lex::TokenKind::CloseSquareBracket);
  132. }
  133. } // namespace Carbon::Parse