Line data Source code
1 : // Copyright (C) 2025-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : /* DO NOT INCLUDE ANYWHERE - this is automatically included
20 : * by rust-parse-impl.h
21 : * This is also the reason why there are no include guards. */
22 :
23 : #include "rust-parse.h"
24 : #include "rust-parse-error.h"
25 : #include "expected.h"
26 :
27 : namespace Rust {
28 :
29 : /* Parses a TokenTree syntactical production. This is either a delimited token
30 : * tree or a non-delimiter token. */
31 : template <typename ManagedTokenSource>
32 : tl::expected<std::unique_ptr<AST::TokenTree>, Parse::Error::Node>
33 66514 : Parser<ManagedTokenSource>::parse_token_tree ()
34 : {
35 66514 : const_TokenPtr t = lexer.peek_token ();
36 :
37 66514 : switch (t->get_id ())
38 : {
39 5510 : case LEFT_PAREN:
40 : case LEFT_SQUARE:
41 : case LEFT_CURLY:
42 : {
43 : // Parse delimited token tree
44 5510 : auto delim_token_tree = parse_delim_token_tree ();
45 5510 : if (!delim_token_tree)
46 : return tl::unexpected<Parse::Error::Node> (
47 2 : Parse::Error::Node::CHILD_ERROR);
48 :
49 : // TODO: use move rather than copy constructor
50 5508 : return std::unique_ptr<AST::DelimTokenTree> (
51 5508 : new AST::DelimTokenTree (delim_token_tree.value ()));
52 5510 : }
53 2 : case RIGHT_PAREN:
54 : case RIGHT_SQUARE:
55 : case RIGHT_CURLY:
56 : // error - should not be called when this a token
57 2 : add_error (Error (t->get_locus (), "unexpected closing delimiter %qs",
58 : t->get_token_description ()));
59 :
60 4 : add_error (Error (Error::Kind::Hint, t->get_locus (),
61 2 : "token tree requires either paired delimiters or "
62 : "non-delimiter tokens"));
63 :
64 2 : lexer.skip_token ();
65 2 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
66 61002 : default:
67 : // parse token itself as TokenTree
68 61002 : lexer.skip_token ();
69 61002 : return std::unique_ptr<AST::Token> (new AST::Token (std::move (t)));
70 : }
71 66514 : }
72 :
73 : // Parses a delimited token tree
74 : template <typename ManagedTokenSource>
75 : tl::expected<AST::DelimTokenTree, Parse::Error::Node>
76 19736 : Parser<ManagedTokenSource>::parse_delim_token_tree ()
77 : {
78 19736 : const_TokenPtr t = lexer.peek_token ();
79 19736 : lexer.skip_token ();
80 19736 : location_t initial_loc = t->get_locus ();
81 :
82 : // save delim type to ensure it is reused later
83 19736 : AST::DelimType delim_type = AST::PARENS;
84 :
85 : // Map tokens to DelimType
86 19736 : switch (t->get_id ())
87 : {
88 : case LEFT_PAREN:
89 : delim_type = AST::PARENS;
90 : break;
91 499 : case LEFT_SQUARE:
92 499 : delim_type = AST::SQUARE;
93 499 : break;
94 2685 : case LEFT_CURLY:
95 2685 : delim_type = AST::CURLY;
96 2685 : break;
97 2 : default:
98 2 : add_error (Error (t->get_locus (),
99 : "unexpected token %qs - expecting delimiters (for a "
100 : "delimited token tree)",
101 : t->get_token_description ()));
102 :
103 2 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
104 : }
105 :
106 : // parse actual token tree vector - 0 or more
107 19734 : std::vector<std::unique_ptr<AST::TokenTree>> token_trees_in_tree;
108 19734 : auto delim_open
109 19734 : = std::unique_ptr<AST::Token> (new AST::Token (std::move (t)));
110 19734 : token_trees_in_tree.push_back (std::move (delim_open));
111 :
112 : // repeat loop until finding the matching delimiter
113 19734 : t = lexer.peek_token ();
114 82261 : while (!Parse::Utils::token_id_matches_delims (t->get_id (), delim_type)
115 82259 : && t->get_id () != END_OF_FILE)
116 : {
117 62527 : auto tok_tree = parse_token_tree ();
118 62527 : if (!tok_tree)
119 : return tl::unexpected<Parse::Error::Node> (
120 2 : Parse::Error::Node::CHILD_ERROR);
121 :
122 62525 : token_trees_in_tree.push_back (std::move (tok_tree.value ()));
123 :
124 : // lexer.skip_token();
125 62525 : t = lexer.peek_token ();
126 : }
127 19732 : auto delim_close
128 19732 : = std::unique_ptr<AST::Token> (new AST::Token (std::move (t)));
129 19732 : token_trees_in_tree.push_back (std::move (delim_close));
130 :
131 19732 : AST::DelimTokenTree token_tree (delim_type, std::move (token_trees_in_tree),
132 : initial_loc);
133 :
134 : // parse end delimiters
135 19732 : t = lexer.peek_token ();
136 :
137 19732 : if (Parse::Utils::token_id_matches_delims (t->get_id (), delim_type))
138 : {
139 : // tokens match opening delimiter, so skip.
140 19725 : lexer.skip_token ();
141 19725 : return token_tree;
142 : }
143 : else
144 : {
145 : // tokens don't match opening delimiters, so produce error
146 7 : Error error (t->get_locus (),
147 : "unexpected token %qs - expecting closing delimiter %qs "
148 : "(for a delimited token tree)",
149 : t->get_token_description (),
150 : (delim_type == AST::PARENS
151 : ? ")"
152 : : (delim_type == AST::SQUARE ? "]" : "}")));
153 7 : add_error (std::move (error));
154 :
155 7 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
156 7 : }
157 19734 : }
158 :
159 : } // namespace Rust
|