From: Owen Avery Date: Thu, 21 Aug 2025 04:05:06 +0000 (-0400) Subject: gccrs: Remove Parser::parse_path_in_expression_pratt X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d81a412a6dc5fdb297fd77efda3385723cc4d675;p=thirdparty%2Fgcc.git gccrs: Remove Parser::parse_path_in_expression_pratt 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 --- 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::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 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::parse_expr (AST::AttrVec outer_attrs, /* Determines action to take when finding token at beginning of expression. */ template std::unique_ptr -Parser::null_denotation (const_TokenPtr tok, - AST::AttrVec outer_attrs, +Parser::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::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::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::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 -AST::PathInExpression -Parser::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 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 std::unique_ptr 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 - 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 null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs, @@ -602,7 +602,6 @@ private: std::unique_ptr 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 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] +}