From 46f4982e8715dbd98df10b25b838191e32c85588 Mon Sep 17 00:00:00 2001 From: Josh L Date: Wed, 21 Aug 2024 23:54:20 +0000 Subject: [PATCH 1/6] Implement new precedence from #4075 --- toolchain/parse/precedence.cpp | 7 +-- .../operators/fail_precedence_as.carbon | 56 ++++++++++++++++++- .../testdata/operators/precedence_as.carbon | 40 +++++-------- ...minus.carbon => recover_star_minus.carbon} | 10 ++-- ...r_star.carbon => recover_star_star.carbon} | 10 ++-- .../testdata/operators/three_stars.carbon | 32 +++++++++++ .../pointer/fail_pointer_type_in_expr.carbon | 54 ------------------ .../testdata/pointer/pointer_type.carbon | 28 ++++++++-- 8 files changed, 135 insertions(+), 102 deletions(-) rename toolchain/parse/testdata/operators/{fail_precedence_star_minus.carbon => recover_star_minus.carbon} (73%) rename toolchain/parse/testdata/operators/{fail_precedence_star_star.carbon => recover_star_star.carbon} (73%) create mode 100644 toolchain/parse/testdata/operators/three_stars.carbon diff --git a/toolchain/parse/precedence.cpp b/toolchain/parse/precedence.cpp index 01354619310bf..81904eeae85ca 100644 --- a/toolchain/parse/precedence.cpp +++ b/toolchain/parse/precedence.cpp @@ -54,22 +54,21 @@ struct OperatorPriorityTable { MarkHigherThan({Highest}, {TermPrefix, LogicalPrefix}); MarkHigherThan({TermPrefix}, {NumericPrefix, BitwisePrefix, IncrementDecrement}); - MarkHigherThan({NumericPrefix, BitwisePrefix}, + MarkHigherThan({NumericPrefix, BitwisePrefix, TypePostfix}, {As, Multiplicative, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift}); MarkHigherThan({Multiplicative}, {Additive}); MarkHigherThan( - {As, Additive, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift}, + {Additive, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift}, {Relational}); MarkHigherThan({Relational, LogicalPrefix}, {LogicalAnd, LogicalOr}); - MarkHigherThan({LogicalAnd, LogicalOr}, {If}); + MarkHigherThan({As, LogicalAnd, LogicalOr}, {If}); MarkHigherThan({If}, {Assignment}); MarkHigherThan({Assignment, IncrementDecrement}, {Lowest}); // Types are mostly a separate precedence graph. MarkHigherThan({Highest}, {TypePrefix}); MarkHigherThan({TypePrefix}, {TypePostfix}); - MarkHigherThan({TypePostfix}, {As}); // Compute the transitive closure of the above relationships: if we parse // `a $ b @ c` as `(a $ b) @ c` and parse `b @ c % d` as `(b @ c) % d`, diff --git a/toolchain/parse/testdata/operators/fail_precedence_as.carbon b/toolchain/parse/testdata/operators/fail_precedence_as.carbon index 8dfa19915d04f..bef27053cb8ac 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_as.carbon +++ b/toolchain/parse/testdata/operators/fail_precedence_as.carbon @@ -16,16 +16,40 @@ fn F(n: i32) { // CHECK:STDERR: not true as bool; - // No ordering between most binary operators and `as`. + // No ordering between mathematical binary operators and `as`. // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:9: ERROR: Parentheses are required to disambiguate operator precedence. // CHECK:STDERR: 1 + 1 as i32; // CHECK:STDERR: ^~ // CHECK:STDERR: 1 + 1 as i32; - // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:9: ERROR: Parentheses are required to disambiguate operator precedence. + // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:9: ERROR: Parentheses are required to disambiguate operator precedence. // CHECK:STDERR: 5 % 2 as i32; // CHECK:STDERR: ^~ + // CHECK:STDERR: 5 % 2 as i32; + + // No ordering between logical binary operators and `as`. + // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:12: ERROR: Parentheses are required to disambiguate operator precedence. + // CHECK:STDERR: 3 as i32 and true; + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + 3 as i32 and true; + // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:14: ERROR: Parentheses are required to disambiguate operator precedence. + // CHECK:STDERR: false or 4 as i32; + // CHECK:STDERR: ^~ + // CHECK:STDERR: + false or 4 as i32; + + // No ordering between comparison binary operators and `as`. + // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:12: ERROR: Parentheses are required to disambiguate operator precedence. + // CHECK:STDERR: 6 as i32 == 7; + // CHECK:STDERR: ^~ + // CHECK:STDERR: + 6 as i32 == 7; + // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:10: ERROR: Parentheses are required to disambiguate operator precedence. + // CHECK:STDERR: 8 <= 9 as i32; + // CHECK:STDERR: ^~ + 8 <= 9 as i32; } // CHECK:STDOUT: - filename: fail_precedence_as.carbon @@ -56,6 +80,32 @@ fn F(n: i32) { // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, // CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 5}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 26}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', has_error: yes, subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'BoolLiteralFalse', text: 'false'}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandOr', text: 'or', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorOr', text: 'or', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '6'}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '7'}, +// CHECK:STDOUT: {kind: 'InfixOperatorEqualEqual', text: '==', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '8'}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '9'}, +// CHECK:STDOUT: {kind: 'InfixOperatorLessEqual', text: '<=', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 52}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/operators/precedence_as.carbon b/toolchain/parse/testdata/operators/precedence_as.carbon index b151bb529928d..b0861f2bd5ccf 100644 --- a/toolchain/parse/testdata/operators/precedence_as.carbon +++ b/toolchain/parse/testdata/operators/precedence_as.carbon @@ -12,10 +12,8 @@ fn F(n: i32) { // Type operators and unary operators are higher precedence than `as`. -n as const i32; &n as i32*; - - // `as` is higher precedence than relational comparisons and - // logical operators. - if (1 as i32 < 2 as i32 and true as bool and false as bool) {} + ^n as i32; + *n as i32; } // CHECK:STDOUT: - filename: precedence_as.carbon @@ -41,28 +39,16 @@ fn F(n: i32) { // CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 5}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, -// CHECK:STDOUT: {kind: 'IfConditionStart', text: '('}, -// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'IntLiteral', text: '2'}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'InfixOperatorLess', text: '<', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 8}, -// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'}, -// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, -// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 12}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 13}, -// CHECK:STDOUT: {kind: 'BoolLiteralFalse', text: 'false'}, -// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, -// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 17}, -// CHECK:STDOUT: {kind: 'IfCondition', text: ')', subtree_size: 19}, -// CHECK:STDOUT: {kind: 'CodeBlockStart', text: '{'}, -// CHECK:STDOUT: {kind: 'CodeBlock', text: '}', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'IfStatement', text: 'if', subtree_size: 22}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 43}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'}, +// CHECK:STDOUT: {kind: 'PrefixOperatorCaret', text: '^', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'}, +// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 31}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon b/toolchain/parse/testdata/operators/recover_star_minus.carbon similarity index 73% rename from toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon rename to toolchain/parse/testdata/operators/recover_star_minus.carbon index 25d98a75a1365..f1977c3c7262e 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon +++ b/toolchain/parse/testdata/operators/recover_star_minus.carbon @@ -4,16 +4,16 @@ // // AUTOUPDATE // TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon // TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon -// CHECK:STDERR: fail_precedence_star_minus.carbon:[[@LINE+3]]:16: ERROR: Parentheses are required to disambiguate operator precedence. +// CHECK:STDERR: recover_star_minus.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator. // CHECK:STDERR: var n: i8 = n* -n; // CHECK:STDERR: ^ var n: i8 = n* -n; -// CHECK:STDOUT: - filename: fail_precedence_star_minus.carbon +// CHECK:STDOUT: - filename: recover_star_minus.carbon // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, @@ -24,7 +24,7 @@ var n: i8 = n* -n; // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'}, // CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'}, -// CHECK:STDOUT: {kind: 'InfixOperatorMinus', text: '-', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'InfixOperatorMinus', text: '-', subtree_size: 4}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 10}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/operators/fail_precedence_star_star.carbon b/toolchain/parse/testdata/operators/recover_star_star.carbon similarity index 73% rename from toolchain/parse/testdata/operators/fail_precedence_star_star.carbon rename to toolchain/parse/testdata/operators/recover_star_star.carbon index 41cf646783d50..dc198f7af1ea2 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_star_star.carbon +++ b/toolchain/parse/testdata/operators/recover_star_star.carbon @@ -4,16 +4,16 @@ // // AUTOUPDATE // TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/fail_precedence_star_star.carbon +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/recover_star_star.carbon // TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/fail_precedence_star_star.carbon +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_star.carbon -// CHECK:STDERR: fail_precedence_star_star.carbon:[[@LINE+3]]:16: ERROR: Parentheses are required to disambiguate operator precedence. +// CHECK:STDERR: recover_star_star.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator. // CHECK:STDERR: var n: i8 = n* *p; // CHECK:STDERR: ^ var n: i8 = n* *p; -// CHECK:STDOUT: - filename: fail_precedence_star_star.carbon +// CHECK:STDOUT: - filename: recover_star_star.carbon // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, @@ -24,7 +24,7 @@ var n: i8 = n* *p; // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'}, // CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'}, -// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 4}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 10}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/operators/three_stars.carbon b/toolchain/parse/testdata/operators/three_stars.carbon new file mode 100644 index 0000000000000..32d3ae98db204 --- /dev/null +++ b/toolchain/parse/testdata/operators/three_stars.carbon @@ -0,0 +1,32 @@ +// 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 +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/three_stars.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/three_stars.carbon + +fn F() { + const T* * *p; +} + +// CHECK:STDOUT: - filename: three_stars.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierName', text: 'F'}, +// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('}, +// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'}, +// CHECK:STDOUT: {kind: 'PrefixOperatorConst', text: 'const', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'}, +// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 13}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon b/toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon index 8d5d09e7c3e23..0a2cfd23dd267 100644 --- a/toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon +++ b/toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon @@ -9,30 +9,6 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon fn F() -> i32 { - // TODO: Indicate the locations of both operators involved in the precedence - // error, so that it's clear what ambiguity we're referring to. - // TODO: Improve error recovery so that we recover as `3 * (i32*) * 4`, not - // as `(3 * i32)* * 4`, to suppress the second error here. - // CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+8]]:17: ERROR: Parentheses are required to disambiguate operator precedence. - // CHECK:STDERR: return 3 * i32* * 4; - // CHECK:STDERR: ^ - // CHECK:STDERR: - // CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+4]]:19: ERROR: Parentheses are required to disambiguate operator precedence. - // CHECK:STDERR: return 3 * i32* * 4; - // CHECK:STDERR: ^ - // CHECK:STDERR: - return 3 * i32* * 4; -} - -fn G() -> i32 { - // CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+4]]:15: ERROR: Parentheses are required to disambiguate operator precedence. - // CHECK:STDERR: return i32* + 4; - // CHECK:STDERR: ^ - // CHECK:STDERR: - return i32* + 4; -} - -fn H() -> i32 { // CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+3]]:14: ERROR: Parentheses are required to disambiguate operator precedence. // CHECK:STDERR: return *i32*; // CHECK:STDERR: ^ @@ -50,36 +26,6 @@ fn H() -> i32 { // CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7}, // CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'}, -// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', has_error: yes, subtree_size: 4}, -// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, -// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', has_error: yes, subtree_size: 6}, -// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 8}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'IdentifierName', text: 'G'}, -// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('}, -// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, -// CHECK:STDOUT: {kind: 'InfixOperatorPlus', text: '+', has_error: yes, subtree_size: 4}, -// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 6}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14}, -// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'IdentifierName', text: 'H'}, -// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('}, -// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, // CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2}, // CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', has_error: yes, subtree_size: 3}, diff --git a/toolchain/parse/testdata/pointer/pointer_type.carbon b/toolchain/parse/testdata/pointer/pointer_type.carbon index 695d55205a9fb..51579b0ba591d 100644 --- a/toolchain/parse/testdata/pointer/pointer_type.carbon +++ b/toolchain/parse/testdata/pointer/pointer_type.carbon @@ -9,7 +9,9 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/pointer/pointer_type.carbon fn F(p: i32*) -> i32* { - return p; + f32* + 0; + 1 * bool* * 2; + return 3 * i32* * *p; } var T: type = if true then i32* else f64*; @@ -29,10 +31,28 @@ var T: type = if true then i32* else f64*; // CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 3}, // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'FloatTypeLiteral', text: 'f32'}, +// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, +// CHECK:STDOUT: {kind: 'InfixOperatorPlus', text: '+', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'}, +// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, +// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '2'}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7}, // CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'}, -// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'}, -// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'}, +// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 9}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 34}, // CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'T'}, // CHECK:STDOUT: {kind: 'TypeTypeLiteral', text: 'type'}, From a1dcebea5487fcfed0020fe98ec0eab37ab875ac Mon Sep 17 00:00:00 2001 From: Josh L Date: Thu, 22 Aug 2024 00:04:10 +0000 Subject: [PATCH 2/6] Delete failing test --- toolchain/parse/precedence_test.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/toolchain/parse/precedence_test.cpp b/toolchain/parse/precedence_test.cpp index 760d29f47102f..20a77bad422b8 100644 --- a/toolchain/parse/precedence_test.cpp +++ b/toolchain/parse/precedence_test.cpp @@ -52,17 +52,12 @@ TEST(PrecedenceTest, InfixVsPostfix) { EXPECT_FALSE( PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->is_binary); - // Infix `*` can appear in `+` contexts; postfix `*` cannot. + // Infix `*` can appear in `+` contexts. EXPECT_THAT( PrecedenceGroup::GetPriority( PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level, PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level), Eq(OperatorPriority::LeftFirst)); - EXPECT_THAT( - PrecedenceGroup::GetPriority( - PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->level, - PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level), - Eq(OperatorPriority::Ambiguous)); } TEST(PrecedenceTest, Associativity) { From 51a7d1717a9ee21ddea5a7282276766c6c479458 Mon Sep 17 00:00:00 2001 From: josh11b <15258583+josh11b@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:22:26 -0700 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: Geoff Romer --- toolchain/parse/testdata/operators/fail_precedence_as.carbon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolchain/parse/testdata/operators/fail_precedence_as.carbon b/toolchain/parse/testdata/operators/fail_precedence_as.carbon index bef27053cb8ac..f767842bf3d6b 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_as.carbon +++ b/toolchain/parse/testdata/operators/fail_precedence_as.carbon @@ -40,7 +40,7 @@ fn F(n: i32) { // CHECK:STDERR: false or 4 as i32; - // No ordering between comparison binary operators and `as`. + // No ordering between relational binary operators and `as`. // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:12: ERROR: Parentheses are required to disambiguate operator precedence. // CHECK:STDERR: 6 as i32 == 7; // CHECK:STDERR: ^~ From f28e01dd49db01d4ab6b6c34fd518b1c716b8380 Mon Sep 17 00:00:00 2001 From: Josh L Date: Thu, 22 Aug 2024 20:23:24 +0000 Subject: [PATCH 4/6] Add TODO based on suggestion --- toolchain/parse/testdata/operators/recover_star_minus.carbon | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/toolchain/parse/testdata/operators/recover_star_minus.carbon b/toolchain/parse/testdata/operators/recover_star_minus.carbon index f1977c3c7262e..7ef1152bb5def 100644 --- a/toolchain/parse/testdata/operators/recover_star_minus.carbon +++ b/toolchain/parse/testdata/operators/recover_star_minus.carbon @@ -8,6 +8,11 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon +// TODO: There are two possible fixes that would make this expression legal: +// `n * -n` and `n* - n`. The parser doesn't realize that the first fix is +// available because it has already accepted that first part of the expression, +// so it is recovering by using the second option, but the diagnostic should +// ideally offer (or consider) both fixes as alternatives. // CHECK:STDERR: recover_star_minus.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator. // CHECK:STDERR: var n: i8 = n* -n; // CHECK:STDERR: ^ From 76871d111d53973809966a4d65156545250ec83f Mon Sep 17 00:00:00 2001 From: Josh L Date: Thu, 22 Aug 2024 20:24:40 +0000 Subject: [PATCH 5/6] Add TODO based on suggestion --- toolchain/parse/testdata/operators/recover_star_minus.carbon | 5 ----- 1 file changed, 5 deletions(-) diff --git a/toolchain/parse/testdata/operators/recover_star_minus.carbon b/toolchain/parse/testdata/operators/recover_star_minus.carbon index 7ef1152bb5def..f1977c3c7262e 100644 --- a/toolchain/parse/testdata/operators/recover_star_minus.carbon +++ b/toolchain/parse/testdata/operators/recover_star_minus.carbon @@ -8,11 +8,6 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon -// TODO: There are two possible fixes that would make this expression legal: -// `n * -n` and `n* - n`. The parser doesn't realize that the first fix is -// available because it has already accepted that first part of the expression, -// so it is recovering by using the second option, but the diagnostic should -// ideally offer (or consider) both fixes as alternatives. // CHECK:STDERR: recover_star_minus.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator. // CHECK:STDERR: var n: i8 = n* -n; // CHECK:STDERR: ^ From df8e758dfe421987e65eb43b8ab3f00a175f038e Mon Sep 17 00:00:00 2001 From: Josh L Date: Thu, 22 Aug 2024 20:25:21 +0000 Subject: [PATCH 6/6] Add TODO based on suggestion --- toolchain/parse/testdata/operators/recover_star_minus.carbon | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/toolchain/parse/testdata/operators/recover_star_minus.carbon b/toolchain/parse/testdata/operators/recover_star_minus.carbon index f1977c3c7262e..7ef1152bb5def 100644 --- a/toolchain/parse/testdata/operators/recover_star_minus.carbon +++ b/toolchain/parse/testdata/operators/recover_star_minus.carbon @@ -8,6 +8,11 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon +// TODO: There are two possible fixes that would make this expression legal: +// `n * -n` and `n* - n`. The parser doesn't realize that the first fix is +// available because it has already accepted that first part of the expression, +// so it is recovering by using the second option, but the diagnostic should +// ideally offer (or consider) both fixes as alternatives. // CHECK:STDERR: recover_star_minus.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator. // CHECK:STDERR: var n: i8 = n* -n; // CHECK:STDERR: ^