parser_handle_brace_expression.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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/parser/parser_context.h"
  5. namespace Carbon {
  6. auto ParserHandleBraceExpression(ParserContext& context) -> void {
  7. auto state = context.PopState();
  8. state.state = ParserState::BraceExpressionFinishAsUnknown;
  9. context.PushState(state);
  10. CARBON_CHECK(context.ConsumeAndAddLeafNodeIf(
  11. TokenKind::OpenCurlyBrace,
  12. ParseNodeKind::StructLiteralOrStructTypeLiteralStart));
  13. if (!context.PositionIs(TokenKind::CloseCurlyBrace)) {
  14. context.PushState(ParserState::BraceExpressionParameterAsUnknown);
  15. }
  16. }
  17. // Prints a diagnostic for brace expression syntax errors.
  18. static auto ParserHandleBraceExpressionParameterError(
  19. ParserContext& context, ParserContext::StateStackEntry state,
  20. ParserState param_finish_state) -> void {
  21. bool is_type =
  22. param_finish_state == ParserState::BraceExpressionParameterFinishAsType;
  23. bool is_value =
  24. param_finish_state == ParserState::BraceExpressionParameterFinishAsValue;
  25. bool is_unknown = param_finish_state ==
  26. ParserState::BraceExpressionParameterFinishAsUnknown;
  27. CARBON_CHECK(is_type || is_value || is_unknown);
  28. CARBON_DIAGNOSTIC(ExpectedStructLiteralField, Error, "Expected {0}{1}{2}.",
  29. llvm::StringRef, llvm::StringRef, llvm::StringRef);
  30. context.emitter().Emit(*context.position(), ExpectedStructLiteralField,
  31. (is_type || is_unknown) ? "`.field: field_type`" : "",
  32. is_unknown ? " or " : "",
  33. (is_value || is_unknown) ? "`.field = value`" : "");
  34. state.state = param_finish_state;
  35. state.has_error = true;
  36. context.PushState(state);
  37. }
  38. // Handles BraceExpressionParameterAs(Type|Value|Unknown).
  39. static auto ParserHandleBraceExpressionParameter(
  40. ParserContext& context, ParserState after_designator_state,
  41. ParserState param_finish_state) -> void {
  42. auto state = context.PopState();
  43. if (!context.PositionIs(TokenKind::Period)) {
  44. ParserHandleBraceExpressionParameterError(context, state,
  45. param_finish_state);
  46. return;
  47. }
  48. state.state = after_designator_state;
  49. context.PushState(state);
  50. context.PushState(ParserState::PeriodAsStruct);
  51. }
  52. auto ParserHandleBraceExpressionParameterAsType(ParserContext& context)
  53. -> void {
  54. ParserHandleBraceExpressionParameter(
  55. context, ParserState::BraceExpressionParameterAfterDesignatorAsType,
  56. ParserState::BraceExpressionParameterFinishAsType);
  57. }
  58. auto ParserHandleBraceExpressionParameterAsValue(ParserContext& context)
  59. -> void {
  60. ParserHandleBraceExpressionParameter(
  61. context, ParserState::BraceExpressionParameterAfterDesignatorAsValue,
  62. ParserState::BraceExpressionParameterFinishAsValue);
  63. }
  64. auto ParserHandleBraceExpressionParameterAsUnknown(ParserContext& context)
  65. -> void {
  66. ParserHandleBraceExpressionParameter(
  67. context, ParserState::BraceExpressionParameterAfterDesignatorAsUnknown,
  68. ParserState::BraceExpressionParameterFinishAsUnknown);
  69. }
  70. // Handles BraceExpressionParameterAfterDesignatorAs(Type|Value|Unknown).
  71. static auto ParserHandleBraceExpressionParameterAfterDesignator(
  72. ParserContext& context, ParserState param_finish_state) -> void {
  73. auto state = context.PopState();
  74. if (state.has_error) {
  75. auto recovery_pos = context.FindNextOf(
  76. {TokenKind::Equal, TokenKind::Colon, TokenKind::Comma});
  77. if (!recovery_pos ||
  78. context.tokens().GetKind(*recovery_pos) == TokenKind::Comma) {
  79. state.state = param_finish_state;
  80. context.PushState(state);
  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(TokenKind::Colon)) {
  88. is_type = true;
  89. } else if (context.PositionIs(TokenKind::Equal)) {
  90. is_type = false;
  91. } else {
  92. ParserHandleBraceExpressionParameterError(context, state,
  93. param_finish_state);
  94. return;
  95. }
  96. // If we're changing from unknown, update the related finish states.
  97. if (param_finish_state ==
  98. ParserState::BraceExpressionParameterFinishAsUnknown) {
  99. auto finish_state = context.PopState();
  100. CARBON_CHECK(finish_state.state ==
  101. ParserState::BraceExpressionFinishAsUnknown);
  102. if (is_type) {
  103. finish_state.state = ParserState::BraceExpressionFinishAsType;
  104. param_finish_state = ParserState::BraceExpressionParameterFinishAsType;
  105. } else {
  106. finish_state.state = ParserState::BraceExpressionFinishAsValue;
  107. param_finish_state = ParserState::BraceExpressionParameterFinishAsValue;
  108. }
  109. context.PushState(finish_state);
  110. }
  111. auto want_param_finish_state =
  112. is_type ? ParserState::BraceExpressionParameterFinishAsType
  113. : ParserState::BraceExpressionParameterFinishAsValue;
  114. if (param_finish_state != want_param_finish_state) {
  115. ParserHandleBraceExpressionParameterError(context, state,
  116. param_finish_state);
  117. return;
  118. }
  119. // Struct type fields and value fields use the same grammar except
  120. // that one has a `:` separator and the other has an `=` separator.
  121. state.state = param_finish_state;
  122. state.token = context.Consume();
  123. context.PushState(state);
  124. context.PushState(ParserState::Expression);
  125. }
  126. auto ParserHandleBraceExpressionParameterAfterDesignatorAsType(
  127. ParserContext& context) -> void {
  128. ParserHandleBraceExpressionParameterAfterDesignator(
  129. context, ParserState::BraceExpressionParameterFinishAsType);
  130. }
  131. auto ParserHandleBraceExpressionParameterAfterDesignatorAsValue(
  132. ParserContext& context) -> void {
  133. ParserHandleBraceExpressionParameterAfterDesignator(
  134. context, ParserState::BraceExpressionParameterFinishAsValue);
  135. }
  136. auto ParserHandleBraceExpressionParameterAfterDesignatorAsUnknown(
  137. ParserContext& context) -> void {
  138. ParserHandleBraceExpressionParameterAfterDesignator(
  139. context, ParserState::BraceExpressionParameterFinishAsUnknown);
  140. }
  141. // Handles BraceExpressionParameterFinishAs(Type|Value|Unknown).
  142. static auto ParserHandleBraceExpressionParameterFinish(ParserContext& context,
  143. ParseNodeKind node_kind,
  144. ParserState param_state)
  145. -> void {
  146. auto state = context.PopState();
  147. if (state.has_error) {
  148. context.AddLeafNode(ParseNodeKind::StructFieldUnknown, state.token,
  149. /*has_error=*/true);
  150. } else {
  151. context.AddNode(node_kind, state.token, state.subtree_start,
  152. /*has_error=*/false);
  153. }
  154. if (context.ConsumeListToken(ParseNodeKind::StructComma,
  155. TokenKind::CloseCurlyBrace, state.has_error) ==
  156. ParserContext::ListTokenKind::Comma) {
  157. context.PushState(param_state);
  158. }
  159. }
  160. auto ParserHandleBraceExpressionParameterFinishAsType(ParserContext& context)
  161. -> void {
  162. ParserHandleBraceExpressionParameterFinish(
  163. context, ParseNodeKind::StructFieldType,
  164. ParserState::BraceExpressionParameterAsType);
  165. }
  166. auto ParserHandleBraceExpressionParameterFinishAsValue(ParserContext& context)
  167. -> void {
  168. ParserHandleBraceExpressionParameterFinish(
  169. context, ParseNodeKind::StructFieldValue,
  170. ParserState::BraceExpressionParameterAsValue);
  171. }
  172. auto ParserHandleBraceExpressionParameterFinishAsUnknown(ParserContext& context)
  173. -> void {
  174. ParserHandleBraceExpressionParameterFinish(
  175. context, ParseNodeKind::StructFieldUnknown,
  176. ParserState::BraceExpressionParameterAsUnknown);
  177. }
  178. // Handles BraceExpressionFinishAs(Type|Value|Unknown).
  179. static auto ParserHandleBraceExpressionFinish(ParserContext& context,
  180. ParseNodeKind node_kind) -> void {
  181. auto state = context.PopState();
  182. context.AddNode(node_kind, context.Consume(), state.subtree_start,
  183. state.has_error);
  184. }
  185. auto ParserHandleBraceExpressionFinishAsType(ParserContext& context) -> void {
  186. ParserHandleBraceExpressionFinish(context, ParseNodeKind::StructTypeLiteral);
  187. }
  188. auto ParserHandleBraceExpressionFinishAsValue(ParserContext& context) -> void {
  189. ParserHandleBraceExpressionFinish(context, ParseNodeKind::StructLiteral);
  190. }
  191. auto ParserHandleBraceExpressionFinishAsUnknown(ParserContext& context)
  192. -> void {
  193. ParserHandleBraceExpressionFinish(context, ParseNodeKind::StructLiteral);
  194. }
  195. } // namespace Carbon