Line data Source code
1 : // Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/csspp
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Test the parser.cpp file.
22 : *
23 : * This test runs a battery of tests agains the parser.cpp file to ensure
24 : * full coverage and many edge cases as expected by CSS 3.
25 : *
26 : * Note that the basic grammar that the parser implements is compatible
27 : * with CSS 1 and 2.1.
28 : *
29 : * Remember that the parser does not do any verification other than the
30 : * ability to parse the input data. So whether the rules are any good
31 : * is not known at the time the parser returns.
32 : */
33 :
34 : // csspp
35 : //
36 : #include <csspp/exception.h>
37 : #include <csspp/parser.h>
38 :
39 :
40 : // self
41 : //
42 : #include "catch_main.h"
43 :
44 :
45 : // C++
46 : //
47 : #include <sstream>
48 :
49 :
50 : // C
51 : //
52 : #include <string.h>
53 :
54 :
55 : // last include
56 : //
57 : #include <snapdev/poison.h>
58 :
59 :
60 :
61 : namespace
62 : {
63 :
64 : } // no name namespace
65 :
66 :
67 :
68 :
69 1 : CATCH_TEST_CASE("Simple stylesheets", "[parser] [stylesheet] [rules]")
70 : {
71 : {
72 1 : std::stringstream ss;
73 1 : ss << "<!-- body { background : white url( /images/background.png ) } -->";
74 3 : csspp::position pos("test.css");
75 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
76 :
77 2 : csspp::parser p(l);
78 :
79 1 : csspp::node::pointer_t n(p.stylesheet());
80 :
81 : //std::cerr << "Result is: [" << *n << "]\n";
82 :
83 1 : std::stringstream out;
84 1 : out << *n;
85 1 : VERIFY_TREES(out.str(),
86 :
87 : "LIST\n"
88 : " COMPONENT_VALUE\n"
89 : " IDENTIFIER \"body\"\n"
90 : " OPEN_CURLYBRACKET B:false\n"
91 : " COMPONENT_VALUE\n"
92 : " IDENTIFIER \"background\"\n"
93 : " WHITESPACE\n"
94 : " COLON\n"
95 : " WHITESPACE\n"
96 : " IDENTIFIER \"white\"\n"
97 : " WHITESPACE\n"
98 : " URL \"/images/background.png\"\n"
99 :
100 : );
101 :
102 : // no error left over
103 1 : VERIFY_ERRORS("");
104 1 : }
105 :
106 : {
107 1 : std::stringstream ss;
108 1 : ss << "<!-- body { background : white url( /images/background.png ) } --><!-- div { border: 1px; } -->";
109 3 : csspp::position pos("test.css");
110 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
111 :
112 2 : csspp::parser p(l);
113 :
114 1 : csspp::node::pointer_t n(p.stylesheet());
115 :
116 : //std::cerr << "Result is: [" << *n << "]\n";
117 :
118 1 : std::stringstream out;
119 1 : out << *n;
120 1 : VERIFY_TREES(out.str(),
121 :
122 : "LIST\n"
123 : " COMPONENT_VALUE\n"
124 : " IDENTIFIER \"body\"\n"
125 : " OPEN_CURLYBRACKET B:false\n"
126 : " COMPONENT_VALUE\n"
127 : " IDENTIFIER \"background\"\n"
128 : " WHITESPACE\n"
129 : " COLON\n"
130 : " WHITESPACE\n"
131 : " IDENTIFIER \"white\"\n"
132 : " WHITESPACE\n"
133 : " URL \"/images/background.png\"\n"
134 : " COMPONENT_VALUE\n"
135 : " IDENTIFIER \"div\"\n"
136 : " OPEN_CURLYBRACKET B:false\n"
137 : " COMPONENT_VALUE\n"
138 : " IDENTIFIER \"border\"\n"
139 : " COLON\n"
140 : " WHITESPACE\n"
141 : " INTEGER \"px\" I:1\n"
142 :
143 : );
144 :
145 : // no error left over
146 1 : VERIFY_ERRORS("");
147 1 : }
148 :
149 : // one large rule with semicolons inside
150 : {
151 1 : std::stringstream ss;
152 : ss << "div\n"
153 : << "{\n"
154 : << " background-color: rgba(33, 77, 99, 0.3);\n"
155 : << " color: rgba(0, 3, 5, 0.95);\n"
156 : << " font-style: italic;\n"
157 1 : << "}";
158 3 : csspp::position pos("test.css");
159 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
160 :
161 2 : csspp::parser p(l);
162 :
163 1 : csspp::node::pointer_t n(p.stylesheet());
164 :
165 : //std::cerr << "Result is: [" << *n << "]\n";
166 :
167 1 : std::stringstream out;
168 1 : out << *n;
169 1 : VERIFY_TREES(out.str(),
170 :
171 : "LIST\n"
172 : " COMPONENT_VALUE\n"
173 : " IDENTIFIER \"div\"\n"
174 : " OPEN_CURLYBRACKET B:false\n"
175 : " LIST\n"
176 : " COMPONENT_VALUE\n"
177 : " IDENTIFIER \"background-color\"\n"
178 : " COLON\n"
179 : " WHITESPACE\n"
180 : " FUNCTION \"rgba\"\n"
181 : " INTEGER \"\" I:33\n"
182 : " COMMA\n"
183 : " WHITESPACE\n"
184 : " INTEGER \"\" I:77\n"
185 : " COMMA\n"
186 : " WHITESPACE\n"
187 : " INTEGER \"\" I:99\n"
188 : " COMMA\n"
189 : " WHITESPACE\n"
190 : " DECIMAL_NUMBER \"\" D:0.3\n"
191 : " COMPONENT_VALUE\n"
192 : " IDENTIFIER \"color\"\n"
193 : " COLON\n"
194 : " WHITESPACE\n"
195 : " FUNCTION \"rgba\"\n"
196 : " INTEGER \"\" I:0\n"
197 : " COMMA\n"
198 : " WHITESPACE\n"
199 : " INTEGER \"\" I:3\n"
200 : " COMMA\n"
201 : " WHITESPACE\n"
202 : " INTEGER \"\" I:5\n"
203 : " COMMA\n"
204 : " WHITESPACE\n"
205 : " DECIMAL_NUMBER \"\" D:0.95\n"
206 : " COMPONENT_VALUE\n"
207 : " IDENTIFIER \"font-style\"\n"
208 : " COLON\n"
209 : " WHITESPACE\n"
210 : " IDENTIFIER \"italic\"\n"
211 :
212 : );
213 :
214 : // no error left over
215 1 : VERIFY_ERRORS("");
216 1 : }
217 :
218 : // a comment, a simple rule, a comment
219 : {
220 1 : std::stringstream ss;
221 : ss << "// $Id: ...$\n"
222 : << "div { border: 1px; }\n"
223 1 : << "/* @preserve Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved. */";
224 3 : csspp::position pos("test.css");
225 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
226 :
227 2 : csspp::parser p(l);
228 :
229 1 : csspp::node::pointer_t n(p.stylesheet());
230 :
231 : //std::cerr << "Result is: [" << *n << "]\n";
232 :
233 1 : std::stringstream out;
234 1 : out << *n;
235 1 : VERIFY_TREES(out.str(),
236 :
237 : "LIST\n"
238 : " COMPONENT_VALUE\n"
239 : " IDENTIFIER \"div\"\n"
240 : " OPEN_CURLYBRACKET B:false\n"
241 : " COMPONENT_VALUE\n"
242 : " IDENTIFIER \"border\"\n"
243 : " COLON\n"
244 : " WHITESPACE\n"
245 : " INTEGER \"px\" I:1\n"
246 : " COMMENT \"@preserve Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved.\" I:1\n"
247 :
248 : );
249 :
250 : // no error left over
251 1 : VERIFY_ERRORS("");
252 1 : }
253 :
254 : // one empty C-like comment
255 : {
256 1 : std::stringstream ss;
257 1 : ss << "div { /**/ border: 1px; /**/ }\n";
258 3 : csspp::position pos("test.css");
259 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
260 :
261 2 : csspp::parser p(l);
262 :
263 1 : csspp::node::pointer_t n(p.stylesheet());
264 :
265 : //std::cerr << "Result is: [" << *n << "]\n";
266 :
267 1 : std::stringstream out;
268 1 : out << *n;
269 1 : VERIFY_TREES(out.str(),
270 :
271 : "LIST\n"
272 : " COMPONENT_VALUE\n"
273 : " IDENTIFIER \"div\"\n"
274 : " OPEN_CURLYBRACKET B:false\n"
275 : " COMPONENT_VALUE\n"
276 : " IDENTIFIER \"border\"\n"
277 : " COLON\n"
278 : " WHITESPACE\n"
279 : " INTEGER \"px\" I:1\n"
280 :
281 : );
282 :
283 : // no error left over
284 1 : VERIFY_ERRORS("");
285 1 : }
286 :
287 : // multiple empty C-like comments
288 : {
289 1 : std::stringstream ss;
290 1 : ss << "div { /**/ /**/ /**/ border: 1px; /**/ /**/ /**/ }\n";
291 3 : csspp::position pos("test.css");
292 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
293 :
294 2 : csspp::parser p(l);
295 :
296 1 : csspp::node::pointer_t n(p.stylesheet());
297 :
298 : //std::cerr << "Result is: [" << *n << "]\n";
299 :
300 1 : std::stringstream out;
301 1 : out << *n;
302 1 : VERIFY_TREES(out.str(),
303 :
304 : "LIST\n"
305 : " COMPONENT_VALUE\n"
306 : " IDENTIFIER \"div\"\n"
307 : " OPEN_CURLYBRACKET B:false\n"
308 : " COMPONENT_VALUE\n"
309 : " IDENTIFIER \"border\"\n"
310 : " COLON\n"
311 : " WHITESPACE\n"
312 : " INTEGER \"px\" I:1\n"
313 :
314 : );
315 :
316 : // no error left over
317 1 : VERIFY_ERRORS("");
318 1 : }
319 :
320 : // cascading fields
321 : {
322 1 : std::stringstream ss;
323 : ss << "div {\n"
324 : << " font: { family: ivory; size: 16pt; style: italic };\n"
325 : << " border: { color: #112389; width: 1px } /**/ ;\n"
326 : << " color: /* text color */ white;\n"
327 1 : << "}";
328 3 : csspp::position pos("test.css");
329 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
330 :
331 2 : csspp::parser p(l);
332 :
333 1 : csspp::node::pointer_t n(p.stylesheet());
334 :
335 : //std::cerr << "Result is: [" << *n << "]\n";
336 1 : VERIFY_ERRORS("");
337 :
338 1 : std::stringstream out;
339 1 : out << *n;
340 1 : VERIFY_TREES(out.str(),
341 :
342 : "LIST\n"
343 : " COMPONENT_VALUE\n"
344 : " IDENTIFIER \"div\"\n"
345 : " OPEN_CURLYBRACKET B:false\n"
346 : " LIST\n"
347 : " COMPONENT_VALUE\n"
348 : " IDENTIFIER \"font\"\n"
349 : " COLON\n"
350 : " OPEN_CURLYBRACKET B:false\n"
351 : " LIST\n"
352 : " COMPONENT_VALUE\n"
353 : " IDENTIFIER \"family\"\n"
354 : " COLON\n"
355 : " WHITESPACE\n"
356 : " IDENTIFIER \"ivory\"\n"
357 : " COMPONENT_VALUE\n"
358 : " IDENTIFIER \"size\"\n"
359 : " COLON\n"
360 : " WHITESPACE\n"
361 : " INTEGER \"pt\" I:16\n"
362 : " COMPONENT_VALUE\n"
363 : " IDENTIFIER \"style\"\n"
364 : " COLON\n"
365 : " WHITESPACE\n"
366 : " IDENTIFIER \"italic\"\n"
367 : " COMPONENT_VALUE\n"
368 : " IDENTIFIER \"border\"\n"
369 : " COLON\n"
370 : " OPEN_CURLYBRACKET B:false\n"
371 : " LIST\n"
372 : " COMPONENT_VALUE\n"
373 : " IDENTIFIER \"color\"\n"
374 : " COLON\n"
375 : " WHITESPACE\n"
376 : " HASH \"112389\"\n"
377 : " COMPONENT_VALUE\n"
378 : " IDENTIFIER \"width\"\n"
379 : " COLON\n"
380 : " WHITESPACE\n"
381 : " INTEGER \"px\" I:1\n"
382 : " COMPONENT_VALUE\n"
383 : " IDENTIFIER \"color\"\n"
384 : " COLON\n"
385 : " WHITESPACE\n"
386 : " IDENTIFIER \"white\"\n"
387 :
388 : );
389 :
390 : // no error left over
391 1 : VERIFY_ERRORS("");
392 1 : }
393 :
394 : // verify support of an empty {}-block
395 : {
396 1 : std::stringstream ss;
397 : ss << "div section span {}\n"
398 1 : << "div p b {}\n";
399 3 : csspp::position pos("test.css");
400 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
401 :
402 2 : csspp::parser p(l);
403 :
404 1 : csspp::node::pointer_t n(p.stylesheet());
405 :
406 : //std::cerr << "Result is: [" << *n << "]\n";
407 1 : VERIFY_ERRORS("");
408 :
409 1 : std::stringstream out;
410 1 : out << *n;
411 1 : VERIFY_TREES(out.str(),
412 :
413 : "LIST\n"
414 : " COMPONENT_VALUE\n"
415 : " IDENTIFIER \"div\"\n"
416 : " WHITESPACE\n"
417 : " IDENTIFIER \"section\"\n"
418 : " WHITESPACE\n"
419 : " IDENTIFIER \"span\"\n"
420 : " OPEN_CURLYBRACKET B:false\n"
421 : " LIST\n"
422 : " COMPONENT_VALUE\n"
423 : " IDENTIFIER \"div\"\n"
424 : " WHITESPACE\n"
425 : " IDENTIFIER \"p\"\n"
426 : " WHITESPACE\n"
427 : " IDENTIFIER \"b\"\n"
428 : " OPEN_CURLYBRACKET B:false\n"
429 : " LIST\n"
430 :
431 : );
432 :
433 : // no error left over
434 1 : VERIFY_ERRORS("");
435 1 : }
436 1 : }
437 :
438 1 : CATCH_TEST_CASE("Invalid stylesheets", "[parser] [stylesheet] [invalid]")
439 : {
440 : // closing '}' one too many times
441 : {
442 1 : std::stringstream ss;
443 1 : ss << "<!-- body { background : white url( /images/background.png ) } --> }";
444 3 : csspp::position pos("test.css");
445 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
446 :
447 2 : csspp::parser p(l);
448 :
449 1 : csspp::node::pointer_t n(p.stylesheet());
450 :
451 : //std::cerr << "Result is: [" << *n << "]\n";
452 :
453 : // this failed with an error, no need to check the "broken" output
454 :
455 1 : VERIFY_ERRORS("test.css(1): error: Unexpected closing block of type: CLOSE_CURLYBRACKET.\n");
456 1 : }
457 :
458 : // closing ']' one too many times
459 : {
460 1 : std::stringstream ss;
461 1 : ss << "<!-- body[browser~=\"great\"]] { background : white url( /images/background.png ) } -->";
462 3 : csspp::position pos("test.css");
463 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
464 :
465 2 : csspp::parser p(l);
466 :
467 1 : csspp::node::pointer_t n(p.stylesheet());
468 :
469 : //std::cerr << "Result is: [" << *n << "]\n";
470 :
471 : // this failed with an error, no need to check the "broken" output
472 :
473 1 : VERIFY_ERRORS(
474 : "test.css(1): error: A qualified rule must end with a { ... } block.\n"
475 : "test.css(1): error: Unexpected closing block of type: CLOSE_SQUAREBRACKET.\n"
476 : );
477 1 : }
478 :
479 : // closing ')' one too many times
480 : {
481 1 : std::stringstream ss;
482 1 : ss << "<!-- body[browser~=\"great\"] { background : white url( /images/background.png ); border-top-color: rgb(1,2,3)); } -->";
483 3 : csspp::position pos("test.css");
484 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
485 :
486 2 : csspp::parser p(l);
487 :
488 1 : csspp::node::pointer_t n(p.stylesheet());
489 :
490 : //std::cerr << "Result is: [" << *n << "]\n";
491 :
492 : // this failed with an error, no need to check the "broken" output
493 :
494 1 : VERIFY_ERRORS(
495 : "test.css(1): error: Block expected to end with CLOSE_CURLYBRACKET but got CLOSE_PARENTHESIS instead.\n"
496 : //"test.css(1): error: Unexpected closing block of type: CLOSE_PARENTHESIS.\n"
497 : );
498 1 : }
499 :
500 : // extra ';'
501 : {
502 1 : std::stringstream ss;
503 1 : ss << "illegal { semi: colon };";
504 3 : csspp::position pos("test.css");
505 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
506 :
507 2 : csspp::parser p(l);
508 :
509 1 : csspp::node::pointer_t n(p.stylesheet());
510 :
511 : //std::cerr << "Result is: [" << *n << "]\n";
512 :
513 : // this failed with an error, no need to check the "broken" output
514 :
515 1 : VERIFY_ERRORS(
516 : "test.css(1): error: A qualified rule cannot end a { ... } block with a ';'.\n"
517 : );
518 1 : }
519 :
520 : // no error left over
521 1 : VERIFY_ERRORS("");
522 1 : }
523 :
524 1 : CATCH_TEST_CASE("Simple rules", "[parser] [rule-list]")
525 : {
526 : // a simple valid rule
527 : {
528 1 : std::stringstream ss;
529 1 : ss << " body { background : gradient(to bottom, #012, #384513 75%, #452) } ";
530 3 : csspp::position pos("test.css");
531 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
532 :
533 2 : csspp::parser p(l);
534 :
535 : // rule list does not like <!-- and -->
536 1 : csspp::node::pointer_t n(p.rule_list());
537 :
538 : //std::cerr << "Result is: [" << *n << "]\n";
539 :
540 1 : std::stringstream out;
541 1 : out << *n;
542 1 : VERIFY_TREES(out.str(),
543 :
544 : "LIST\n"
545 : " COMPONENT_VALUE\n"
546 : " IDENTIFIER \"body\"\n"
547 : " OPEN_CURLYBRACKET B:false\n"
548 : " COMPONENT_VALUE\n"
549 : " IDENTIFIER \"background\"\n"
550 : " WHITESPACE\n"
551 : " COLON\n"
552 : " WHITESPACE\n"
553 : " FUNCTION \"gradient\"\n"
554 : " IDENTIFIER \"to\"\n"
555 : " WHITESPACE\n"
556 : " IDENTIFIER \"bottom\"\n"
557 : " COMMA\n"
558 : " WHITESPACE\n"
559 : " HASH \"012\"\n"
560 : " COMMA\n"
561 : " WHITESPACE\n"
562 : " HASH \"384513\"\n"
563 : " WHITESPACE\n"
564 : " PERCENT D:0.75\n"
565 : " COMMA\n"
566 : " WHITESPACE\n"
567 : " HASH \"452\"\n"
568 :
569 : );
570 :
571 : // no error left over
572 1 : VERIFY_ERRORS("");
573 1 : }
574 :
575 : // a simple valid rule
576 : {
577 1 : std::stringstream ss;
578 : ss << " div { color: blue; }"
579 : << " @media screen { viewport: 1000px 500px; } "
580 1 : << " div#op{color:hsl(120,1,0.5)}";
581 3 : csspp::position pos("test.css");
582 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
583 :
584 2 : csspp::parser p(l);
585 :
586 : // rule list does not like <!-- and -->
587 1 : csspp::node::pointer_t n(p.rule_list());
588 :
589 : //std::cerr << "Result is: [" << *n << "]\n";
590 :
591 1 : std::stringstream out;
592 1 : out << *n;
593 1 : VERIFY_TREES(out.str(),
594 :
595 : "LIST\n"
596 : " COMPONENT_VALUE\n"
597 : " IDENTIFIER \"div\"\n"
598 : " OPEN_CURLYBRACKET B:false\n"
599 : " COMPONENT_VALUE\n"
600 : " IDENTIFIER \"color\"\n"
601 : " COLON\n"
602 : " WHITESPACE\n"
603 : " IDENTIFIER \"blue\"\n"
604 : " AT_KEYWORD \"media\" I:0\n"
605 : " IDENTIFIER \"screen\"\n"
606 : " OPEN_CURLYBRACKET B:false\n"
607 : " COMPONENT_VALUE\n"
608 : " IDENTIFIER \"viewport\"\n"
609 : " COLON\n"
610 : " WHITESPACE\n"
611 : " INTEGER \"px\" I:1000\n"
612 : " WHITESPACE\n"
613 : " INTEGER \"px\" I:500\n"
614 : " COMPONENT_VALUE\n"
615 : " IDENTIFIER \"div\"\n"
616 : " HASH \"op\"\n"
617 : " OPEN_CURLYBRACKET B:false\n"
618 : " COMPONENT_VALUE\n"
619 : " IDENTIFIER \"color\"\n"
620 : " COLON\n"
621 : " FUNCTION \"hsl\"\n"
622 : " INTEGER \"\" I:120\n"
623 : " COMMA\n"
624 : " INTEGER \"\" I:1\n"
625 : " COMMA\n"
626 : " DECIMAL_NUMBER \"\" D:0.5\n"
627 :
628 : );
629 :
630 : // no error left over
631 1 : VERIFY_ERRORS("");
632 1 : }
633 1 : }
634 :
635 1 : CATCH_TEST_CASE("Nested rules", "[parser] [rule-list]")
636 : {
637 : // at rule inside another at rule
638 : {
639 1 : std::stringstream ss;
640 1 : ss << "@if true { @message \"blah\"; }";
641 3 : csspp::position pos("test.css");
642 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
643 :
644 2 : csspp::parser p(l);
645 :
646 1 : csspp::node::pointer_t n(p.rule_list());
647 :
648 : // no error left over
649 1 : VERIFY_ERRORS("");
650 :
651 : //std::cerr << "Result is: [" << *n << "]\n";
652 :
653 1 : std::stringstream out;
654 1 : out << *n;
655 1 : VERIFY_TREES(out.str(),
656 :
657 : "LIST\n"
658 : " AT_KEYWORD \"if\" I:0\n"
659 : " IDENTIFIER \"true\"\n"
660 : " OPEN_CURLYBRACKET B:false\n"
661 : " COMPONENT_VALUE\n"
662 : " AT_KEYWORD \"message\" I:0\n"
663 : " STRING \"blah\"\n"
664 :
665 : );
666 1 : }
667 1 : }
668 :
669 1 : CATCH_TEST_CASE("Invalid rules", "[parser] [rule-list] [invalid]")
670 : {
671 : // breaks on the <!--
672 : {
673 1 : std::stringstream ss;
674 1 : ss << "<!-- body { background : white url( /images/background.png ) } -->";
675 3 : csspp::position pos("test.css");
676 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
677 :
678 2 : csspp::parser p(l);
679 :
680 : // rule list does not like <!-- and -->
681 1 : csspp::node::pointer_t n(p.rule_list());
682 :
683 : //std::cerr << "Result is: [" << *n << "]\n";
684 :
685 : // this failed with an error, no need to check the "broken" output
686 :
687 1 : VERIFY_ERRORS("test.css(1): error: HTML comment delimiters (<!-- and -->) are not allowed in this CSS document.\n");
688 1 : }
689 :
690 : // breaks on the -->
691 : {
692 1 : std::stringstream ss;
693 1 : ss << "body { background : white url( /images/background.png ) 44px } -->";
694 3 : csspp::position pos("test.css");
695 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
696 :
697 2 : csspp::parser p(l);
698 :
699 : // rule list does not like <!-- and -->
700 1 : csspp::node::pointer_t n(p.rule_list());
701 :
702 : //std::cerr << "Result is: [" << *n << "]\n";
703 :
704 : // this failed with an error, no need to check the "broken" output
705 :
706 1 : VERIFY_ERRORS(
707 : "test.css(1): error: A qualified rule cannot be empty; you are missing a { ... } block.\n"
708 : "test.css(1): error: HTML comment delimiters (<!-- and -->) are not allowed in this CSS document.\n"
709 : );
710 1 : }
711 :
712 : // breaks on the }
713 : {
714 1 : std::stringstream ss;
715 1 : ss << "body { background : white url( /images/background.png ) } }";
716 3 : csspp::position pos("test.css");
717 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
718 :
719 2 : csspp::parser p(l);
720 :
721 : // rule list does not like <!-- and -->
722 1 : csspp::node::pointer_t n(p.rule_list());
723 :
724 : //std::cerr << "Result is: [" << *n << "]\n";
725 :
726 : // this failed with an error, no need to check the "broken" output
727 :
728 1 : VERIFY_ERRORS(
729 : "test.css(1): error: A qualified rule cannot be empty; you are missing a { ... } block.\n"
730 : "test.css(1): error: Unexpected closing block of type: CLOSE_CURLYBRACKET.\n"
731 : );
732 1 : }
733 :
734 : // breaks on the ]
735 : {
736 1 : std::stringstream ss;
737 1 : ss << "body[lili=\"joe\"]] { background : white url( /images/background.png ) } }";
738 3 : csspp::position pos("test.css");
739 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
740 :
741 2 : csspp::parser p(l);
742 :
743 : // rule list does not like <!-- and -->
744 1 : csspp::node::pointer_t n(p.rule_list());
745 :
746 : //std::cerr << "Result is: [" << *n << "]\n";
747 :
748 : // this failed with an error, no need to check the "broken" output
749 :
750 1 : VERIFY_ERRORS(
751 : "test.css(1): error: A qualified rule must end with a { ... } block.\n"
752 : "test.css(1): error: Unexpected closing block of type: CLOSE_SQUAREBRACKET.\n"
753 : );
754 1 : }
755 :
756 : // breaks on the )
757 : {
758 1 : std::stringstream ss;
759 1 : ss << " body[lili=\"joe\"] { background : white url( /images/background.png ); color:rgba(0,0,0,0)); } ";
760 3 : csspp::position pos("test.css");
761 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
762 :
763 2 : csspp::parser p(l);
764 :
765 : // rule list does not like <!-- and -->
766 1 : csspp::node::pointer_t n(p.rule_list());
767 :
768 : //std::cerr << "Result is: [" << *n << "]\n";
769 :
770 : // this failed with an error, no need to check the "broken" output
771 :
772 1 : VERIFY_ERRORS(
773 : "test.css(1): error: Block expected to end with CLOSE_CURLYBRACKET but got CLOSE_PARENTHESIS instead.\n"
774 : //"test.css(1): error: Unexpected closing block of type: CLOSE_PARENTHESIS.\n"
775 : );
776 1 : }
777 :
778 : // a @-rule cannot be empty
779 : {
780 1 : std::stringstream ss;
781 : ss << " div { color: blue; }"
782 1 : << " @media";
783 3 : csspp::position pos("test.css");
784 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
785 :
786 2 : csspp::parser p(l);
787 :
788 : // rule list does not like <!-- and -->
789 1 : csspp::node::pointer_t n(p.rule_list());
790 :
791 : //std::cerr << "Result is: [" << *n << "]\n";
792 :
793 1 : VERIFY_ERRORS("test.css(1): error: At '@' command cannot be empty (missing expression or block) unless ended by a semicolon (;).\n");
794 1 : }
795 :
796 : // a @-rule cannot be empty
797 : {
798 1 : std::stringstream ss;
799 1 : ss << "@media test and (this one too) or (that maybe)";
800 3 : csspp::position pos("test.css");
801 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
802 :
803 2 : csspp::parser p(l);
804 :
805 : // rule list does not like <!-- and -->
806 1 : csspp::node::pointer_t n(p.rule_list());
807 :
808 : //std::cerr << "Result is: [" << *n << "]\n";
809 :
810 1 : VERIFY_ERRORS("test.css(1): error: At '@' command must end with a block or a ';'.\n");
811 1 : }
812 :
813 : // :INTEGER is not valid, plus it is viewed as a nested rule!
814 : {
815 1 : std::stringstream ss;
816 1 : ss << "div:556 {color:bisque}";
817 3 : csspp::position pos("test.css");
818 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
819 :
820 2 : csspp::parser p(l);
821 :
822 1 : csspp::node::pointer_t n(p.stylesheet());
823 :
824 1 : VERIFY_ERRORS("test.css(1): error: Variable set to a block and a nested property block must end with a semicolon (;) after said block.\n");
825 1 : }
826 :
827 : // no error left over
828 1 : VERIFY_ERRORS("");
829 1 : }
830 :
831 1 : CATCH_TEST_CASE("One simple rule", "[parser] [rule]")
832 : {
833 : // a simple valid rule
834 : {
835 1 : std::stringstream ss;
836 1 : ss << " body { background : gradient(to bottom, #012, #384513 75%, #452) } ";
837 3 : csspp::position pos("test.css");
838 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
839 :
840 2 : csspp::parser p(l);
841 :
842 1 : csspp::node::pointer_t n(p.rule());
843 :
844 : //std::cerr << "Result is: [" << *n << "]\n";
845 :
846 1 : std::stringstream out;
847 1 : out << *n;
848 1 : VERIFY_TREES(out.str(),
849 :
850 : "COMPONENT_VALUE\n"
851 : " IDENTIFIER \"body\"\n"
852 : " OPEN_CURLYBRACKET B:false\n"
853 : " COMPONENT_VALUE\n"
854 : " IDENTIFIER \"background\"\n"
855 : " WHITESPACE\n"
856 : " COLON\n"
857 : " WHITESPACE\n"
858 : " FUNCTION \"gradient\"\n"
859 : " IDENTIFIER \"to\"\n"
860 : " WHITESPACE\n"
861 : " IDENTIFIER \"bottom\"\n"
862 : " COMMA\n"
863 : " WHITESPACE\n"
864 : " HASH \"012\"\n"
865 : " COMMA\n"
866 : " WHITESPACE\n"
867 : " HASH \"384513\"\n"
868 : " WHITESPACE\n"
869 : " PERCENT D:0.75\n"
870 : " COMMA\n"
871 : " WHITESPACE\n"
872 : " HASH \"452\"\n"
873 :
874 : );
875 :
876 1 : }
877 :
878 : // a simple valid rule
879 : {
880 1 : std::stringstream ss;
881 : ss << " div { color: blue; }"
882 : << " @media screen { viewport: 1000px 500px; } "
883 1 : << " div#op{color:hsl(120,1,0.5)}";
884 3 : csspp::position pos("test.css");
885 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
886 :
887 2 : csspp::parser p(l);
888 :
889 1 : csspp::node::pointer_t n(p.rule());
890 :
891 : //std::cerr << "Result is: [" << *n << "]\n";
892 :
893 1 : std::stringstream out;
894 1 : out << *n;
895 1 : VERIFY_TREES(out.str(),
896 :
897 : "COMPONENT_VALUE\n"
898 : " IDENTIFIER \"div\"\n"
899 : " OPEN_CURLYBRACKET B:false\n"
900 : " COMPONENT_VALUE\n"
901 : " IDENTIFIER \"color\"\n"
902 : " COLON\n"
903 : " WHITESPACE\n"
904 : " IDENTIFIER \"blue\"\n"
905 :
906 : );
907 :
908 1 : n = p.rule();
909 :
910 1 : out.str("");
911 1 : out << *n;
912 1 : VERIFY_TREES(out.str(),
913 :
914 : "AT_KEYWORD \"media\" I:0\n"
915 : " IDENTIFIER \"screen\"\n"
916 : " OPEN_CURLYBRACKET B:false\n"
917 : " COMPONENT_VALUE\n"
918 : " IDENTIFIER \"viewport\"\n"
919 : " COLON\n"
920 : " WHITESPACE\n"
921 : " INTEGER \"px\" I:1000\n"
922 : " WHITESPACE\n"
923 : " INTEGER \"px\" I:500\n"
924 :
925 : );
926 :
927 1 : n = p.rule();
928 :
929 1 : out.str("");
930 1 : out << *n;
931 1 : VERIFY_TREES(out.str(),
932 :
933 : "COMPONENT_VALUE\n"
934 : " IDENTIFIER \"div\"\n"
935 : " HASH \"op\"\n"
936 : " OPEN_CURLYBRACKET B:false\n"
937 : " COMPONENT_VALUE\n"
938 : " IDENTIFIER \"color\"\n"
939 : " COLON\n"
940 : " FUNCTION \"hsl\"\n"
941 : " INTEGER \"\" I:120\n"
942 : " COMMA\n"
943 : " INTEGER \"\" I:1\n"
944 : " COMMA\n"
945 : " DECIMAL_NUMBER \"\" D:0.5\n"
946 :
947 : );
948 :
949 1 : }
950 :
951 : // no error left over
952 1 : VERIFY_ERRORS("");
953 1 : }
954 :
955 1 : CATCH_TEST_CASE("Invalid one rule", "[parser] [rule] [invalid]")
956 : {
957 : // breaks on the <!--
958 : {
959 1 : std::stringstream ss;
960 1 : ss << "<!-- body { background : white url( /images/background.png ) } -->";
961 3 : csspp::position pos("test.css");
962 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
963 :
964 2 : csspp::parser p(l);
965 :
966 1 : csspp::node::pointer_t n(p.rule());
967 :
968 : //std::cerr << "Result is: [" << *n << "]\n";
969 :
970 : // this failed with an error, no need to check the "broken" output
971 :
972 1 : VERIFY_ERRORS("test.css(1): error: HTML comment delimiters (<!-- and -->) are not allowed in this CSS document.\n");
973 1 : }
974 :
975 : // breaks on the -->
976 : {
977 1 : std::stringstream ss;
978 1 : ss << "--> body { background : white url( /images/background.png ) }";
979 3 : csspp::position pos("test.css");
980 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
981 :
982 2 : csspp::parser p(l);
983 :
984 1 : csspp::node::pointer_t n(p.rule());
985 :
986 : //std::cerr << "Result is: [" << *n << "]\n";
987 :
988 : // this failed with an error, no need to check the "broken" output
989 :
990 1 : VERIFY_ERRORS("test.css(1): error: HTML comment delimiters (<!-- and -->) are not allowed in this CSS document.\n");
991 1 : }
992 :
993 : // breaks on the }
994 : {
995 1 : std::stringstream ss;
996 1 : ss << "body { background : white url( /images/background.png ) } }";
997 3 : csspp::position pos("test.css");
998 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
999 :
1000 2 : csspp::parser p(l);
1001 :
1002 : // the first read works as expected
1003 1 : csspp::node::pointer_t n(p.rule());
1004 :
1005 : //std::cerr << "Result is: [" << *n << "]\n";
1006 :
1007 1 : std::stringstream out;
1008 1 : out << *n;
1009 1 : VERIFY_TREES(out.str(),
1010 :
1011 : "COMPONENT_VALUE\n"
1012 : " IDENTIFIER \"body\"\n"
1013 : " OPEN_CURLYBRACKET B:false\n"
1014 : " COMPONENT_VALUE\n"
1015 : " IDENTIFIER \"background\"\n"
1016 : " WHITESPACE\n"
1017 : " COLON\n"
1018 : " WHITESPACE\n"
1019 : " IDENTIFIER \"white\"\n"
1020 : " WHITESPACE\n"
1021 : " URL \"/images/background.png\"\n"
1022 :
1023 : );
1024 :
1025 : // this failed with an error, no need to check the "broken" output
1026 1 : n = p.rule();
1027 :
1028 1 : VERIFY_ERRORS(
1029 : "test.css(1): error: A qualified rule cannot be empty; you are missing a { ... } block.\n"
1030 : //"test.css(1): error: Unexpected closing block of type: CLOSE_CURLYBRACKET.\n"
1031 : );
1032 1 : }
1033 :
1034 : // breaks on the ]
1035 : {
1036 1 : std::stringstream ss;
1037 1 : ss << "body[lili=\"joe\"]] { background : white url( /images/background.png ) } }";
1038 3 : csspp::position pos("test.css");
1039 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1040 :
1041 2 : csspp::parser p(l);
1042 :
1043 : // rule up to the spurious ']' is all proper
1044 1 : csspp::node::pointer_t n(p.rule());
1045 :
1046 : //std::cerr << "Result is: [" << *n << "]\n";
1047 :
1048 1 : std::stringstream out;
1049 1 : out << *n;
1050 1 : VERIFY_TREES(out.str(),
1051 :
1052 : "COMPONENT_VALUE\n"
1053 : " IDENTIFIER \"body\"\n"
1054 : " OPEN_SQUAREBRACKET\n"
1055 : " IDENTIFIER \"lili\"\n"
1056 : " EQUAL\n"
1057 : " STRING \"joe\"\n"
1058 :
1059 : );
1060 :
1061 : // this failed with an error, no need to check the "broken" output
1062 1 : n = p.rule();
1063 :
1064 1 : VERIFY_ERRORS(
1065 : "test.css(1): error: A qualified rule must end with a { ... } block.\n"
1066 : "test.css(1): error: Unexpected closing block of type: CLOSE_SQUAREBRACKET.\n"
1067 : );
1068 1 : }
1069 :
1070 : // breaks on the )
1071 : {
1072 1 : std::stringstream ss;
1073 1 : ss << " body[lili=\"joe\"] { background : white url( /images/background.png ); color:rgba(0,0,0,0)); } ";
1074 3 : csspp::position pos("test.css");
1075 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1076 :
1077 2 : csspp::parser p(l);
1078 :
1079 1 : csspp::node::pointer_t n(p.rule());
1080 :
1081 : //std::cerr << "Result is: [" << *n << "]\n";
1082 :
1083 : // this failed with an error, no need to check the "broken" output
1084 :
1085 1 : VERIFY_ERRORS(
1086 : "test.css(1): error: Block expected to end with CLOSE_CURLYBRACKET but got CLOSE_PARENTHESIS instead.\n"
1087 : //"test.css(1): error: Unexpected closing block of type: CLOSE_PARENTHESIS.\n"
1088 : );
1089 1 : }
1090 :
1091 : // // a @-rule cannot be empty
1092 : // {
1093 : // std::stringstream ss;
1094 : // ss << " div { color: blue; }"
1095 : // << " @media";
1096 : // csspp::position pos("test.css");
1097 : // csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1098 : //
1099 : // csspp::parser p(l);
1100 : //
1101 : // csspp::node::pointer_t n(p.rule());
1102 : //
1103 : ////std::cerr << "Result is: [" << *n << "]\n";
1104 : //
1105 : // std::stringstream out;
1106 : // out << *n;
1107 : // VERIFY_TREES(out.str(),
1108 : //
1109 : //"COMPONENT_VALUE\n"
1110 : //" IDENTIFIER \"div\"\n"
1111 : //" OPEN_CURLYBRACKET B:false\n"
1112 : //" IDENTIFIER \"color\"\n"
1113 : //" COLON\n"
1114 : //" WHITESPACE\n"
1115 : //" IDENTIFIER \"blue\"\n"
1116 : //
1117 : // );
1118 : //
1119 : // // this failed with an error, no need to check the "broken" output
1120 : // n = p.rule();
1121 : //
1122 : // VERIFY_ERRORS("test.css(1): error: At '@' command cannot be empty (missing expression or block) unless ended by a semicolon (;).\n");
1123 : // }
1124 : //
1125 : // // a @-rule cannot be empty
1126 : // {
1127 : // std::stringstream ss;
1128 : // ss << "@media test and (this one too) or (that maybe)";
1129 : // csspp::position pos("test.css");
1130 : // csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1131 : //
1132 : // csspp::parser p(l);
1133 : //
1134 : // csspp::node::pointer_t n(p.rule());
1135 : //
1136 : ////std::cerr << "Result is: [" << *n << "]\n";
1137 : //
1138 : // VERIFY_ERRORS("test.css(1): error: At '@' command must end with a block or a ';'.\n");
1139 : // }
1140 :
1141 : // no error left over
1142 1 : VERIFY_ERRORS("");
1143 1 : }
1144 :
1145 1 : CATCH_TEST_CASE("Simple component values", "[parser] [component-value]")
1146 : {
1147 : // a simple valid rule
1148 : {
1149 1 : std::stringstream ss;
1150 1 : ss << " body { background : gradient(to bottom, #012, #384513 75%, #452) } ";
1151 3 : csspp::position pos("test.css");
1152 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1153 :
1154 2 : csspp::parser p(l);
1155 :
1156 1 : csspp::node::pointer_t n(p.component_value_list());
1157 :
1158 : //std::cerr << "Result is: [" << *n << "]\n";
1159 :
1160 1 : std::stringstream out;
1161 1 : out << *n;
1162 1 : VERIFY_TREES(out.str(),
1163 :
1164 : "COMPONENT_VALUE\n"
1165 : " IDENTIFIER \"body\"\n"
1166 : " OPEN_CURLYBRACKET B:false\n"
1167 : " COMPONENT_VALUE\n"
1168 : " IDENTIFIER \"background\"\n"
1169 : " WHITESPACE\n"
1170 : " COLON\n"
1171 : " WHITESPACE\n"
1172 : " FUNCTION \"gradient\"\n"
1173 : " IDENTIFIER \"to\"\n"
1174 : " WHITESPACE\n"
1175 : " IDENTIFIER \"bottom\"\n"
1176 : " COMMA\n"
1177 : " WHITESPACE\n"
1178 : " HASH \"012\"\n"
1179 : " COMMA\n"
1180 : " WHITESPACE\n"
1181 : " HASH \"384513\"\n"
1182 : " WHITESPACE\n"
1183 : " PERCENT D:0.75\n"
1184 : " COMMA\n"
1185 : " WHITESPACE\n"
1186 : " HASH \"452\"\n"
1187 :
1188 : );
1189 :
1190 1 : }
1191 :
1192 : // a simple valid rule
1193 : {
1194 1 : std::stringstream ss;
1195 : ss << " div { color: blue; }"
1196 : << " @media screen { viewport: 1000px 500px; } "
1197 1 : << " div#op{color:hsl(120,1,0.5)}";
1198 3 : csspp::position pos("test.css");
1199 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1200 :
1201 2 : csspp::parser p(l);
1202 :
1203 1 : csspp::node::pointer_t n(p.component_value_list());
1204 :
1205 : //std::cerr << "Result is: [" << *n << "]\n";
1206 :
1207 1 : std::stringstream out;
1208 1 : out << *n;
1209 1 : VERIFY_TREES(out.str(),
1210 :
1211 : "COMPONENT_VALUE\n"
1212 : " IDENTIFIER \"div\"\n"
1213 : " OPEN_CURLYBRACKET B:false\n"
1214 : " COMPONENT_VALUE\n"
1215 : " IDENTIFIER \"color\"\n"
1216 : " COLON\n"
1217 : " WHITESPACE\n"
1218 : " IDENTIFIER \"blue\"\n"
1219 :
1220 : );
1221 :
1222 1 : n = p.rule();
1223 :
1224 1 : out.str("");
1225 1 : out << *n;
1226 1 : VERIFY_TREES(out.str(),
1227 :
1228 : "AT_KEYWORD \"media\" I:0\n"
1229 : " IDENTIFIER \"screen\"\n"
1230 : " OPEN_CURLYBRACKET B:false\n"
1231 : " COMPONENT_VALUE\n"
1232 : " IDENTIFIER \"viewport\"\n"
1233 : " COLON\n"
1234 : " WHITESPACE\n"
1235 : " INTEGER \"px\" I:1000\n"
1236 : " WHITESPACE\n"
1237 : " INTEGER \"px\" I:500\n"
1238 :
1239 : );
1240 :
1241 1 : n = p.rule();
1242 :
1243 1 : out.str("");
1244 1 : out << *n;
1245 1 : VERIFY_TREES(out.str(),
1246 :
1247 : "COMPONENT_VALUE\n"
1248 : " IDENTIFIER \"div\"\n"
1249 : " HASH \"op\"\n"
1250 : " OPEN_CURLYBRACKET B:false\n"
1251 : " COMPONENT_VALUE\n"
1252 : " IDENTIFIER \"color\"\n"
1253 : " COLON\n"
1254 : " FUNCTION \"hsl\"\n"
1255 : " INTEGER \"\" I:120\n"
1256 : " COMMA\n"
1257 : " INTEGER \"\" I:1\n"
1258 : " COMMA\n"
1259 : " DECIMAL_NUMBER \"\" D:0.5\n"
1260 :
1261 : );
1262 :
1263 1 : }
1264 :
1265 : // no error left over
1266 1 : VERIFY_ERRORS("");
1267 1 : }
1268 :
1269 1 : CATCH_TEST_CASE("Invalid component values", "[parser] [component-value] [invalid]")
1270 : {
1271 : // breaks on missing }
1272 : {
1273 1 : std::stringstream ss;
1274 1 : ss << "body { background : white url( /images/background.png )";
1275 3 : csspp::position pos("test.css");
1276 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1277 :
1278 2 : csspp::parser p(l);
1279 :
1280 1 : csspp::node::pointer_t n(p.component_value_list());
1281 :
1282 : //std::cerr << "Result is: [" << *n << "]\n";
1283 :
1284 : // this failed with an error, no need to check the "broken" output
1285 :
1286 1 : VERIFY_ERRORS(
1287 : "test.css(1): error: Block expected to end with CLOSE_CURLYBRACKET but got EOF_TOKEN instead.\n"
1288 : );
1289 1 : }
1290 :
1291 : // breaks on missing ]
1292 : {
1293 1 : std::stringstream ss;
1294 1 : ss << "body[lili=\"joe\" { background : white url( /images/background.png ) } }";
1295 3 : csspp::position pos("test.css");
1296 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1297 :
1298 2 : csspp::parser p(l);
1299 :
1300 : // rule list does not like <!-- and -->
1301 1 : csspp::node::pointer_t n(p.component_value_list());
1302 :
1303 : //std::cerr << "Result is: [" << *n << "]\n";
1304 :
1305 : // this failed with an error, no need to check the "broken" output
1306 :
1307 1 : VERIFY_ERRORS(
1308 : "test.css(1): error: Block expected to end with CLOSE_SQUAREBRACKET but got CLOSE_CURLYBRACKET instead.\n"
1309 : );
1310 1 : }
1311 :
1312 : // breaks on missing )
1313 : {
1314 1 : std::stringstream ss;
1315 1 : ss << " body[lili=\"joe\"] { background : white url( /images/background.png ); color:rgba(0,0,0,0; } ";
1316 3 : csspp::position pos("test.css");
1317 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1318 :
1319 2 : csspp::parser p(l);
1320 :
1321 1 : csspp::node::pointer_t n(p.component_value_list());
1322 :
1323 : //std::cerr << "Result is: [" << *n << "]\n";
1324 :
1325 : // this failed with an error, no need to check the "broken" output
1326 :
1327 1 : VERIFY_ERRORS(
1328 : "test.css(1): error: Block expected to end with CLOSE_PARENTHESIS but got CLOSE_CURLYBRACKET instead.\n"
1329 : );
1330 1 : }
1331 :
1332 : // no error left over
1333 1 : VERIFY_ERRORS("");
1334 1 : }
1335 :
1336 1 : CATCH_TEST_CASE("Simple one component value", "[parser] [component-value]")
1337 : {
1338 : // a simple valid rule
1339 : {
1340 1 : std::stringstream ss;
1341 : ss << " body { background : gradient(to bottom, #012, #384513 75%, #452) }"
1342 1 : << " @media screen { viewport: 1000px 500px; }";
1343 3 : csspp::position pos("test.css");
1344 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1345 :
1346 2 : csspp::parser p(l);
1347 :
1348 1 : char const *results[] =
1349 : {
1350 : "WHITESPACE\n",
1351 :
1352 : "IDENTIFIER \"body\"\n",
1353 :
1354 : "WHITESPACE\n",
1355 :
1356 : "OPEN_CURLYBRACKET B:false\n"
1357 : " COMPONENT_VALUE\n"
1358 : " IDENTIFIER \"background\"\n"
1359 : " WHITESPACE\n"
1360 : " COLON\n"
1361 : " WHITESPACE\n"
1362 : " FUNCTION \"gradient\"\n"
1363 : " IDENTIFIER \"to\"\n"
1364 : " WHITESPACE\n"
1365 : " IDENTIFIER \"bottom\"\n"
1366 : " COMMA\n"
1367 : " WHITESPACE\n"
1368 : " HASH \"012\"\n"
1369 : " COMMA\n"
1370 : " WHITESPACE\n"
1371 : " HASH \"384513\"\n"
1372 : " WHITESPACE\n"
1373 : " PERCENT D:0.75\n"
1374 : " COMMA\n"
1375 : " WHITESPACE\n"
1376 : " HASH \"452\"\n",
1377 :
1378 : "WHITESPACE\n",
1379 :
1380 : "AT_KEYWORD \"media\" I:0\n",
1381 :
1382 : "WHITESPACE\n",
1383 :
1384 : "IDENTIFIER \"screen\"\n",
1385 :
1386 : "WHITESPACE\n",
1387 :
1388 : "OPEN_CURLYBRACKET B:false\n"
1389 : " COMPONENT_VALUE\n"
1390 : " IDENTIFIER \"viewport\"\n"
1391 : " COLON\n"
1392 : " WHITESPACE\n"
1393 : " INTEGER \"px\" I:1000\n"
1394 : " WHITESPACE\n"
1395 : " INTEGER \"px\" I:500\n",
1396 :
1397 : // make sure to keep the following to make sure we got everything
1398 : // through the parser
1399 : "EOF_TOKEN\n"
1400 : };
1401 :
1402 12 : for(size_t i(0); i < sizeof(results) / sizeof(results[0]); ++i)
1403 : {
1404 11 : csspp::node::pointer_t n(p.component_value());
1405 11 : std::stringstream out;
1406 11 : out << *n;
1407 11 : VERIFY_TREES(out.str(), results[i]);
1408 11 : csspp_test::compare(out.str(), results[i], __FILE__, i + 1);
1409 11 : }
1410 :
1411 1 : }
1412 :
1413 : // no error left over
1414 1 : VERIFY_ERRORS("");
1415 1 : }
1416 :
1417 1 : CATCH_TEST_CASE("Invalid one component value", "[parser] [component-value] [invalid]")
1418 : {
1419 : // breaks on missing }
1420 : {
1421 1 : std::stringstream ss;
1422 1 : ss << "body { background : 123";
1423 3 : csspp::position pos("test.css");
1424 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1425 :
1426 2 : csspp::parser p(l);
1427 :
1428 1 : char const *results[] =
1429 : {
1430 : "IDENTIFIER \"body\"\n",
1431 :
1432 : "WHITESPACE\n",
1433 :
1434 : "OPEN_CURLYBRACKET B:false\n"
1435 : " COMPONENT_VALUE\n"
1436 : " IDENTIFIER \"background\"\n"
1437 : " WHITESPACE\n"
1438 : " COLON\n"
1439 : " WHITESPACE\n"
1440 : " INTEGER \"\" I:123\n",
1441 :
1442 : // make sure to keep the following to make sure we got everything
1443 : // through the parser
1444 : "EOF_TOKEN\n"
1445 : };
1446 :
1447 5 : for(size_t i(0); i < sizeof(results) / sizeof(results[0]); ++i)
1448 : {
1449 4 : csspp::node::pointer_t n(p.component_value());
1450 4 : std::stringstream out;
1451 4 : out << *n;
1452 4 : VERIFY_TREES(out.str(), results[i]);
1453 4 : csspp_test::compare(out.str(), results[i], __FILE__, i + 1);
1454 4 : }
1455 :
1456 1 : VERIFY_ERRORS("test.css(1): error: Block expected to end with CLOSE_CURLYBRACKET but got EOF_TOKEN instead.\n");
1457 1 : }
1458 :
1459 : // breaks on missing ]
1460 : {
1461 1 : std::stringstream ss;
1462 1 : ss << "body[color='55'";
1463 3 : csspp::position pos("test.css");
1464 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1465 :
1466 2 : csspp::parser p(l);
1467 :
1468 1 : char const *results[] =
1469 : {
1470 : "IDENTIFIER \"body\"\n",
1471 :
1472 : "OPEN_SQUAREBRACKET\n"
1473 : " IDENTIFIER \"color\"\n"
1474 : " EQUAL\n"
1475 : " STRING \"55\"\n",
1476 :
1477 : // make sure to keep the following to make sure we got everything
1478 : // through the parser
1479 : "EOF_TOKEN\n"
1480 : };
1481 :
1482 4 : for(size_t i(0); i < sizeof(results) / sizeof(results[0]); ++i)
1483 : {
1484 3 : csspp::node::pointer_t n(p.component_value());
1485 3 : std::stringstream out;
1486 3 : out << *n;
1487 3 : VERIFY_TREES(out.str(), results[i]);
1488 3 : csspp_test::compare(out.str(), results[i], __FILE__, i + 1);
1489 3 : }
1490 :
1491 1 : VERIFY_ERRORS("test.css(1): error: Block expected to end with CLOSE_SQUAREBRACKET but got EOF_TOKEN instead.\n");
1492 1 : }
1493 :
1494 : // breaks on missing )
1495 : {
1496 1 : std::stringstream ss;
1497 1 : ss << "body{color:rgba(1,2}";
1498 3 : csspp::position pos("test.css");
1499 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1500 :
1501 2 : csspp::parser p(l);
1502 :
1503 1 : char const *results[] =
1504 : {
1505 : "IDENTIFIER \"body\"\n",
1506 :
1507 : "OPEN_CURLYBRACKET B:false\n"
1508 : " COMPONENT_VALUE\n"
1509 : " IDENTIFIER \"color\"\n"
1510 : " COLON\n"
1511 : " FUNCTION \"rgba\"\n"
1512 : " INTEGER \"\" I:1\n"
1513 : " COMMA\n"
1514 : " INTEGER \"\" I:2\n",
1515 :
1516 : // make sure to keep the following to make sure we got everything
1517 : // through the parser
1518 : "EOF_TOKEN\n"
1519 : };
1520 :
1521 4 : for(size_t i(0); i < sizeof(results) / sizeof(results[0]); ++i)
1522 : {
1523 3 : csspp::node::pointer_t n(p.component_value());
1524 3 : std::stringstream out;
1525 3 : out << *n;
1526 3 : VERIFY_TREES(out.str(), results[i]);
1527 3 : csspp_test::compare(out.str(), results[i], __FILE__, i + 1);
1528 3 : }
1529 :
1530 1 : VERIFY_ERRORS("test.css(1): error: Block expected to end with CLOSE_PARENTHESIS but got CLOSE_CURLYBRACKET instead.\n");
1531 1 : }
1532 :
1533 : // no error left over
1534 1 : VERIFY_ERRORS("");
1535 1 : }
1536 :
1537 1 : CATCH_TEST_CASE("Simple declarations", "[parser] [declaration]")
1538 : {
1539 : // a simple valid declaration
1540 : {
1541 1 : std::stringstream ss;
1542 1 : ss << " background : gradient(to bottom, #012, #384513 75%, #452) { width: 300px } ";
1543 3 : csspp::position pos("test.css");
1544 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1545 :
1546 2 : csspp::parser p(l);
1547 :
1548 : // rule list does not like <!-- and -->
1549 1 : csspp::node::pointer_t n(p.declaration_list());
1550 :
1551 : //std::cerr << "Result is: [" << *n << "]\n";
1552 :
1553 1 : std::stringstream out;
1554 1 : out << *n;
1555 1 : VERIFY_TREES(out.str(),
1556 :
1557 : "LIST\n"
1558 : " DECLARATION \"background\"\n"
1559 : " COMPONENT_VALUE\n"
1560 : " FUNCTION \"gradient\"\n"
1561 : " IDENTIFIER \"to\"\n"
1562 : " WHITESPACE\n"
1563 : " IDENTIFIER \"bottom\"\n"
1564 : " COMMA\n"
1565 : " WHITESPACE\n"
1566 : " HASH \"012\"\n"
1567 : " COMMA\n"
1568 : " WHITESPACE\n"
1569 : " HASH \"384513\"\n"
1570 : " WHITESPACE\n"
1571 : " PERCENT D:0.75\n"
1572 : " COMMA\n"
1573 : " WHITESPACE\n"
1574 : " HASH \"452\"\n"
1575 : " OPEN_CURLYBRACKET B:false\n"
1576 : " COMPONENT_VALUE\n"
1577 : " IDENTIFIER \"width\"\n"
1578 : " COLON\n"
1579 : " WHITESPACE\n"
1580 : " INTEGER \"px\" I:300\n"
1581 :
1582 : );
1583 :
1584 : // no error left over
1585 1 : VERIFY_ERRORS("");
1586 1 : }
1587 :
1588 : // a @-rule in a declaration
1589 : {
1590 1 : std::stringstream ss;
1591 1 : ss << " @enhanced capabilities { background : gradient(to bottom, #012, #384513 75%, #452) } ";
1592 3 : csspp::position pos("test.css");
1593 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1594 :
1595 2 : csspp::parser p(l);
1596 :
1597 : // rule list does not like <!-- and -->
1598 1 : csspp::node::pointer_t n(p.declaration_list());
1599 :
1600 : //std::cerr << "Result is: [" << *n << "]\n";
1601 :
1602 1 : std::stringstream out;
1603 1 : out << *n;
1604 1 : VERIFY_TREES(out.str(),
1605 :
1606 : "LIST\n"
1607 : " AT_KEYWORD \"enhanced\" I:0\n"
1608 : " IDENTIFIER \"capabilities\"\n"
1609 : " OPEN_CURLYBRACKET B:false\n"
1610 : " COMPONENT_VALUE\n"
1611 : " IDENTIFIER \"background\"\n"
1612 : " WHITESPACE\n"
1613 : " COLON\n"
1614 : " WHITESPACE\n"
1615 : " FUNCTION \"gradient\"\n"
1616 : " IDENTIFIER \"to\"\n"
1617 : " WHITESPACE\n"
1618 : " IDENTIFIER \"bottom\"\n"
1619 : " COMMA\n"
1620 : " WHITESPACE\n"
1621 : " HASH \"012\"\n"
1622 : " COMMA\n"
1623 : " WHITESPACE\n"
1624 : " HASH \"384513\"\n"
1625 : " WHITESPACE\n"
1626 : " PERCENT D:0.75\n"
1627 : " COMMA\n"
1628 : " WHITESPACE\n"
1629 : " HASH \"452\"\n"
1630 :
1631 : );
1632 :
1633 : // no error left over
1634 1 : VERIFY_ERRORS("");
1635 1 : }
1636 :
1637 : // multiple declarations require a ';'
1638 : {
1639 1 : std::stringstream ss;
1640 1 : ss << "a: 33px; b: 66px; c: 123px";
1641 3 : csspp::position pos("test.css");
1642 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1643 :
1644 2 : csspp::parser p(l);
1645 :
1646 : // rule list does not like <!-- and -->
1647 1 : csspp::node::pointer_t n(p.declaration_list());
1648 :
1649 : //std::cerr << "Result is: [" << *n << "]\n";
1650 :
1651 1 : std::stringstream out;
1652 1 : out << *n;
1653 1 : VERIFY_TREES(out.str(),
1654 :
1655 : "LIST\n"
1656 : " DECLARATION \"a\"\n"
1657 : " COMPONENT_VALUE\n"
1658 : " INTEGER \"px\" I:33\n"
1659 : " DECLARATION \"b\"\n"
1660 : " COMPONENT_VALUE\n"
1661 : " INTEGER \"px\" I:66\n"
1662 : " DECLARATION \"c\"\n"
1663 : " COMPONENT_VALUE\n"
1664 : " INTEGER \"px\" I:123\n"
1665 :
1666 : );
1667 :
1668 : // no error left over
1669 1 : VERIFY_ERRORS("");
1670 1 : }
1671 :
1672 : // multiple declarations require a ';'
1673 : {
1674 1 : std::stringstream ss;
1675 1 : ss << "a: 33px ! important ; b: 66px !global ; c: 123px 55em !import";
1676 3 : csspp::position pos("test.css");
1677 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1678 :
1679 2 : csspp::parser p(l);
1680 :
1681 : // rule list does not like <!-- and -->
1682 1 : csspp::node::pointer_t n(p.declaration_list());
1683 :
1684 : //std::cerr << "Result is: [" << *n << "]\n";
1685 :
1686 1 : std::stringstream out;
1687 1 : out << *n;
1688 1 : VERIFY_TREES(out.str(),
1689 :
1690 : "LIST\n"
1691 : " DECLARATION \"a\"\n"
1692 : " COMPONENT_VALUE\n"
1693 : " INTEGER \"px\" I:33\n"
1694 : " EXCLAMATION \"important\"\n"
1695 : " DECLARATION \"b\"\n"
1696 : " COMPONENT_VALUE\n"
1697 : " INTEGER \"px\" I:66\n"
1698 : " EXCLAMATION \"global\"\n"
1699 : " DECLARATION \"c\"\n"
1700 : " COMPONENT_VALUE\n"
1701 : " INTEGER \"px\" I:123\n"
1702 : " WHITESPACE\n"
1703 : " INTEGER \"em\" I:55\n"
1704 : " EXCLAMATION \"import\"\n"
1705 :
1706 : );
1707 :
1708 : // no error left over
1709 1 : VERIFY_ERRORS("");
1710 1 : }
1711 1 : }
1712 :
1713 1 : CATCH_TEST_CASE("Invalid declarations", "[parser] [declaration] [invalid]")
1714 : {
1715 : // declarations must end with EOF
1716 : {
1717 1 : std::stringstream ss;
1718 1 : ss << " background : gradient(to bottom, #012, #384513 75%, #452) { width: 300px } <!--";
1719 3 : csspp::position pos("test.css");
1720 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1721 :
1722 2 : csspp::parser p(l);
1723 :
1724 : // rule list does not like <!-- and -->
1725 1 : csspp::node::pointer_t n(p.declaration_list());
1726 :
1727 : //std::cerr << "Result is: [" << *n << "]\n";
1728 :
1729 1 : VERIFY_ERRORS("test.css(1): error: the end of the stream was not reached in this declaration, we stopped on a CDO.\n");
1730 1 : }
1731 :
1732 : // declarations missing a ':'
1733 : {
1734 1 : std::stringstream ss;
1735 1 : ss << " background gradient(to bottom, #012, #384513 75%, #452) { width: 300px } ";
1736 3 : csspp::position pos("test.css");
1737 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1738 :
1739 2 : csspp::parser p(l);
1740 :
1741 : // rule list does not like <!-- and -->
1742 1 : csspp::node::pointer_t n(p.declaration_list());
1743 :
1744 : //std::cerr << "Result is: [" << *n << "]\n";
1745 :
1746 1 : VERIFY_ERRORS(
1747 : "test.css(1): error: ':' missing in your declaration starting with \"background\".\n"
1748 : );
1749 1 : }
1750 :
1751 : // '!' without an identifier
1752 : {
1753 1 : std::stringstream ss;
1754 1 : ss << "background: !gradient(to bottom, #012, #384513 75%, #452)";
1755 3 : csspp::position pos("test.css");
1756 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1757 :
1758 2 : csspp::parser p(l);
1759 :
1760 : // rule list does not like <!-- and -->
1761 1 : csspp::node::pointer_t n(p.declaration_list());
1762 :
1763 : //std::cerr << "Result is: [" << *n << "]\n";
1764 :
1765 1 : VERIFY_ERRORS(
1766 : "test.css(1): error: A '!' must be followed by an identifier, got a FUNCTION instead.\n"
1767 : //"test.css(1): error: the end of the stream was not reached in this declaration, we stopped on a FUNCTION.\n"
1768 : );
1769 1 : }
1770 :
1771 : // no error left over
1772 1 : VERIFY_ERRORS("");
1773 1 : }
1774 :
1775 1 : CATCH_TEST_CASE("Multi-line, multi-level stylesheet", "[parser] [rules]")
1776 : {
1777 : {
1778 1 : std::stringstream ss;
1779 : ss << "body { background : white url( /images/background.png ) }"
1780 : "div.power-house { !important margin: 0; color: red ; }"
1781 : "a { text-decoration: none; }"
1782 : "$green: #080;"
1783 : "#doll { background-color: $green; &:hover { color: teal; } }"
1784 1 : "@supports (background-color and border-radius) or (background-image) { body > E ~ F + G H { font-style: italic } }"
1785 : ;
1786 3 : csspp::position pos("test.css");
1787 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1788 :
1789 2 : csspp::parser p(l);
1790 :
1791 1 : csspp::node::pointer_t n(p.stylesheet());
1792 :
1793 : // no error happened
1794 1 : VERIFY_ERRORS("");
1795 :
1796 : //std::cerr << "Result is: [" << *n << "]\n";
1797 :
1798 1 : std::stringstream out;
1799 1 : out << *n;
1800 1 : VERIFY_TREES(out.str(),
1801 :
1802 : "LIST\n"
1803 : " COMPONENT_VALUE\n"
1804 : " IDENTIFIER \"body\"\n"
1805 : " OPEN_CURLYBRACKET B:false\n"
1806 : " COMPONENT_VALUE\n"
1807 : " IDENTIFIER \"background\"\n"
1808 : " WHITESPACE\n"
1809 : " COLON\n"
1810 : " WHITESPACE\n"
1811 : " IDENTIFIER \"white\"\n"
1812 : " WHITESPACE\n"
1813 : " URL \"/images/background.png\"\n"
1814 : " COMPONENT_VALUE\n"
1815 : " IDENTIFIER \"div\"\n"
1816 : " PERIOD\n"
1817 : " IDENTIFIER \"power-house\"\n"
1818 : " OPEN_CURLYBRACKET B:false\n"
1819 : " LIST\n"
1820 : " COMPONENT_VALUE\n"
1821 : " EXCLAMATION \"important\"\n"
1822 : " IDENTIFIER \"margin\"\n"
1823 : " COLON\n"
1824 : " WHITESPACE\n"
1825 : " INTEGER \"\" I:0\n"
1826 : " COMPONENT_VALUE\n"
1827 : " IDENTIFIER \"color\"\n"
1828 : " COLON\n"
1829 : " WHITESPACE\n"
1830 : " IDENTIFIER \"red\"\n"
1831 : " COMPONENT_VALUE\n"
1832 : " IDENTIFIER \"a\"\n"
1833 : " OPEN_CURLYBRACKET B:false\n"
1834 : " COMPONENT_VALUE\n"
1835 : " IDENTIFIER \"text-decoration\"\n"
1836 : " COLON\n"
1837 : " WHITESPACE\n"
1838 : " IDENTIFIER \"none\"\n"
1839 : " COMPONENT_VALUE\n"
1840 : " VARIABLE \"green\"\n"
1841 : " COLON\n"
1842 : " WHITESPACE\n"
1843 : " HASH \"080\"\n"
1844 : " COMPONENT_VALUE\n"
1845 : " HASH \"doll\"\n"
1846 : " OPEN_CURLYBRACKET B:false\n"
1847 : " LIST\n"
1848 : " COMPONENT_VALUE\n"
1849 : " IDENTIFIER \"background-color\"\n"
1850 : " COLON\n"
1851 : " WHITESPACE\n"
1852 : " VARIABLE \"green\"\n"
1853 : " COMPONENT_VALUE\n"
1854 : " REFERENCE\n"
1855 : " COLON\n"
1856 : " IDENTIFIER \"hover\"\n"
1857 : " OPEN_CURLYBRACKET B:false\n"
1858 : " COMPONENT_VALUE\n"
1859 : " IDENTIFIER \"color\"\n"
1860 : " COLON\n"
1861 : " WHITESPACE\n"
1862 : " IDENTIFIER \"teal\"\n"
1863 : " AT_KEYWORD \"supports\" I:0\n"
1864 : " OPEN_PARENTHESIS\n"
1865 : " IDENTIFIER \"background-color\"\n"
1866 : " WHITESPACE\n"
1867 : " IDENTIFIER \"and\"\n"
1868 : " WHITESPACE\n"
1869 : " IDENTIFIER \"border-radius\"\n"
1870 : " WHITESPACE\n"
1871 : " IDENTIFIER \"or\"\n"
1872 : " OPEN_PARENTHESIS\n"
1873 : " IDENTIFIER \"background-image\"\n"
1874 : " OPEN_CURLYBRACKET B:false\n"
1875 : " COMPONENT_VALUE\n"
1876 : " IDENTIFIER \"body\"\n"
1877 : " WHITESPACE\n"
1878 : " GREATER_THAN\n"
1879 : " WHITESPACE\n"
1880 : " IDENTIFIER \"E\"\n"
1881 : " WHITESPACE\n"
1882 : " PRECEDED\n"
1883 : " WHITESPACE\n"
1884 : " IDENTIFIER \"F\"\n"
1885 : " WHITESPACE\n"
1886 : " ADD\n"
1887 : " WHITESPACE\n"
1888 : " IDENTIFIER \"G\"\n"
1889 : " WHITESPACE\n"
1890 : " IDENTIFIER \"H\"\n"
1891 : " OPEN_CURLYBRACKET B:false\n"
1892 : " COMPONENT_VALUE\n"
1893 : " IDENTIFIER \"font-style\"\n"
1894 : " COLON\n"
1895 : " WHITESPACE\n"
1896 : " IDENTIFIER \"italic\"\n"
1897 :
1898 : );
1899 1 : }
1900 :
1901 : // no error left over
1902 1 : VERIFY_ERRORS("");
1903 1 : }
1904 :
1905 1 : CATCH_TEST_CASE("Is variable set", "[parser] [variable] [invalid]")
1906 : {
1907 : // simple test with a value + value (SASS compatible)
1908 : {
1909 1 : std::stringstream ss;
1910 1 : ss << "$a: 33px;";
1911 3 : csspp::position pos("test.css");
1912 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1913 :
1914 2 : csspp::parser p(l);
1915 :
1916 1 : csspp::node::pointer_t n(p.stylesheet());
1917 :
1918 : // no error happened
1919 1 : VERIFY_ERRORS("");
1920 :
1921 : //std::cerr << "Result is: [" << *n << "]\n";
1922 :
1923 1 : std::stringstream out;
1924 1 : out << *n;
1925 1 : VERIFY_TREES(out.str(),
1926 :
1927 : "LIST\n"
1928 : " COMPONENT_VALUE\n"
1929 : " VARIABLE \"a\"\n"
1930 : " COLON\n"
1931 : " WHITESPACE\n"
1932 : " INTEGER \"px\" I:33\n"
1933 :
1934 : );
1935 :
1936 1 : csspp::node::pointer_t var(n->get_child(0));
1937 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, false));
1938 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, true));
1939 1 : }
1940 :
1941 : // case were we actually use a variable to define a selector
1942 : // this is not a variable set
1943 : {
1944 1 : std::stringstream ss;
1945 1 : ss << "$a .cute { color: red; }";
1946 3 : csspp::position pos("test.css");
1947 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1948 :
1949 2 : csspp::parser p(l);
1950 :
1951 1 : csspp::node::pointer_t n(p.stylesheet());
1952 :
1953 : // no error happened
1954 1 : VERIFY_ERRORS("");
1955 :
1956 : //std::cerr << "Result is: [" << *n << "]\n";
1957 :
1958 1 : std::stringstream out;
1959 1 : out << *n;
1960 1 : VERIFY_TREES(out.str(),
1961 :
1962 : "LIST\n"
1963 : " COMPONENT_VALUE\n"
1964 : " VARIABLE \"a\"\n"
1965 : " WHITESPACE\n"
1966 : " PERIOD\n"
1967 : " IDENTIFIER \"cute\"\n"
1968 : " OPEN_CURLYBRACKET B:false\n"
1969 : " COMPONENT_VALUE\n"
1970 : " IDENTIFIER \"color\"\n"
1971 : " COLON\n"
1972 : " WHITESPACE\n"
1973 : " IDENTIFIER \"red\"\n"
1974 :
1975 : );
1976 :
1977 1 : csspp::node::pointer_t var(n->get_child(0));
1978 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, false));
1979 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, true));
1980 1 : }
1981 :
1982 : // test with a variable block
1983 : {
1984 1 : std::stringstream ss;
1985 1 : ss << "$a: { color: red; };";
1986 3 : csspp::position pos("test.css");
1987 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1988 :
1989 2 : csspp::parser p(l);
1990 :
1991 1 : csspp::node::pointer_t n(p.stylesheet());
1992 :
1993 : // no error happened
1994 1 : VERIFY_ERRORS("");
1995 :
1996 : //std::cerr << "Result is: [" << *n << "]\n";
1997 :
1998 1 : std::stringstream out;
1999 1 : out << *n;
2000 1 : VERIFY_TREES(out.str(),
2001 :
2002 : "LIST\n"
2003 : " COMPONENT_VALUE\n"
2004 : " VARIABLE \"a\"\n"
2005 : " COLON\n"
2006 : " OPEN_CURLYBRACKET B:false\n"
2007 : " COMPONENT_VALUE\n"
2008 : " IDENTIFIER \"color\"\n"
2009 : " COLON\n"
2010 : " WHITESPACE\n"
2011 : " IDENTIFIER \"red\"\n"
2012 :
2013 : );
2014 :
2015 1 : csspp::node::pointer_t var(n->get_child(0));
2016 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, false));
2017 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, true));
2018 1 : }
2019 :
2020 : // test with the missing ';'
2021 : {
2022 1 : std::stringstream ss;
2023 1 : ss << "$a: { color: red; }";
2024 3 : csspp::position pos("test.css");
2025 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2026 :
2027 2 : csspp::parser p(l);
2028 :
2029 1 : csspp::node::pointer_t n(p.stylesheet());
2030 :
2031 : // the ';' at the end is missing
2032 1 : VERIFY_ERRORS("test.css(1): error: Variable set to a block and a nested property block must end with a semicolon (;) after said block.\n");
2033 1 : }
2034 :
2035 : // simple test with a value + value (SASS compatible)
2036 : {
2037 1 : std::stringstream ss;
2038 1 : ss << "$a($arg1): 33px;";
2039 3 : csspp::position pos("test.css");
2040 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2041 :
2042 2 : csspp::parser p(l);
2043 :
2044 1 : csspp::node::pointer_t n(p.stylesheet());
2045 :
2046 : // no error happened
2047 1 : VERIFY_ERRORS("");
2048 :
2049 : //std::cerr << "Result is: [" << *n << "]\n";
2050 :
2051 1 : std::stringstream out;
2052 1 : out << *n;
2053 1 : VERIFY_TREES(out.str(),
2054 :
2055 : "LIST\n"
2056 : " COMPONENT_VALUE\n"
2057 : " VARIABLE_FUNCTION \"a\"\n"
2058 : " VARIABLE \"arg1\"\n"
2059 : " COLON\n"
2060 : " WHITESPACE\n"
2061 : " INTEGER \"px\" I:33\n"
2062 :
2063 : );
2064 :
2065 1 : csspp::node::pointer_t var(n->get_child(0));
2066 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, false));
2067 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, true));
2068 1 : }
2069 :
2070 : // case were we actually use a variable to define a selector
2071 : // this is not a variable set
2072 : {
2073 1 : std::stringstream ss;
2074 1 : ss << "$a(33) .cute { color: red; }";
2075 3 : csspp::position pos("test.css");
2076 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2077 :
2078 2 : csspp::parser p(l);
2079 :
2080 1 : csspp::node::pointer_t n(p.stylesheet());
2081 :
2082 : // no error happened
2083 1 : VERIFY_ERRORS("");
2084 :
2085 : //std::cerr << "Result is: [" << *n << "]\n";
2086 :
2087 1 : std::stringstream out;
2088 1 : out << *n;
2089 1 : VERIFY_TREES(out.str(),
2090 :
2091 : "LIST\n"
2092 : " COMPONENT_VALUE\n"
2093 : " VARIABLE_FUNCTION \"a\"\n"
2094 : " INTEGER \"\" I:33\n"
2095 : " WHITESPACE\n"
2096 : " PERIOD\n"
2097 : " IDENTIFIER \"cute\"\n"
2098 : " OPEN_CURLYBRACKET B:false\n"
2099 : " COMPONENT_VALUE\n"
2100 : " IDENTIFIER \"color\"\n"
2101 : " COLON\n"
2102 : " WHITESPACE\n"
2103 : " IDENTIFIER \"red\"\n"
2104 :
2105 : );
2106 :
2107 1 : csspp::node::pointer_t var(n->get_child(0));
2108 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, false));
2109 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_variable_set(var, true));
2110 1 : }
2111 :
2112 : // test with a variable block
2113 : {
2114 1 : std::stringstream ss;
2115 1 : ss << "$a($arg1): { color: red; };";
2116 3 : csspp::position pos("test.css");
2117 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2118 :
2119 2 : csspp::parser p(l);
2120 :
2121 1 : csspp::node::pointer_t n(p.stylesheet());
2122 :
2123 : // no error happened
2124 1 : VERIFY_ERRORS("");
2125 :
2126 : //std::cerr << "Result is: [" << *n << "]\n";
2127 :
2128 1 : std::stringstream out;
2129 1 : out << *n;
2130 1 : VERIFY_TREES(out.str(),
2131 :
2132 : "LIST\n"
2133 : " COMPONENT_VALUE\n"
2134 : " VARIABLE_FUNCTION \"a\"\n"
2135 : " VARIABLE \"arg1\"\n"
2136 : " COLON\n"
2137 : " OPEN_CURLYBRACKET B:false\n"
2138 : " COMPONENT_VALUE\n"
2139 : " IDENTIFIER \"color\"\n"
2140 : " COLON\n"
2141 : " WHITESPACE\n"
2142 : " IDENTIFIER \"red\"\n"
2143 :
2144 : );
2145 :
2146 1 : csspp::node::pointer_t var(n->get_child(0));
2147 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, false));
2148 1 : CATCH_REQUIRE(csspp::parser::is_variable_set(var, true));
2149 1 : }
2150 :
2151 : // test with the missing ';'
2152 : {
2153 1 : std::stringstream ss;
2154 1 : ss << "$a($arg1): { color: red; }";
2155 3 : csspp::position pos("test.css");
2156 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2157 :
2158 2 : csspp::parser p(l);
2159 :
2160 1 : csspp::node::pointer_t n(p.stylesheet());
2161 :
2162 : // the ';' at the end is missing
2163 1 : VERIFY_ERRORS("test.css(1): error: Variable set to a block and a nested property block must end with a semicolon (;) after said block.\n");
2164 1 : }
2165 :
2166 : // no error left over
2167 1 : VERIFY_ERRORS("");
2168 1 : }
2169 :
2170 1 : CATCH_TEST_CASE("Is nested declaration", "[parser] [variable] [invalid]")
2171 : {
2172 : // which a field name with a simple nested declaration
2173 : {
2174 1 : std::stringstream ss;
2175 1 : ss << "width : { color : red } ;";
2176 3 : csspp::position pos("test.css");
2177 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2178 :
2179 2 : csspp::parser p(l);
2180 :
2181 1 : csspp::node::pointer_t n(p.stylesheet());
2182 :
2183 : // no error happened
2184 1 : VERIFY_ERRORS("");
2185 :
2186 : //std::cerr << "Result is: [" << *n << "]\n";
2187 :
2188 1 : std::stringstream out;
2189 1 : out << *n;
2190 1 : VERIFY_TREES(out.str(),
2191 :
2192 : "LIST\n"
2193 : " COMPONENT_VALUE\n"
2194 : " IDENTIFIER \"width\"\n"
2195 : " WHITESPACE\n"
2196 : " COLON\n"
2197 : " OPEN_CURLYBRACKET B:false\n"
2198 : " COMPONENT_VALUE\n"
2199 : " IDENTIFIER \"color\"\n"
2200 : " WHITESPACE\n"
2201 : " COLON\n"
2202 : " WHITESPACE\n"
2203 : " IDENTIFIER \"red\"\n"
2204 :
2205 : );
2206 :
2207 1 : csspp::node::pointer_t var(n->get_child(0));
2208 1 : CATCH_REQUIRE(csspp::parser::is_nested_declaration(var));
2209 1 : }
2210 :
2211 : // which a field name with a simple nested declaration
2212 : {
2213 1 : std::stringstream ss;
2214 1 : ss << "width :nth-child(3n+2) span{ color : red } ";
2215 3 : csspp::position pos("test.css");
2216 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2217 :
2218 2 : csspp::parser p(l);
2219 :
2220 1 : csspp::node::pointer_t n(p.stylesheet());
2221 :
2222 : // no error happened
2223 1 : VERIFY_ERRORS("");
2224 :
2225 : //std::cerr << "Result is: [" << *n << "]\n";
2226 :
2227 1 : std::stringstream out;
2228 1 : out << *n;
2229 1 : VERIFY_TREES(out.str(),
2230 :
2231 : "LIST\n"
2232 : " COMPONENT_VALUE\n"
2233 : " IDENTIFIER \"width\"\n"
2234 : " WHITESPACE\n"
2235 : " COLON\n"
2236 : " FUNCTION \"nth-child\"\n"
2237 : " INTEGER \"n\" I:3\n"
2238 : " INTEGER \"\" I:2\n"
2239 : " WHITESPACE\n"
2240 : " IDENTIFIER \"span\"\n"
2241 : " OPEN_CURLYBRACKET B:false\n"
2242 : " COMPONENT_VALUE\n"
2243 : " IDENTIFIER \"color\"\n"
2244 : " WHITESPACE\n"
2245 : " COLON\n"
2246 : " WHITESPACE\n"
2247 : " IDENTIFIER \"red\"\n"
2248 :
2249 : );
2250 :
2251 1 : csspp::node::pointer_t var(n->get_child(0));
2252 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(var));
2253 1 : }
2254 :
2255 : // which a field name with a simple nested declaration
2256 : {
2257 1 : std::stringstream ss;
2258 1 : ss << "width :not(.color) { color : red } ";
2259 3 : csspp::position pos("test.css");
2260 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2261 :
2262 2 : csspp::parser p(l);
2263 :
2264 1 : csspp::node::pointer_t n(p.stylesheet());
2265 :
2266 : // no error happened
2267 1 : VERIFY_ERRORS("");
2268 :
2269 : //std::cerr << "Result is: [" << *n << "]\n";
2270 :
2271 1 : std::stringstream out;
2272 1 : out << *n;
2273 1 : VERIFY_TREES(out.str(),
2274 :
2275 : "LIST\n"
2276 : " COMPONENT_VALUE\n"
2277 : " IDENTIFIER \"width\"\n"
2278 : " WHITESPACE\n"
2279 : " COLON\n"
2280 : " FUNCTION \"not\"\n"
2281 : " PERIOD\n"
2282 : " IDENTIFIER \"color\"\n"
2283 : " OPEN_CURLYBRACKET B:false\n"
2284 : " COMPONENT_VALUE\n"
2285 : " IDENTIFIER \"color\"\n"
2286 : " WHITESPACE\n"
2287 : " COLON\n"
2288 : " WHITESPACE\n"
2289 : " IDENTIFIER \"red\"\n"
2290 :
2291 : );
2292 :
2293 1 : csspp::node::pointer_t var(n->get_child(0));
2294 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(var));
2295 1 : }
2296 :
2297 : // in this case it is clear that none are declarations
2298 : // (although the span:not() is not valid since it is
2299 : // missing the {}-block at the end)
2300 : {
2301 1 : std::stringstream ss;
2302 1 : ss << "div { span :not(.wrap); p { color : red } } ";
2303 3 : csspp::position pos("test.css");
2304 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2305 :
2306 2 : csspp::parser p(l);
2307 :
2308 1 : csspp::node::pointer_t n(p.stylesheet());
2309 :
2310 : // no error happened
2311 1 : VERIFY_ERRORS("");
2312 :
2313 : //std::cerr << "Result is: [" << *n << "]\n";
2314 :
2315 1 : std::stringstream out;
2316 1 : out << *n;
2317 1 : VERIFY_TREES(out.str(),
2318 :
2319 : "LIST\n"
2320 : " COMPONENT_VALUE\n"
2321 : " IDENTIFIER \"div\"\n"
2322 : " OPEN_CURLYBRACKET B:false\n"
2323 : " LIST\n"
2324 : " COMPONENT_VALUE\n"
2325 : " IDENTIFIER \"span\"\n"
2326 : " WHITESPACE\n"
2327 : " COLON\n"
2328 : " FUNCTION \"not\"\n"
2329 : " PERIOD\n"
2330 : " IDENTIFIER \"wrap\"\n"
2331 : " COMPONENT_VALUE\n"
2332 : " IDENTIFIER \"p\"\n"
2333 : " OPEN_CURLYBRACKET B:false\n"
2334 : " COMPONENT_VALUE\n"
2335 : " IDENTIFIER \"color\"\n"
2336 : " WHITESPACE\n"
2337 : " COLON\n"
2338 : " WHITESPACE\n"
2339 : " IDENTIFIER \"red\"\n"
2340 :
2341 : );
2342 :
2343 : // check the first COMPONENT_VALUE
2344 1 : csspp::node::pointer_t div(n->get_child(0));
2345 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2346 :
2347 : // check the second COMPONENT_VALUE
2348 4 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0)->get_child(0));
2349 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2350 :
2351 : // check the third COMPONENT_VALUE
2352 4 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(1));
2353 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2354 1 : }
2355 :
2356 : // in this case it is clear that none are declarations
2357 : // (although the span:not() is not valid since it is
2358 : // missing the {}-block at the end)
2359 : {
2360 1 : std::stringstream ss;
2361 1 : ss << "div { span : { color : red }; } ";
2362 3 : csspp::position pos("test.css");
2363 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2364 :
2365 2 : csspp::parser p(l);
2366 :
2367 1 : csspp::node::pointer_t n(p.stylesheet());
2368 :
2369 : // no error happened
2370 1 : VERIFY_ERRORS("");
2371 :
2372 : //std::cerr << "Result is: [" << *n << "]\n";
2373 :
2374 1 : std::stringstream out;
2375 1 : out << *n;
2376 1 : VERIFY_TREES(out.str(),
2377 :
2378 : "LIST\n"
2379 : " COMPONENT_VALUE\n"
2380 : " IDENTIFIER \"div\"\n"
2381 : " OPEN_CURLYBRACKET B:false\n"
2382 : " COMPONENT_VALUE\n"
2383 : " IDENTIFIER \"span\"\n"
2384 : " WHITESPACE\n"
2385 : " COLON\n"
2386 : " OPEN_CURLYBRACKET B:false\n"
2387 : " COMPONENT_VALUE\n"
2388 : " IDENTIFIER \"color\"\n"
2389 : " WHITESPACE\n"
2390 : " COLON\n"
2391 : " WHITESPACE\n"
2392 : " IDENTIFIER \"red\"\n"
2393 :
2394 : );
2395 :
2396 : // check the first COMPONENT_VALUE
2397 1 : csspp::node::pointer_t div(n->get_child(0));
2398 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2399 :
2400 : // check the second COMPONENT_VALUE
2401 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2402 1 : CATCH_REQUIRE(csspp::parser::is_nested_declaration(span));
2403 :
2404 : // check the third COMPONENT_VALUE
2405 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(3)->get_child(0));
2406 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2407 1 : }
2408 :
2409 : // ':' always marks a selector
2410 : {
2411 1 : std::stringstream ss;
2412 1 : ss << "div { span :section : { color : red }; } ";
2413 3 : csspp::position pos("test.css");
2414 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2415 :
2416 2 : csspp::parser p(l);
2417 :
2418 1 : csspp::node::pointer_t n(p.stylesheet());
2419 :
2420 : // no error happened
2421 1 : VERIFY_ERRORS("");
2422 :
2423 : //std::cerr << "Result is: [" << *n << "]\n";
2424 :
2425 1 : std::stringstream out;
2426 1 : out << *n;
2427 1 : VERIFY_TREES(out.str(),
2428 :
2429 : "LIST\n"
2430 : " COMPONENT_VALUE\n"
2431 : " IDENTIFIER \"div\"\n"
2432 : " OPEN_CURLYBRACKET B:false\n"
2433 : " COMPONENT_VALUE\n"
2434 : " IDENTIFIER \"span\"\n"
2435 : " WHITESPACE\n"
2436 : " COLON\n"
2437 : " IDENTIFIER \"section\"\n"
2438 : " WHITESPACE\n"
2439 : " COLON\n"
2440 : " OPEN_CURLYBRACKET B:false\n"
2441 : " COMPONENT_VALUE\n"
2442 : " IDENTIFIER \"color\"\n"
2443 : " WHITESPACE\n"
2444 : " COLON\n"
2445 : " WHITESPACE\n"
2446 : " IDENTIFIER \"red\"\n"
2447 : " LIST\n"
2448 :
2449 : );
2450 :
2451 : // check the first COMPONENT_VALUE
2452 1 : csspp::node::pointer_t div(n->get_child(0));
2453 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2454 :
2455 : // check the second COMPONENT_VALUE
2456 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2457 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2458 :
2459 : // check the third COMPONENT_VALUE
2460 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(6)->get_child(0));
2461 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2462 1 : }
2463 :
2464 : // '%<id>' always marks a selector
2465 : {
2466 1 : std::stringstream ss;
2467 1 : ss << "div { span :section%july { color : red }; } ";
2468 3 : csspp::position pos("test.css");
2469 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2470 :
2471 2 : csspp::parser p(l);
2472 :
2473 1 : csspp::node::pointer_t n(p.stylesheet());
2474 :
2475 : // no error happened
2476 1 : VERIFY_ERRORS("");
2477 :
2478 : //std::cerr << "Result is: [" << *n << "]\n";
2479 :
2480 1 : std::stringstream out;
2481 1 : out << *n;
2482 1 : VERIFY_TREES(out.str(),
2483 :
2484 : "LIST\n"
2485 : " COMPONENT_VALUE\n"
2486 : " IDENTIFIER \"div\"\n"
2487 : " OPEN_CURLYBRACKET B:false\n"
2488 : " COMPONENT_VALUE\n"
2489 : " IDENTIFIER \"span\"\n"
2490 : " WHITESPACE\n"
2491 : " COLON\n"
2492 : " IDENTIFIER \"section\"\n"
2493 : " PLACEHOLDER \"july\"\n"
2494 : " OPEN_CURLYBRACKET B:false\n"
2495 : " COMPONENT_VALUE\n"
2496 : " IDENTIFIER \"color\"\n"
2497 : " WHITESPACE\n"
2498 : " COLON\n"
2499 : " WHITESPACE\n"
2500 : " IDENTIFIER \"red\"\n"
2501 : " LIST\n"
2502 :
2503 : );
2504 :
2505 : // check the first COMPONENT_VALUE
2506 1 : csspp::node::pointer_t div(n->get_child(0));
2507 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2508 :
2509 : // check the second COMPONENT_VALUE
2510 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2511 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2512 :
2513 : // check the third COMPONENT_VALUE
2514 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(5)->get_child(0));
2515 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2516 1 : }
2517 :
2518 : // 'E ~ E' always marks a selector
2519 : {
2520 1 : std::stringstream ss;
2521 1 : ss << "div { span :section ~ july { color : red }; } ";
2522 3 : csspp::position pos("test.css");
2523 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2524 :
2525 2 : csspp::parser p(l);
2526 :
2527 1 : csspp::node::pointer_t n(p.stylesheet());
2528 :
2529 : // no error happened
2530 1 : VERIFY_ERRORS("");
2531 :
2532 : //std::cerr << "Result is: [" << *n << "]\n";
2533 :
2534 1 : std::stringstream out;
2535 1 : out << *n;
2536 1 : VERIFY_TREES(out.str(),
2537 :
2538 : "LIST\n"
2539 : " COMPONENT_VALUE\n"
2540 : " IDENTIFIER \"div\"\n"
2541 : " OPEN_CURLYBRACKET B:false\n"
2542 : " COMPONENT_VALUE\n"
2543 : " IDENTIFIER \"span\"\n"
2544 : " WHITESPACE\n"
2545 : " COLON\n"
2546 : " IDENTIFIER \"section\"\n"
2547 : " WHITESPACE\n"
2548 : " PRECEDED\n"
2549 : " WHITESPACE\n"
2550 : " IDENTIFIER \"july\"\n"
2551 : " OPEN_CURLYBRACKET B:false\n"
2552 : " COMPONENT_VALUE\n"
2553 : " IDENTIFIER \"color\"\n"
2554 : " WHITESPACE\n"
2555 : " COLON\n"
2556 : " WHITESPACE\n"
2557 : " IDENTIFIER \"red\"\n"
2558 : " LIST\n"
2559 :
2560 : );
2561 :
2562 : // check the first COMPONENT_VALUE
2563 1 : csspp::node::pointer_t div(n->get_child(0));
2564 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2565 :
2566 : // check the second COMPONENT_VALUE
2567 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2568 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2569 :
2570 : // check the third COMPONENT_VALUE
2571 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(8)->get_child(0));
2572 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2573 1 : }
2574 :
2575 : // 'E & E' always marks a selector
2576 : {
2577 1 : std::stringstream ss;
2578 1 : ss << "div { span :section & july { color : red }; } ";
2579 3 : csspp::position pos("test.css");
2580 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2581 :
2582 2 : csspp::parser p(l);
2583 :
2584 1 : csspp::node::pointer_t n(p.stylesheet());
2585 :
2586 : // no error happened
2587 1 : VERIFY_ERRORS("");
2588 :
2589 : //std::cerr << "Result is: [" << *n << "]\n";
2590 :
2591 1 : std::stringstream out;
2592 1 : out << *n;
2593 1 : VERIFY_TREES(out.str(),
2594 :
2595 : "LIST\n"
2596 : " COMPONENT_VALUE\n"
2597 : " IDENTIFIER \"div\"\n"
2598 : " OPEN_CURLYBRACKET B:false\n"
2599 : " COMPONENT_VALUE\n"
2600 : " IDENTIFIER \"span\"\n"
2601 : " WHITESPACE\n"
2602 : " COLON\n"
2603 : " IDENTIFIER \"section\"\n"
2604 : " WHITESPACE\n"
2605 : " REFERENCE\n"
2606 : " WHITESPACE\n"
2607 : " IDENTIFIER \"july\"\n"
2608 : " OPEN_CURLYBRACKET B:false\n"
2609 : " COMPONENT_VALUE\n"
2610 : " IDENTIFIER \"color\"\n"
2611 : " WHITESPACE\n"
2612 : " COLON\n"
2613 : " WHITESPACE\n"
2614 : " IDENTIFIER \"red\"\n"
2615 : " LIST\n"
2616 :
2617 : );
2618 :
2619 : // check the first COMPONENT_VALUE
2620 1 : csspp::node::pointer_t div(n->get_child(0));
2621 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2622 :
2623 : // check the second COMPONENT_VALUE
2624 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2625 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2626 :
2627 : // check the third COMPONENT_VALUE
2628 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(8)->get_child(0));
2629 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2630 1 : }
2631 :
2632 : // 'E|E' always marks a selector
2633 : {
2634 1 : std::stringstream ss;
2635 1 : ss << "div { span :section *|july { color : red }; } ";
2636 3 : csspp::position pos("test.css");
2637 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2638 :
2639 2 : csspp::parser p(l);
2640 :
2641 1 : csspp::node::pointer_t n(p.stylesheet());
2642 :
2643 : // no error happened
2644 1 : VERIFY_ERRORS("");
2645 :
2646 : //std::cerr << "Result is: [" << *n << "]\n";
2647 :
2648 1 : std::stringstream out;
2649 1 : out << *n;
2650 1 : VERIFY_TREES(out.str(),
2651 :
2652 : "LIST\n"
2653 : " COMPONENT_VALUE\n"
2654 : " IDENTIFIER \"div\"\n"
2655 : " OPEN_CURLYBRACKET B:false\n"
2656 : " COMPONENT_VALUE\n"
2657 : " IDENTIFIER \"span\"\n"
2658 : " WHITESPACE\n"
2659 : " COLON\n"
2660 : " IDENTIFIER \"section\"\n"
2661 : " WHITESPACE\n"
2662 : " MULTIPLY\n"
2663 : " SCOPE\n"
2664 : " IDENTIFIER \"july\"\n"
2665 : " OPEN_CURLYBRACKET B:false\n"
2666 : " COMPONENT_VALUE\n"
2667 : " IDENTIFIER \"color\"\n"
2668 : " WHITESPACE\n"
2669 : " COLON\n"
2670 : " WHITESPACE\n"
2671 : " IDENTIFIER \"red\"\n"
2672 : " LIST\n"
2673 :
2674 : );
2675 :
2676 : // check the first COMPONENT_VALUE
2677 1 : csspp::node::pointer_t div(n->get_child(0));
2678 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(div));
2679 :
2680 : // check the second COMPONENT_VALUE
2681 3 : csspp::node::pointer_t span(n->get_child(0)->get_child(1)->get_child(0));
2682 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(span));
2683 :
2684 : // check the third COMPONENT_VALUE
2685 5 : csspp::node::pointer_t p_tag(n->get_child(0)->get_child(1)->get_child(0)->get_child(8)->get_child(0));
2686 1 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(p_tag));
2687 1 : }
2688 :
2689 : // a nested block must end with a ';'
2690 : {
2691 1 : std::stringstream ss;
2692 1 : ss << "width : { color : red }";
2693 3 : csspp::position pos("test.css");
2694 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2695 :
2696 2 : csspp::parser p(l);
2697 :
2698 1 : csspp::node::pointer_t n(p.stylesheet());
2699 :
2700 : // no error happened
2701 1 : VERIFY_ERRORS("test.css(1): error: Variable set to a block and a nested property block must end with a semicolon (;) after said block.\n");
2702 1 : }
2703 :
2704 : // test special cases which woudl be really hard to get from the
2705 : // normal parser/lexer combo
2706 33 : for(int i(0); i < (1 << 5); ++i)
2707 : {
2708 96 : csspp::position pos("test.css");
2709 32 : csspp::node::pointer_t root(new csspp::node(csspp::node_type_t::LIST, pos));
2710 :
2711 : // name WS ':' WS '{'
2712 32 : if((i & (1 << 0)) != 0)
2713 : {
2714 16 : csspp::node::pointer_t name(new csspp::node(csspp::node_type_t::IDENTIFIER, pos));
2715 16 : name->set_string("field-name");
2716 16 : root->add_child(name);
2717 16 : }
2718 :
2719 32 : if((i & (1 << 1)) != 0)
2720 : {
2721 16 : csspp::node::pointer_t whitespace1(new csspp::node(csspp::node_type_t::WHITESPACE, pos));
2722 16 : root->add_child(whitespace1);
2723 16 : }
2724 :
2725 32 : if((i & (1 << 2)) != 0)
2726 : {
2727 16 : csspp::node::pointer_t colon(new csspp::node(csspp::node_type_t::COLON, pos));
2728 16 : root->add_child(colon);
2729 16 : }
2730 :
2731 32 : if((i & (1 << 3)) != 0)
2732 : {
2733 16 : csspp::node::pointer_t whitespace2(new csspp::node(csspp::node_type_t::WHITESPACE, pos));
2734 16 : root->add_child(whitespace2);
2735 16 : }
2736 :
2737 32 : if((i & (1 << 4)) != 0)
2738 : {
2739 16 : csspp::node::pointer_t curlybracket(new csspp::node(csspp::node_type_t::OPEN_CURLYBRACKET, pos));
2740 16 : root->add_child(curlybracket);
2741 16 : }
2742 :
2743 : // this one is "valid"
2744 32 : switch(i)
2745 : {
2746 4 : case 0x1F: // all with and without spaces are valid
2747 : case 0x1D:
2748 : case 0x17:
2749 : case 0x15:
2750 4 : CATCH_REQUIRE(csspp::parser::is_nested_declaration(root));
2751 4 : break;
2752 :
2753 28 : default:
2754 28 : CATCH_REQUIRE_FALSE(csspp::parser::is_nested_declaration(root));
2755 28 : break;
2756 :
2757 : }
2758 32 : }
2759 :
2760 : // no error left over
2761 1 : VERIFY_ERRORS("");
2762 1 : }
2763 :
2764 1 : CATCH_TEST_CASE("Rules defined inside an @-Keyword", "[parser] [variable] [invalid]")
2765 : {
2766 : // which a field name with a simple nested declaration
2767 : {
2768 1 : std::stringstream ss;
2769 : ss << "@document url(http://www.example.com/), regexp(\"https://.*\")\n"
2770 : << "{\n"
2771 : << " body { width: 8.5in; height: 9in; }\n"
2772 : << " div { border: 0.25in solid lightgray }\n"
2773 : << "}\n"
2774 1 : << "#edge { border: 1px solid black }\n";
2775 3 : csspp::position pos("test.css");
2776 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2777 :
2778 2 : csspp::parser p(l);
2779 :
2780 1 : csspp::node::pointer_t n(p.stylesheet());
2781 :
2782 : // no error happened
2783 1 : VERIFY_ERRORS("");
2784 :
2785 : //std::cerr << "Result is: [" << *n << "]\n";
2786 :
2787 1 : std::stringstream out;
2788 1 : out << *n;
2789 1 : VERIFY_TREES(out.str(),
2790 :
2791 : "LIST\n"
2792 : " AT_KEYWORD \"document\" I:0\n"
2793 : " URL \"http://www.example.com/\"\n"
2794 : " COMMA\n"
2795 : " WHITESPACE\n"
2796 : " FUNCTION \"regexp\"\n"
2797 : " STRING \"https://.*\"\n"
2798 : " OPEN_CURLYBRACKET B:false\n"
2799 : " COMPONENT_VALUE\n"
2800 : " IDENTIFIER \"body\"\n"
2801 : " OPEN_CURLYBRACKET B:false\n"
2802 : " LIST\n"
2803 : " COMPONENT_VALUE\n"
2804 : " IDENTIFIER \"width\"\n"
2805 : " COLON\n"
2806 : " WHITESPACE\n"
2807 : " DECIMAL_NUMBER \"in\" D:8.5\n"
2808 : " COMPONENT_VALUE\n"
2809 : " IDENTIFIER \"height\"\n"
2810 : " COLON\n"
2811 : " WHITESPACE\n"
2812 : " INTEGER \"in\" I:9\n"
2813 : " COMPONENT_VALUE\n"
2814 : " IDENTIFIER \"div\"\n"
2815 : " OPEN_CURLYBRACKET B:false\n"
2816 : " COMPONENT_VALUE\n"
2817 : " IDENTIFIER \"border\"\n"
2818 : " COLON\n"
2819 : " WHITESPACE\n"
2820 : " DECIMAL_NUMBER \"in\" D:0.25\n"
2821 : " WHITESPACE\n"
2822 : " IDENTIFIER \"solid\"\n"
2823 : " WHITESPACE\n"
2824 : " IDENTIFIER \"lightgray\"\n"
2825 : " COMPONENT_VALUE\n"
2826 : " HASH \"edge\"\n"
2827 : " OPEN_CURLYBRACKET B:false\n"
2828 : " COMPONENT_VALUE\n"
2829 : " IDENTIFIER \"border\"\n"
2830 : " COLON\n"
2831 : " WHITESPACE\n"
2832 : " INTEGER \"px\" I:1\n"
2833 : " WHITESPACE\n"
2834 : " IDENTIFIER \"solid\"\n"
2835 : " WHITESPACE\n"
2836 : " IDENTIFIER \"black\"\n"
2837 :
2838 : );
2839 :
2840 1 : }
2841 :
2842 : // no error left over
2843 1 : VERIFY_ERRORS("");
2844 1 : }
2845 :
2846 1 : CATCH_TEST_CASE("Parse argify", "[parser] [stylesheet]")
2847 : {
2848 : {
2849 1 : std::stringstream ss;
2850 : ss << "a,b{color:red}\n"
2851 : << "a, b{color:red}\n"
2852 : << "a,b ,c{color:red}\n"
2853 : << "a , b,c{color:red}\n"
2854 : << "a{color:red}\n"
2855 : << "a {color:red}\n"
2856 1 : << "a,b {color:red}\n"
2857 : ;
2858 3 : csspp::position pos("test.css");
2859 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2860 :
2861 2 : csspp::parser p(l);
2862 :
2863 1 : csspp::node::pointer_t n(p.stylesheet());
2864 :
2865 : //std::cerr << "Result is: [" << *n << "]\n";
2866 :
2867 1 : std::stringstream out;
2868 1 : out << *n;
2869 1 : VERIFY_TREES(out.str(),
2870 :
2871 : "LIST\n"
2872 : " COMPONENT_VALUE\n"
2873 : " IDENTIFIER \"a\"\n"
2874 : " COMMA\n"
2875 : " IDENTIFIER \"b\"\n"
2876 : " OPEN_CURLYBRACKET B:false\n"
2877 : " COMPONENT_VALUE\n"
2878 : " IDENTIFIER \"color\"\n"
2879 : " COLON\n"
2880 : " IDENTIFIER \"red\"\n"
2881 : " COMPONENT_VALUE\n"
2882 : " IDENTIFIER \"a\"\n"
2883 : " COMMA\n"
2884 : " WHITESPACE\n"
2885 : " IDENTIFIER \"b\"\n"
2886 : " OPEN_CURLYBRACKET B:false\n"
2887 : " COMPONENT_VALUE\n"
2888 : " IDENTIFIER \"color\"\n"
2889 : " COLON\n"
2890 : " IDENTIFIER \"red\"\n"
2891 : " COMPONENT_VALUE\n"
2892 : " IDENTIFIER \"a\"\n"
2893 : " COMMA\n"
2894 : " IDENTIFIER \"b\"\n"
2895 : " WHITESPACE\n"
2896 : " COMMA\n"
2897 : " IDENTIFIER \"c\"\n"
2898 : " OPEN_CURLYBRACKET B:false\n"
2899 : " COMPONENT_VALUE\n"
2900 : " IDENTIFIER \"color\"\n"
2901 : " COLON\n"
2902 : " IDENTIFIER \"red\"\n"
2903 : " COMPONENT_VALUE\n"
2904 : " IDENTIFIER \"a\"\n"
2905 : " WHITESPACE\n"
2906 : " COMMA\n"
2907 : " WHITESPACE\n"
2908 : " IDENTIFIER \"b\"\n"
2909 : " COMMA\n"
2910 : " IDENTIFIER \"c\"\n"
2911 : " OPEN_CURLYBRACKET B:false\n"
2912 : " COMPONENT_VALUE\n"
2913 : " IDENTIFIER \"color\"\n"
2914 : " COLON\n"
2915 : " IDENTIFIER \"red\"\n"
2916 : " COMPONENT_VALUE\n"
2917 : " IDENTIFIER \"a\"\n"
2918 : " OPEN_CURLYBRACKET B:false\n"
2919 : " COMPONENT_VALUE\n"
2920 : " IDENTIFIER \"color\"\n"
2921 : " COLON\n"
2922 : " IDENTIFIER \"red\"\n"
2923 : " COMPONENT_VALUE\n"
2924 : " IDENTIFIER \"a\"\n"
2925 : " OPEN_CURLYBRACKET B:false\n"
2926 : " COMPONENT_VALUE\n"
2927 : " IDENTIFIER \"color\"\n"
2928 : " COLON\n"
2929 : " IDENTIFIER \"red\"\n"
2930 : " COMPONENT_VALUE\n"
2931 : " IDENTIFIER \"a\"\n"
2932 : " COMMA\n"
2933 : " IDENTIFIER \"b\"\n"
2934 : " OPEN_CURLYBRACKET B:false\n"
2935 : " COMPONENT_VALUE\n"
2936 : " IDENTIFIER \"color\"\n"
2937 : " COLON\n"
2938 : " IDENTIFIER \"red\"\n"
2939 :
2940 : );
2941 :
2942 : // Argify the list under each COMPONENT_VALUE
2943 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
2944 :
2945 1 : size_t const max_children(n->size());
2946 8 : for(size_t idx(0); idx < max_children; ++idx)
2947 : {
2948 7 : csspp::node::pointer_t component_value(n->get_child(idx));
2949 7 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
2950 7 : CATCH_REQUIRE(csspp::parser::argify(component_value));
2951 7 : }
2952 :
2953 : //std::cerr << "Argified result is: [" << *n << "]\n";
2954 :
2955 : // no errors so far
2956 1 : VERIFY_ERRORS("");
2957 :
2958 1 : std::stringstream out2;
2959 1 : out2 << *n;
2960 1 : VERIFY_TREES(out2.str(),
2961 :
2962 : "LIST\n"
2963 : " COMPONENT_VALUE\n"
2964 : " ARG\n"
2965 : " IDENTIFIER \"a\"\n"
2966 : " ARG\n"
2967 : " IDENTIFIER \"b\"\n"
2968 : " OPEN_CURLYBRACKET B:false\n"
2969 : " COMPONENT_VALUE\n"
2970 : " IDENTIFIER \"color\"\n"
2971 : " COLON\n"
2972 : " IDENTIFIER \"red\"\n"
2973 : " COMPONENT_VALUE\n"
2974 : " ARG\n"
2975 : " IDENTIFIER \"a\"\n"
2976 : " ARG\n"
2977 : " IDENTIFIER \"b\"\n"
2978 : " OPEN_CURLYBRACKET B:false\n"
2979 : " COMPONENT_VALUE\n"
2980 : " IDENTIFIER \"color\"\n"
2981 : " COLON\n"
2982 : " IDENTIFIER \"red\"\n"
2983 : " COMPONENT_VALUE\n"
2984 : " ARG\n"
2985 : " IDENTIFIER \"a\"\n"
2986 : " ARG\n"
2987 : " IDENTIFIER \"b\"\n"
2988 : " ARG\n"
2989 : " IDENTIFIER \"c\"\n"
2990 : " OPEN_CURLYBRACKET B:false\n"
2991 : " COMPONENT_VALUE\n"
2992 : " IDENTIFIER \"color\"\n"
2993 : " COLON\n"
2994 : " IDENTIFIER \"red\"\n"
2995 : " COMPONENT_VALUE\n"
2996 : " ARG\n"
2997 : " IDENTIFIER \"a\"\n"
2998 : " ARG\n"
2999 : " IDENTIFIER \"b\"\n"
3000 : " ARG\n"
3001 : " IDENTIFIER \"c\"\n"
3002 : " OPEN_CURLYBRACKET B:false\n"
3003 : " COMPONENT_VALUE\n"
3004 : " IDENTIFIER \"color\"\n"
3005 : " COLON\n"
3006 : " IDENTIFIER \"red\"\n"
3007 : " COMPONENT_VALUE\n"
3008 : " ARG\n"
3009 : " IDENTIFIER \"a\"\n"
3010 : " OPEN_CURLYBRACKET B:false\n"
3011 : " COMPONENT_VALUE\n"
3012 : " IDENTIFIER \"color\"\n"
3013 : " COLON\n"
3014 : " IDENTIFIER \"red\"\n"
3015 : " COMPONENT_VALUE\n"
3016 : " ARG\n"
3017 : " IDENTIFIER \"a\"\n"
3018 : " OPEN_CURLYBRACKET B:false\n"
3019 : " COMPONENT_VALUE\n"
3020 : " IDENTIFIER \"color\"\n"
3021 : " COLON\n"
3022 : " IDENTIFIER \"red\"\n"
3023 : " COMPONENT_VALUE\n"
3024 : " ARG\n"
3025 : " IDENTIFIER \"a\"\n"
3026 : " ARG\n"
3027 : " IDENTIFIER \"b\"\n"
3028 : " OPEN_CURLYBRACKET B:false\n"
3029 : " COMPONENT_VALUE\n"
3030 : " IDENTIFIER \"color\"\n"
3031 : " COLON\n"
3032 : " IDENTIFIER \"red\"\n"
3033 :
3034 : );
3035 :
3036 : // no error left over
3037 1 : VERIFY_ERRORS("");
3038 1 : }
3039 1 : }
3040 :
3041 1 : CATCH_TEST_CASE("Invalid argify", "[parser] [stylesheet]")
3042 : {
3043 : // A starting comma is illegal
3044 : {
3045 1 : std::stringstream ss;
3046 1 : ss << ",a{color:red}\n";
3047 3 : csspp::position pos("test.css");
3048 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3049 :
3050 2 : csspp::parser p(l);
3051 :
3052 1 : csspp::node::pointer_t n(p.stylesheet());
3053 :
3054 : //std::cerr << "Result is: [" << *n << "]\n";
3055 :
3056 : // no errors so far
3057 1 : VERIFY_ERRORS("");
3058 :
3059 1 : std::stringstream out;
3060 1 : out << *n;
3061 1 : VERIFY_TREES(out.str(),
3062 :
3063 : "LIST\n"
3064 : " COMPONENT_VALUE\n"
3065 : " COMMA\n"
3066 : " IDENTIFIER \"a\"\n"
3067 : " OPEN_CURLYBRACKET B:false\n"
3068 : " COMPONENT_VALUE\n"
3069 : " IDENTIFIER \"color\"\n"
3070 : " COLON\n"
3071 : " IDENTIFIER \"red\"\n"
3072 :
3073 : );
3074 :
3075 : // Argify the list under each COMPONENT_VALUE
3076 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
3077 :
3078 1 : size_t const max_children(n->size());
3079 2 : for(size_t idx(0); idx < max_children; ++idx)
3080 : {
3081 1 : csspp::node::pointer_t component_value(n->get_child(idx));
3082 1 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
3083 1 : CATCH_REQUIRE_FALSE(csspp::parser::argify(component_value));
3084 1 : }
3085 :
3086 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the beginning of a list of arguments or selectors.\n");
3087 1 : }
3088 :
3089 : // An ending comma is illegal
3090 : {
3091 1 : std::stringstream ss;
3092 1 : ss << "a,{color:red}\n";
3093 3 : csspp::position pos("test.css");
3094 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3095 :
3096 2 : csspp::parser p(l);
3097 :
3098 1 : csspp::node::pointer_t n(p.stylesheet());
3099 :
3100 : // no errors so far
3101 1 : VERIFY_ERRORS("");
3102 :
3103 : //std::cerr << "Result is: [" << *n << "]\n";
3104 :
3105 1 : std::stringstream out;
3106 1 : out << *n;
3107 1 : VERIFY_TREES(out.str(),
3108 :
3109 : "LIST\n"
3110 : " COMPONENT_VALUE\n"
3111 : " IDENTIFIER \"a\"\n"
3112 : " COMMA\n"
3113 : " OPEN_CURLYBRACKET B:false\n"
3114 : " COMPONENT_VALUE\n"
3115 : " IDENTIFIER \"color\"\n"
3116 : " COLON\n"
3117 : " IDENTIFIER \"red\"\n"
3118 :
3119 : );
3120 :
3121 : // Argify the list under each COMPONENT_VALUE
3122 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
3123 :
3124 1 : size_t const max_children(n->size());
3125 2 : for(size_t idx(0); idx < max_children; ++idx)
3126 : {
3127 1 : csspp::node::pointer_t component_value(n->get_child(idx));
3128 1 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
3129 1 : CATCH_REQUIRE_FALSE(csspp::parser::argify(component_value));
3130 1 : }
3131 :
3132 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the end of a list of arguments or selectors.\n");
3133 1 : }
3134 :
3135 : // Two commas in a row is illegal
3136 : {
3137 1 : std::stringstream ss;
3138 1 : ss << "a,,b{color:red}\n";
3139 3 : csspp::position pos("test.css");
3140 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3141 :
3142 2 : csspp::parser p(l);
3143 :
3144 1 : csspp::node::pointer_t n(p.stylesheet());
3145 :
3146 : // no errors so far
3147 1 : VERIFY_ERRORS("");
3148 :
3149 : //std::cerr << "Result is: [" << *n << "]\n";
3150 :
3151 1 : std::stringstream out;
3152 1 : out << *n;
3153 1 : VERIFY_TREES(out.str(),
3154 :
3155 : "LIST\n"
3156 : " COMPONENT_VALUE\n"
3157 : " IDENTIFIER \"a\"\n"
3158 : " COMMA\n"
3159 : " COMMA\n"
3160 : " IDENTIFIER \"b\"\n"
3161 : " OPEN_CURLYBRACKET B:false\n"
3162 : " COMPONENT_VALUE\n"
3163 : " IDENTIFIER \"color\"\n"
3164 : " COLON\n"
3165 : " IDENTIFIER \"red\"\n"
3166 :
3167 : );
3168 :
3169 : // Argify the list under each COMPONENT_VALUE
3170 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
3171 :
3172 1 : size_t const max_children(n->size());
3173 2 : for(size_t idx(0); idx < max_children; ++idx)
3174 : {
3175 1 : csspp::node::pointer_t component_value(n->get_child(idx));
3176 1 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
3177 1 : CATCH_REQUIRE_FALSE(csspp::parser::argify(component_value));
3178 1 : }
3179 :
3180 1 : VERIFY_ERRORS("test.css(1): error: two commas in a row are invalid in a list of arguments or selectors.\n");
3181 1 : }
3182 :
3183 : // Just a comma is illegal
3184 : {
3185 1 : std::stringstream ss;
3186 1 : ss << ",{color:red}\n";
3187 3 : csspp::position pos("test.css");
3188 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3189 :
3190 2 : csspp::parser p(l);
3191 :
3192 1 : csspp::node::pointer_t n(p.stylesheet());
3193 :
3194 : // no errors so far
3195 1 : VERIFY_ERRORS("");
3196 :
3197 : //std::cerr << "Result is: [" << *n << "]\n";
3198 :
3199 1 : std::stringstream out;
3200 1 : out << *n;
3201 1 : VERIFY_TREES(out.str(),
3202 :
3203 : "LIST\n"
3204 : " COMPONENT_VALUE\n"
3205 : " COMMA\n"
3206 : " OPEN_CURLYBRACKET B:false\n"
3207 : " COMPONENT_VALUE\n"
3208 : " IDENTIFIER \"color\"\n"
3209 : " COLON\n"
3210 : " IDENTIFIER \"red\"\n"
3211 :
3212 : );
3213 :
3214 : // Argify the list under each COMPONENT_VALUE
3215 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
3216 :
3217 1 : size_t const max_children(n->size());
3218 2 : for(size_t idx(0); idx < max_children; ++idx)
3219 : {
3220 1 : csspp::node::pointer_t component_value(n->get_child(idx));
3221 1 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
3222 1 : CATCH_REQUIRE_FALSE(csspp::parser::argify(component_value));
3223 1 : }
3224 :
3225 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the beginning of a list of arguments or selectors.\n");
3226 1 : }
3227 :
3228 : // calling argify with the wrong separators
3229 : {
3230 1 : std::stringstream ss;
3231 1 : ss << "a,b{color:red}\n";
3232 3 : csspp::position pos("test.css");
3233 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3234 :
3235 2 : csspp::parser p(l);
3236 :
3237 1 : csspp::node::pointer_t n(p.stylesheet());
3238 :
3239 : // no errors so far
3240 1 : VERIFY_ERRORS("");
3241 :
3242 : //std::cerr << "Result is: [" << *n << "]\n";
3243 :
3244 1 : std::stringstream out;
3245 1 : out << *n;
3246 1 : VERIFY_TREES(out.str(),
3247 :
3248 : "LIST\n"
3249 : " COMPONENT_VALUE\n"
3250 : " IDENTIFIER \"a\"\n"
3251 : " COMMA\n"
3252 : " IDENTIFIER \"b\"\n"
3253 : " OPEN_CURLYBRACKET B:false\n"
3254 : " COMPONENT_VALUE\n"
3255 : " IDENTIFIER \"color\"\n"
3256 : " COLON\n"
3257 : " IDENTIFIER \"red\"\n"
3258 :
3259 : );
3260 :
3261 : // Attempt to argify the list under each COMPONENT_VALUE using
3262 : // the wrong type
3263 1 : CATCH_REQUIRE(n->is(csspp::node_type_t::LIST));
3264 :
3265 1 : size_t const max_children(n->size());
3266 2 : for(size_t idx(0); idx < max_children; ++idx)
3267 : {
3268 1 : csspp::node::pointer_t component_value(n->get_child(idx));
3269 1 : CATCH_REQUIRE(component_value->is(csspp::node_type_t::COMPONENT_VALUE));
3270 :
3271 1 : for(csspp::node_type_t w(csspp::node_type_t::UNKNOWN);
3272 69 : w <= csspp::node_type_t::max_type;
3273 68 : w = static_cast<csspp::node_type_t>(static_cast<int>(w) + 1))
3274 : {
3275 68 : switch(w)
3276 : {
3277 2 : case csspp::node_type_t::COMMA:
3278 : case csspp::node_type_t::DIVIDE:
3279 2 : continue;
3280 :
3281 66 : default:
3282 66 : break;
3283 :
3284 : }
3285 198 : CATCH_REQUIRE_THROWS_AS(csspp::parser::argify(component_value, w), csspp::csspp_exception_logic);
3286 : }
3287 1 : }
3288 :
3289 1 : VERIFY_ERRORS("");
3290 1 : }
3291 :
3292 : // no error left over
3293 1 : VERIFY_ERRORS("");
3294 1 : }
3295 :
3296 : // vim: ts=4 sw=4 et
|