handle_brace_expr.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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/diagnostics/format_providers.h"
  5. #include "toolchain/parse/context.h"
  6. #include "toolchain/parse/handle.h"
  7. namespace Carbon::Parse {
  8. auto HandleBraceExpr(Context& context) -> void {
  9. auto state = context.PopState();
  10. context.PushState(state, StateKind::BraceExprFinishAsUnknown);
  11. CARBON_CHECK(context.ConsumeAndAddLeafNodeIf(Lex::TokenKind::OpenCurlyBrace,
  12. NodeKind::Placeholder));
  13. if (!context.PositionIs(Lex::TokenKind::CloseCurlyBrace)) {
  14. context.PushState(StateKind::BraceExprParamAsUnknown);
  15. }
  16. }
  17. // Prints a diagnostic for brace expression syntax errors.
  18. static auto HandleBraceExprParamError(Context& context,
  19. Context::StateStackEntry state,
  20. StateKind param_finish_state_kind)
  21. -> void {
  22. Diagnostics::IntAsSelect mode(0);
  23. switch (param_finish_state_kind) {
  24. case StateKind::BraceExprParamFinishAsType:
  25. mode.value = 0;
  26. break;
  27. case StateKind::BraceExprParamFinishAsValue:
  28. mode.value = 1;
  29. break;
  30. case StateKind::BraceExprParamFinishAsUnknown:
  31. mode.value = 2;
  32. break;
  33. default:
  34. CARBON_FATAL("Unexpected state: {0}", param_finish_state_kind);
  35. }
  36. CARBON_DIAGNOSTIC(
  37. ExpectedStructLiteralField, Error,
  38. "expected {0:=0:`.field: field_type`|"
  39. "=1:`.field = value`|=2:`.field: field_type` or `.field = value`}",
  40. Diagnostics::IntAsSelect);
  41. context.emitter().Emit(*context.position(), ExpectedStructLiteralField, mode);
  42. state.has_error = true;
  43. context.PushState(state, param_finish_state_kind);
  44. }
  45. // Handles BraceExprParamAs(Type|Value|Unknown).
  46. static auto HandleBraceExprParam(Context& context,
  47. StateKind after_designator_kind,
  48. StateKind param_finish_kind) -> void {
  49. auto state = context.PopState();
  50. if (!context.PositionIs(Lex::TokenKind::Period)) {
  51. HandleBraceExprParamError(context, state, param_finish_kind);
  52. return;
  53. }
  54. context.PushState(state, after_designator_kind);
  55. context.PushState(StateKind::PeriodAsStruct);
  56. }
  57. auto HandleBraceExprParamAsType(Context& context) -> void {
  58. HandleBraceExprParam(context, StateKind::BraceExprParamAfterDesignatorAsType,
  59. StateKind::BraceExprParamFinishAsType);
  60. }
  61. auto HandleBraceExprParamAsValue(Context& context) -> void {
  62. HandleBraceExprParam(context, StateKind::BraceExprParamAfterDesignatorAsValue,
  63. StateKind::BraceExprParamFinishAsValue);
  64. }
  65. auto HandleBraceExprParamAsUnknown(Context& context) -> void {
  66. HandleBraceExprParam(context,
  67. StateKind::BraceExprParamAfterDesignatorAsUnknown,
  68. StateKind::BraceExprParamFinishAsUnknown);
  69. }
  70. // Handles BraceExprParamAfterDesignatorAs(Type|Value|Unknown).
  71. static auto HandleBraceExprParamAfterDesignator(Context& context,
  72. StateKind param_finish_kind)
  73. -> void {
  74. auto state = context.PopState();
  75. if (state.has_error) {
  76. auto recovery_pos = context.FindNextOf(
  77. {Lex::TokenKind::Equal, Lex::TokenKind::Colon, Lex::TokenKind::Comma});
  78. if (!recovery_pos ||
  79. context.tokens().GetKind(*recovery_pos) == Lex::TokenKind::Comma) {
  80. context.PushState(state, param_finish_kind);
  81. return;
  82. }
  83. context.SkipTo(*recovery_pos);
  84. }
  85. // Work out the kind of this element.
  86. bool is_type;
  87. if (context.PositionIs(Lex::TokenKind::Colon)) {
  88. is_type = true;
  89. } else if (context.PositionIs(Lex::TokenKind::Equal)) {
  90. is_type = false;
  91. } else {
  92. HandleBraceExprParamError(context, state, param_finish_kind);
  93. return;
  94. }
  95. // If we're changing from unknown, update the related finish states.
  96. if (param_finish_kind == StateKind::BraceExprParamFinishAsUnknown) {
  97. auto finish_state = context.PopState();
  98. CARBON_CHECK(finish_state.kind == StateKind::BraceExprFinishAsUnknown);
  99. if (is_type) {
  100. finish_state.kind = StateKind::BraceExprFinishAsType;
  101. param_finish_kind = StateKind::BraceExprParamFinishAsType;
  102. } else {
  103. finish_state.kind = StateKind::BraceExprFinishAsValue;
  104. param_finish_kind = StateKind::BraceExprParamFinishAsValue;
  105. }
  106. context.PushState(finish_state);
  107. }
  108. auto want_param_finish_kind = is_type
  109. ? StateKind::BraceExprParamFinishAsType
  110. : StateKind::BraceExprParamFinishAsValue;
  111. if (param_finish_kind != want_param_finish_kind) {
  112. HandleBraceExprParamError(context, state, param_finish_kind);
  113. return;
  114. }
  115. // Struct type fields and value fields use the same grammar except
  116. // that one has a `:` separator and the other has an `=` separator.
  117. state.token = context.Consume();
  118. context.PushState(state, param_finish_kind);
  119. context.PushState(StateKind::Expr);
  120. }
  121. auto HandleBraceExprParamAfterDesignatorAsType(Context& context) -> void {
  122. HandleBraceExprParamAfterDesignator(context,
  123. StateKind::BraceExprParamFinishAsType);
  124. }
  125. auto HandleBraceExprParamAfterDesignatorAsValue(Context& context) -> void {
  126. HandleBraceExprParamAfterDesignator(context,
  127. StateKind::BraceExprParamFinishAsValue);
  128. }
  129. auto HandleBraceExprParamAfterDesignatorAsUnknown(Context& context) -> void {
  130. HandleBraceExprParamAfterDesignator(context,
  131. StateKind::BraceExprParamFinishAsUnknown);
  132. }
  133. // Handles BraceExprParamFinishAs(Type|Value|Unknown).
  134. static auto HandleBraceExprParamFinish(Context& context, NodeKind field_kind,
  135. NodeKind comma_kind,
  136. StateKind param_state) -> void {
  137. auto state = context.PopState();
  138. if (state.has_error) {
  139. context.AddLeafNode(NodeKind::InvalidParse, state.token,
  140. /*has_error=*/true);
  141. context.ReturnErrorOnState();
  142. } else {
  143. context.AddNode(field_kind, state.token, /*has_error=*/false);
  144. }
  145. if (context.ConsumeListToken(comma_kind, Lex::TokenKind::CloseCurlyBrace,
  146. state.has_error) ==
  147. Context::ListTokenKind::Comma) {
  148. context.PushState(param_state);
  149. }
  150. }
  151. auto HandleBraceExprParamFinishAsType(Context& context) -> void {
  152. HandleBraceExprParamFinish(context, NodeKind::StructTypeLiteralField,
  153. NodeKind::StructTypeLiteralComma,
  154. StateKind::BraceExprParamAsType);
  155. }
  156. auto HandleBraceExprParamFinishAsValue(Context& context) -> void {
  157. HandleBraceExprParamFinish(context, NodeKind::StructLiteralField,
  158. NodeKind::StructLiteralComma,
  159. StateKind::BraceExprParamAsValue);
  160. }
  161. auto HandleBraceExprParamFinishAsUnknown(Context& context) -> void {
  162. HandleBraceExprParamFinish(context, NodeKind::InvalidParse,
  163. NodeKind::InvalidParse,
  164. StateKind::BraceExprParamAsUnknown);
  165. }
  166. // Handles BraceExprFinishAs(Type|Value|Unknown).
  167. static auto HandleBraceExprFinish(Context& context, NodeKind start_kind,
  168. NodeKind end_kind) -> void {
  169. auto state = context.PopState();
  170. context.ReplacePlaceholderNode(state.subtree_start, start_kind, state.token);
  171. context.AddNode(end_kind, context.Consume(), state.has_error);
  172. }
  173. auto HandleBraceExprFinishAsType(Context& context) -> void {
  174. HandleBraceExprFinish(context, NodeKind::StructTypeLiteralStart,
  175. NodeKind::StructTypeLiteral);
  176. }
  177. auto HandleBraceExprFinishAsValue(Context& context) -> void {
  178. HandleBraceExprFinish(context, NodeKind::StructLiteralStart,
  179. NodeKind::StructLiteral);
  180. }
  181. auto HandleBraceExprFinishAsUnknown(Context& context) -> void {
  182. HandleBraceExprFinishAsValue(context);
  183. }
  184. } // namespace Carbon::Parse