1 /*
2     This file is part of Magnum.
3 
4     Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
5               Vladimír Vondruš <mosra@centrum.cz>
6 
7     Permission is hereby granted, free of charge, to any person obtaining a
8     copy of this software and associated documentation files (the "Software"),
9     to deal in the Software without restriction, including without limitation
10     the rights to use, copy, modify, merge, publish, distribute, sublicense,
11     and/or sell copies of the Software, and to permit persons to whom the
12     Software is furnished to do so, subject to the following conditions:
13 
14     The above copyright notice and this permission notice shall be included
15     in all copies or substantial portions of the Software.
16 
17     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23     DEALINGS IN THE SOFTWARE.
24 */
25 
26 #include <tuple>
27 #include <Corrade/TestSuite/Tester.h>
28 #include <Corrade/Utility/DebugStl.h>
29 
30 #include "Magnum/OpenDdl/Document.h"
31 #include "Magnum/OpenDdl/Property.h"
32 #include "Magnum/OpenDdl/Implementation/Parsers.h"
33 
34 namespace Magnum { namespace OpenDdl { namespace Test { namespace {
35 
36 struct ParsersTest: TestSuite::Tester {
37     explicit ParsersTest();
38 
39     void equals();
40     void findLastOf();
41     void whitespace();
42     void onelineComment();
43     void multilineComment();
44 
45     void escapedCharInvalid();
46     void escapedChar();
47     void escapedCharHex();
48 
49     void escapedUnicodeInvalid();
50     void escapedUnicode4();
51     void escapedUnicode6();
52 
53     void identifierInvalid();
54     void identifier();
55 
56     void boolLiteralInvalid();
57     void boolLiteral();
58 
59     void characterLiteralInvalid();
60     void characterLiteral();
61     void characterLiteralEscaped();
62 
63     void integerLiteralInvalid();
64     void integerLiteral();
65     void integerLiteralChar();
66     void integerLiteralBinary();
67 
68     void floatLiteralInvalid();
69     void floatLiteral();
70     void floatLiteralBinary();
71 
72     void stringLiteralInvalid();
73     void stringLiteralEmpty();
74     void stringLiteral();
75     void stringLiteralEscaped();
76     void stringLiteralConcatenated();
77 
78     void nameLiteralInvalid();
79     void nameLiteral();
80 
81     void referenceLiteralInvalid();
82     void referenceLiteralNull();
83     void referenceLiteral();
84 
85     void typeLiteralInvalid();
86     void typeLiteral();
87 
88     void propertyValueInvalid();
89     void propertyValueBool();
90     void propertyValueIntegral();
91     void propertyValueCharacter();
92     void propertyValueBinary();
93     void propertyValueFloatingPoint();
94     void propertyValueString();
95     void propertyValueReference();
96     void propertyValueReferenceNull();
97     void propertyValueType();
98 };
99 
ParsersTest()100 ParsersTest::ParsersTest() {
101     addTests({&ParsersTest::equals,
102               &ParsersTest::findLastOf,
103               &ParsersTest::whitespace,
104               &ParsersTest::onelineComment,
105               &ParsersTest::multilineComment,
106 
107               &ParsersTest::escapedCharInvalid,
108               &ParsersTest::escapedChar,
109               &ParsersTest::escapedCharHex,
110 
111               &ParsersTest::escapedUnicodeInvalid,
112               &ParsersTest::escapedUnicode4,
113               &ParsersTest::escapedUnicode6,
114 
115               &ParsersTest::identifierInvalid,
116               &ParsersTest::identifier,
117 
118               &ParsersTest::boolLiteralInvalid,
119               &ParsersTest::boolLiteral,
120 
121               &ParsersTest::characterLiteralInvalid,
122               &ParsersTest::characterLiteral,
123               &ParsersTest::characterLiteralEscaped,
124 
125               &ParsersTest::integerLiteralInvalid,
126               &ParsersTest::integerLiteral,
127               &ParsersTest::integerLiteralChar,
128               &ParsersTest::integerLiteralBinary,
129 
130               &ParsersTest::floatLiteralInvalid,
131               &ParsersTest::floatLiteral,
132               &ParsersTest::floatLiteralBinary,
133 
134               &ParsersTest::stringLiteralInvalid,
135               &ParsersTest::stringLiteralEmpty,
136               &ParsersTest::stringLiteral,
137               &ParsersTest::stringLiteralEscaped,
138               &ParsersTest::stringLiteralConcatenated,
139 
140               &ParsersTest::nameLiteralInvalid,
141               &ParsersTest::nameLiteral,
142 
143               &ParsersTest::referenceLiteralInvalid,
144               &ParsersTest::referenceLiteralNull,
145               &ParsersTest::referenceLiteral,
146 
147               &ParsersTest::typeLiteralInvalid,
148               &ParsersTest::typeLiteral,
149 
150               &ParsersTest::propertyValueInvalid,
151               &ParsersTest::propertyValueBool,
152               &ParsersTest::propertyValueIntegral,
153               &ParsersTest::propertyValueCharacter,
154               &ParsersTest::propertyValueBinary,
155               &ParsersTest::propertyValueFloatingPoint,
156               &ParsersTest::propertyValueString,
157               &ParsersTest::propertyValueReference,
158               &ParsersTest::propertyValueReferenceNull,
159               &ParsersTest::propertyValueType});
160 }
161 
162 #define VERIFY_PARSED(e, data, i, parsed) \
163     CORRADE_COMPARE(e.error, Implementation::ParseErrorType::NoError); \
164     CORRADE_VERIFY(i >= data.begin()); \
165     CORRADE_COMPARE((std::string{data.begin(), std::size_t(i - data.begin())}), parsed);
166 
equals()167 void ParsersTest::equals() {
168     CharacterLiteral a{"HelloWorld"};
169     CharacterLiteral b{"Hello"};
170 
171     CORRADE_VERIFY(Implementation::equals(a, a));
172     CORRADE_VERIFY(!Implementation::equals(a, b));
173     CORRADE_VERIFY(!Implementation::equals(b, a));
174 }
175 
findLastOf()176 void ParsersTest::findLastOf() {
177     /* I'm too lazy to create another VERIFY_SUFFIX_PARSED(), so I'll test to
178        prefix instead */
179     CharacterLiteral a{"$hello%world"};
180     auto ai = Implementation::findLastOf(a, "$%");
181     VERIFY_PARSED(Implementation::ParseError{}, a, ai, "$hello");
182 
183     CharacterLiteral b{"%hello$world"};
184     auto bi = Implementation::findLastOf(b, "$%");
185     VERIFY_PARSED(Implementation::ParseError{}, b, bi, "%hello");
186 
187     Containers::ArrayView<const char> c{"%", 0};
188     auto ci = Implementation::findLastOf({c, 0}, "$%");
189     VERIFY_PARSED(Implementation::ParseError{}, c, ci, "");
190 }
191 
whitespace()192 void ParsersTest::whitespace() {
193     CharacterLiteral a{""};
194     auto ai = Implementation::whitespace(a);
195     VERIFY_PARSED(Implementation::ParseError{}, a, ai, "");
196 
197     /* Just whitespace */
198     CharacterLiteral b{"\n  "};
199     auto bi = Implementation::whitespace(b);
200     VERIFY_PARSED(Implementation::ParseError{}, b, bi, "\n  ");
201 
202     /* Whitespace and something after */
203     CharacterLiteral c{" \b \t \n  X"};
204     auto ci = Implementation::whitespace(c);
205     VERIFY_PARSED(Implementation::ParseError{}, c, ci, " \b \t \n  ");
206 }
207 
onelineComment()208 void ParsersTest::onelineComment() {
209     CharacterLiteral a{" \b \t // comment \nX"};
210     auto ai = Implementation::whitespace(a);
211     VERIFY_PARSED(Implementation::ParseError{}, a, ai, " \b \t // comment \n");
212 
213     CharacterLiteral b{" \b \t // comment /* other comment \n*/ \nX"};
214     auto bi = Implementation::whitespace(b);
215     VERIFY_PARSED(Implementation::ParseError{}, b, bi, " \b \t // comment /* other comment \n");
216 }
217 
multilineComment()218 void ParsersTest::multilineComment() {
219     CharacterLiteral a{" \b \t /* comment \n bla \n comment */X"};
220     auto ai = Implementation::whitespace(a);
221     VERIFY_PARSED(Implementation::ParseError{}, a, ai, " \b \t /* comment \n bla \n comment */");
222 
223     CharacterLiteral b{" \b \t /* comment \n // bla \n comment */X"};
224     auto bi = Implementation::whitespace(b);
225     VERIFY_PARSED(Implementation::ParseError{}, b, bi, " \b \t /* comment \n // bla \n comment */");
226 }
227 
escapedCharInvalid()228 void ParsersTest::escapedCharInvalid() {
229     Implementation::ParseError error;
230 
231     CORRADE_VERIFY(!Implementation::escapedChar(CharacterLiteral{"\\"}, error).first);
232     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
233 
234     CORRADE_VERIFY(!Implementation::escapedChar(CharacterLiteral{"\\h"}, error).first);
235     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
236 
237     CORRADE_VERIFY(!Implementation::escapedChar(CharacterLiteral{"\\x1"}, error).first);
238     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
239 }
240 
escapedChar()241 void ParsersTest::escapedChar() {
242     CharacterLiteral a{"\\nX"};
243 
244     Implementation::ParseError error;
245     const char* ai;
246     char c;
247     std::tie(ai, c) = Implementation::escapedChar(a, error);
248     VERIFY_PARSED(error, a, ai, "\\n");
249     CORRADE_COMPARE(c, '\n');
250 }
251 
escapedCharHex()252 void ParsersTest::escapedCharHex() {
253     CharacterLiteral a{"\\x0AX"};
254 
255     Implementation::ParseError error;
256     const char* ai;
257     char c;
258     std::tie(ai, c) = Implementation::escapedChar(a, error);
259     VERIFY_PARSED(error, a, ai, "\\x0A");
260     CORRADE_COMPARE(c, '\n');
261 }
262 
escapedUnicodeInvalid()263 void ParsersTest::escapedUnicodeInvalid() {
264     Implementation::ParseError error;
265     std::string s;
266 
267     CORRADE_VERIFY(!Implementation::escapedUnicode(CharacterLiteral{"\\"}, s, error));
268     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
269 
270     CORRADE_VERIFY(!Implementation::escapedUnicode(CharacterLiteral{"\\u123"}, s, error));
271     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
272 
273     CORRADE_VERIFY(!Implementation::escapedUnicode(CharacterLiteral{"\\U12345"}, s, error));
274     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidEscapeSequence);
275 }
276 
escapedUnicode4()277 void ParsersTest::escapedUnicode4() {
278     CharacterLiteral a{"\\u006dX"};
279     Implementation::ParseError error;
280     std::string s;
281     const char* ai = Implementation::escapedUnicode(a, s, error);
282     VERIFY_PARSED(error, a, ai, "\\u006d");
283     CORRADE_EXPECT_FAIL("Not yet implemented.");
284     CORRADE_COMPARE(s, "m");
285 }
286 
escapedUnicode6()287 void ParsersTest::escapedUnicode6() {
288     CharacterLiteral a{"\\U00006DX"};
289     Implementation::ParseError error;
290     std::string s;
291     const char* ai = Implementation::escapedUnicode(a, s, error);
292     VERIFY_PARSED(error, a, ai, "\\U00006D");
293     CORRADE_EXPECT_FAIL("Not yet implemented.");
294     CORRADE_COMPARE(s, "m");
295 }
296 
identifierInvalid()297 void ParsersTest::identifierInvalid() {
298     Implementation::ParseError error;
299 
300     CORRADE_VERIFY(!Implementation::identifier(CharacterLiteral{""}, error));
301     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedIdentifier);
302 
303     CORRADE_VERIFY(!Implementation::identifier(CharacterLiteral{"0"}, error));
304     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidIdentifier);
305 }
306 
identifier()307 void ParsersTest::identifier() {
308     CharacterLiteral a{"my_mesh,"};
309     Implementation::ParseError error;
310     const char* ai = Implementation::identifier(a, error);
311     VERIFY_PARSED(error, a, ai, "my_mesh");
312 }
313 
boolLiteralInvalid()314 void ParsersTest::boolLiteralInvalid() {
315     Implementation::ParseError error;
316 
317     CORRADE_VERIFY(!Implementation::boolLiteral(CharacterLiteral{""}, error).first);
318     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
319 
320     CORRADE_VERIFY(!Implementation::boolLiteral(CharacterLiteral{"TRUE"}, error).first);
321     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
322 }
323 
boolLiteral()324 void ParsersTest::boolLiteral() {
325     CharacterLiteral a{"trueX"};
326 
327     Implementation::ParseError error;
328     const char* ai;
329     bool value;
330     std::tie(ai, value) = Implementation::boolLiteral(a, error);
331     VERIFY_PARSED(error, a, ai, "true");
332     CORRADE_COMPARE(value, true);
333 }
334 
characterLiteralInvalid()335 void ParsersTest::characterLiteralInvalid() {
336     Implementation::ParseError error;
337 
338     CORRADE_VERIFY(!Implementation::characterLiteral(CharacterLiteral{""}, error).first);
339     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidCharacterLiteral);
340 
341     CORRADE_VERIFY(!Implementation::characterLiteral(CharacterLiteral{"'"}, error).first);
342     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidCharacterLiteral);
343 
344     CORRADE_VERIFY(!Implementation::characterLiteral(CharacterLiteral{"'a"}, error).first);
345     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidCharacterLiteral);
346 
347     CORRADE_VERIFY(!Implementation::characterLiteral(CharacterLiteral{"'\n"}, error).first);
348     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidCharacterLiteral);
349 }
350 
characterLiteral()351 void ParsersTest::characterLiteral() {
352     CharacterLiteral a{"'a'X"};
353 
354     Implementation::ParseError error;
355     const char* ai;
356     char value;
357     std::tie(ai, value) = Implementation::characterLiteral(a, error);
358     VERIFY_PARSED(error, a, ai, "'a'");
359     CORRADE_COMPARE(value, 'a');
360 }
361 
characterLiteralEscaped()362 void ParsersTest::characterLiteralEscaped() {
363     CharacterLiteral a{"'\\n'X"};
364 
365     Implementation::ParseError error;
366     const char* ai;
367     char value;
368     std::tie(ai, value) = Implementation::characterLiteral(a, error);
369     VERIFY_PARSED(error, a, ai, "'\\n'");
370     CORRADE_COMPARE(value, '\n');
371 }
372 
integerLiteralInvalid()373 void ParsersTest::integerLiteralInvalid() {
374     Implementation::ParseError error;
375     std::string buffer;
376 
377     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{""}, buffer, error)));
378     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedLiteral);
379 
380     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{"+"}, buffer, error)));
381     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
382 
383     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{"A"}, buffer, error)));
384     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
385 
386     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{"_1"}, buffer, error)));
387     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
388 
389     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{"0b_1"}, buffer, error)));
390     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
391 
392     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<Short>(CharacterLiteral{"32768"}, buffer, error)));
393     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::LiteralOutOfRange);
394 
395     CORRADE_VERIFY(!std::get<0>(Implementation::integralLiteral<UnsignedShort>(CharacterLiteral{"-1"}, buffer, error)));
396     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::LiteralOutOfRange);
397 }
398 
integerLiteral()399 void ParsersTest::integerLiteral() {
400     CharacterLiteral a{"-3_7X"};
401 
402     Implementation::ParseError error;
403     std::string buffer;
404     const char* ai;
405     Short value;
406     Int base;
407     std::tie(ai, value, base) = Implementation::integralLiteral<Short>(a, buffer, error);
408     VERIFY_PARSED(error, a, ai, "-3_7");
409     CORRADE_COMPARE(value, -37);
410     CORRADE_COMPARE(base, 10);
411 }
412 
integerLiteralChar()413 void ParsersTest::integerLiteralChar() {
414     CharacterLiteral a{"+'a'X"};
415 
416     Implementation::ParseError error;
417     std::string buffer;
418     const char* ai;
419     Short value;
420     Int base;
421     std::tie(ai, value, base) = Implementation::integralLiteral<Short>(a, buffer, error);
422     VERIFY_PARSED(error, a, ai, "+'a'");
423     CORRADE_COMPARE(value, 'a');
424     CORRADE_COMPARE(base, 256);
425 }
426 
integerLiteralBinary()427 void ParsersTest::integerLiteralBinary() {
428     CharacterLiteral a{"-0o7_5"};
429 
430     Implementation::ParseError error;
431     std::string buffer;
432     const char* ai;
433     Short value;
434     Int base;
435     std::tie(ai, value, base) = Implementation::integralLiteral<Short>(a, buffer, error);
436     VERIFY_PARSED(error, a, ai, "-0o7_5");
437     CORRADE_COMPARE(value, -075);
438     CORRADE_COMPARE(base, 8);
439 }
440 
floatLiteralInvalid()441 void ParsersTest::floatLiteralInvalid() {
442     Implementation::ParseError error;
443     std::string buffer;
444 
445     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{""}, buffer, error).first);
446     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedLiteral);
447 
448     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{"+"}, buffer, error).first);
449     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
450 
451     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{"A"}, buffer, error).first);
452     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
453 
454     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{"_1"}, buffer, error).first);
455     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
456 
457     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{"."}, buffer, error).first);
458     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
459 
460     CORRADE_VERIFY(!Implementation::floatingPointLiteral<Float>(CharacterLiteral{"0.e-"}, buffer, error).first);
461     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
462 }
463 
floatLiteral()464 void ParsersTest::floatLiteral() {
465     CharacterLiteral a{"-1_.0_0e+5X"};
466 
467     Implementation::ParseError error;
468     std::string buffer;
469     const char* ai;
470     Float value;
471     std::tie(ai, value) = Implementation::floatingPointLiteral<Float>(a, buffer, error);
472     VERIFY_PARSED(error, a, ai, "-1_.0_0e+5");
473     CORRADE_COMPARE(value, -1.0e+5);
474 }
475 
floatLiteralBinary()476 void ParsersTest::floatLiteralBinary() {
477     CharacterLiteral a{"-0xbad_cafe_X"};
478 
479     Implementation::ParseError error;
480     std::string buffer;
481     const char* ai;
482     Float value;
483     std::tie(ai, value) = Implementation::floatingPointLiteral<Float>(a, buffer, error);
484     VERIFY_PARSED(error, a, ai, "-0xbad_cafe_");
485     UnsignedInt v = 0xbadcafe;
486     CORRADE_COMPARE(value, -reinterpret_cast<Float&>(v));
487 }
488 
stringLiteralInvalid()489 void ParsersTest::stringLiteralInvalid() {
490     Implementation::ParseError error;
491 
492     CORRADE_VERIFY(!Implementation::stringLiteral(CharacterLiteral{""}, error).first);
493     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedLiteral);
494 
495     CORRADE_VERIFY(!Implementation::stringLiteral(CharacterLiteral{"\""}, error).first);
496     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::LiteralOutOfRange);
497 
498     CORRADE_VERIFY(!Implementation::stringLiteral(CharacterLiteral{"\"\n\""}, error).first);
499     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
500 }
501 
stringLiteralEmpty()502 void ParsersTest::stringLiteralEmpty() {
503     CharacterLiteral a{"\"\"X"};
504 
505     Implementation::ParseError error;
506     const char* ai;
507     std::string value;
508     std::tie(ai, value) = Implementation::stringLiteral(a, error);
509     VERIFY_PARSED(error, a, ai, "\"\"");
510     CORRADE_COMPARE(value, "");
511 }
512 
stringLiteral()513 void ParsersTest::stringLiteral() {
514     CharacterLiteral a{"\"abc ěšč\"X"};
515 
516     Implementation::ParseError error;
517     const char* ai;
518     std::string value;
519     std::tie(ai, value) = Implementation::stringLiteral(a, error);
520     VERIFY_PARSED(error, a, ai, "\"abc ěšč\"");
521     CORRADE_COMPARE(value, "abc ěšč");
522 }
523 
stringLiteralEscaped()524 void ParsersTest::stringLiteralEscaped() {
525     CharacterLiteral a{"\"abc \\n0\\\" heh\"X"};
526 
527     Implementation::ParseError error;
528     const char* ai;
529     std::string value;
530     std::tie(ai, value) = Implementation::stringLiteral(a, error);
531     VERIFY_PARSED(error, a, ai, "\"abc \\n0\\\" heh\"");
532     CORRADE_COMPARE(value, "abc \n0\" heh");
533 }
534 
stringLiteralConcatenated()535 void ParsersTest::stringLiteralConcatenated() {
536     CharacterLiteral a{"\"abc\" /* comment */ \" ěšč\"X"};
537 
538     Implementation::ParseError error;
539     const char* ai;
540     std::string value;
541     std::tie(ai, value) = Implementation::stringLiteral(a, error);
542     VERIFY_PARSED(error, a, ai, "\"abc\" /* comment */ \" ěšč\"");
543     CORRADE_COMPARE(value, "abc ěšč");
544 }
545 
nameLiteralInvalid()546 void ParsersTest::nameLiteralInvalid() {
547     Implementation::ParseError error;
548 
549     CORRADE_VERIFY(!Implementation::nameLiteral(CharacterLiteral{""}, error).first);
550     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedName);
551 
552     CORRADE_VERIFY(!Implementation::nameLiteral(CharacterLiteral{"a"}, error).first);
553     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidName);
554 
555     CORRADE_VERIFY(!Implementation::nameLiteral(CharacterLiteral{"$"}, error).first);
556     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedIdentifier);
557 }
558 
nameLiteral()559 void ParsersTest::nameLiteral() {
560     CharacterLiteral a{"%my_array,"};
561 
562     Implementation::ParseError error;
563     const char* ai;
564     std::string value;
565     std::tie(ai, value) = Implementation::nameLiteral(a, error);
566     VERIFY_PARSED(error, a, ai, "%my_array");
567     CORRADE_COMPARE(value, "%my_array");
568 }
569 
referenceLiteralInvalid()570 void ParsersTest::referenceLiteralInvalid() {
571     Implementation::ParseError error;
572 
573     CORRADE_VERIFY(!Implementation::referenceLiteral(CharacterLiteral{""}, error).first);
574     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedLiteral);
575 
576     CORRADE_VERIFY(!Implementation::referenceLiteral(CharacterLiteral{"a"}, error).first);
577     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
578 
579     CORRADE_VERIFY(!Implementation::referenceLiteral(CharacterLiteral{"%"}, error).first);
580     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedIdentifier);
581 
582     CORRADE_VERIFY(!Implementation::referenceLiteral(CharacterLiteral{"$%a"}, error).first);
583     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidIdentifier);
584 }
585 
referenceLiteralNull()586 void ParsersTest::referenceLiteralNull() {
587     CharacterLiteral a{"null,"};
588 
589     Implementation::ParseError error;
590     const char* ai;
591     Containers::ArrayView<const char> value;
592     std::tie(ai, value) = Implementation::referenceLiteral(a, error);
593     VERIFY_PARSED(error, a, ai, "null");
594     CORRADE_VERIFY(value.empty());
595 }
596 
referenceLiteral()597 void ParsersTest::referenceLiteral() {
598     CharacterLiteral a{"$my_mesh%my_array,"};
599 
600     Implementation::ParseError error;
601     const char* ai;
602     Containers::ArrayView<const char> value;
603     std::tie(ai, value) = Implementation::referenceLiteral(a, error);
604     VERIFY_PARSED(error, a, ai, "$my_mesh%my_array");
605     CORRADE_COMPARE((std::string{value, value.size()}), "$my_mesh%my_array");
606 }
607 
typeLiteralInvalid()608 void ParsersTest::typeLiteralInvalid() {
609     Implementation::ParseError error;
610 
611     CORRADE_VERIFY(!Implementation::typeLiteral(CharacterLiteral{""}, error).first);
612     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedLiteral);
613 
614     CORRADE_VERIFY(!Implementation::typeLiteral(CharacterLiteral{"boo"}, error).first);
615     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidLiteral);
616 }
617 
typeLiteral()618 void ParsersTest::typeLiteral() {
619     CharacterLiteral a{"unsigned_int16,"};
620 
621     Implementation::ParseError error;
622     const char* ai;
623     Type value;
624     std::tie(ai, value) = Implementation::typeLiteral(a, error);
625     VERIFY_PARSED(error, a, ai, "unsigned_int16");
626     CORRADE_COMPARE(value, Type::UnsignedShort);
627 }
628 
propertyValueInvalid()629 void ParsersTest::propertyValueInvalid() {
630     Implementation::ParseError error;
631     std::string buffer;
632 
633     bool boolValue = {};
634     Int integerValue = {};
635     Float floatingPointValue = {};
636     std::string stringValue;
637     Containers::ArrayView<const char> referenceValue;
638     Type typeValue = {};
639 
640     CORRADE_VERIFY(!Implementation::propertyValue(CharacterLiteral{""}, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error).first);
641     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::ExpectedPropertyValue);
642 
643     CORRADE_VERIFY(!Implementation::propertyValue(CharacterLiteral{"bleh"}, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error).first);
644     CORRADE_COMPARE(error.error, Implementation::ParseErrorType::InvalidPropertyValue);
645 }
646 
propertyValueBool()647 void ParsersTest::propertyValueBool() {
648     CharacterLiteral a{"true,"};
649 
650     Implementation::ParseError error;
651     std::string buffer;
652     bool boolValue = {};
653     Int integerValue = {};
654     Float floatingPointValue = {};
655     std::string stringValue;
656     Containers::ArrayView<const char> referenceValue;
657     Type typeValue = {};
658     const char* ai;
659     Implementation::InternalPropertyType type;
660     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
661     VERIFY_PARSED(error, a, ai, "true");
662     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Bool);
663     CORRADE_COMPARE(boolValue, true);
664 }
665 
propertyValueIntegral()666 void ParsersTest::propertyValueIntegral() {
667     CharacterLiteral a{"17, 0.0"};
668 
669     Implementation::ParseError error;
670     std::string buffer;
671     bool boolValue = {};
672     Int integerValue = {};
673     Float floatingPointValue = {};
674     std::string stringValue;
675     Containers::ArrayView<const char> referenceValue;
676     Type typeValue = {};
677     const char* ai;
678     Implementation::InternalPropertyType type;
679     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
680     VERIFY_PARSED(error, a, ai, "17");
681     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Integral);
682     CORRADE_COMPARE(integerValue, 17);
683 }
684 
propertyValueCharacter()685 void ParsersTest::propertyValueCharacter() {
686     CharacterLiteral a{"'a', 0.0"};
687 
688     Implementation::ParseError error;
689     std::string buffer;
690     bool boolValue = {};
691     Int integerValue = {};
692     Float floatingPointValue = {};
693     std::string stringValue;
694     Containers::ArrayView<const char> referenceValue;
695     Type typeValue = {};
696     const char* ai;
697     Implementation::InternalPropertyType type;
698     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
699     VERIFY_PARSED(error, a, ai, "'a'");
700     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Character);
701     CORRADE_COMPARE(integerValue, 'a');
702 }
703 
propertyValueBinary()704 void ParsersTest::propertyValueBinary() {
705     CharacterLiteral a{"0xff, 0.0"};
706 
707     Implementation::ParseError error;
708     std::string buffer;
709     bool boolValue = {};
710     Int integerValue = {};
711     Float floatingPointValue = {};
712     std::string stringValue;
713     Containers::ArrayView<const char> referenceValue;
714     Type typeValue = {};
715     const char* ai;
716     Implementation::InternalPropertyType type;
717     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
718     VERIFY_PARSED(error, a, ai, "0xff");
719     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Binary);
720     CORRADE_COMPARE(integerValue, 0xff);
721 }
722 
propertyValueFloatingPoint()723 void ParsersTest::propertyValueFloatingPoint() {
724     CharacterLiteral a{"15.0_0,"};
725 
726     Implementation::ParseError error;
727     std::string buffer;
728     bool boolValue = {};
729     Int integerValue = {};
730     Float floatingPointValue = {};
731     std::string stringValue;
732     Containers::ArrayView<const char> referenceValue;
733     Type typeValue = {};
734     const char* ai;
735     Implementation::InternalPropertyType type;
736     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
737     VERIFY_PARSED(error, a, ai, "15.0_0");
738     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Float);
739     CORRADE_COMPARE(floatingPointValue, 15.0f);
740 }
741 
propertyValueString()742 void ParsersTest::propertyValueString() {
743     CharacterLiteral a{"\"hello\","};
744 
745     Implementation::ParseError error;
746     std::string buffer;
747     bool boolValue = {};
748     Int integerValue = {};
749     Float floatingPointValue = {};
750     std::string stringValue;
751     Containers::ArrayView<const char> referenceValue;
752     Type typeValue = {};
753     const char* ai;
754     Implementation::InternalPropertyType type;
755     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
756     VERIFY_PARSED(error, a, ai, "\"hello\"");
757     CORRADE_COMPARE(type, Implementation::InternalPropertyType::String);
758     CORRADE_COMPARE(stringValue, "hello");
759 }
760 
propertyValueReference()761 void ParsersTest::propertyValueReference() {
762     CharacterLiteral a{"%my_array2,"};
763 
764     Implementation::ParseError error;
765     std::string buffer;
766     bool boolValue = {};
767     Int integerValue = {};
768     Float floatingPointValue = {};
769     std::string stringValue;
770     Containers::ArrayView<const char> referenceValue;
771     Type typeValue = {};
772     const char* ai;
773     Implementation::InternalPropertyType type;
774     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
775     VERIFY_PARSED(error, a, ai, "%my_array2");
776     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Reference);
777     CORRADE_COMPARE((std::string{referenceValue, referenceValue.size()}), "%my_array2");
778 }
779 
propertyValueReferenceNull()780 void ParsersTest::propertyValueReferenceNull() {
781     CharacterLiteral a{"null,"};
782 
783     Implementation::ParseError error;
784     std::string buffer;
785     bool boolValue = {};
786     Int integerValue = {};
787     Float floatingPointValue = {};
788     std::string stringValue;
789     Containers::ArrayView<const char> referenceValue;
790     Type typeValue = {};
791     const char* ai;
792     Implementation::InternalPropertyType type;
793     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
794     VERIFY_PARSED(error, a, ai, "null");
795     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Reference);
796     CORRADE_VERIFY(referenceValue.empty());
797 }
798 
propertyValueType()799 void ParsersTest::propertyValueType() {
800     CharacterLiteral a{"float,"};
801 
802     Implementation::ParseError error;
803     std::string buffer;
804     bool boolValue = {};
805     Int integerValue = {};
806     Float floatingPointValue = {};
807     std::string stringValue;
808     Containers::ArrayView<const char> referenceValue;
809     Type typeValue = {};
810     const char* ai;
811     Implementation::InternalPropertyType type;
812     std::tie(ai, type) = Implementation::propertyValue(a, boolValue, integerValue, floatingPointValue, stringValue, referenceValue, typeValue, buffer, error);
813     VERIFY_PARSED(error, a, ai, "float");
814     CORRADE_COMPARE(type, Implementation::InternalPropertyType::Type);
815     CORRADE_COMPARE(typeValue, Type::Float);
816 }
817 
818 }}}}
819 
820 CORRADE_TEST_MAIN(Magnum::OpenDdl::Test::ParsersTest)
821