aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-08 13:26:07 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-09 09:47:13 +0000
commit60cccd8e58f2a024676599cc00971a6e406e6d42 (patch)
treefbdf44ca68e745e5af0d89fb16789570673c8a75 /gcc
parent9f3ddb35959606cbf7059362acfc27a9966ac3d4 (diff)
downloadgcc-60cccd8e58f2a024676599cc00971a6e406e6d42.zip
gcc-60cccd8e58f2a024676599cc00971a6e406e6d42.tar.gz
gcc-60cccd8e58f2a024676599cc00971a6e406e6d42.tar.bz2
Fixes parsing if expressions as part of an expression.
This allows for rust style ternery expressions. Fixes #214
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/parse/rust-parse-impl.h50
-rw-r--r--gcc/rust/parse/rust-parse.h6
-rw-r--r--gcc/testsuite/rust.test/compilable/block_expr_parser_bug.rs4
3 files changed, 50 insertions, 10 deletions
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<ManagedTokenSource>::parse_loop_label ()
template <typename ManagedTokenSource>
std::unique_ptr<AST::IfExpr>
Parser<ManagedTokenSource>::parse_if_expr (
- std::vector<AST::Attribute> outer_attrs ATTRIBUTE_UNUSED)
+ std::vector<AST::Attribute> 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<ManagedTokenSource>::parse_if_expr (
template <typename ManagedTokenSource>
std::unique_ptr<AST::IfLetExpr>
Parser<ManagedTokenSource>::parse_if_let_expr (
- std::vector<AST::Attribute> outer_attrs ATTRIBUTE_UNUSED)
+ std::vector<AST::Attribute> 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<ManagedTokenSource>::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<AST::IfExpr>
parse_if_expr (std::vector<AST::Attribute> outer_attrs
- = std::vector<AST::Attribute> ());
+ = std::vector<AST::Attribute> (),
+ bool pratt_parse = false);
std::unique_ptr<AST::IfLetExpr>
parse_if_let_expr (std::vector<AST::Attribute> outer_attrs
- = std::vector<AST::Attribute> ());
+ = std::vector<AST::Attribute> (),
+ bool pratt_parse = false);
std::unique_ptr<AST::LoopExpr>
parse_loop_expr (std::vector<AST::Attribute> outer_attrs
= std::vector<AST::Attribute> (),
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 };
+}