From 6cca85534f3084b59188233337cfc1d35f6b4b73 Mon Sep 17 00:00:00 2001 From: Farzana Ahmed Siddique Date: Fri, 28 Jul 2023 11:31:12 -0700 Subject: [PATCH] Parser for index expression such as a[0] (#3033) Co-authored-by: Farzana Ahmed Siddique --- toolchain/parser/parse_node_kind.def | 8 ++++++ toolchain/parser/parser_handle_expression.cpp | 6 +++++ .../parser/parser_handle_index_expression.cpp | 27 +++++++++++++++++++ toolchain/parser/parser_state.def | 16 +++++++++++ .../testdata/index/assign_to_var.carbon | 20 ++++++++++++++ .../testdata/index/fail_empty_expr.carbon | 23 ++++++++++++++++ .../semantics/semantics_handle_index.cpp | 21 +++++++++++++++ 7 files changed, 121 insertions(+) create mode 100644 toolchain/parser/parser_handle_index_expression.cpp create mode 100644 toolchain/parser/testdata/index/assign_to_var.carbon create mode 100644 toolchain/parser/testdata/index/fail_empty_expr.carbon create mode 100644 toolchain/semantics/semantics_handle_index.cpp diff --git a/toolchain/parser/parse_node_kind.def b/toolchain/parser/parse_node_kind.def index 7dde952b05f2..0b8a78b536a7 100644 --- a/toolchain/parser/parse_node_kind.def +++ b/toolchain/parser/parse_node_kind.def @@ -208,6 +208,14 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileConditionStart, 0) CARBON_PARSE_NODE_KIND_BRACKET(WhileCondition, WhileConditionStart) CARBON_PARSE_NODE_KIND_CHILD_COUNT(WhileStatement, 2) +// Index expressions, such as `a[1]`: +// _external_: expression +// IndexExpressionStart +// _external_: expression +// IndexExpression +CARBON_PARSE_NODE_KIND_CHILD_COUNT(IndexExpressionStart, 1) +CARBON_PARSE_NODE_KIND_BRACKET(IndexExpression, IndexExpressionStart) + // Parenthesized expressions, such as `(2)`: // ParenExpressionOrTupleLiteralStart // _external_: expression diff --git a/toolchain/parser/parser_handle_expression.cpp b/toolchain/parser/parser_handle_expression.cpp index d6461e8788be..854877ce3afa 100644 --- a/toolchain/parser/parser_handle_expression.cpp +++ b/toolchain/parser/parser_handle_expression.cpp @@ -137,6 +137,12 @@ auto ParserHandleExpressionInPostfixLoop(ParserContext& context) -> void { context.PushState(state); break; } + case TokenKind::OpenSquareBracket: { + context.PushState(state); + state.state = ParserState::IndexExpression; + context.PushState(state); + break; + } default: { if (state.has_error) { context.ReturnErrorOnState(); diff --git a/toolchain/parser/parser_handle_index_expression.cpp b/toolchain/parser/parser_handle_index_expression.cpp new file mode 100644 index 000000000000..831ed14ab7cf --- /dev/null +++ b/toolchain/parser/parser_handle_index_expression.cpp @@ -0,0 +1,27 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/lexer/token_kind.h" +#include "toolchain/parser/parser_context.h" + +namespace Carbon { + +auto ParserHandleIndexExpression(ParserContext& context) -> void { + auto state = context.PopState(); + state.state = ParserState::IndexExpressionFinish; + context.PushState(state); + context.AddNode(ParseNodeKind::IndexExpressionStart, + context.ConsumeChecked(TokenKind::OpenSquareBracket), + state.subtree_start, state.has_error); + context.PushState(ParserState::Expression); +} + +auto ParserHandleIndexExpressionFinish(ParserContext& context) -> void { + auto state = context.PopState(); + context.AddNode(ParseNodeKind::IndexExpression, + context.ConsumeChecked(TokenKind::CloseSquareBracket), + state.subtree_start, state.has_error); +} + +} // namespace Carbon diff --git a/toolchain/parser/parser_state.def b/toolchain/parser/parser_state.def index c49d75169a4b..d0e2da477518 100644 --- a/toolchain/parser/parser_state.def +++ b/toolchain/parser/parser_state.def @@ -39,6 +39,19 @@ CARBON_PARSER_STATE_VARIANT(State, Variant1) \ CARBON_PARSER_STATE_VARIANTS2(State, Variant2, Variant3) +// Handles an index expression `a[0]`. +// +// Always: +// 1. Expression +// 2. IndexExpressionFinish +CARBON_PARSER_STATE(IndexExpression) + +// Handles finishing the index expression. +// +// Always: +// (state done) +CARBON_PARSER_STATE(IndexExpressionFinish) + // Handles the `{` of a brace expression. // // If `CloseCurlyBrace`: @@ -263,6 +276,9 @@ CARBON_PARSER_STATE(ExpressionInPostfix) // If `OpenParen`: // 1. CallExpression // 2. ExpressionInPostfixLoop +// If `OpenSquareBracket`: +// 1. IndexExpressionStart +// 2. ExpressionInPostfixLoop // Else: // (state done) CARBON_PARSER_STATE(ExpressionInPostfixLoop) diff --git a/toolchain/parser/testdata/index/assign_to_var.carbon b/toolchain/parser/testdata/index/assign_to_var.carbon new file mode 100644 index 000000000000..19839b2cca30 --- /dev/null +++ b/toolchain/parser/testdata/index/assign_to_var.carbon @@ -0,0 +1,20 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: [ +// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, +// CHECK:STDOUT: {kind: 'Name', text: 'v'}, +// CHECK:STDOUT: {kind: 'Literal', text: 'i32'}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, +// CHECK:STDOUT: {kind: 'NameExpression', text: 't'}, +// CHECK:STDOUT: {kind: 'IndexExpressionStart', text: '[', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'Literal', text: '0'}, +// CHECK:STDOUT: {kind: 'IndexExpression', text: ']', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] + +var v: i32 = t[0]; diff --git a/toolchain/parser/testdata/index/fail_empty_expr.carbon b/toolchain/parser/testdata/index/fail_empty_expr.carbon new file mode 100644 index 000000000000..8e0020984078 --- /dev/null +++ b/toolchain/parser/testdata/index/fail_empty_expr.carbon @@ -0,0 +1,23 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: [ +// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, +// CHECK:STDOUT: {kind: 'Name', text: 'v'}, +// CHECK:STDOUT: {kind: 'Literal', text: 'i32'}, +// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, +// CHECK:STDOUT: {kind: 'NameExpression', text: 't'}, +// CHECK:STDOUT: {kind: 'IndexExpressionStart', text: '[', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: ']', has_error: yes}, +// CHECK:STDOUT: {kind: 'IndexExpression', text: ']', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_empty_expr.carbon:[[@LINE+3]]:16: Expected expression. +// CHECK:STDERR: var v: i32 = t[]; +// CHECK:STDERR: ^ +var v: i32 = t[]; diff --git a/toolchain/semantics/semantics_handle_index.cpp b/toolchain/semantics/semantics_handle_index.cpp new file mode 100644 index 000000000000..9cdbef3b42bd --- /dev/null +++ b/toolchain/semantics/semantics_handle_index.cpp @@ -0,0 +1,21 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#include "toolchain/semantics/semantics_context.h" + +namespace Carbon { + +auto SemanticsHandleIndexExpressionStart(SemanticsContext& context, + ParseTree::Node parse_node) -> bool { + return context.TODO(parse_node, "HandleIndexExpressionStart"); +} + +auto SemanticsHandleIndexExpression(SemanticsContext& context, + ParseTree::Node parse_node) -> bool { + return context.TODO(parse_node, "HandleIndexExpression"); +} + +} // namespace Carbon