@@ -37,39 +37,42 @@ struct FormatArgsParseError
37
37
} kind;
38
38
};
39
39
40
- static tl::expected<FormatArgsInput, FormatArgsParseError>
41
- format_args_parse_arguments (AST::MacroInvocData &invoc)
40
+ static inline tl::expected<std::string, AST::Fragment>
41
+ format_args_parse_expr (location_t invoc_locus, AST::MacroInvocData &invoc,
42
+ Parser<MacroInvocLexer> &parser,
43
+ BuiltinMacro macro_kind)
42
44
{
43
- MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
44
- Parser<MacroInvocLexer> parser (lex);
45
-
46
- // TODO: check if EOF - return that format_args!() requires at least one
47
- // argument
48
-
49
- auto args = AST::FormatArguments ();
50
- auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
51
- std::unique_ptr<AST::Expr> format_expr = nullptr ;
45
+ std::unique_ptr<AST::Expr> format_expr = parser.parse_expr ();
46
+ rust_assert (format_expr);
52
47
53
- // TODO: Handle the case where we're not parsing a string literal (macro
54
- // invocation for e.g.)
55
- switch (parser.peek_current_token ()->get_id ())
48
+ if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation)
56
49
{
57
- case STRING_LITERAL:
58
- case RAW_STRING_LITERAL:
59
- format_expr = parser.parse_literal_expr ();
60
- default :
61
- // do nothing
62
- ;
50
+ std::vector<std::unique_ptr<AST::MacroInvocation>> pending;
51
+ pending.emplace_back (
52
+ static_cast <AST::MacroInvocation *> (format_expr.release ()));
53
+ return tl::unexpected (
54
+ make_eager_builtin_invocation (macro_kind, invoc_locus,
55
+ invoc.get_delim_tok_tree (),
56
+ std::move (pending)));
63
57
}
64
58
65
- rust_assert (format_expr);
66
-
67
59
// TODO(Arthur): Clean this up - if we haven't parsed a string literal but a
68
60
// macro invocation, what do we do here? return a tl::unexpected?
69
- auto format_str = static_cast <AST::LiteralExpr &> (*format_expr)
70
- .get_literal ()
71
- .as_string ();
61
+ rust_assert (format_expr->is_literal ());
62
+ return static_cast <AST::LiteralExpr &> (*format_expr)
63
+ .get_literal ()
64
+ .as_string ();
65
+ }
66
+
67
+ static inline tl::expected<AST::FormatArguments, FormatArgsParseError>
68
+ format_args_parse_arguments (AST::MacroInvocData &invoc,
69
+ Parser<MacroInvocLexer> &parser,
70
+ TokenId last_token_id)
71
+ {
72
+ // TODO: check if EOF - return that format_args!() requires at least one
73
+ // argument
72
74
75
+ auto args = AST::FormatArguments ();
73
76
// TODO: Allow implicit captures ONLY if the the first arg is a string literal
74
77
// and not a macro invocation
75
78
@@ -126,7 +129,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
126
129
// we need to skip commas, don't we?
127
130
}
128
131
129
- return FormatArgsInput{ std::move (format_str), std::move ( args)} ;
132
+ return args;
130
133
}
131
134
132
135
tl::optional<AST::Fragment>
@@ -135,9 +138,24 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
135
138
AST::InvocKind semicolon,
136
139
AST::FormatArgs::Newline nl)
137
140
{
138
- auto input = format_args_parse_arguments (invoc);
141
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
142
+ Parser<MacroInvocLexer> parser (lex);
143
+
144
+ auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
145
+
146
+ auto format_str = format_args_parse_expr (invoc_locus, invoc, parser,
147
+ nl == AST::FormatArgs::Newline::Yes
148
+ ? BuiltinMacro::FormatArgsNl
149
+ : BuiltinMacro::FormatArgs);
150
+
151
+ if (!format_str)
152
+ {
153
+ return std::move (format_str.error ());
154
+ }
155
+
156
+ auto args = format_args_parse_arguments (invoc, parser, last_token_id);
139
157
140
- if (!input )
158
+ if (!args )
141
159
{
142
160
rust_error_at (invoc_locus,
143
161
" could not parse arguments to %<format_args!()%>" );
@@ -173,7 +191,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
173
191
174
192
bool append_newline = nl == AST::FormatArgs::Newline::Yes;
175
193
176
- auto fmt_str = std::move (input-> format_str );
194
+ auto fmt_str = std::move (format_str. value () );
177
195
if (append_newline)
178
196
fmt_str += ' \n ' ;
179
197
@@ -189,7 +207,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
189
207
// for creating the `template`
190
208
191
209
auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces),
192
- std::move (input-> args ));
210
+ std::move (args. value () ));
193
211
194
212
auto expanded
195
213
= Fmt::expand_format_args (fmt_args_node,
0 commit comments