From 60cccd8e58f2a024676599cc00971a6e406e6d42 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 8 Feb 2021 13:26:07 +0000 Subject: Fixes parsing if expressions as part of an expression. This allows for rust style ternery expressions. Fixes #214 --- gcc/rust/parse/rust-parse-impl.h | 50 ++++++++++++++++++---- gcc/rust/parse/rust-parse.h | 6 ++- .../rust.test/compilable/block_expr_parser_bug.rs | 4 ++ 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/rust.test/compilable/block_expr_parser_bug.rs (limited to 'gcc') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ea468ca..906f6b1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7504,12 +7504,23 @@ Parser::parse_loop_label () template std::unique_ptr Parser::parse_if_expr ( - std::vector outer_attrs ATTRIBUTE_UNUSED) + std::vector outer_attrs ATTRIBUTE_UNUSED, bool pratt_parse) { // TODO: make having outer attributes an error? - - Location locus = lexer.peek_token ()->get_locus (); - skip_token (IF); + Location locus = Linemap::unknown_location (); + if (!pratt_parse) + { + locus = lexer.peek_token ()->get_locus (); + if (!skip_token (IF)) + { + skip_after_end_block (); + return nullptr; + } + } + else + { + locus = lexer.peek_token ()->get_locus () - 1; + } // detect accidental if let if (lexer.peek_token ()->get_id () == LET) @@ -7640,12 +7651,23 @@ Parser::parse_if_expr ( template std::unique_ptr Parser::parse_if_let_expr ( - std::vector outer_attrs ATTRIBUTE_UNUSED) + std::vector outer_attrs ATTRIBUTE_UNUSED, bool pratt_parse) { // TODO: make having outer attributes an error? - - Location locus = lexer.peek_token ()->get_locus (); - skip_token (IF); + Location locus = Linemap::unknown_location (); + if (!pratt_parse) + { + locus = lexer.peek_token ()->get_locus (); + if (!skip_token (IF)) + { + skip_after_end_block (); + return nullptr; + } + } + else + { + locus = lexer.peek_token ()->get_locus () - 1; + } // detect accidental if expr parsed as if let expr if (lexer.peek_token ()->get_id () != LET) @@ -12399,6 +12421,18 @@ Parser::null_denotation ( case LEFT_CURLY: // ok - this is an expression with block for once. return parse_block_expr (std::move (outer_attrs), true); + case IF: + // if or if let, so more lookahead to find out + if (lexer.peek_token (1)->get_id () == LET) + { + // if let expr + return parse_if_let_expr (std::move (outer_attrs), true); + } + else + { + // if expr + return parse_if_expr (std::move (outer_attrs), true); + } case MATCH_TOK: // also an expression with block return parse_match_expr (std::move (outer_attrs), true); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 2778ec7..aeda82b 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -480,10 +480,12 @@ private: bool pratt_parse = false); std::unique_ptr parse_if_expr (std::vector outer_attrs - = std::vector ()); + = std::vector (), + bool pratt_parse = false); std::unique_ptr parse_if_let_expr (std::vector outer_attrs - = std::vector ()); + = std::vector (), + bool pratt_parse = false); std::unique_ptr parse_loop_expr (std::vector outer_attrs = std::vector (), diff --git a/gcc/testsuite/rust.test/compilable/block_expr_parser_bug.rs b/gcc/testsuite/rust.test/compilable/block_expr_parser_bug.rs new file mode 100644 index 0000000..e583008 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/block_expr_parser_bug.rs @@ -0,0 +1,4 @@ +fn main() { + let a = 123; + let b = if a > 10 { a - 1 } else { a + 1 }; +} -- cgit v1.1