From: Owen Avery <[email protected]>
This improves our handling of PathInExpression and fixes
https://github.com/Rust-GCC/gccrs/issues/4056.
gcc/rust/ChangeLog:
* parse/rust-parse-impl.h (Parser::parse_expr): Avoid skipping
or splitting tokens.
(Parser::null_denotation): Assume initial token was not skipped
and adjust function signature to match. Use
parse_path_in_expression instead of
parse_path_in_expression_pratt and handle SCOPE_RESOLUTION.
(Parser::parse_path_in_expression_pratt): Remove function.
* parse/rust-parse.h (null_denotation): Remove initial token
parameter.
(parse_path_in_expression_pratt): Remove function.
gcc/testsuite/ChangeLog:
* rust/compile/global-path-array.rs: New test.
Signed-off-by: Owen Avery <[email protected]>
---
gcc/rust/parse/rust-parse-impl.h | 148 ++----------------
gcc/rust/parse/rust-parse.h | 3 +-
.../rust/compile/global-path-array.rs | 5 +
3 files changed, 19 insertions(+), 137 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/global-path-array.rs
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 90c4da4a4d3..eef3b2f1592 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -12155,20 +12155,12 @@ Parser<ManagedTokenSource>::parse_expr (int
right_binding_power,
return nullptr;
}
- if (current_token->get_id () == LEFT_SHIFT)
- {
- lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
- current_token = lexer.peek_token ();
- }
-
- lexer.skip_token ();
-
ParseRestrictions null_denotation_restrictions = restrictions;
null_denotation_restrictions.expr_can_be_stmt = false;
// parse null denotation (unary part of expression)
std::unique_ptr<AST::Expr> expr
- = null_denotation (current_token, {}, null_denotation_restrictions);
+ = null_denotation ({}, null_denotation_restrictions);
return left_denotations (std::move (expr), right_binding_power,
std::move (outer_attrs), restrictions);
@@ -12236,8 +12228,7 @@ Parser<ManagedTokenSource>::parse_expr (AST::AttrVec
outer_attrs,
/* Determines action to take when finding token at beginning of expression. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::Expr>
-Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
- AST::AttrVec outer_attrs,
+Parser<ManagedTokenSource>::null_denotation (AST::AttrVec outer_attrs,
ParseRestrictions restrictions)
{
/* note: tok is previous character in input stream, not current one, as
@@ -12247,6 +12238,8 @@ Parser<ManagedTokenSource>::null_denotation
(const_TokenPtr tok,
* denotation and then a left denotation), null denotations handle primaries
* and unary operands (but only prefix unary operands) */
+ auto tok = lexer.peek_token ();
+
switch (tok->get_id ())
{
case IDENTIFIER:
@@ -12255,28 +12248,26 @@ Parser<ManagedTokenSource>::null_denotation
(const_TokenPtr tok,
case DOLLAR_SIGN:
case CRATE:
case SUPER:
+ case SCOPE_RESOLUTION:
{
// DEBUG
rust_debug ("beginning null denotation identifier handling");
/* best option: parse as path, then extract identifier, macro,
* struct/enum, or just path info from it */
- AST::PathInExpression path = parse_path_in_expression_pratt (tok);
+ AST::PathInExpression path = parse_path_in_expression ();
return null_denotation_path (std::move (path), std::move (outer_attrs),
restrictions);
}
- case SCOPE_RESOLUTION:
- {
- // TODO: fix: this is for global paths, i.e. std::string::whatever
- Error error (tok->get_locus (),
- "found null denotation scope resolution operator, and "
- "have not written handling for it");
- add_error (std::move (error));
-
- return nullptr;
- }
default:
+ if (tok->get_id () == LEFT_SHIFT)
+ {
+ lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
+ tok = lexer.peek_token ();
+ }
+
+ lexer.skip_token ();
return null_denotation_not_path (std::move (tok), std::move
(outer_attrs),
restrictions);
}
@@ -14442,119 +14433,6 @@
Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial (
std::move (outer_attrs), path_locus));
}
-/* Parses a path in expression with the first token passed as a parameter (as
- * it is skipped in token stream). Note that this only parses segment-first
- * paths, not global ones. */
-template <typename ManagedTokenSource>
-AST::PathInExpression
-Parser<ManagedTokenSource>::parse_path_in_expression_pratt (const_TokenPtr tok)
-{
- // HACK-y way of making up for pratt-parsing consuming first token
-
- // DEBUG
- rust_debug ("current peek token when starting path pratt parse: '%s'",
- lexer.peek_token ()->get_token_description ());
-
- // create segment vector
- std::vector<AST::PathExprSegment> segments;
-
- std::string initial_str;
-
- switch (tok->get_id ())
- {
- case IDENTIFIER:
- initial_str = tok->get_str ();
- break;
- case SUPER:
- initial_str = Values::Keywords::SUPER;
- break;
- case SELF:
- initial_str = Values::Keywords::SELF;
- break;
- case SELF_ALIAS:
- initial_str = Values::Keywords::SELF_ALIAS;
- break;
- case CRATE:
- initial_str = Values::Keywords::CRATE;
- break;
- case DOLLAR_SIGN:
- if (lexer.peek_token ()->get_id () == CRATE)
- {
- initial_str = "$crate";
- break;
- }
- gcc_fallthrough ();
- default:
- add_error (Error (tok->get_locus (),
- "unrecognised token %qs in path in expression",
- tok->get_token_description ()));
-
- return AST::PathInExpression::create_error ();
- }
-
- // parse required initial segment
- AST::PathExprSegment initial_segment (initial_str, tok->get_locus ());
- // parse generic args (and turbofish), if they exist
- /* use lookahead to determine if they actually exist (don't want to
- * accidently parse over next ident segment) */
- if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
- && lexer.peek_token (1)->get_id () == LEFT_ANGLE)
- {
- // skip scope resolution
- lexer.skip_token ();
-
- AST::GenericArgs generic_args = parse_path_generic_args ();
-
- initial_segment
- = AST::PathExprSegment (AST::PathIdentSegment (initial_str,
- tok->get_locus ()),
- tok->get_locus (), std::move (generic_args));
- }
- if (initial_segment.is_error ())
- {
- // skip after somewhere?
- // don't necessarily throw error but yeah
-
- // DEBUG
- rust_debug ("initial segment is error - returning null");
-
- return AST::PathInExpression::create_error ();
- }
- segments.push_back (std::move (initial_segment));
-
- // parse optional segments (as long as scope resolution operator exists)
- const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () == SCOPE_RESOLUTION)
- {
- // skip scope resolution operator
- lexer.skip_token ();
-
- // parse the actual segment - it is an error if it doesn't exist now
- AST::PathExprSegment segment = parse_path_expr_segment ();
- if (segment.is_error ())
- {
- // skip after somewhere?
- Error error (t->get_locus (),
- "could not parse path expression segment");
- add_error (std::move (error));
-
- return AST::PathInExpression::create_error ();
- }
-
- segments.push_back (std::move (segment));
-
- t = lexer.peek_token ();
- }
-
- // DEBUG:
- rust_debug (
- "current token (just about to return path to null denotation): '%s'",
- lexer.peek_token ()->get_token_description ());
-
- return AST::PathInExpression (std::move (segments), {}, tok->get_locus (),
- false);
-}
-
// Parses a closure expression with pratt parsing (from null denotation).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ClosureExpr>
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index fa9c909338b..228b9fecd98 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -397,7 +397,7 @@ private:
AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
- null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec
(),
+ null_denotation (AST::AttrVec outer_attrs = AST::AttrVec (),
ParseRestrictions restrictions = ParseRestrictions ());
std::unique_ptr<AST::Expr>
null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs,
@@ -602,7 +602,6 @@ private:
std::unique_ptr<AST::CallExpr>
parse_struct_expr_tuple_partial (AST::PathInExpression path,
AST::AttrVec outer_attrs);
- AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok);
std::unique_ptr<AST::ClosureExpr>
parse_closure_expr_pratt (const_TokenPtr tok,
AST::AttrVec outer_attrs = AST::AttrVec ());
diff --git a/gcc/testsuite/rust/compile/global-path-array.rs
b/gcc/testsuite/rust/compile/global-path-array.rs
new file mode 100644
index 00000000000..c3aa0249563
--- /dev/null
+++ b/gcc/testsuite/rust/compile/global-path-array.rs
@@ -0,0 +1,5 @@
+const X: i32 = 1;
+
+pub fn foo() -> [i32; 1] {
+ [::X]
+}
--
2.50.1