@@ -186,44 +186,70 @@ struct primary_expression_node
186
186
187
187
188
188
struct literal_node {
189
- token const * literal = {};
190
- token const * user_defined_suffix = {};
189
+ // A literal is represented as a sequence of tokens:
190
+ // - length 1: a literal (most common)
191
+ // - length 2: a literal and a user-defined suffix
192
+ // - length >= 2: a series of one or more of either of the above for string literals
193
+ std::vector <token const *> pieces = {};
191
194
192
195
// API
193
196
//
194
197
auto get_token () const
195
198
-> token const *
196
199
{
197
- return literal;
200
+ assert (!pieces.empty ());
201
+ return pieces.front ();
198
202
}
199
203
200
204
auto to_string () const
201
205
-> std::string
202
206
{
203
- assert (literal);
204
- auto ret = literal->to_string ();
205
- if (user_defined_suffix) {
206
- ret += user_defined_suffix->to_string ();
207
+ assert (!pieces.empty ());
208
+ auto ret = std::string{};
209
+
210
+ for (bool first = true ; auto p : pieces)
211
+ {
212
+ assert (p);
213
+
214
+ // Add a space to non-first pieces that start with " (i.e., not a UDL suffix)
215
+ if (
216
+ !std::exchange (first, false )
217
+ && p->as_string_view ().starts_with (" \" " )
218
+ )
219
+ {
220
+ ret += " " ;
221
+ }
222
+
223
+ ret += *p;
207
224
}
225
+
208
226
return ret;
209
227
}
210
228
229
+ auto has_user_defined_suffix ()
230
+ -> bool
231
+ {
232
+ return
233
+ std::ssize (pieces) > 1
234
+ && !pieces[1 ]->as_string_view ().starts_with (" \" " )
235
+ ;
236
+ }
237
+
211
238
// Internals
212
239
//
213
240
auto position () const
214
241
-> source_position
215
242
{
216
- assert (literal );
217
- return literal ->position ();
243
+ assert (!pieces. empty () );
244
+ return get_token () ->position ();
218
245
}
219
246
220
247
auto visit (auto & v, int depth) -> void
221
248
{
222
249
v.start (*this , depth);
223
- assert (literal);
224
- literal->visit (v, depth+1 );
225
- if (user_defined_suffix) {
226
- user_defined_suffix->visit (v, depth+1 );
250
+ for (auto p : pieces) {
251
+ assert (p);
252
+ p->visit (v, depth+1 );
227
253
}
228
254
v.end (*this , depth);
229
255
}
@@ -4617,18 +4643,7 @@ auto pretty_print_visualize(primary_expression_node const& n, int indent)
4617
4643
auto pretty_print_visualize (literal_node const & n, int )
4618
4644
-> std::string
4619
4645
{
4620
- // TODO: This is an initial visualizer implementation, and still
4621
- // skips a few rarer things (such as raw string literals)
4622
-
4623
- assert (n.literal );
4624
-
4625
- auto ret = n.literal ->to_string ();
4626
-
4627
- if (n.user_defined_suffix ) {
4628
- ret += n.user_defined_suffix ->as_string_view ();
4629
- }
4630
-
4631
- return ret;
4646
+ return n.to_string ();
4632
4647
}
4633
4648
4634
4649
@@ -6908,12 +6923,26 @@ class parser
6908
6923
{
6909
6924
if (is_literal (curr ().type ())) {
6910
6925
auto n = std::make_unique<literal_node>();
6911
- n->literal = &curr ();
6926
+ n->pieces . push_back ( &curr () );
6912
6927
next ();
6913
6928
if (curr ().type () == lexeme::UserDefinedLiteralSuffix) {
6914
- n->user_defined_suffix = &curr ();
6929
+ n->pieces . push_back ( &curr () );
6915
6930
next ();
6916
6931
}
6932
+
6933
+ // String literals can have multiple chunks, such as "xyzzy" "plugh"
6934
+ // (in Cpp2 these are merged in the preprocessor, in Cpp2 they're in the grammar)
6935
+ if (n->pieces .front ()->type () == lexeme::StringLiteral) {
6936
+ while (curr ().type () == lexeme::StringLiteral) {
6937
+ n->pieces .push_back (&curr ());
6938
+ next ();
6939
+ if (curr ().type () == lexeme::UserDefinedLiteralSuffix) {
6940
+ n->pieces .push_back (&curr ());
6941
+ next ();
6942
+ }
6943
+ }
6944
+ }
6945
+
6917
6946
return n;
6918
6947
}
6919
6948
return {};
0 commit comments