Skip to content

Commit 058959d

Browse files
powerboat9philberty
authored andcommitted
Improve parsing of simple paths
gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_simple_path): Be more careful about skipping SCOPE_RESOLUTION tokens. (Parser::parse_simple_path_segment): Allow parsing from a starting offset. (Parser::parse_use_tree): Handle a non-skipped SCOPE_RESOLUTION token. * parse/rust-parse.h (Parser::parse_simple_path_segment): Add parameter for parsing from a starting offset. gcc/testsuite/ChangeLog: * rust/compile/parse_simple_path_fail_1.rs: New test. * rust/compile/parse_simple_path_fail_2.rs: New test. Signed-off-by: Owen Avery <[email protected]>
1 parent 293b7a3 commit 058959d

File tree

4 files changed

+85
-67
lines changed

4 files changed

+85
-67
lines changed

gcc/rust/parse/rust-parse-impl.h

Lines changed: 72 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -654,10 +654,7 @@ Parser<ManagedTokenSource>::parse_simple_path ()
654654
// Parse all other simple path segments
655655
while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
656656
{
657-
// Skip scope resolution operator
658-
lexer.skip_token ();
659-
660-
AST::SimplePathSegment new_segment = parse_simple_path_segment ();
657+
AST::SimplePathSegment new_segment = parse_simple_path_segment (1);
661658

662659
// Return path as currently constructed if segment in error state.
663660
if (new_segment.is_error ())
@@ -685,35 +682,36 @@ Parser<ManagedTokenSource>::parse_simple_path ()
685682
}
686683

687684
/* Parses a single SimplePathSegment (does not handle the scope resolution
688-
* operators) */
685+
* operators)
686+
* Starts parsing at an offset of base_peek */
689687
template <typename ManagedTokenSource>
690688
AST::SimplePathSegment
691-
Parser<ManagedTokenSource>::parse_simple_path_segment ()
689+
Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek)
692690
{
693691
using namespace Values;
694-
const_TokenPtr t = lexer.peek_token ();
692+
const_TokenPtr t = lexer.peek_token (base_peek);
695693
switch (t->get_id ())
696694
{
697695
case IDENTIFIER:
698-
lexer.skip_token ();
696+
lexer.skip_token (base_peek);
699697

700698
return AST::SimplePathSegment (t->get_str (), t->get_locus ());
701699
case SUPER:
702-
lexer.skip_token ();
700+
lexer.skip_token (base_peek);
703701

704702
return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ());
705703
case SELF:
706-
lexer.skip_token ();
704+
lexer.skip_token (base_peek);
707705

708706
return AST::SimplePathSegment (Keywords::SELF, t->get_locus ());
709707
case CRATE:
710-
lexer.skip_token ();
708+
lexer.skip_token (base_peek);
711709

712710
return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ());
713711
case DOLLAR_SIGN:
714-
if (lexer.peek_token (1)->get_id () == CRATE)
712+
if (lexer.peek_token (base_peek + 1)->get_id () == CRATE)
715713
{
716-
lexer.skip_token (1);
714+
lexer.skip_token (base_peek + 1);
717715

718716
return AST::SimplePathSegment ("$crate", t->get_locus ());
719717
}
@@ -2807,58 +2805,10 @@ Parser<ManagedTokenSource>::parse_use_tree ()
28072805
}
28082806
else
28092807
{
2810-
/* Due to aforementioned implementation issues, the trailing :: token is
2811-
* consumed by the path, so it can not be used as a disambiguator.
2812-
* NOPE, not true anymore - TODO what are the consequences of this? */
2813-
28142808
const_TokenPtr t = lexer.peek_token ();
2809+
28152810
switch (t->get_id ())
28162811
{
2817-
case ASTERISK:
2818-
// glob UseTree type
2819-
lexer.skip_token ();
2820-
2821-
return std::unique_ptr<AST::UseTreeGlob> (
2822-
new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
2823-
std::move (path), locus));
2824-
case LEFT_CURLY:
2825-
{
2826-
// nested tree UseTree type
2827-
lexer.skip_token ();
2828-
2829-
std::vector<std::unique_ptr<AST::UseTree>> use_trees;
2830-
2831-
// TODO: think of better control structure
2832-
const_TokenPtr t = lexer.peek_token ();
2833-
while (t->get_id () != RIGHT_CURLY)
2834-
{
2835-
std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
2836-
if (use_tree == nullptr)
2837-
{
2838-
break;
2839-
}
2840-
2841-
use_trees.push_back (std::move (use_tree));
2842-
2843-
if (lexer.peek_token ()->get_id () != COMMA)
2844-
break;
2845-
2846-
lexer.skip_token ();
2847-
t = lexer.peek_token ();
2848-
}
2849-
2850-
// skip end curly delimiter
2851-
if (!skip_token (RIGHT_CURLY))
2852-
{
2853-
// skip after somewhere?
2854-
return nullptr;
2855-
}
2856-
2857-
return std::unique_ptr<AST::UseTreeList> (
2858-
new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
2859-
std::move (path), std::move (use_trees),
2860-
locus));
2861-
}
28622812
case AS:
28632813
{
28642814
// rebind UseTree type
@@ -2899,16 +2849,72 @@ Parser<ManagedTokenSource>::parse_use_tree ()
28992849

29002850
// don't skip semicolon - handled in parse_use_tree
29012851
// lexer.skip_token();
2902-
2903-
return std::unique_ptr<AST::UseTreeRebind> (
2904-
new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
2905-
locus));
29062852
case COMMA:
29072853
case RIGHT_CURLY:
29082854
// this may occur in recursive calls - assume it is ok and ignore it
29092855
return std::unique_ptr<AST::UseTreeRebind> (
29102856
new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
29112857
locus));
2858+
case SCOPE_RESOLUTION:
2859+
// keep going
2860+
break;
2861+
default:
2862+
add_error (Error (t->get_locus (),
2863+
"unexpected token %qs in use tree with valid path",
2864+
t->get_token_description ()));
2865+
return nullptr;
2866+
}
2867+
2868+
skip_token ();
2869+
t = lexer.peek_token ();
2870+
2871+
switch (t->get_id ())
2872+
{
2873+
case ASTERISK:
2874+
// glob UseTree type
2875+
lexer.skip_token ();
2876+
2877+
return std::unique_ptr<AST::UseTreeGlob> (
2878+
new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
2879+
std::move (path), locus));
2880+
case LEFT_CURLY:
2881+
{
2882+
// nested tree UseTree type
2883+
lexer.skip_token ();
2884+
2885+
std::vector<std::unique_ptr<AST::UseTree>> use_trees;
2886+
2887+
// TODO: think of better control structure
2888+
const_TokenPtr t = lexer.peek_token ();
2889+
while (t->get_id () != RIGHT_CURLY)
2890+
{
2891+
std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
2892+
if (use_tree == nullptr)
2893+
{
2894+
break;
2895+
}
2896+
2897+
use_trees.push_back (std::move (use_tree));
2898+
2899+
if (lexer.peek_token ()->get_id () != COMMA)
2900+
break;
2901+
2902+
lexer.skip_token ();
2903+
t = lexer.peek_token ();
2904+
}
2905+
2906+
// skip end curly delimiter
2907+
if (!skip_token (RIGHT_CURLY))
2908+
{
2909+
// skip after somewhere?
2910+
return nullptr;
2911+
}
2912+
2913+
return std::unique_ptr<AST::UseTreeList> (
2914+
new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
2915+
std::move (path), std::move (use_trees),
2916+
locus));
2917+
}
29122918
default:
29132919
add_error (Error (t->get_locus (),
29142920
"unexpected token %qs in use tree with valid path",

gcc/rust/parse/rust-parse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ template <typename ManagedTokenSource> class Parser
227227

228228
// Path-related
229229
AST::SimplePath parse_simple_path ();
230-
AST::SimplePathSegment parse_simple_path_segment ();
230+
AST::SimplePathSegment parse_simple_path_segment (int base_peek = 0);
231231
AST::TypePath parse_type_path ();
232232
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
233233
AST::PathIdentSegment parse_path_ident_segment ();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub(in crate::) struct S;
2+
// { dg-error "expecting ... but .::. found" "" { target *-*-* } .-1 }
3+
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod A {
2+
struct B;
3+
}
4+
5+
use A{B};
6+
// { dg-error "unexpected token" "" { target *-*-* } .-1 }
7+
// { dg-error "could not parse use tree" "" { target *-*-* } .-2 }
8+
// { dg-error "failed to parse item in crate" "" { target *-*-* } 10 }
9+
// ^^^ TODO: should the above error happen at line 10?

0 commit comments

Comments
 (0)