handle_paren_expr.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. auto HandleParenExpr(Context& context) -> void {
  7. auto state = context.PopState();
  8. // Advance past the open paren.
  9. context.AddLeafNode(NodeKind::ParenExprOrTupleLiteralStart,
  10. context.ConsumeChecked(Lex::TokenKind::OpenParen));
  11. if (context.PositionIs(Lex::TokenKind::CloseParen)) {
  12. state.state = State::ParenExprFinishAsTuple;
  13. context.PushState(state);
  14. } else {
  15. state.state = State::ParenExprFinishAsNormal;
  16. context.PushState(state);
  17. context.PushState(State::ParenExprParamFinishAsUnknown);
  18. context.PushState(State::Expr);
  19. }
  20. }
  21. // Handles ParenExprParamFinishAs(Unknown|Tuple).
  22. static auto HandleParenExprParamFinish(Context& context, bool as_tuple)
  23. -> void {
  24. auto state = context.PopState();
  25. auto list_token_kind = context.ConsumeListToken(
  26. NodeKind::TupleLiteralComma, Lex::TokenKind::CloseParen, state.has_error);
  27. if (list_token_kind == Context::ListTokenKind::Close) {
  28. return;
  29. }
  30. // If this is the first item and a comma was found, switch to tuple handling.
  31. // Note this could be `(expr,)` so we may not reuse the current state, but
  32. // it's still necessary to switch the parent.
  33. if (!as_tuple) {
  34. state.state = State::ParenExprParamFinishAsTuple;
  35. auto finish_state = context.PopState();
  36. CARBON_CHECK(finish_state.state == State::ParenExprFinishAsNormal)
  37. << "Unexpected parent state, found: " << finish_state.state;
  38. finish_state.state = State::ParenExprFinishAsTuple;
  39. context.PushState(finish_state);
  40. }
  41. // On a comma, push another expression handler.
  42. if (list_token_kind == Context::ListTokenKind::Comma) {
  43. context.PushState(state);
  44. context.PushState(State::Expr);
  45. }
  46. }
  47. auto HandleParenExprParamFinishAsUnknown(Context& context) -> void {
  48. HandleParenExprParamFinish(context, /*as_tuple=*/false);
  49. }
  50. auto HandleParenExprParamFinishAsTuple(Context& context) -> void {
  51. HandleParenExprParamFinish(context, /*as_tuple=*/true);
  52. }
  53. auto HandleParenExprFinishAsNormal(Context& context) -> void {
  54. auto state = context.PopState();
  55. context.AddNode(NodeKind::ParenExpr, context.Consume(), state.subtree_start,
  56. state.has_error);
  57. }
  58. auto HandleParenExprFinishAsTuple(Context& context) -> void {
  59. auto state = context.PopState();
  60. context.AddNode(NodeKind::TupleLiteral, context.Consume(),
  61. state.subtree_start, state.has_error);
  62. }
  63. } // namespace Carbon::Parse