bash - ast_compound_test.go
1 package bash
2
3 import "testing"
4
5 func TestCompounds(t *testing.T) {
6 doTests(t, []sourceFn{
7 {"if a; then b; fi", func(t *test, tk Tokens) { // 1
8 t.Output = Compound{
9 IfCompound: &IfCompound{
10 If: TestConsequence{
11 Test: Statement{
12 Pipeline: Pipeline{
13 CommandOrCompound: CommandOrCompound{
14 Command: &Command{
15 AssignmentsOrWords: []AssignmentOrWord{
16 {
17 Word: &Word{
18 Parts: []WordPart{
19 {
20 Part: &tk[2],
21 Tokens: tk[2:3],
22 },
23 },
24 Tokens: tk[2:3],
25 },
26 Tokens: tk[2:3],
27 },
28 },
29 Tokens: tk[2:3],
30 },
31 Tokens: tk[2:3],
32 },
33 Tokens: tk[2:3],
34 },
35 Tokens: tk[2:4],
36 },
37 Consequence: File{
38 Lines: []Line{
39 {
40 Statements: []Statement{
41 {
42 Pipeline: Pipeline{
43 CommandOrCompound: CommandOrCompound{
44 Command: &Command{
45 AssignmentsOrWords: []AssignmentOrWord{
46 {
47 Word: &Word{
48 Parts: []WordPart{
49 {
50 Part: &tk[7],
51 Tokens: tk[7:8],
52 },
53 },
54 Tokens: tk[7:8],
55 },
56 Tokens: tk[7:8],
57 },
58 },
59 Tokens: tk[7:8],
60 },
61 Tokens: tk[7:8],
62 },
63 Tokens: tk[7:8],
64 },
65 Tokens: tk[7:9],
66 },
67 },
68 Tokens: tk[7:9],
69 },
70 },
71 Tokens: tk[7:9],
72 },
73 Tokens: tk[2:9],
74 },
75 Tokens: tk[:11],
76 },
77 Tokens: tk[:11],
78 }
79 }},
80 {"case a in b)c\nesac", func(t *test, tk Tokens) { // 2
81 t.Output = Compound{
82 CaseCompound: &CaseCompound{
83 Word: Word{
84 Parts: []WordPart{
85 {
86 Part: &tk[2],
87 Tokens: tk[2:3],
88 },
89 },
90 Tokens: tk[2:3],
91 },
92 Matches: []PatternLines{
93 {
94 Patterns: []Word{
95 {
96 Parts: []WordPart{
97 {
98 Part: &tk[6],
99 Tokens: tk[6:7],
100 },
101 },
102 Tokens: tk[6:7],
103 },
104 },
105 Lines: File{
106 Lines: []Line{
107 {
108 Statements: []Statement{
109 {
110 Pipeline: Pipeline{
111 CommandOrCompound: CommandOrCompound{
112 Command: &Command{
113 AssignmentsOrWords: []AssignmentOrWord{
114 {
115 Word: &Word{
116 Parts: []WordPart{
117 {
118 Part: &tk[8],
119 Tokens: tk[8:9],
120 },
121 },
122 Tokens: tk[8:9],
123 },
124 Tokens: tk[8:9],
125 },
126 },
127 Tokens: tk[8:9],
128 },
129 Tokens: tk[8:9],
130 },
131 Tokens: tk[8:9],
132 },
133 Tokens: tk[8:9],
134 },
135 },
136 Tokens: tk[8:9],
137 },
138 },
139 Tokens: tk[8:9],
140 },
141 Tokens: tk[6:9],
142 },
143 },
144 Tokens: tk[:11],
145 },
146 Tokens: tk[:11],
147 }
148 }},
149 {"while a\ndo\nb\ndone", func(t *test, tk Tokens) { // 3
150 t.Output = Compound{
151 LoopCompound: &LoopCompound{
152 Statement: Statement{
153 Pipeline: Pipeline{
154 CommandOrCompound: CommandOrCompound{
155 Command: &Command{
156 AssignmentsOrWords: []AssignmentOrWord{
157 {
158 Word: &Word{
159 Parts: []WordPart{
160 {
161 Part: &tk[2],
162 Tokens: tk[2:3],
163 },
164 },
165 Tokens: tk[2:3],
166 },
167 Tokens: tk[2:3],
168 },
169 },
170 Tokens: tk[2:3],
171 },
172 Tokens: tk[2:3],
173 },
174 Tokens: tk[2:3],
175 },
176 Tokens: tk[2:3],
177 },
178 File: File{
179 Lines: []Line{
180 {
181 Statements: []Statement{
182 {
183 Pipeline: Pipeline{
184 CommandOrCompound: CommandOrCompound{
185 Command: &Command{
186 AssignmentsOrWords: []AssignmentOrWord{
187 {
188 Word: &Word{
189 Parts: []WordPart{
190 {
191 Part: &tk[6],
192 Tokens: tk[6:7],
193 },
194 },
195 Tokens: tk[6:7],
196 },
197 Tokens: tk[6:7],
198 },
199 },
200 Tokens: tk[6:7],
201 },
202 Tokens: tk[6:7],
203 },
204 Tokens: tk[6:7],
205 },
206 Tokens: tk[6:7],
207 },
208 },
209 Tokens: tk[6:7],
210 },
211 },
212 Tokens: tk[6:7],
213 },
214 Tokens: tk[:9],
215 },
216 Tokens: tk[:9],
217 }
218 }},
219 {"until a; do b; done", func(t *test, tk Tokens) { // 4
220 t.Output = Compound{
221 LoopCompound: &LoopCompound{
222 Until: true,
223 Statement: Statement{
224 Pipeline: Pipeline{
225 CommandOrCompound: CommandOrCompound{
226 Command: &Command{
227 AssignmentsOrWords: []AssignmentOrWord{
228 {
229 Word: &Word{
230 Parts: []WordPart{
231 {
232 Part: &tk[2],
233 Tokens: tk[2:3],
234 },
235 },
236 Tokens: tk[2:3],
237 },
238 Tokens: tk[2:3],
239 },
240 },
241 Tokens: tk[2:3],
242 },
243 Tokens: tk[2:3],
244 },
245 Tokens: tk[2:3],
246 },
247 Tokens: tk[2:4],
248 },
249 File: File{
250 Lines: []Line{
251 {
252 Statements: []Statement{
253 {
254 Pipeline: Pipeline{
255 CommandOrCompound: CommandOrCompound{
256 Command: &Command{
257 AssignmentsOrWords: []AssignmentOrWord{
258 {
259 Word: &Word{
260 Parts: []WordPart{
261 {
262 Part: &tk[7],
263 Tokens: tk[7:8],
264 },
265 },
266 Tokens: tk[7:8],
267 },
268 Tokens: tk[7:8],
269 },
270 },
271 Tokens: tk[7:8],
272 },
273 Tokens: tk[7:8],
274 },
275 Tokens: tk[7:8],
276 },
277 Tokens: tk[7:9],
278 },
279 },
280 Tokens: tk[7:9],
281 },
282 },
283 Tokens: tk[7:9],
284 },
285 Tokens: tk[:11],
286 },
287 Tokens: tk[:11],
288 }
289 }},
290 {"for a; do b;done", func(t *test, tk Tokens) { // 5
291 t.Output = Compound{
292 ForCompound: &ForCompound{
293 Identifier: &tk[2],
294 File: File{
295 Lines: []Line{
296 {
297 Statements: []Statement{
298 {
299 Pipeline: Pipeline{
300 CommandOrCompound: CommandOrCompound{
301 Command: &Command{
302 AssignmentsOrWords: []AssignmentOrWord{
303 {
304 Word: &Word{
305 Parts: []WordPart{
306 {
307 Part: &tk[7],
308 Tokens: tk[7:8],
309 },
310 },
311 Tokens: tk[7:8],
312 },
313 Tokens: tk[7:8],
314 },
315 },
316 Tokens: tk[7:8],
317 },
318 Tokens: tk[7:8],
319 },
320 Tokens: tk[7:8],
321 },
322 Tokens: tk[7:9],
323 },
324 },
325 Tokens: tk[7:9],
326 },
327 },
328 Tokens: tk[7:9],
329 },
330 Tokens: tk[:10],
331 },
332 Tokens: tk[:10],
333 }
334 }},
335 {"select a; do b;done", func(t *test, tk Tokens) { // 6
336 t.Output = Compound{
337 SelectCompound: &SelectCompound{
338 Identifier: &tk[2],
339 File: File{
340 Lines: []Line{
341 {
342 Statements: []Statement{
343 {
344 Pipeline: Pipeline{
345 CommandOrCompound: CommandOrCompound{
346 Command: &Command{
347 AssignmentsOrWords: []AssignmentOrWord{
348 {
349 Word: &Word{
350 Parts: []WordPart{
351 {
352 Part: &tk[7],
353 Tokens: tk[7:8],
354 },
355 },
356 Tokens: tk[7:8],
357 },
358 Tokens: tk[7:8],
359 },
360 },
361 Tokens: tk[7:8],
362 },
363 Tokens: tk[7:8],
364 },
365 Tokens: tk[7:8],
366 },
367 Tokens: tk[7:9],
368 },
369 },
370 Tokens: tk[7:9],
371 },
372 },
373 Tokens: tk[7:9],
374 },
375 Tokens: tk[:10],
376 },
377 Tokens: tk[:10],
378 }
379 }},
380 {"[[ a = b ]]", func(t *test, tk Tokens) { // 7
381 t.Output = Compound{
382 TestCompound: &TestCompound{
383 Tests: Tests{
384 Test: TestOperatorStringsEqual,
385 Word: &Word{
386 Parts: []WordPart{
387 {
388 Part: &tk[2],
389 Tokens: tk[2:3],
390 },
391 },
392 Tokens: tk[2:3],
393 },
394 Pattern: &Pattern{
395 Parts: []WordPart{
396 {
397 Part: &tk[6],
398 Tokens: tk[6:7],
399 },
400 },
401 Tokens: tk[6:7],
402 },
403 Tokens: tk[2:7],
404 },
405 Tokens: tk[:9],
406 },
407 Tokens: tk[:9],
408 }
409 }},
410 {"(a)", func(t *test, tk Tokens) { // 8
411 t.Output = Compound{
412 GroupingCompound: &GroupingCompound{
413 SubShell: true,
414 File: File{
415 Lines: []Line{
416 {
417 Statements: []Statement{
418 {
419 Pipeline: Pipeline{
420 CommandOrCompound: CommandOrCompound{
421 Command: &Command{
422 AssignmentsOrWords: []AssignmentOrWord{
423 {
424 Word: &Word{
425 Parts: []WordPart{
426 {
427 Part: &tk[1],
428 Tokens: tk[1:2],
429 },
430 },
431 Tokens: tk[1:2],
432 },
433 Tokens: tk[1:2],
434 },
435 },
436 Tokens: tk[1:2],
437 },
438 Tokens: tk[1:2],
439 },
440 Tokens: tk[1:2],
441 },
442 Tokens: tk[1:2],
443 },
444 },
445 Tokens: tk[1:2],
446 },
447 },
448 Tokens: tk[1:2],
449 },
450 Tokens: tk[:3],
451 },
452 Tokens: tk[:3],
453 }
454 }},
455 {"{\na\n}", func(t *test, tk Tokens) { // 9
456 t.Output = Compound{
457 GroupingCompound: &GroupingCompound{
458 File: File{
459 Lines: []Line{
460 {
461 Statements: []Statement{
462 {
463 Pipeline: Pipeline{
464 CommandOrCompound: CommandOrCompound{
465 Command: &Command{
466 AssignmentsOrWords: []AssignmentOrWord{
467 {
468 Word: &Word{
469 Parts: []WordPart{
470 {
471 Part: &tk[2],
472 Tokens: tk[2:3],
473 },
474 },
475 Tokens: tk[2:3],
476 },
477 Tokens: tk[2:3],
478 },
479 },
480 Tokens: tk[2:3],
481 },
482 Tokens: tk[2:3],
483 },
484 Tokens: tk[2:3],
485 },
486 Tokens: tk[2:3],
487 },
488 },
489 Tokens: tk[2:3],
490 },
491 },
492 Tokens: tk[2:3],
493 },
494 Tokens: tk[:5],
495 },
496 Tokens: tk[:5],
497 }
498 }},
499 {"function a() { b; }", func(t *test, tk Tokens) { // 10
500 t.Output = Compound{
501 FunctionCompound: &FunctionCompound{
502 HasKeyword: true,
503 Identifier: &tk[2],
504 Body: Compound{
505 GroupingCompound: &GroupingCompound{
506 File: File{
507 Lines: []Line{
508 {
509 Statements: []Statement{
510 {
511 Pipeline: Pipeline{
512 CommandOrCompound: CommandOrCompound{
513 Command: &Command{
514 AssignmentsOrWords: []AssignmentOrWord{
515 {
516 Word: &Word{
517 Parts: []WordPart{
518 {
519 Part: &tk[8],
520 Tokens: tk[8:9],
521 },
522 },
523 Tokens: tk[8:9],
524 },
525 Tokens: tk[8:9],
526 },
527 },
528 Tokens: tk[8:9],
529 },
530 Tokens: tk[8:9],
531 },
532 Tokens: tk[8:9],
533 },
534 Tokens: tk[8:10],
535 },
536 },
537 Tokens: tk[8:10],
538 },
539 },
540 Tokens: tk[8:10],
541 },
542 Tokens: tk[6:12],
543 },
544 Tokens: tk[6:12],
545 },
546 Tokens: tk[:12],
547 },
548 Tokens: tk[:12],
549 }
550 }},
551 {"a() { b; }", func(t *test, tk Tokens) { // 11
552 t.Output = Compound{
553 FunctionCompound: &FunctionCompound{
554 Identifier: &tk[0],
555 Body: Compound{
556 GroupingCompound: &GroupingCompound{
557 File: File{
558 Lines: []Line{
559 {
560 Statements: []Statement{
561 {
562 Pipeline: Pipeline{
563 CommandOrCompound: CommandOrCompound{
564 Command: &Command{
565 AssignmentsOrWords: []AssignmentOrWord{
566 {
567 Word: &Word{
568 Parts: []WordPart{
569 {
570 Part: &tk[6],
571 Tokens: tk[6:7],
572 },
573 },
574 Tokens: tk[6:7],
575 },
576 Tokens: tk[6:7],
577 },
578 },
579 Tokens: tk[6:7],
580 },
581 Tokens: tk[6:7],
582 },
583 Tokens: tk[6:7],
584 },
585 Tokens: tk[6:8],
586 },
587 },
588 Tokens: tk[6:8],
589 },
590 },
591 Tokens: tk[6:8],
592 },
593 Tokens: tk[4:10],
594 },
595 Tokens: tk[4:10],
596 },
597 Tokens: tk[:10],
598 },
599 Tokens: tk[:10],
600 }
601 }},
602 {"(( a ))", func(t *test, tk Tokens) { // 12
603 t.Output = Compound{
604 ArithmeticCompound: &ArithmeticExpansion{
605 Expression: true,
606 WordsAndOperators: []WordOrOperator{
607 {
608 Word: &Word{
609 Parts: []WordPart{
610 {
611 Part: &tk[2],
612 Tokens: tk[2:3],
613 },
614 },
615 Tokens: tk[2:3],
616 },
617 Tokens: tk[2:3],
618 },
619 },
620 Tokens: tk[:5],
621 },
622 Tokens: tk[:5],
623 }
624 }},
625 {"[[ a = b ]] >c", func(t *test, tk Tokens) { // 13
626 t.Output = Compound{
627 TestCompound: &TestCompound{
628 Tests: Tests{
629 Test: TestOperatorStringsEqual,
630 Word: &Word{
631 Parts: []WordPart{
632 {
633 Part: &tk[2],
634 Tokens: tk[2:3],
635 },
636 },
637 Tokens: tk[2:3],
638 },
639 Pattern: &Pattern{
640 Parts: []WordPart{
641 {
642 Part: &tk[6],
643 Tokens: tk[6:7],
644 },
645 },
646 Tokens: tk[6:7],
647 },
648 Tokens: tk[2:7],
649 },
650 Tokens: tk[:9],
651 },
652 Redirections: []Redirection{
653 {
654 Redirector: &tk[10],
655 Output: Word{
656 Parts: []WordPart{
657 {
658 Part: &tk[11],
659 Tokens: tk[11:12],
660 },
661 },
662 Tokens: tk[11:12],
663 },
664 Tokens: tk[10:12],
665 },
666 },
667 Tokens: tk[:12],
668 }
669 }},
670 {"[[ a = b ]] >a 2>&1", func(t *test, tk Tokens) { // 14
671 t.Output = Compound{
672 TestCompound: &TestCompound{
673 Tests: Tests{
674 Test: TestOperatorStringsEqual,
675 Word: &Word{
676 Parts: []WordPart{
677 {
678 Part: &tk[2],
679 Tokens: tk[2:3],
680 },
681 },
682 Tokens: tk[2:3],
683 },
684 Pattern: &Pattern{
685 Parts: []WordPart{
686 {
687 Part: &tk[6],
688 Tokens: tk[6:7],
689 },
690 },
691 Tokens: tk[6:7],
692 },
693 Tokens: tk[2:7],
694 },
695 Tokens: tk[:9],
696 },
697 Redirections: []Redirection{
698 {
699 Redirector: &tk[10],
700 Output: Word{
701 Parts: []WordPart{
702 {
703 Part: &tk[11],
704 Tokens: tk[11:12],
705 },
706 },
707 Tokens: tk[11:12],
708 },
709 Tokens: tk[10:12],
710 },
711 {
712 Input: &tk[13],
713 Redirector: &tk[14],
714 Output: Word{
715 Parts: []WordPart{
716 {
717 Part: &tk[15],
718 Tokens: tk[15:16],
719 },
720 },
721 Tokens: tk[15:16],
722 },
723 Tokens: tk[13:16],
724 },
725 },
726 Tokens: tk[:16],
727 }
728 }},
729 {"if ||;then b;fi", func(t *test, tk Tokens) { // 15
730 t.Err = Error{
731 Err: Error{
732 Err: Error{
733 Err: Error{
734 Err: Error{
735 Err: Error{
736 Err: Error{
737 Err: ErrMissingWord,
738 Parsing: "Command",
739 Token: tk[2],
740 },
741 Parsing: "CommandOrCompound",
742 Token: tk[2],
743 },
744 Parsing: "Pipeline",
745 Token: tk[2],
746 },
747 Parsing: "Statement",
748 Token: tk[2],
749 },
750 Parsing: "TestConsequence",
751 Token: tk[2],
752 },
753 Parsing: "IfCompound",
754 Token: tk[2],
755 },
756 Parsing: "Compound",
757 Token: tk[0],
758 }
759 }},
760 {"case $(||) in b)c;esac", func(t *test, tk Tokens) { // 16
761 t.Err = Error{
762 Err: Error{
763 Err: Error{
764 Err: Error{
765 Err: Error{
766 Err: Error{
767 Err: Error{
768 Err: Error{
769 Err: Error{
770 Err: Error{
771 Err: Error{
772 Err: ErrMissingWord,
773 Parsing: "Command",
774 Token: tk[3],
775 },
776 Parsing: "CommandOrCompound",
777 Token: tk[3],
778 },
779 Parsing: "Pipeline",
780 Token: tk[3],
781 },
782 Parsing: "Statement",
783 Token: tk[3],
784 },
785 Parsing: "Line",
786 Token: tk[3],
787 },
788 Parsing: "File",
789 Token: tk[3],
790 },
791 Parsing: "CommandSubstitution",
792 Token: tk[3],
793 },
794 Parsing: "WordPart",
795 Token: tk[2],
796 },
797 Parsing: "Word",
798 Token: tk[2],
799 },
800 Parsing: "CaseCompound",
801 Token: tk[2],
802 },
803 Parsing: "Compound",
804 Token: tk[0],
805 }
806 }},
807 {"while ||; do b; done", func(t *test, tk Tokens) { // 17
808 t.Err = Error{
809 Err: Error{
810 Err: Error{
811 Err: Error{
812 Err: Error{
813 Err: Error{
814 Err: ErrMissingWord,
815 Parsing: "Command",
816 Token: tk[2],
817 },
818 Parsing: "CommandOrCompound",
819 Token: tk[2],
820 },
821 Parsing: "Pipeline",
822 Token: tk[2],
823 },
824 Parsing: "Statement",
825 Token: tk[2],
826 },
827 Parsing: "LoopCompound",
828 Token: tk[2],
829 },
830 Parsing: "Compound",
831 Token: tk[0],
832 }
833 }},
834 {"until a; do ||; done", func(t *test, tk Tokens) { // 18
835 t.Err = Error{
836 Err: Error{
837 Err: Error{
838 Err: Error{
839 Err: Error{
840 Err: Error{
841 Err: Error{
842 Err: Error{
843 Err: ErrMissingWord,
844 Parsing: "Command",
845 Token: tk[7],
846 },
847 Parsing: "CommandOrCompound",
848 Token: tk[7],
849 },
850 Parsing: "Pipeline",
851 Token: tk[7],
852 },
853 Parsing: "Statement",
854 Token: tk[7],
855 },
856 Parsing: "Line",
857 Token: tk[7],
858 },
859 Parsing: "File",
860 Token: tk[7],
861 },
862 Parsing: "LoopCompound",
863 Token: tk[7],
864 },
865 Parsing: "Compound",
866 Token: tk[0],
867 }
868 }},
869 {"for a in $(||); do b;done", func(t *test, tk Tokens) { // 19
870 t.Err = Error{
871 Err: Error{
872 Err: Error{
873 Err: Error{
874 Err: Error{
875 Err: Error{
876 Err: Error{
877 Err: Error{
878 Err: Error{
879 Err: Error{
880 Err: Error{
881 Err: ErrMissingWord,
882 Parsing: "Command",
883 Token: tk[7],
884 },
885 Parsing: "CommandOrCompound",
886 Token: tk[7],
887 },
888 Parsing: "Pipeline",
889 Token: tk[7],
890 },
891 Parsing: "Statement",
892 Token: tk[7],
893 },
894 Parsing: "Line",
895 Token: tk[7],
896 },
897 Parsing: "File",
898 Token: tk[7],
899 },
900 Parsing: "CommandSubstitution",
901 Token: tk[7],
902 },
903 Parsing: "WordPart",
904 Token: tk[6],
905 },
906 Parsing: "Word",
907 Token: tk[6],
908 },
909 Parsing: "ForCompound",
910 Token: tk[6],
911 },
912 Parsing: "Compound",
913 Token: tk[0],
914 }
915 }},
916 {"select a in $(||); do b;done", func(t *test, tk Tokens) { // 20
917 t.Err = Error{
918 Err: Error{
919 Err: Error{
920 Err: Error{
921 Err: Error{
922 Err: Error{
923 Err: Error{
924 Err: Error{
925 Err: Error{
926 Err: Error{
927 Err: Error{
928 Err: ErrMissingWord,
929 Parsing: "Command",
930 Token: tk[7],
931 },
932 Parsing: "CommandOrCompound",
933 Token: tk[7],
934 },
935 Parsing: "Pipeline",
936 Token: tk[7],
937 },
938 Parsing: "Statement",
939 Token: tk[7],
940 },
941 Parsing: "Line",
942 Token: tk[7],
943 },
944 Parsing: "File",
945 Token: tk[7],
946 },
947 Parsing: "CommandSubstitution",
948 Token: tk[7],
949 },
950 Parsing: "WordPart",
951 Token: tk[6],
952 },
953 Parsing: "Word",
954 Token: tk[6],
955 },
956 Parsing: "SelectCompound",
957 Token: tk[6],
958 },
959 Parsing: "Compound",
960 Token: tk[0],
961 }
962 }},
963 {"[[ -a $(||) ]]", func(t *test, tk Tokens) { // 21
964 t.Err = Error{
965 Err: Error{
966 Err: Error{
967 Err: Error{
968 Err: Error{
969 Err: Error{
970 Err: Error{
971 Err: Error{
972 Err: Error{
973 Err: Error{
974 Err: Error{
975 Err: Error{
976 Err: ErrMissingWord,
977 Parsing: "Command",
978 Token: tk[5],
979 },
980 Parsing: "CommandOrCompound",
981 Token: tk[5],
982 },
983 Parsing: "Pipeline",
984 Token: tk[5],
985 },
986 Parsing: "Statement",
987 Token: tk[5],
988 },
989 Parsing: "Line",
990 Token: tk[5],
991 },
992 Parsing: "File",
993 Token: tk[5],
994 },
995 Parsing: "CommandSubstitution",
996 Token: tk[5],
997 },
998 Parsing: "WordPart",
999 Token: tk[4],
1000 },
1001 Parsing: "Word",
1002 Token: tk[4],
1003 },
1004 Parsing: "Tests",
1005 Token: tk[4],
1006 },
1007 Parsing: "TestCompound",
1008 Token: tk[2],
1009 },
1010 Parsing: "Compound",
1011 Token: tk[0],
1012 }
1013 }},
1014 {"(||)", func(t *test, tk Tokens) { // 22
1015 t.Err = Error{
1016 Err: Error{
1017 Err: Error{
1018 Err: Error{
1019 Err: Error{
1020 Err: Error{
1021 Err: Error{
1022 Err: Error{
1023 Err: ErrMissingWord,
1024 Parsing: "Command",
1025 Token: tk[1],
1026 },
1027 Parsing: "CommandOrCompound",
1028 Token: tk[1],
1029 },
1030 Parsing: "Pipeline",
1031 Token: tk[1],
1032 },
1033 Parsing: "Statement",
1034 Token: tk[1],
1035 },
1036 Parsing: "Line",
1037 Token: tk[1],
1038 },
1039 Parsing: "File",
1040 Token: tk[1],
1041 },
1042 Parsing: "GroupingCompound",
1043 Token: tk[1],
1044 },
1045 Parsing: "Compound",
1046 Token: tk[0],
1047 }
1048 }},
1049 {"function a() { || }", func(t *test, tk Tokens) { // 23
1050 t.Err = Error{
1051 Err: Error{
1052 Err: Error{
1053 Err: Error{
1054 Err: Error{
1055 Err: Error{
1056 Err: Error{
1057 Err: Error{
1058 Err: Error{
1059 Err: Error{
1060 Err: ErrMissingWord,
1061 Parsing: "Command",
1062 Token: tk[8],
1063 },
1064 Parsing: "CommandOrCompound",
1065 Token: tk[8],
1066 },
1067 Parsing: "Pipeline",
1068 Token: tk[8],
1069 },
1070 Parsing: "Statement",
1071 Token: tk[8],
1072 },
1073 Parsing: "Line",
1074 Token: tk[8],
1075 },
1076 Parsing: "File",
1077 Token: tk[8],
1078 },
1079 Parsing: "GroupingCompound",
1080 Token: tk[8],
1081 },
1082 Parsing: "Compound",
1083 Token: tk[6],
1084 },
1085 Parsing: "FunctionCompound",
1086 Token: tk[6],
1087 },
1088 Parsing: "Compound",
1089 Token: tk[0],
1090 }
1091 }},
1092 {"(($(||)))", func(t *test, tk Tokens) { // 24
1093 t.Err = Error{
1094 Err: Error{
1095 Err: Error{
1096 Err: Error{
1097 Err: Error{
1098 Err: Error{
1099 Err: Error{
1100 Err: Error{
1101 Err: Error{
1102 Err: Error{
1103 Err: Error{
1104 Err: Error{
1105 Err: ErrMissingWord,
1106 Parsing: "Command",
1107 Token: tk[2],
1108 },
1109 Parsing: "CommandOrCompound",
1110 Token: tk[2],
1111 },
1112 Parsing: "Pipeline",
1113 Token: tk[2],
1114 },
1115 Parsing: "Statement",
1116 Token: tk[2],
1117 },
1118 Parsing: "Line",
1119 Token: tk[2],
1120 },
1121 Parsing: "File",
1122 Token: tk[2],
1123 },
1124 Parsing: "CommandSubstitution",
1125 Token: tk[2],
1126 },
1127 Parsing: "WordPart",
1128 Token: tk[1],
1129 },
1130 Parsing: "Word",
1131 Token: tk[1],
1132 },
1133 Parsing: "WordOrOperator",
1134 Token: tk[1],
1135 },
1136 Parsing: "ArithmeticExpansion",
1137 Token: tk[1],
1138 },
1139 Parsing: "Compound",
1140 Token: tk[0],
1141 }
1142 }},
1143 {"[[ a = b ]] >$(||)", func(t *test, tk Tokens) { // 25
1144 t.Err = Error{
1145 Err: Error{
1146 Err: Error{
1147 Err: Error{
1148 Err: Error{
1149 Err: Error{
1150 Err: Error{
1151 Err: Error{
1152 Err: Error{
1153 Err: Error{
1154 Err: Error{
1155 Err: ErrMissingWord,
1156 Parsing: "Command",
1157 Token: tk[12],
1158 },
1159 Parsing: "CommandOrCompound",
1160 Token: tk[12],
1161 },
1162 Parsing: "Pipeline",
1163 Token: tk[12],
1164 },
1165 Parsing: "Statement",
1166 Token: tk[12],
1167 },
1168 Parsing: "Line",
1169 Token: tk[12],
1170 },
1171 Parsing: "File",
1172 Token: tk[12],
1173 },
1174 Parsing: "CommandSubstitution",
1175 Token: tk[12],
1176 },
1177 Parsing: "WordPart",
1178 Token: tk[11],
1179 },
1180 Parsing: "Word",
1181 Token: tk[11],
1182 },
1183 Parsing: "Redirection",
1184 Token: tk[11],
1185 },
1186 Parsing: "Compound",
1187 Token: tk[10],
1188 }
1189 }},
1190 {"if a; then b; fi c", func(t *test, tk Tokens) { // 26
1191 t.Err = Error{
1192 Err: ErrInvalidEndOfStatement,
1193 Parsing: "Compound",
1194 Token: tk[12],
1195 }
1196 }},
1197 }, func(t *test) (Type, error) {
1198 var c Compound
1199
1200 err := c.parse(t.Parser)
1201
1202 return c, err
1203 })
1204 }
1205
1206 func TestIfCompound(t *testing.T) {
1207 doTests(t, []sourceFn{
1208 {"if a; then b; fi", func(t *test, tk Tokens) { // 1
1209 t.Output = IfCompound{
1210 If: TestConsequence{
1211 Test: Statement{
1212 Pipeline: Pipeline{
1213 CommandOrCompound: CommandOrCompound{
1214 Command: &Command{
1215 AssignmentsOrWords: []AssignmentOrWord{
1216 {
1217 Word: &Word{
1218 Parts: []WordPart{
1219 {
1220 Part: &tk[2],
1221 Tokens: tk[2:3],
1222 },
1223 },
1224 Tokens: tk[2:3],
1225 },
1226 Tokens: tk[2:3],
1227 },
1228 },
1229 Tokens: tk[2:3],
1230 },
1231 Tokens: tk[2:3],
1232 },
1233 Tokens: tk[2:3],
1234 },
1235 Tokens: tk[2:4],
1236 },
1237 Consequence: File{
1238 Lines: []Line{
1239 {
1240 Statements: []Statement{
1241 {
1242 Pipeline: Pipeline{
1243 CommandOrCompound: CommandOrCompound{
1244 Command: &Command{
1245 AssignmentsOrWords: []AssignmentOrWord{
1246 {
1247 Word: &Word{
1248 Parts: []WordPart{
1249 {
1250 Part: &tk[7],
1251 Tokens: tk[7:8],
1252 },
1253 },
1254 Tokens: tk[7:8],
1255 },
1256 Tokens: tk[7:8],
1257 },
1258 },
1259 Tokens: tk[7:8],
1260 },
1261 Tokens: tk[7:8],
1262 },
1263 Tokens: tk[7:8],
1264 },
1265 Tokens: tk[7:9],
1266 },
1267 },
1268 Tokens: tk[7:9],
1269 },
1270 },
1271 Tokens: tk[7:9],
1272 },
1273 Tokens: tk[2:9],
1274 },
1275 Tokens: tk[:11],
1276 }
1277 }},
1278 {"if { a; } then b; fi", func(t *test, tk Tokens) { // 2
1279 t.Output = IfCompound{
1280 If: TestConsequence{
1281 Test: Statement{
1282 Pipeline: Pipeline{
1283 CommandOrCompound: CommandOrCompound{
1284 Compound: &Compound{
1285 GroupingCompound: &GroupingCompound{
1286 File: File{
1287 Lines: []Line{
1288 {
1289 Statements: []Statement{
1290 {
1291 Pipeline: Pipeline{
1292 CommandOrCompound: CommandOrCompound{
1293 Command: &Command{
1294 AssignmentsOrWords: []AssignmentOrWord{
1295 {
1296 Word: &Word{
1297 Parts: []WordPart{
1298 {
1299 Part: &tk[4],
1300 Tokens: tk[4:5],
1301 },
1302 },
1303 Tokens: tk[4:5],
1304 },
1305 Tokens: tk[4:5],
1306 },
1307 },
1308 Tokens: tk[4:5],
1309 },
1310 Tokens: tk[4:5],
1311 },
1312 Tokens: tk[4:5],
1313 },
1314 Tokens: tk[4:6],
1315 },
1316 },
1317 Tokens: tk[4:6],
1318 },
1319 },
1320 Tokens: tk[4:6],
1321 },
1322 Tokens: tk[2:8],
1323 },
1324 Tokens: tk[2:8],
1325 },
1326 Tokens: tk[2:8],
1327 },
1328 Tokens: tk[2:8],
1329 },
1330 Tokens: tk[2:8],
1331 },
1332 Consequence: File{
1333 Lines: []Line{
1334 {
1335 Statements: []Statement{
1336 {
1337 Pipeline: Pipeline{
1338 CommandOrCompound: CommandOrCompound{
1339 Command: &Command{
1340 AssignmentsOrWords: []AssignmentOrWord{
1341 {
1342 Word: &Word{
1343 Parts: []WordPart{
1344 {
1345 Part: &tk[11],
1346 Tokens: tk[11:12],
1347 },
1348 },
1349 Tokens: tk[11:12],
1350 },
1351 Tokens: tk[11:12],
1352 },
1353 },
1354 Tokens: tk[11:12],
1355 },
1356 Tokens: tk[11:12],
1357 },
1358 Tokens: tk[11:12],
1359 },
1360 Tokens: tk[11:13],
1361 },
1362 },
1363 Tokens: tk[11:13],
1364 },
1365 },
1366 Tokens: tk[11:13],
1367 },
1368 Tokens: tk[2:13],
1369 },
1370 Tokens: tk[:15],
1371 }
1372 }},
1373 {"if\na\nthen\nb\nfi", func(t *test, tk Tokens) { // 3
1374 t.Output = IfCompound{
1375 If: TestConsequence{
1376 Test: Statement{
1377 Pipeline: Pipeline{
1378 CommandOrCompound: CommandOrCompound{
1379 Command: &Command{
1380 AssignmentsOrWords: []AssignmentOrWord{
1381 {
1382 Word: &Word{
1383 Parts: []WordPart{
1384 {
1385 Part: &tk[2],
1386 Tokens: tk[2:3],
1387 },
1388 },
1389 Tokens: tk[2:3],
1390 },
1391 Tokens: tk[2:3],
1392 },
1393 },
1394 Tokens: tk[2:3],
1395 },
1396 Tokens: tk[2:3],
1397 },
1398 Tokens: tk[2:3],
1399 },
1400 Tokens: tk[2:3],
1401 },
1402 Consequence: File{
1403 Lines: []Line{
1404 {
1405 Statements: []Statement{
1406 {
1407 Pipeline: Pipeline{
1408 CommandOrCompound: CommandOrCompound{
1409 Command: &Command{
1410 AssignmentsOrWords: []AssignmentOrWord{
1411 {
1412 Word: &Word{
1413 Parts: []WordPart{
1414 {
1415 Part: &tk[6],
1416 Tokens: tk[6:7],
1417 },
1418 },
1419 Tokens: tk[6:7],
1420 },
1421 Tokens: tk[6:7],
1422 },
1423 },
1424 Tokens: tk[6:7],
1425 },
1426 Tokens: tk[6:7],
1427 },
1428 Tokens: tk[6:7],
1429 },
1430 Tokens: tk[6:7],
1431 },
1432 },
1433 Tokens: tk[6:7],
1434 },
1435 },
1436 Tokens: tk[6:7],
1437 },
1438 Tokens: tk[2:7],
1439 },
1440 Tokens: tk[:9],
1441 }
1442 }},
1443 {"if a; then b; else c; fi", func(t *test, tk Tokens) { // 4
1444 t.Output = IfCompound{
1445 If: TestConsequence{
1446 Test: Statement{
1447 Pipeline: Pipeline{
1448 CommandOrCompound: CommandOrCompound{
1449 Command: &Command{
1450 AssignmentsOrWords: []AssignmentOrWord{
1451 {
1452 Word: &Word{
1453 Parts: []WordPart{
1454 {
1455 Part: &tk[2],
1456 Tokens: tk[2:3],
1457 },
1458 },
1459 Tokens: tk[2:3],
1460 },
1461 Tokens: tk[2:3],
1462 },
1463 },
1464 Tokens: tk[2:3],
1465 },
1466 Tokens: tk[2:3],
1467 },
1468 Tokens: tk[2:3],
1469 },
1470 Tokens: tk[2:4],
1471 },
1472 Consequence: File{
1473 Lines: []Line{
1474 {
1475 Statements: []Statement{
1476 {
1477 Pipeline: Pipeline{
1478 CommandOrCompound: CommandOrCompound{
1479 Command: &Command{
1480 AssignmentsOrWords: []AssignmentOrWord{
1481 {
1482 Word: &Word{
1483 Parts: []WordPart{
1484 {
1485 Part: &tk[7],
1486 Tokens: tk[7:8],
1487 },
1488 },
1489 Tokens: tk[7:8],
1490 },
1491 Tokens: tk[7:8],
1492 },
1493 },
1494 Tokens: tk[7:8],
1495 },
1496 Tokens: tk[7:8],
1497 },
1498 Tokens: tk[7:8],
1499 },
1500 Tokens: tk[7:9],
1501 },
1502 },
1503 Tokens: tk[7:9],
1504 },
1505 },
1506 Tokens: tk[7:9],
1507 },
1508 Tokens: tk[2:9],
1509 },
1510 Else: &File{
1511 Lines: []Line{
1512 {
1513 Statements: []Statement{
1514 {
1515 Pipeline: Pipeline{
1516 CommandOrCompound: CommandOrCompound{
1517 Command: &Command{
1518 AssignmentsOrWords: []AssignmentOrWord{
1519 {
1520 Word: &Word{
1521 Parts: []WordPart{
1522 {
1523 Part: &tk[12],
1524 Tokens: tk[12:13],
1525 },
1526 },
1527 Tokens: tk[12:13],
1528 },
1529 Tokens: tk[12:13],
1530 },
1531 },
1532 Tokens: tk[12:13],
1533 },
1534 Tokens: tk[12:13],
1535 },
1536 Tokens: tk[12:13],
1537 },
1538 Tokens: tk[12:14],
1539 },
1540 },
1541 Tokens: tk[12:14],
1542 },
1543 },
1544 Tokens: tk[12:14],
1545 },
1546 Tokens: tk[:16],
1547 }
1548 }},
1549 {"if a; then b; elif c; then d; fi", func(t *test, tk Tokens) { // 5
1550 t.Output = IfCompound{
1551 If: TestConsequence{
1552 Test: Statement{
1553 Pipeline: Pipeline{
1554 CommandOrCompound: CommandOrCompound{
1555 Command: &Command{
1556 AssignmentsOrWords: []AssignmentOrWord{
1557 {
1558 Word: &Word{
1559 Parts: []WordPart{
1560 {
1561 Part: &tk[2],
1562 Tokens: tk[2:3],
1563 },
1564 },
1565 Tokens: tk[2:3],
1566 },
1567 Tokens: tk[2:3],
1568 },
1569 },
1570 Tokens: tk[2:3],
1571 },
1572 Tokens: tk[2:3],
1573 },
1574 Tokens: tk[2:3],
1575 },
1576 Tokens: tk[2:4],
1577 },
1578 Consequence: File{
1579 Lines: []Line{
1580 {
1581 Statements: []Statement{
1582 {
1583 Pipeline: Pipeline{
1584 CommandOrCompound: CommandOrCompound{
1585 Command: &Command{
1586 AssignmentsOrWords: []AssignmentOrWord{
1587 {
1588 Word: &Word{
1589 Parts: []WordPart{
1590 {
1591 Part: &tk[7],
1592 Tokens: tk[7:8],
1593 },
1594 },
1595 Tokens: tk[7:8],
1596 },
1597 Tokens: tk[7:8],
1598 },
1599 },
1600 Tokens: tk[7:8],
1601 },
1602 Tokens: tk[7:8],
1603 },
1604 Tokens: tk[7:8],
1605 },
1606 Tokens: tk[7:9],
1607 },
1608 },
1609 Tokens: tk[7:9],
1610 },
1611 },
1612 Tokens: tk[7:9],
1613 },
1614 Tokens: tk[2:9],
1615 },
1616 ElIf: []TestConsequence{
1617 {
1618 Test: Statement{
1619 Pipeline: Pipeline{
1620 CommandOrCompound: CommandOrCompound{
1621 Command: &Command{
1622 AssignmentsOrWords: []AssignmentOrWord{
1623 {
1624 Word: &Word{
1625 Parts: []WordPart{
1626 {
1627 Part: &tk[12],
1628 Tokens: tk[12:13],
1629 },
1630 },
1631 Tokens: tk[12:13],
1632 },
1633 Tokens: tk[12:13],
1634 },
1635 },
1636 Tokens: tk[12:13],
1637 },
1638 Tokens: tk[12:13],
1639 },
1640 Tokens: tk[12:13],
1641 },
1642 Tokens: tk[12:14],
1643 },
1644 Consequence: File{
1645 Lines: []Line{
1646 {
1647 Statements: []Statement{
1648 {
1649 Pipeline: Pipeline{
1650 CommandOrCompound: CommandOrCompound{
1651 Command: &Command{
1652 AssignmentsOrWords: []AssignmentOrWord{
1653 {
1654 Word: &Word{
1655 Parts: []WordPart{
1656 {
1657 Part: &tk[17],
1658 Tokens: tk[17:18],
1659 },
1660 },
1661 Tokens: tk[17:18],
1662 },
1663 Tokens: tk[17:18],
1664 },
1665 },
1666 Tokens: tk[17:18],
1667 },
1668 Tokens: tk[17:18],
1669 },
1670 Tokens: tk[17:18],
1671 },
1672 Tokens: tk[17:19],
1673 },
1674 },
1675 Tokens: tk[17:19],
1676 },
1677 },
1678 Tokens: tk[17:19],
1679 },
1680 Tokens: tk[12:19],
1681 },
1682 },
1683 Tokens: tk[:21],
1684 }
1685 }},
1686 {"if a; then b; else\n# comment\nc; fi", func(t *test, tk Tokens) { // 6
1687 t.Output = IfCompound{
1688 If: TestConsequence{
1689 Test: Statement{
1690 Pipeline: Pipeline{
1691 CommandOrCompound: CommandOrCompound{
1692 Command: &Command{
1693 AssignmentsOrWords: []AssignmentOrWord{
1694 {
1695 Word: &Word{
1696 Parts: []WordPart{
1697 {
1698 Part: &tk[2],
1699 Tokens: tk[2:3],
1700 },
1701 },
1702 Tokens: tk[2:3],
1703 },
1704 Tokens: tk[2:3],
1705 },
1706 },
1707 Tokens: tk[2:3],
1708 },
1709 Tokens: tk[2:3],
1710 },
1711 Tokens: tk[2:3],
1712 },
1713 Tokens: tk[2:4],
1714 },
1715 Consequence: File{
1716 Lines: []Line{
1717 {
1718 Statements: []Statement{
1719 {
1720 Pipeline: Pipeline{
1721 CommandOrCompound: CommandOrCompound{
1722 Command: &Command{
1723 AssignmentsOrWords: []AssignmentOrWord{
1724 {
1725 Word: &Word{
1726 Parts: []WordPart{
1727 {
1728 Part: &tk[7],
1729 Tokens: tk[7:8],
1730 },
1731 },
1732 Tokens: tk[7:8],
1733 },
1734 Tokens: tk[7:8],
1735 },
1736 },
1737 Tokens: tk[7:8],
1738 },
1739 Tokens: tk[7:8],
1740 },
1741 Tokens: tk[7:8],
1742 },
1743 Tokens: tk[7:9],
1744 },
1745 },
1746 Tokens: tk[7:9],
1747 },
1748 },
1749 Tokens: tk[7:9],
1750 },
1751 Tokens: tk[2:9],
1752 },
1753 Else: &File{
1754 Lines: []Line{
1755 {
1756 Statements: []Statement{
1757 {
1758 Pipeline: Pipeline{
1759 CommandOrCompound: CommandOrCompound{
1760 Command: &Command{
1761 AssignmentsOrWords: []AssignmentOrWord{
1762 {
1763 Word: &Word{
1764 Parts: []WordPart{
1765 {
1766 Part: &tk[14],
1767 Tokens: tk[14:15],
1768 },
1769 },
1770 Tokens: tk[14:15],
1771 },
1772 Tokens: tk[14:15],
1773 },
1774 },
1775 Tokens: tk[14:15],
1776 },
1777 Tokens: tk[14:15],
1778 },
1779 Tokens: tk[14:15],
1780 },
1781 Tokens: tk[14:16],
1782 },
1783 },
1784 Comments: [2]Comments{{tk[12]}},
1785 Tokens: tk[12:16],
1786 },
1787 },
1788 Tokens: tk[12:16],
1789 },
1790 Tokens: tk[:18],
1791 }
1792 }},
1793 {"if a; then b; else # comment\nc; fi", func(t *test, tk Tokens) { // 7
1794 t.Output = IfCompound{
1795 If: TestConsequence{
1796 Test: Statement{
1797 Pipeline: Pipeline{
1798 CommandOrCompound: CommandOrCompound{
1799 Command: &Command{
1800 AssignmentsOrWords: []AssignmentOrWord{
1801 {
1802 Word: &Word{
1803 Parts: []WordPart{
1804 {
1805 Part: &tk[2],
1806 Tokens: tk[2:3],
1807 },
1808 },
1809 Tokens: tk[2:3],
1810 },
1811 Tokens: tk[2:3],
1812 },
1813 },
1814 Tokens: tk[2:3],
1815 },
1816 Tokens: tk[2:3],
1817 },
1818 Tokens: tk[2:3],
1819 },
1820 Tokens: tk[2:4],
1821 },
1822 Consequence: File{
1823 Lines: []Line{
1824 {
1825 Statements: []Statement{
1826 {
1827 Pipeline: Pipeline{
1828 CommandOrCompound: CommandOrCompound{
1829 Command: &Command{
1830 AssignmentsOrWords: []AssignmentOrWord{
1831 {
1832 Word: &Word{
1833 Parts: []WordPart{
1834 {
1835 Part: &tk[7],
1836 Tokens: tk[7:8],
1837 },
1838 },
1839 Tokens: tk[7:8],
1840 },
1841 Tokens: tk[7:8],
1842 },
1843 },
1844 Tokens: tk[7:8],
1845 },
1846 Tokens: tk[7:8],
1847 },
1848 Tokens: tk[7:8],
1849 },
1850 Tokens: tk[7:9],
1851 },
1852 },
1853 Tokens: tk[7:9],
1854 },
1855 },
1856 Tokens: tk[7:9],
1857 },
1858 Tokens: tk[2:9],
1859 },
1860 Else: &File{
1861 Lines: []Line{
1862 {
1863 Statements: []Statement{
1864 {
1865 Pipeline: Pipeline{
1866 CommandOrCompound: CommandOrCompound{
1867 Command: &Command{
1868 AssignmentsOrWords: []AssignmentOrWord{
1869 {
1870 Word: &Word{
1871 Parts: []WordPart{
1872 {
1873 Part: &tk[14],
1874 Tokens: tk[14:15],
1875 },
1876 },
1877 Tokens: tk[14:15],
1878 },
1879 Tokens: tk[14:15],
1880 },
1881 },
1882 Tokens: tk[14:15],
1883 },
1884 Tokens: tk[14:15],
1885 },
1886 Tokens: tk[14:15],
1887 },
1888 Tokens: tk[14:16],
1889 },
1890 },
1891 Tokens: tk[14:16],
1892 },
1893 },
1894 Comments: [2]Comments{{tk[12]}},
1895 Tokens: tk[12:16],
1896 },
1897 Tokens: tk[:18],
1898 }
1899 }},
1900 {"if ||;then b;fi", func(t *test, tk Tokens) { // 8
1901 t.Err = Error{
1902 Err: Error{
1903 Err: Error{
1904 Err: Error{
1905 Err: Error{
1906 Err: Error{
1907 Err: ErrMissingWord,
1908 Parsing: "Command",
1909 Token: tk[2],
1910 },
1911 Parsing: "CommandOrCompound",
1912 Token: tk[2],
1913 },
1914 Parsing: "Pipeline",
1915 Token: tk[2],
1916 },
1917 Parsing: "Statement",
1918 Token: tk[2],
1919 },
1920 Parsing: "TestConsequence",
1921 Token: tk[2],
1922 },
1923 Parsing: "IfCompound",
1924 Token: tk[2],
1925 }
1926 }},
1927 {"if a;then b;elif ||;then d;fi", func(t *test, tk Tokens) { // 9
1928 t.Err = Error{
1929 Err: Error{
1930 Err: Error{
1931 Err: Error{
1932 Err: Error{
1933 Err: Error{
1934 Err: ErrMissingWord,
1935 Parsing: "Command",
1936 Token: tk[10],
1937 },
1938 Parsing: "CommandOrCompound",
1939 Token: tk[10],
1940 },
1941 Parsing: "Pipeline",
1942 Token: tk[10],
1943 },
1944 Parsing: "Statement",
1945 Token: tk[10],
1946 },
1947 Parsing: "TestConsequence",
1948 Token: tk[10],
1949 },
1950 Parsing: "IfCompound",
1951 Token: tk[10],
1952 }
1953 }},
1954 {"if a;then b;else ||;fi", func(t *test, tk Tokens) { // 10
1955 t.Err = Error{
1956 Err: Error{
1957 Err: Error{
1958 Err: Error{
1959 Err: Error{
1960 Err: Error{
1961 Err: Error{
1962 Err: ErrMissingWord,
1963 Parsing: "Command",
1964 Token: tk[10],
1965 },
1966 Parsing: "CommandOrCompound",
1967 Token: tk[10],
1968 },
1969 Parsing: "Pipeline",
1970 Token: tk[10],
1971 },
1972 Parsing: "Statement",
1973 Token: tk[10],
1974 },
1975 Parsing: "Line",
1976 Token: tk[10],
1977 },
1978 Parsing: "File",
1979 Token: tk[10],
1980 },
1981 Parsing: "IfCompound",
1982 Token: tk[10],
1983 }
1984 }},
1985 }, func(t *test) (Type, error) {
1986 var i IfCompound
1987
1988 err := i.parse(t.Parser)
1989
1990 return i, err
1991 })
1992 }
1993
1994 func TestTestConsequence(t *testing.T) {
1995 doTests(t, []sourceFn{
1996 {"if a; then b;fi", func(t *test, tk Tokens) { // 1
1997 t.Output = TestConsequence{
1998 Test: Statement{
1999 Pipeline: Pipeline{
2000 CommandOrCompound: CommandOrCompound{
2001 Command: &Command{
2002 AssignmentsOrWords: []AssignmentOrWord{
2003 {
2004 Word: &Word{
2005 Parts: []WordPart{
2006 {
2007 Part: &tk[2],
2008 Tokens: tk[2:3],
2009 },
2010 },
2011 Tokens: tk[2:3],
2012 },
2013 Tokens: tk[2:3],
2014 },
2015 },
2016 Tokens: tk[2:3],
2017 },
2018 Tokens: tk[2:3],
2019 },
2020 Tokens: tk[2:3],
2021 },
2022 Tokens: tk[2:4],
2023 },
2024 Consequence: File{
2025 Lines: []Line{
2026 {
2027 Statements: []Statement{
2028 {
2029 Pipeline: Pipeline{
2030 CommandOrCompound: CommandOrCompound{
2031 Command: &Command{
2032 AssignmentsOrWords: []AssignmentOrWord{
2033 {
2034 Word: &Word{
2035 Parts: []WordPart{
2036 {
2037 Part: &tk[7],
2038 Tokens: tk[7:8],
2039 },
2040 },
2041 Tokens: tk[7:8],
2042 },
2043 Tokens: tk[7:8],
2044 },
2045 },
2046 Tokens: tk[7:8],
2047 },
2048 Tokens: tk[7:8],
2049 },
2050 Tokens: tk[7:8],
2051 },
2052 Tokens: tk[7:9],
2053 },
2054 },
2055 Tokens: tk[7:9],
2056 },
2057 },
2058 Tokens: tk[7:9],
2059 },
2060 Tokens: tk[2:9],
2061 }
2062 }},
2063 {"if a\nthen\nb\nc\nfi", func(t *test, tk Tokens) { // 2
2064 t.Output = TestConsequence{
2065 Test: Statement{
2066 Pipeline: Pipeline{
2067 CommandOrCompound: CommandOrCompound{
2068 Command: &Command{
2069 AssignmentsOrWords: []AssignmentOrWord{
2070 {
2071 Word: &Word{
2072 Parts: []WordPart{
2073 {
2074 Part: &tk[2],
2075 Tokens: tk[2:3],
2076 },
2077 },
2078 Tokens: tk[2:3],
2079 },
2080 Tokens: tk[2:3],
2081 },
2082 },
2083 Tokens: tk[2:3],
2084 },
2085 Tokens: tk[2:3],
2086 },
2087 Tokens: tk[2:3],
2088 },
2089 Tokens: tk[2:3],
2090 },
2091 Consequence: File{
2092 Lines: []Line{
2093 {
2094 Statements: []Statement{
2095 {
2096 Pipeline: Pipeline{
2097 CommandOrCompound: CommandOrCompound{
2098 Command: &Command{
2099 AssignmentsOrWords: []AssignmentOrWord{
2100 {
2101 Word: &Word{
2102 Parts: []WordPart{
2103 {
2104 Part: &tk[6],
2105 Tokens: tk[6:7],
2106 },
2107 },
2108 Tokens: tk[6:7],
2109 },
2110 Tokens: tk[6:7],
2111 },
2112 },
2113 Tokens: tk[6:7],
2114 },
2115 Tokens: tk[6:7],
2116 },
2117 Tokens: tk[6:7],
2118 },
2119 Tokens: tk[6:7],
2120 },
2121 },
2122 Tokens: tk[6:7],
2123 },
2124 {
2125 Statements: []Statement{
2126 {
2127 Pipeline: Pipeline{
2128 CommandOrCompound: CommandOrCompound{
2129 Command: &Command{
2130 AssignmentsOrWords: []AssignmentOrWord{
2131 {
2132 Word: &Word{
2133 Parts: []WordPart{
2134 {
2135 Part: &tk[8],
2136 Tokens: tk[8:9],
2137 },
2138 },
2139 Tokens: tk[8:9],
2140 },
2141 Tokens: tk[8:9],
2142 },
2143 },
2144 Tokens: tk[8:9],
2145 },
2146 Tokens: tk[8:9],
2147 },
2148 Tokens: tk[8:9],
2149 },
2150 Tokens: tk[8:9],
2151 },
2152 },
2153 Tokens: tk[8:9],
2154 },
2155 },
2156 Tokens: tk[6:9],
2157 },
2158 Tokens: tk[2:9],
2159 }
2160 }},
2161 {"if a; #comment\nthen b;fi", func(t *test, tk Tokens) { // 3
2162 t.Output = TestConsequence{
2163 Test: Statement{
2164 Pipeline: Pipeline{
2165 CommandOrCompound: CommandOrCompound{
2166 Command: &Command{
2167 AssignmentsOrWords: []AssignmentOrWord{
2168 {
2169 Word: &Word{
2170 Parts: []WordPart{
2171 {
2172 Part: &tk[2],
2173 Tokens: tk[2:3],
2174 },
2175 },
2176 Tokens: tk[2:3],
2177 },
2178 Tokens: tk[2:3],
2179 },
2180 },
2181 Tokens: tk[2:3],
2182 },
2183 Tokens: tk[2:3],
2184 },
2185 Tokens: tk[2:3],
2186 },
2187 Tokens: tk[2:4],
2188 },
2189 Consequence: File{
2190 Lines: []Line{
2191 {
2192 Statements: []Statement{
2193 {
2194 Pipeline: Pipeline{
2195 CommandOrCompound: CommandOrCompound{
2196 Command: &Command{
2197 AssignmentsOrWords: []AssignmentOrWord{
2198 {
2199 Word: &Word{
2200 Parts: []WordPart{
2201 {
2202 Part: &tk[9],
2203 Tokens: tk[9:10],
2204 },
2205 },
2206 Tokens: tk[9:10],
2207 },
2208 Tokens: tk[9:10],
2209 },
2210 },
2211 Tokens: tk[9:10],
2212 },
2213 Tokens: tk[9:10],
2214 },
2215 Tokens: tk[9:10],
2216 },
2217 Tokens: tk[9:11],
2218 },
2219 },
2220 Tokens: tk[9:11],
2221 },
2222 },
2223 Tokens: tk[9:11],
2224 },
2225 Comments: Comments{tk[5]},
2226 Tokens: tk[2:11],
2227 }
2228 }},
2229 {"if a\n#comment\nthen b;fi", func(t *test, tk Tokens) { // 4
2230 t.Output = TestConsequence{
2231 Test: Statement{
2232 Pipeline: Pipeline{
2233 CommandOrCompound: CommandOrCompound{
2234 Command: &Command{
2235 AssignmentsOrWords: []AssignmentOrWord{
2236 {
2237 Word: &Word{
2238 Parts: []WordPart{
2239 {
2240 Part: &tk[2],
2241 Tokens: tk[2:3],
2242 },
2243 },
2244 Tokens: tk[2:3],
2245 },
2246 Tokens: tk[2:3],
2247 },
2248 },
2249 Tokens: tk[2:3],
2250 },
2251 Tokens: tk[2:3],
2252 },
2253 Tokens: tk[2:3],
2254 },
2255 Tokens: tk[2:3],
2256 },
2257 Consequence: File{
2258 Lines: []Line{
2259 {
2260 Statements: []Statement{
2261 {
2262 Pipeline: Pipeline{
2263 CommandOrCompound: CommandOrCompound{
2264 Command: &Command{
2265 AssignmentsOrWords: []AssignmentOrWord{
2266 {
2267 Word: &Word{
2268 Parts: []WordPart{
2269 {
2270 Part: &tk[8],
2271 Tokens: tk[8:9],
2272 },
2273 },
2274 Tokens: tk[8:9],
2275 },
2276 Tokens: tk[8:9],
2277 },
2278 },
2279 Tokens: tk[8:9],
2280 },
2281 Tokens: tk[8:9],
2282 },
2283 Tokens: tk[8:9],
2284 },
2285 Tokens: tk[8:10],
2286 },
2287 },
2288 Tokens: tk[8:10],
2289 },
2290 },
2291 Tokens: tk[8:10],
2292 },
2293 Comments: Comments{tk[4]},
2294 Tokens: tk[2:10],
2295 }
2296 }},
2297 {"if a; then # comment\nb;fi", func(t *test, tk Tokens) { // 5
2298 t.Output = TestConsequence{
2299 Test: Statement{
2300 Pipeline: Pipeline{
2301 CommandOrCompound: CommandOrCompound{
2302 Command: &Command{
2303 AssignmentsOrWords: []AssignmentOrWord{
2304 {
2305 Word: &Word{
2306 Parts: []WordPart{
2307 {
2308 Part: &tk[2],
2309 Tokens: tk[2:3],
2310 },
2311 },
2312 Tokens: tk[2:3],
2313 },
2314 Tokens: tk[2:3],
2315 },
2316 },
2317 Tokens: tk[2:3],
2318 },
2319 Tokens: tk[2:3],
2320 },
2321 Tokens: tk[2:3],
2322 },
2323 Tokens: tk[2:4],
2324 },
2325 Consequence: File{
2326 Lines: []Line{
2327 {
2328 Statements: []Statement{
2329 {
2330 Pipeline: Pipeline{
2331 CommandOrCompound: CommandOrCompound{
2332 Command: &Command{
2333 AssignmentsOrWords: []AssignmentOrWord{
2334 {
2335 Word: &Word{
2336 Parts: []WordPart{
2337 {
2338 Part: &tk[9],
2339 Tokens: tk[9:10],
2340 },
2341 },
2342 Tokens: tk[9:10],
2343 },
2344 Tokens: tk[9:10],
2345 },
2346 },
2347 Tokens: tk[9:10],
2348 },
2349 Tokens: tk[9:10],
2350 },
2351 Tokens: tk[9:10],
2352 },
2353 Tokens: tk[9:11],
2354 },
2355 },
2356 Tokens: tk[9:11],
2357 },
2358 },
2359 Comments: [2]Comments{{tk[7]}},
2360 Tokens: tk[7:11],
2361 },
2362 Tokens: tk[2:11],
2363 }
2364 }},
2365 {"if a; then\n# comment\nb;fi", func(t *test, tk Tokens) { // 6
2366 t.Output = TestConsequence{
2367 Test: Statement{
2368 Pipeline: Pipeline{
2369 CommandOrCompound: CommandOrCompound{
2370 Command: &Command{
2371 AssignmentsOrWords: []AssignmentOrWord{
2372 {
2373 Word: &Word{
2374 Parts: []WordPart{
2375 {
2376 Part: &tk[2],
2377 Tokens: tk[2:3],
2378 },
2379 },
2380 Tokens: tk[2:3],
2381 },
2382 Tokens: tk[2:3],
2383 },
2384 },
2385 Tokens: tk[2:3],
2386 },
2387 Tokens: tk[2:3],
2388 },
2389 Tokens: tk[2:3],
2390 },
2391 Tokens: tk[2:4],
2392 },
2393 Consequence: File{
2394 Lines: []Line{
2395 {
2396 Statements: []Statement{
2397 {
2398 Pipeline: Pipeline{
2399 CommandOrCompound: CommandOrCompound{
2400 Command: &Command{
2401 AssignmentsOrWords: []AssignmentOrWord{
2402 {
2403 Word: &Word{
2404 Parts: []WordPart{
2405 {
2406 Part: &tk[9],
2407 Tokens: tk[9:10],
2408 },
2409 },
2410 Tokens: tk[9:10],
2411 },
2412 Tokens: tk[9:10],
2413 },
2414 },
2415 Tokens: tk[9:10],
2416 },
2417 Tokens: tk[9:10],
2418 },
2419 Tokens: tk[9:10],
2420 },
2421 Tokens: tk[9:11],
2422 },
2423 },
2424 Comments: [2]Comments{{tk[7]}},
2425 Tokens: tk[7:11],
2426 },
2427 },
2428 Tokens: tk[7:11],
2429 },
2430 Tokens: tk[2:11],
2431 }
2432 }},
2433 {"if ||; then b;fi", func(t *test, tk Tokens) { // 7
2434 t.Err = Error{
2435 Err: Error{
2436 Err: Error{
2437 Err: Error{
2438 Err: Error{
2439 Err: ErrMissingWord,
2440 Parsing: "Command",
2441 Token: tk[2],
2442 },
2443 Parsing: "CommandOrCompound",
2444 Token: tk[2],
2445 },
2446 Parsing: "Pipeline",
2447 Token: tk[2],
2448 },
2449 Parsing: "Statement",
2450 Token: tk[2],
2451 },
2452 Parsing: "TestConsequence",
2453 Token: tk[2],
2454 }
2455 }},
2456 {"if a; then ||;fi", func(t *test, tk Tokens) { // 8
2457 t.Err = Error{
2458 Err: Error{
2459 Err: Error{
2460 Err: Error{
2461 Err: Error{
2462 Err: Error{
2463 Err: Error{
2464 Err: ErrMissingWord,
2465 Parsing: "Command",
2466 Token: tk[7],
2467 },
2468 Parsing: "CommandOrCompound",
2469 Token: tk[7],
2470 },
2471 Parsing: "Pipeline",
2472 Token: tk[7],
2473 },
2474 Parsing: "Statement",
2475 Token: tk[7],
2476 },
2477 Parsing: "Line",
2478 Token: tk[7],
2479 },
2480 Parsing: "File",
2481 Token: tk[7],
2482 },
2483 Parsing: "TestConsequence",
2484 Token: tk[7],
2485 }
2486 }},
2487 }, func(t *test) (Type, error) {
2488 var tc TestConsequence
2489
2490 t.Parser.Tokens = t.Parser.Tokens[2:2]
2491 err := tc.parse(t.Parser)
2492
2493 return tc, err
2494 })
2495 }
2496
2497 func TestCaseCompound(t *testing.T) {
2498 doTests(t, []sourceFn{
2499 {"case a in b)c\nesac", func(t *test, tk Tokens) { // 1
2500 t.Output = CaseCompound{
2501 Word: Word{
2502 Parts: []WordPart{
2503 {
2504 Part: &tk[2],
2505 Tokens: tk[2:3],
2506 },
2507 },
2508 Tokens: tk[2:3],
2509 },
2510 Matches: []PatternLines{
2511 {
2512 Patterns: []Word{
2513 {
2514 Parts: []WordPart{
2515 {
2516 Part: &tk[6],
2517 Tokens: tk[6:7],
2518 },
2519 },
2520 Tokens: tk[6:7],
2521 },
2522 },
2523 Lines: File{
2524 Lines: []Line{
2525 {
2526 Statements: []Statement{
2527 {
2528 Pipeline: Pipeline{
2529 CommandOrCompound: CommandOrCompound{
2530 Command: &Command{
2531 AssignmentsOrWords: []AssignmentOrWord{
2532 {
2533 Word: &Word{
2534 Parts: []WordPart{
2535 {
2536 Part: &tk[8],
2537 Tokens: tk[8:9],
2538 },
2539 },
2540 Tokens: tk[8:9],
2541 },
2542 Tokens: tk[8:9],
2543 },
2544 },
2545 Tokens: tk[8:9],
2546 },
2547 Tokens: tk[8:9],
2548 },
2549 Tokens: tk[8:9],
2550 },
2551 Tokens: tk[8:9],
2552 },
2553 },
2554 Tokens: tk[8:9],
2555 },
2556 },
2557 Tokens: tk[8:9],
2558 },
2559 Tokens: tk[6:9],
2560 },
2561 },
2562 Tokens: tk[:11],
2563 }
2564 }},
2565 {"case a in b)c;esac", func(t *test, tk Tokens) { // 2
2566 t.Output = CaseCompound{
2567 Word: Word{
2568 Parts: []WordPart{
2569 {
2570 Part: &tk[2],
2571 Tokens: tk[2:3],
2572 },
2573 },
2574 Tokens: tk[2:3],
2575 },
2576 Matches: []PatternLines{
2577 {
2578 Patterns: []Word{
2579 {
2580 Parts: []WordPart{
2581 {
2582 Part: &tk[6],
2583 Tokens: tk[6:7],
2584 },
2585 },
2586 Tokens: tk[6:7],
2587 },
2588 },
2589 Lines: File{
2590 Lines: []Line{
2591 {
2592 Statements: []Statement{
2593 {
2594 Pipeline: Pipeline{
2595 CommandOrCompound: CommandOrCompound{
2596 Command: &Command{
2597 AssignmentsOrWords: []AssignmentOrWord{
2598 {
2599 Word: &Word{
2600 Parts: []WordPart{
2601 {
2602 Part: &tk[8],
2603 Tokens: tk[8:9],
2604 },
2605 },
2606 Tokens: tk[8:9],
2607 },
2608 Tokens: tk[8:9],
2609 },
2610 },
2611 Tokens: tk[8:9],
2612 },
2613 Tokens: tk[8:9],
2614 },
2615 Tokens: tk[8:9],
2616 },
2617 Tokens: tk[8:10],
2618 },
2619 },
2620 Tokens: tk[8:10],
2621 },
2622 },
2623 Tokens: tk[8:10],
2624 },
2625 Tokens: tk[6:10],
2626 },
2627 },
2628 Tokens: tk[:11],
2629 }
2630 }},
2631 {"case a in b)c;;esac", func(t *test, tk Tokens) { // 3
2632 t.Output = CaseCompound{
2633 Word: Word{
2634 Parts: []WordPart{
2635 {
2636 Part: &tk[2],
2637 Tokens: tk[2:3],
2638 },
2639 },
2640 Tokens: tk[2:3],
2641 },
2642 Matches: []PatternLines{
2643 {
2644 Patterns: []Word{
2645 {
2646 Parts: []WordPart{
2647 {
2648 Part: &tk[6],
2649 Tokens: tk[6:7],
2650 },
2651 },
2652 Tokens: tk[6:7],
2653 },
2654 },
2655 Lines: File{
2656 Lines: []Line{
2657 {
2658 Statements: []Statement{
2659 {
2660 Pipeline: Pipeline{
2661 CommandOrCompound: CommandOrCompound{
2662 Command: &Command{
2663 AssignmentsOrWords: []AssignmentOrWord{
2664 {
2665 Word: &Word{
2666 Parts: []WordPart{
2667 {
2668 Part: &tk[8],
2669 Tokens: tk[8:9],
2670 },
2671 },
2672 Tokens: tk[8:9],
2673 },
2674 Tokens: tk[8:9],
2675 },
2676 },
2677 Tokens: tk[8:9],
2678 },
2679 Tokens: tk[8:9],
2680 },
2681 Tokens: tk[8:9],
2682 },
2683 Tokens: tk[8:9],
2684 },
2685 },
2686 Tokens: tk[8:9],
2687 },
2688 },
2689 Tokens: tk[8:9],
2690 },
2691 CaseTerminationType: CaseTerminationEnd,
2692 Tokens: tk[6:10],
2693 },
2694 },
2695 Tokens: tk[:11],
2696 }
2697 }},
2698 {"case a in b)c;;\nd|e)f;;esac", func(t *test, tk Tokens) { // 4
2699 t.Output = CaseCompound{
2700 Word: Word{
2701 Parts: []WordPart{
2702 {
2703 Part: &tk[2],
2704 Tokens: tk[2:3],
2705 },
2706 },
2707 Tokens: tk[2:3],
2708 },
2709 Matches: []PatternLines{
2710 {
2711 Patterns: []Word{
2712 {
2713 Parts: []WordPart{
2714 {
2715 Part: &tk[6],
2716 Tokens: tk[6:7],
2717 },
2718 },
2719 Tokens: tk[6:7],
2720 },
2721 },
2722 Lines: File{
2723 Lines: []Line{
2724 {
2725 Statements: []Statement{
2726 {
2727 Pipeline: Pipeline{
2728 CommandOrCompound: CommandOrCompound{
2729 Command: &Command{
2730 AssignmentsOrWords: []AssignmentOrWord{
2731 {
2732 Word: &Word{
2733 Parts: []WordPart{
2734 {
2735 Part: &tk[8],
2736 Tokens: tk[8:9],
2737 },
2738 },
2739 Tokens: tk[8:9],
2740 },
2741 Tokens: tk[8:9],
2742 },
2743 },
2744 Tokens: tk[8:9],
2745 },
2746 Tokens: tk[8:9],
2747 },
2748 Tokens: tk[8:9],
2749 },
2750 Tokens: tk[8:9],
2751 },
2752 },
2753 Tokens: tk[8:9],
2754 },
2755 },
2756 Tokens: tk[8:9],
2757 },
2758 CaseTerminationType: CaseTerminationEnd,
2759 Tokens: tk[6:10],
2760 },
2761 {
2762 Patterns: []Word{
2763 {
2764 Parts: []WordPart{
2765 {
2766 Part: &tk[11],
2767 Tokens: tk[11:12],
2768 },
2769 },
2770 Tokens: tk[11:12],
2771 },
2772 {
2773 Parts: []WordPart{
2774 {
2775 Part: &tk[13],
2776 Tokens: tk[13:14],
2777 },
2778 },
2779 Tokens: tk[13:14],
2780 },
2781 },
2782 Lines: File{
2783 Lines: []Line{
2784 {
2785 Statements: []Statement{
2786 {
2787 Pipeline: Pipeline{
2788 CommandOrCompound: CommandOrCompound{
2789 Command: &Command{
2790 AssignmentsOrWords: []AssignmentOrWord{
2791 {
2792 Word: &Word{
2793 Parts: []WordPart{
2794 {
2795 Part: &tk[15],
2796 Tokens: tk[15:16],
2797 },
2798 },
2799 Tokens: tk[15:16],
2800 },
2801 Tokens: tk[15:16],
2802 },
2803 },
2804 Tokens: tk[15:16],
2805 },
2806 Tokens: tk[15:16],
2807 },
2808 Tokens: tk[15:16],
2809 },
2810 Tokens: tk[15:16],
2811 },
2812 },
2813 Tokens: tk[15:16],
2814 },
2815 },
2816 Tokens: tk[15:16],
2817 },
2818 CaseTerminationType: CaseTerminationEnd,
2819 Tokens: tk[11:17],
2820 },
2821 },
2822 Tokens: tk[:18],
2823 }
2824 }},
2825 {"case a # comment\nin b)c;;esac", func(t *test, tk Tokens) { // 5
2826 t.Output = CaseCompound{
2827 Word: Word{
2828 Parts: []WordPart{
2829 {
2830 Part: &tk[2],
2831 Tokens: tk[2:3],
2832 },
2833 },
2834 Tokens: tk[2:3],
2835 },
2836 Matches: []PatternLines{
2837 {
2838 Patterns: []Word{
2839 {
2840 Parts: []WordPart{
2841 {
2842 Part: &tk[8],
2843 Tokens: tk[8:9],
2844 },
2845 },
2846 Tokens: tk[8:9],
2847 },
2848 },
2849 Lines: File{
2850 Lines: []Line{
2851 {
2852 Statements: []Statement{
2853 {
2854 Pipeline: Pipeline{
2855 CommandOrCompound: CommandOrCompound{
2856 Command: &Command{
2857 AssignmentsOrWords: []AssignmentOrWord{
2858 {
2859 Word: &Word{
2860 Parts: []WordPart{
2861 {
2862 Part: &tk[10],
2863 Tokens: tk[10:11],
2864 },
2865 },
2866 Tokens: tk[10:11],
2867 },
2868 Tokens: tk[10:11],
2869 },
2870 },
2871 Tokens: tk[10:11],
2872 },
2873 Tokens: tk[10:11],
2874 },
2875 Tokens: tk[10:11],
2876 },
2877 Tokens: tk[10:11],
2878 },
2879 },
2880 Tokens: tk[10:11],
2881 },
2882 },
2883 Tokens: tk[10:11],
2884 },
2885 CaseTerminationType: CaseTerminationEnd,
2886 Tokens: tk[8:12],
2887 },
2888 },
2889 Comments: [3]Comments{{tk[4]}},
2890 Tokens: tk[:13],
2891 }
2892 }},
2893 {"case a in # comment\nb)c;;esac", func(t *test, tk Tokens) { // 6
2894 t.Output = CaseCompound{
2895 Word: Word{
2896 Parts: []WordPart{
2897 {
2898 Part: &tk[2],
2899 Tokens: tk[2:3],
2900 },
2901 },
2902 Tokens: tk[2:3],
2903 },
2904 Matches: []PatternLines{
2905 {
2906 Patterns: []Word{
2907 {
2908 Parts: []WordPart{
2909 {
2910 Part: &tk[8],
2911 Tokens: tk[8:9],
2912 },
2913 },
2914 Tokens: tk[8:9],
2915 },
2916 },
2917 Lines: File{
2918 Lines: []Line{
2919 {
2920 Statements: []Statement{
2921 {
2922 Pipeline: Pipeline{
2923 CommandOrCompound: CommandOrCompound{
2924 Command: &Command{
2925 AssignmentsOrWords: []AssignmentOrWord{
2926 {
2927 Word: &Word{
2928 Parts: []WordPart{
2929 {
2930 Part: &tk[10],
2931 Tokens: tk[10:11],
2932 },
2933 },
2934 Tokens: tk[10:11],
2935 },
2936 Tokens: tk[10:11],
2937 },
2938 },
2939 Tokens: tk[10:11],
2940 },
2941 Tokens: tk[10:11],
2942 },
2943 Tokens: tk[10:11],
2944 },
2945 Tokens: tk[10:11],
2946 },
2947 },
2948 Tokens: tk[10:11],
2949 },
2950 },
2951 Tokens: tk[10:11],
2952 },
2953 CaseTerminationType: CaseTerminationEnd,
2954 Tokens: tk[8:12],
2955 },
2956 },
2957 Comments: [3]Comments{nil, {tk[6]}},
2958 Tokens: tk[:13],
2959 }
2960 }},
2961 {"case a in\n# comment\nb)c;;esac", func(t *test, tk Tokens) { // 7
2962 t.Output = CaseCompound{
2963 Word: Word{
2964 Parts: []WordPart{
2965 {
2966 Part: &tk[2],
2967 Tokens: tk[2:3],
2968 },
2969 },
2970 Tokens: tk[2:3],
2971 },
2972 Matches: []PatternLines{
2973 {
2974 Patterns: []Word{
2975 {
2976 Parts: []WordPart{
2977 {
2978 Part: &tk[8],
2979 Tokens: tk[8:9],
2980 },
2981 },
2982 Tokens: tk[8:9],
2983 },
2984 },
2985 Lines: File{
2986 Lines: []Line{
2987 {
2988 Statements: []Statement{
2989 {
2990 Pipeline: Pipeline{
2991 CommandOrCompound: CommandOrCompound{
2992 Command: &Command{
2993 AssignmentsOrWords: []AssignmentOrWord{
2994 {
2995 Word: &Word{
2996 Parts: []WordPart{
2997 {
2998 Part: &tk[10],
2999 Tokens: tk[10:11],
3000 },
3001 },
3002 Tokens: tk[10:11],
3003 },
3004 Tokens: tk[10:11],
3005 },
3006 },
3007 Tokens: tk[10:11],
3008 },
3009 Tokens: tk[10:11],
3010 },
3011 Tokens: tk[10:11],
3012 },
3013 Tokens: tk[10:11],
3014 },
3015 },
3016 Tokens: tk[10:11],
3017 },
3018 },
3019 Tokens: tk[10:11],
3020 },
3021 CaseTerminationType: CaseTerminationEnd,
3022 Comments: Comments{tk[6]},
3023 Tokens: tk[6:12],
3024 },
3025 },
3026 Tokens: tk[:13],
3027 }
3028 }},
3029 {"case a in b)c;; # comment\nesac", func(t *test, tk Tokens) { // 8
3030 t.Output = CaseCompound{
3031 Word: Word{
3032 Parts: []WordPart{
3033 {
3034 Part: &tk[2],
3035 Tokens: tk[2:3],
3036 },
3037 },
3038 Tokens: tk[2:3],
3039 },
3040 Matches: []PatternLines{
3041 {
3042 Patterns: []Word{
3043 {
3044 Parts: []WordPart{
3045 {
3046 Part: &tk[6],
3047 Tokens: tk[6:7],
3048 },
3049 },
3050 Tokens: tk[6:7],
3051 },
3052 },
3053 Lines: File{
3054 Lines: []Line{
3055 {
3056 Statements: []Statement{
3057 {
3058 Pipeline: Pipeline{
3059 CommandOrCompound: CommandOrCompound{
3060 Command: &Command{
3061 AssignmentsOrWords: []AssignmentOrWord{
3062 {
3063 Word: &Word{
3064 Parts: []WordPart{
3065 {
3066 Part: &tk[8],
3067 Tokens: tk[8:9],
3068 },
3069 },
3070 Tokens: tk[8:9],
3071 },
3072 Tokens: tk[8:9],
3073 },
3074 },
3075 Tokens: tk[8:9],
3076 },
3077 Tokens: tk[8:9],
3078 },
3079 Tokens: tk[8:9],
3080 },
3081 Tokens: tk[8:9],
3082 },
3083 },
3084 Tokens: tk[8:9],
3085 },
3086 },
3087 Tokens: tk[8:9],
3088 },
3089 CaseTerminationType: CaseTerminationEnd,
3090 Tokens: tk[6:10],
3091 },
3092 },
3093 Comments: [3]Comments{nil, nil, {tk[11]}},
3094 Tokens: tk[:14],
3095 }
3096 }},
3097 {"case $(||) in b)c;esac", func(t *test, tk Tokens) { // 9
3098 t.Err = Error{
3099 Err: Error{
3100 Err: Error{
3101 Err: Error{
3102 Err: Error{
3103 Err: Error{
3104 Err: Error{
3105 Err: Error{
3106 Err: Error{
3107 Err: Error{
3108 Err: ErrMissingWord,
3109 Parsing: "Command",
3110 Token: tk[3],
3111 },
3112 Parsing: "CommandOrCompound",
3113 Token: tk[3],
3114 },
3115 Parsing: "Pipeline",
3116 Token: tk[3],
3117 },
3118 Parsing: "Statement",
3119 Token: tk[3],
3120 },
3121 Parsing: "Line",
3122 Token: tk[3],
3123 },
3124 Parsing: "File",
3125 Token: tk[3],
3126 },
3127 Parsing: "CommandSubstitution",
3128 Token: tk[3],
3129 },
3130 Parsing: "WordPart",
3131 Token: tk[2],
3132 },
3133 Parsing: "Word",
3134 Token: tk[2],
3135 },
3136 Parsing: "CaseCompound",
3137 Token: tk[2],
3138 }
3139 }},
3140 {"case a in b)||;esac", func(t *test, tk Tokens) { // 10
3141 t.Err = Error{
3142 Err: Error{
3143 Err: Error{
3144 Err: Error{
3145 Err: Error{
3146 Err: Error{
3147 Err: Error{
3148 Err: Error{
3149 Err: ErrMissingWord,
3150 Parsing: "Command",
3151 Token: tk[8],
3152 },
3153 Parsing: "CommandOrCompound",
3154 Token: tk[8],
3155 },
3156 Parsing: "Pipeline",
3157 Token: tk[8],
3158 },
3159 Parsing: "Statement",
3160 Token: tk[8],
3161 },
3162 Parsing: "Line",
3163 Token: tk[8],
3164 },
3165 Parsing: "File",
3166 Token: tk[8],
3167 },
3168 Parsing: "PatternLines",
3169 Token: tk[8],
3170 },
3171 Parsing: "CaseCompound",
3172 Token: tk[6],
3173 }
3174 }},
3175 }, func(t *test) (Type, error) {
3176 var cc CaseCompound
3177
3178 err := cc.parse(t.Parser)
3179
3180 return cc, err
3181 })
3182 }
3183
3184 func TestPatternLines(t *testing.T) {
3185 doTests(t, []sourceFn{
3186 {"case a in a)b\nesac", func(t *test, tk Tokens) { // 1
3187 t.Output = PatternLines{
3188 Patterns: []Word{
3189 {
3190 Parts: []WordPart{
3191 {
3192 Part: &tk[6],
3193 Tokens: tk[6:7],
3194 },
3195 },
3196 Tokens: tk[6:7],
3197 },
3198 },
3199 Lines: File{
3200 Lines: []Line{
3201 {
3202 Statements: []Statement{
3203 {
3204 Pipeline: Pipeline{
3205 CommandOrCompound: CommandOrCompound{
3206 Command: &Command{
3207 AssignmentsOrWords: []AssignmentOrWord{
3208 {
3209 Word: &Word{
3210 Parts: []WordPart{
3211 {
3212 Part: &tk[8],
3213 Tokens: tk[8:9],
3214 },
3215 },
3216 Tokens: tk[8:9],
3217 },
3218 Tokens: tk[8:9],
3219 },
3220 },
3221 Tokens: tk[8:9],
3222 },
3223 Tokens: tk[8:9],
3224 },
3225 Tokens: tk[8:9],
3226 },
3227 Tokens: tk[8:9],
3228 },
3229 },
3230 Tokens: tk[8:9],
3231 },
3232 },
3233 Tokens: tk[8:9],
3234 },
3235 Tokens: tk[6:9],
3236 }
3237 }},
3238 {"case a in a)b;esac", func(t *test, tk Tokens) { // 2
3239 t.Output = PatternLines{
3240 Patterns: []Word{
3241 {
3242 Parts: []WordPart{
3243 {
3244 Part: &tk[6],
3245 Tokens: tk[6:7],
3246 },
3247 },
3248 Tokens: tk[6:7],
3249 },
3250 },
3251 Lines: File{
3252 Lines: []Line{
3253 {
3254 Statements: []Statement{
3255 {
3256 Pipeline: Pipeline{
3257 CommandOrCompound: CommandOrCompound{
3258 Command: &Command{
3259 AssignmentsOrWords: []AssignmentOrWord{
3260 {
3261 Word: &Word{
3262 Parts: []WordPart{
3263 {
3264 Part: &tk[8],
3265 Tokens: tk[8:9],
3266 },
3267 },
3268 Tokens: tk[8:9],
3269 },
3270 Tokens: tk[8:9],
3271 },
3272 },
3273 Tokens: tk[8:9],
3274 },
3275 Tokens: tk[8:9],
3276 },
3277 Tokens: tk[8:9],
3278 },
3279 Tokens: tk[8:10],
3280 },
3281 },
3282 Tokens: tk[8:10],
3283 },
3284 },
3285 Tokens: tk[8:10],
3286 },
3287 Tokens: tk[6:10],
3288 }
3289 }},
3290 {"case a in a)b;;esac", func(t *test, tk Tokens) { // 3
3291 t.Output = PatternLines{
3292 Patterns: []Word{
3293 {
3294 Parts: []WordPart{
3295 {
3296 Part: &tk[6],
3297 Tokens: tk[6:7],
3298 },
3299 },
3300 Tokens: tk[6:7],
3301 },
3302 },
3303 Lines: File{
3304 Lines: []Line{
3305 {
3306 Statements: []Statement{
3307 {
3308 Pipeline: Pipeline{
3309 CommandOrCompound: CommandOrCompound{
3310 Command: &Command{
3311 AssignmentsOrWords: []AssignmentOrWord{
3312 {
3313 Word: &Word{
3314 Parts: []WordPart{
3315 {
3316 Part: &tk[8],
3317 Tokens: tk[8:9],
3318 },
3319 },
3320 Tokens: tk[8:9],
3321 },
3322 Tokens: tk[8:9],
3323 },
3324 },
3325 Tokens: tk[8:9],
3326 },
3327 Tokens: tk[8:9],
3328 },
3329 Tokens: tk[8:9],
3330 },
3331 Tokens: tk[8:9],
3332 },
3333 },
3334 Tokens: tk[8:9],
3335 },
3336 },
3337 Tokens: tk[8:9],
3338 },
3339 CaseTerminationType: CaseTerminationEnd,
3340 Tokens: tk[6:10],
3341 }
3342 }},
3343 {"case a in a)b;&esac", func(t *test, tk Tokens) { // 4
3344 t.Output = PatternLines{
3345 Patterns: []Word{
3346 {
3347 Parts: []WordPart{
3348 {
3349 Part: &tk[6],
3350 Tokens: tk[6:7],
3351 },
3352 },
3353 Tokens: tk[6:7],
3354 },
3355 },
3356 Lines: File{
3357 Lines: []Line{
3358 {
3359 Statements: []Statement{
3360 {
3361 Pipeline: Pipeline{
3362 CommandOrCompound: CommandOrCompound{
3363 Command: &Command{
3364 AssignmentsOrWords: []AssignmentOrWord{
3365 {
3366 Word: &Word{
3367 Parts: []WordPart{
3368 {
3369 Part: &tk[8],
3370 Tokens: tk[8:9],
3371 },
3372 },
3373 Tokens: tk[8:9],
3374 },
3375 Tokens: tk[8:9],
3376 },
3377 },
3378 Tokens: tk[8:9],
3379 },
3380 Tokens: tk[8:9],
3381 },
3382 Tokens: tk[8:9],
3383 },
3384 Tokens: tk[8:9],
3385 },
3386 },
3387 Tokens: tk[8:9],
3388 },
3389 },
3390 Tokens: tk[8:9],
3391 },
3392 CaseTerminationType: CaseTerminationContinue,
3393 Tokens: tk[6:10],
3394 }
3395 }},
3396 {"case a in a)b;;&esac", func(t *test, tk Tokens) { // 5
3397 t.Output = PatternLines{
3398 Patterns: []Word{
3399 {
3400 Parts: []WordPart{
3401 {
3402 Part: &tk[6],
3403 Tokens: tk[6:7],
3404 },
3405 },
3406 Tokens: tk[6:7],
3407 },
3408 },
3409 Lines: File{
3410 Lines: []Line{
3411 {
3412 Statements: []Statement{
3413 {
3414 Pipeline: Pipeline{
3415 CommandOrCompound: CommandOrCompound{
3416 Command: &Command{
3417 AssignmentsOrWords: []AssignmentOrWord{
3418 {
3419 Word: &Word{
3420 Parts: []WordPart{
3421 {
3422 Part: &tk[8],
3423 Tokens: tk[8:9],
3424 },
3425 },
3426 Tokens: tk[8:9],
3427 },
3428 Tokens: tk[8:9],
3429 },
3430 },
3431 Tokens: tk[8:9],
3432 },
3433 Tokens: tk[8:9],
3434 },
3435 Tokens: tk[8:9],
3436 },
3437 Tokens: tk[8:9],
3438 },
3439 },
3440 Tokens: tk[8:9],
3441 },
3442 },
3443 Tokens: tk[8:9],
3444 },
3445 CaseTerminationType: CaseTerminationFallthrough,
3446 Tokens: tk[6:10],
3447 }
3448 }},
3449 {"case a in a|b|c)d;;esac", func(t *test, tk Tokens) { // 6
3450 t.Output = PatternLines{
3451 Patterns: []Word{
3452 {
3453 Parts: []WordPart{
3454 {
3455 Part: &tk[6],
3456 Tokens: tk[6:7],
3457 },
3458 },
3459 Tokens: tk[6:7],
3460 },
3461 {
3462 Parts: []WordPart{
3463 {
3464 Part: &tk[8],
3465 Tokens: tk[8:9],
3466 },
3467 },
3468 Tokens: tk[8:9],
3469 },
3470 {
3471 Parts: []WordPart{
3472 {
3473 Part: &tk[10],
3474 Tokens: tk[10:11],
3475 },
3476 },
3477 Tokens: tk[10:11],
3478 },
3479 },
3480 Lines: File{
3481 Lines: []Line{
3482 {
3483 Statements: []Statement{
3484 {
3485 Pipeline: Pipeline{
3486 CommandOrCompound: CommandOrCompound{
3487 Command: &Command{
3488 AssignmentsOrWords: []AssignmentOrWord{
3489 {
3490 Word: &Word{
3491 Parts: []WordPart{
3492 {
3493 Part: &tk[12],
3494 Tokens: tk[12:13],
3495 },
3496 },
3497 Tokens: tk[12:13],
3498 },
3499 Tokens: tk[12:13],
3500 },
3501 },
3502 Tokens: tk[12:13],
3503 },
3504 Tokens: tk[12:13],
3505 },
3506 Tokens: tk[12:13],
3507 },
3508 Tokens: tk[12:13],
3509 },
3510 },
3511 Tokens: tk[12:13],
3512 },
3513 },
3514 Tokens: tk[12:13],
3515 },
3516 CaseTerminationType: CaseTerminationEnd,
3517 Tokens: tk[6:14],
3518 }
3519 }},
3520 {"case a in a)# comment\nb;;# comment2\nesac", func(t *test, tk Tokens) { // 7
3521 t.Output = PatternLines{
3522 Patterns: []Word{
3523 {
3524 Parts: []WordPart{
3525 {
3526 Part: &tk[6],
3527 Tokens: tk[6:7],
3528 },
3529 },
3530 Tokens: tk[6:7],
3531 },
3532 },
3533 Lines: File{
3534 Lines: []Line{
3535 {
3536 Statements: []Statement{
3537 {
3538 Pipeline: Pipeline{
3539 CommandOrCompound: CommandOrCompound{
3540 Command: &Command{
3541 AssignmentsOrWords: []AssignmentOrWord{
3542 {
3543 Word: &Word{
3544 Parts: []WordPart{
3545 {
3546 Part: &tk[10],
3547 Tokens: tk[10:11],
3548 },
3549 },
3550 Tokens: tk[10:11],
3551 },
3552 Tokens: tk[10:11],
3553 },
3554 },
3555 Tokens: tk[10:11],
3556 },
3557 Tokens: tk[10:11],
3558 },
3559 Tokens: tk[10:11],
3560 },
3561 Tokens: tk[10:11],
3562 },
3563 },
3564 Tokens: tk[10:11],
3565 },
3566 },
3567 Comments: [2]Comments{{tk[8]}},
3568 Tokens: tk[8:11],
3569 },
3570 CaseTerminationType: CaseTerminationEnd,
3571 Tokens: tk[6:12],
3572 }
3573 }},
3574 {"case a in a)# comment\nb;\n# comment2\nesac", func(t *test, tk Tokens) { // 8
3575 t.Output = PatternLines{
3576 Patterns: []Word{
3577 {
3578 Parts: []WordPart{
3579 {
3580 Part: &tk[6],
3581 Tokens: tk[6:7],
3582 },
3583 },
3584 Tokens: tk[6:7],
3585 },
3586 },
3587 Lines: File{
3588 Lines: []Line{
3589 {
3590 Statements: []Statement{
3591 {
3592 Pipeline: Pipeline{
3593 CommandOrCompound: CommandOrCompound{
3594 Command: &Command{
3595 AssignmentsOrWords: []AssignmentOrWord{
3596 {
3597 Word: &Word{
3598 Parts: []WordPart{
3599 {
3600 Part: &tk[10],
3601 Tokens: tk[10:11],
3602 },
3603 },
3604 Tokens: tk[10:11],
3605 },
3606 Tokens: tk[10:11],
3607 },
3608 },
3609 Tokens: tk[10:11],
3610 },
3611 Tokens: tk[10:11],
3612 },
3613 Tokens: tk[10:11],
3614 },
3615 Tokens: tk[10:12],
3616 },
3617 },
3618 Tokens: tk[10:12],
3619 },
3620 },
3621 Comments: [2]Comments{{tk[8]}, {tk[13]}},
3622 Tokens: tk[8:14],
3623 },
3624 Tokens: tk[6:14],
3625 }
3626 }},
3627 {"case a in\n# comment\na)b;;esac", func(t *test, tk Tokens) { // 9
3628 t.Output = PatternLines{
3629 Patterns: []Word{
3630 {
3631 Parts: []WordPart{
3632 {
3633 Part: &tk[8],
3634 Tokens: tk[8:9],
3635 },
3636 },
3637 Tokens: tk[8:9],
3638 },
3639 },
3640 Lines: File{
3641 Lines: []Line{
3642 {
3643 Statements: []Statement{
3644 {
3645 Pipeline: Pipeline{
3646 CommandOrCompound: CommandOrCompound{
3647 Command: &Command{
3648 AssignmentsOrWords: []AssignmentOrWord{
3649 {
3650 Word: &Word{
3651 Parts: []WordPart{
3652 {
3653 Part: &tk[10],
3654 Tokens: tk[10:11],
3655 },
3656 },
3657 Tokens: tk[10:11],
3658 },
3659 Tokens: tk[10:11],
3660 },
3661 },
3662 Tokens: tk[10:11],
3663 },
3664 Tokens: tk[10:11],
3665 },
3666 Tokens: tk[10:11],
3667 },
3668 Tokens: tk[10:11],
3669 },
3670 },
3671 Tokens: tk[10:11],
3672 },
3673 },
3674 Tokens: tk[10:11],
3675 },
3676 CaseTerminationType: CaseTerminationEnd,
3677 Comments: Comments{tk[6]},
3678 Tokens: tk[6:12],
3679 }
3680 }},
3681 {"case a in $(||))d;;esac", func(t *test, tk Tokens) { // 10
3682 t.Err = Error{
3683 Err: Error{
3684 Err: Error{
3685 Err: Error{
3686 Err: Error{
3687 Err: Error{
3688 Err: Error{
3689 Err: Error{
3690 Err: Error{
3691 Err: Error{
3692 Err: ErrMissingWord,
3693 Parsing: "Command",
3694 Token: tk[7],
3695 },
3696 Parsing: "CommandOrCompound",
3697 Token: tk[7],
3698 },
3699 Parsing: "Pipeline",
3700 Token: tk[7],
3701 },
3702 Parsing: "Statement",
3703 Token: tk[7],
3704 },
3705 Parsing: "Line",
3706 Token: tk[7],
3707 },
3708 Parsing: "File",
3709 Token: tk[7],
3710 },
3711 Parsing: "CommandSubstitution",
3712 Token: tk[7],
3713 },
3714 Parsing: "WordPart",
3715 Token: tk[6],
3716 },
3717 Parsing: "Word",
3718 Token: tk[6],
3719 },
3720 Parsing: "PatternLines",
3721 Token: tk[6],
3722 }
3723 }},
3724 {"case a in a|\nb)c;;esac", func(t *test, tk Tokens) { // 11
3725 t.Err = Error{
3726 Err: ErrMissingClosingPattern,
3727 Parsing: "PatternLines",
3728 Token: tk[8],
3729 }
3730 }},
3731 {"case a in a)||;;esac", func(t *test, tk Tokens) { // 12
3732 t.Err = Error{
3733 Err: Error{
3734 Err: Error{
3735 Err: Error{
3736 Err: Error{
3737 Err: Error{
3738 Err: Error{
3739 Err: ErrMissingWord,
3740 Parsing: "Command",
3741 Token: tk[8],
3742 },
3743 Parsing: "CommandOrCompound",
3744 Token: tk[8],
3745 },
3746 Parsing: "Pipeline",
3747 Token: tk[8],
3748 },
3749 Parsing: "Statement",
3750 Token: tk[8],
3751 },
3752 Parsing: "Line",
3753 Token: tk[8],
3754 },
3755 Parsing: "File",
3756 Token: tk[8],
3757 },
3758 Parsing: "PatternLines",
3759 Token: tk[8],
3760 }
3761 }},
3762 }, func(t *test) (Type, error) {
3763 var p PatternLines
3764
3765 t.Parser.Tokens = t.Parser.Tokens[6:6]
3766 err := p.parse(t.Parser)
3767
3768 return p, err
3769 })
3770 }
3771
3772 func TestLoopCompound(t *testing.T) {
3773 doTests(t, []sourceFn{
3774 {"while a\ndo\nb\ndone", func(t *test, tk Tokens) { // 1
3775 t.Output = LoopCompound{
3776 Statement: Statement{
3777 Pipeline: Pipeline{
3778 CommandOrCompound: CommandOrCompound{
3779 Command: &Command{
3780 AssignmentsOrWords: []AssignmentOrWord{
3781 {
3782 Word: &Word{
3783 Parts: []WordPart{
3784 {
3785 Part: &tk[2],
3786 Tokens: tk[2:3],
3787 },
3788 },
3789 Tokens: tk[2:3],
3790 },
3791 Tokens: tk[2:3],
3792 },
3793 },
3794 Tokens: tk[2:3],
3795 },
3796 Tokens: tk[2:3],
3797 },
3798 Tokens: tk[2:3],
3799 },
3800 Tokens: tk[2:3],
3801 },
3802 File: File{
3803 Lines: []Line{
3804 {
3805 Statements: []Statement{
3806 {
3807 Pipeline: Pipeline{
3808 CommandOrCompound: CommandOrCompound{
3809 Command: &Command{
3810 AssignmentsOrWords: []AssignmentOrWord{
3811 {
3812 Word: &Word{
3813 Parts: []WordPart{
3814 {
3815 Part: &tk[6],
3816 Tokens: tk[6:7],
3817 },
3818 },
3819 Tokens: tk[6:7],
3820 },
3821 Tokens: tk[6:7],
3822 },
3823 },
3824 Tokens: tk[6:7],
3825 },
3826 Tokens: tk[6:7],
3827 },
3828 Tokens: tk[6:7],
3829 },
3830 Tokens: tk[6:7],
3831 },
3832 },
3833 Tokens: tk[6:7],
3834 },
3835 },
3836 Tokens: tk[6:7],
3837 },
3838 Tokens: tk[:9],
3839 }
3840 }},
3841 {"while (a) do\nb\ndone", func(t *test, tk Tokens) { // 2
3842 t.Output = LoopCompound{
3843 Statement: Statement{
3844 Pipeline: Pipeline{
3845 CommandOrCompound: CommandOrCompound{
3846 Compound: &Compound{
3847 GroupingCompound: &GroupingCompound{
3848 SubShell: true,
3849 File: File{
3850 Lines: []Line{
3851 {
3852 Statements: []Statement{
3853 {
3854 Pipeline: Pipeline{
3855 CommandOrCompound: CommandOrCompound{
3856 Command: &Command{
3857 AssignmentsOrWords: []AssignmentOrWord{
3858 {
3859 Word: &Word{
3860 Parts: []WordPart{
3861 {
3862 Part: &tk[3],
3863 Tokens: tk[3:4],
3864 },
3865 },
3866 Tokens: tk[3:4],
3867 },
3868 Tokens: tk[3:4],
3869 },
3870 },
3871 Tokens: tk[3:4],
3872 },
3873 Tokens: tk[3:4],
3874 },
3875 Tokens: tk[3:4],
3876 },
3877 Tokens: tk[3:4],
3878 },
3879 },
3880 Tokens: tk[3:4],
3881 },
3882 },
3883 Tokens: tk[3:4],
3884 },
3885 Tokens: tk[2:5],
3886 },
3887 Tokens: tk[2:5],
3888 },
3889 Tokens: tk[2:5],
3890 },
3891 Tokens: tk[2:5],
3892 },
3893 Tokens: tk[2:5],
3894 },
3895 File: File{
3896 Lines: []Line{
3897 {
3898 Statements: []Statement{
3899 {
3900 Pipeline: Pipeline{
3901 CommandOrCompound: CommandOrCompound{
3902 Command: &Command{
3903 AssignmentsOrWords: []AssignmentOrWord{
3904 {
3905 Word: &Word{
3906 Parts: []WordPart{
3907 {
3908 Part: &tk[8],
3909 Tokens: tk[8:9],
3910 },
3911 },
3912 Tokens: tk[8:9],
3913 },
3914 Tokens: tk[8:9],
3915 },
3916 },
3917 Tokens: tk[8:9],
3918 },
3919 Tokens: tk[8:9],
3920 },
3921 Tokens: tk[8:9],
3922 },
3923 Tokens: tk[8:9],
3924 },
3925 },
3926 Tokens: tk[8:9],
3927 },
3928 },
3929 Tokens: tk[8:9],
3930 },
3931 Tokens: tk[:11],
3932 }
3933 }},
3934 {"until a; do b; done", func(t *test, tk Tokens) { // 3
3935 t.Output = LoopCompound{
3936 Until: true,
3937 Statement: Statement{
3938 Pipeline: Pipeline{
3939 CommandOrCompound: CommandOrCompound{
3940 Command: &Command{
3941 AssignmentsOrWords: []AssignmentOrWord{
3942 {
3943 Word: &Word{
3944 Parts: []WordPart{
3945 {
3946 Part: &tk[2],
3947 Tokens: tk[2:3],
3948 },
3949 },
3950 Tokens: tk[2:3],
3951 },
3952 Tokens: tk[2:3],
3953 },
3954 },
3955 Tokens: tk[2:3],
3956 },
3957 Tokens: tk[2:3],
3958 },
3959 Tokens: tk[2:3],
3960 },
3961 Tokens: tk[2:4],
3962 },
3963 File: File{
3964 Lines: []Line{
3965 {
3966 Statements: []Statement{
3967 {
3968 Pipeline: Pipeline{
3969 CommandOrCompound: CommandOrCompound{
3970 Command: &Command{
3971 AssignmentsOrWords: []AssignmentOrWord{
3972 {
3973 Word: &Word{
3974 Parts: []WordPart{
3975 {
3976 Part: &tk[7],
3977 Tokens: tk[7:8],
3978 },
3979 },
3980 Tokens: tk[7:8],
3981 },
3982 Tokens: tk[7:8],
3983 },
3984 },
3985 Tokens: tk[7:8],
3986 },
3987 Tokens: tk[7:8],
3988 },
3989 Tokens: tk[7:8],
3990 },
3991 Tokens: tk[7:9],
3992 },
3993 },
3994 Tokens: tk[7:9],
3995 },
3996 },
3997 Tokens: tk[7:9],
3998 },
3999 Tokens: tk[:11],
4000 }
4001 }},
4002 {"while a # comment\ndo b; done", func(t *test, tk Tokens) { // 4
4003 t.Output = LoopCompound{
4004 Statement: Statement{
4005 Pipeline: Pipeline{
4006 CommandOrCompound: CommandOrCompound{
4007 Command: &Command{
4008 AssignmentsOrWords: []AssignmentOrWord{
4009 {
4010 Word: &Word{
4011 Parts: []WordPart{
4012 {
4013 Part: &tk[2],
4014 Tokens: tk[2:3],
4015 },
4016 },
4017 Tokens: tk[2:3],
4018 },
4019 Tokens: tk[2:3],
4020 },
4021 },
4022 Tokens: tk[2:3],
4023 },
4024 Tokens: tk[2:3],
4025 },
4026 Tokens: tk[2:3],
4027 },
4028 Tokens: tk[2:3],
4029 },
4030 File: File{
4031 Lines: []Line{
4032 {
4033 Statements: []Statement{
4034 {
4035 Pipeline: Pipeline{
4036 CommandOrCompound: CommandOrCompound{
4037 Command: &Command{
4038 AssignmentsOrWords: []AssignmentOrWord{
4039 {
4040 Word: &Word{
4041 Parts: []WordPart{
4042 {
4043 Part: &tk[8],
4044 Tokens: tk[8:9],
4045 },
4046 },
4047 Tokens: tk[8:9],
4048 },
4049 Tokens: tk[8:9],
4050 },
4051 },
4052 Tokens: tk[8:9],
4053 },
4054 Tokens: tk[8:9],
4055 },
4056 Tokens: tk[8:9],
4057 },
4058 Tokens: tk[8:10],
4059 },
4060 },
4061 Tokens: tk[8:10],
4062 },
4063 },
4064 Tokens: tk[8:10],
4065 },
4066 Comments: Comments{tk[4]},
4067 Tokens: tk[:12],
4068 }
4069 }},
4070 {"until a; do # comment\nb; done", func(t *test, tk Tokens) { // 5
4071 t.Output = LoopCompound{
4072 Until: true,
4073 Statement: Statement{
4074 Pipeline: Pipeline{
4075 CommandOrCompound: CommandOrCompound{
4076 Command: &Command{
4077 AssignmentsOrWords: []AssignmentOrWord{
4078 {
4079 Word: &Word{
4080 Parts: []WordPart{
4081 {
4082 Part: &tk[2],
4083 Tokens: tk[2:3],
4084 },
4085 },
4086 Tokens: tk[2:3],
4087 },
4088 Tokens: tk[2:3],
4089 },
4090 },
4091 Tokens: tk[2:3],
4092 },
4093 Tokens: tk[2:3],
4094 },
4095 Tokens: tk[2:3],
4096 },
4097 Tokens: tk[2:4],
4098 },
4099 File: File{
4100 Lines: []Line{
4101 {
4102 Statements: []Statement{
4103 {
4104 Pipeline: Pipeline{
4105 CommandOrCompound: CommandOrCompound{
4106 Command: &Command{
4107 AssignmentsOrWords: []AssignmentOrWord{
4108 {
4109 Word: &Word{
4110 Parts: []WordPart{
4111 {
4112 Part: &tk[9],
4113 Tokens: tk[9:10],
4114 },
4115 },
4116 Tokens: tk[9:10],
4117 },
4118 Tokens: tk[9:10],
4119 },
4120 },
4121 Tokens: tk[9:10],
4122 },
4123 Tokens: tk[9:10],
4124 },
4125 Tokens: tk[9:10],
4126 },
4127 Tokens: tk[9:11],
4128 },
4129 },
4130 Tokens: tk[9:11],
4131 },
4132 },
4133 Comments: [2]Comments{{tk[7]}},
4134 Tokens: tk[7:11],
4135 },
4136 Tokens: tk[:13],
4137 }
4138 }},
4139 {"while ||; do b; done", func(t *test, tk Tokens) { // 6
4140 t.Err = Error{
4141 Err: Error{
4142 Err: Error{
4143 Err: Error{
4144 Err: Error{
4145 Err: ErrMissingWord,
4146 Parsing: "Command",
4147 Token: tk[2],
4148 },
4149 Parsing: "CommandOrCompound",
4150 Token: tk[2],
4151 },
4152 Parsing: "Pipeline",
4153 Token: tk[2],
4154 },
4155 Parsing: "Statement",
4156 Token: tk[2],
4157 },
4158 Parsing: "LoopCompound",
4159 Token: tk[2],
4160 }
4161 }},
4162 {"until a; do ||; done", func(t *test, tk Tokens) { // 7
4163 t.Err = Error{
4164 Err: Error{
4165 Err: Error{
4166 Err: Error{
4167 Err: Error{
4168 Err: Error{
4169 Err: Error{
4170 Err: ErrMissingWord,
4171 Parsing: "Command",
4172 Token: tk[7],
4173 },
4174 Parsing: "CommandOrCompound",
4175 Token: tk[7],
4176 },
4177 Parsing: "Pipeline",
4178 Token: tk[7],
4179 },
4180 Parsing: "Statement",
4181 Token: tk[7],
4182 },
4183 Parsing: "Line",
4184 Token: tk[7],
4185 },
4186 Parsing: "File",
4187 Token: tk[7],
4188 },
4189 Parsing: "LoopCompound",
4190 Token: tk[7],
4191 }
4192 }},
4193 }, func(t *test) (Type, error) {
4194 var l LoopCompound
4195
4196 err := l.parse(t.Parser)
4197
4198 return l, err
4199 })
4200 }
4201
4202 func TestForCompound(t *testing.T) {
4203 doTests(t, []sourceFn{
4204 {"for a; do b;done", func(t *test, tk Tokens) { // 1
4205 t.Output = ForCompound{
4206 Identifier: &tk[2],
4207 File: File{
4208 Lines: []Line{
4209 {
4210 Statements: []Statement{
4211 {
4212 Pipeline: Pipeline{
4213 CommandOrCompound: CommandOrCompound{
4214 Command: &Command{
4215 AssignmentsOrWords: []AssignmentOrWord{
4216 {
4217 Word: &Word{
4218 Parts: []WordPart{
4219 {
4220 Part: &tk[7],
4221 Tokens: tk[7:8],
4222 },
4223 },
4224 Tokens: tk[7:8],
4225 },
4226 Tokens: tk[7:8],
4227 },
4228 },
4229 Tokens: tk[7:8],
4230 },
4231 Tokens: tk[7:8],
4232 },
4233 Tokens: tk[7:8],
4234 },
4235 Tokens: tk[7:9],
4236 },
4237 },
4238 Tokens: tk[7:9],
4239 },
4240 },
4241 Tokens: tk[7:9],
4242 },
4243 Tokens: tk[:10],
4244 }
4245 }},
4246 {"for a\ndo b\ndone", func(t *test, tk Tokens) { // 2
4247 t.Output = ForCompound{
4248 Identifier: &tk[2],
4249 File: File{
4250 Lines: []Line{
4251 {
4252 Statements: []Statement{
4253 {
4254 Pipeline: Pipeline{
4255 CommandOrCompound: CommandOrCompound{
4256 Command: &Command{
4257 AssignmentsOrWords: []AssignmentOrWord{
4258 {
4259 Word: &Word{
4260 Parts: []WordPart{
4261 {
4262 Part: &tk[6],
4263 Tokens: tk[6:7],
4264 },
4265 },
4266 Tokens: tk[6:7],
4267 },
4268 Tokens: tk[6:7],
4269 },
4270 },
4271 Tokens: tk[6:7],
4272 },
4273 Tokens: tk[6:7],
4274 },
4275 Tokens: tk[6:7],
4276 },
4277 Tokens: tk[6:7],
4278 },
4279 },
4280 Tokens: tk[6:7],
4281 },
4282 },
4283 Tokens: tk[6:7],
4284 },
4285 Tokens: tk[:9],
4286 }
4287 }},
4288 {"for a in; do b;done", func(t *test, tk Tokens) { // 3
4289 t.Output = ForCompound{
4290 Identifier: &tk[2],
4291 Words: []Word{},
4292 File: File{
4293 Lines: []Line{
4294 {
4295 Statements: []Statement{
4296 {
4297 Pipeline: Pipeline{
4298 CommandOrCompound: CommandOrCompound{
4299 Command: &Command{
4300 AssignmentsOrWords: []AssignmentOrWord{
4301 {
4302 Word: &Word{
4303 Parts: []WordPart{
4304 {
4305 Part: &tk[9],
4306 Tokens: tk[9:10],
4307 },
4308 },
4309 Tokens: tk[9:10],
4310 },
4311 Tokens: tk[9:10],
4312 },
4313 },
4314 Tokens: tk[9:10],
4315 },
4316 Tokens: tk[9:10],
4317 },
4318 Tokens: tk[9:10],
4319 },
4320 Tokens: tk[9:11],
4321 },
4322 },
4323 Tokens: tk[9:11],
4324 },
4325 },
4326 Tokens: tk[9:11],
4327 },
4328 Tokens: tk[:12],
4329 }
4330 }},
4331 {"for a in b; do c;done", func(t *test, tk Tokens) { // 4
4332 t.Output = ForCompound{
4333 Identifier: &tk[2],
4334 Words: []Word{
4335 {
4336 Parts: []WordPart{
4337 {
4338 Part: &tk[6],
4339 Tokens: tk[6:7],
4340 },
4341 },
4342 Tokens: tk[6:7],
4343 },
4344 },
4345 File: File{
4346 Lines: []Line{
4347 {
4348 Statements: []Statement{
4349 {
4350 Pipeline: Pipeline{
4351 CommandOrCompound: CommandOrCompound{
4352 Command: &Command{
4353 AssignmentsOrWords: []AssignmentOrWord{
4354 {
4355 Word: &Word{
4356 Parts: []WordPart{
4357 {
4358 Part: &tk[11],
4359 Tokens: tk[11:12],
4360 },
4361 },
4362 Tokens: tk[11:12],
4363 },
4364 Tokens: tk[11:12],
4365 },
4366 },
4367 Tokens: tk[11:12],
4368 },
4369 Tokens: tk[11:12],
4370 },
4371 Tokens: tk[11:12],
4372 },
4373 Tokens: tk[11:13],
4374 },
4375 },
4376 Tokens: tk[11:13],
4377 },
4378 },
4379 Tokens: tk[11:13],
4380 },
4381 Tokens: tk[:14],
4382 }
4383 }},
4384 {"for a in b c; do d;done", func(t *test, tk Tokens) { // 5
4385 t.Output = ForCompound{
4386 Identifier: &tk[2],
4387 Words: []Word{
4388 {
4389 Parts: []WordPart{
4390 {
4391 Part: &tk[6],
4392 Tokens: tk[6:7],
4393 },
4394 },
4395 Tokens: tk[6:7],
4396 },
4397 {
4398 Parts: []WordPart{
4399 {
4400 Part: &tk[8],
4401 Tokens: tk[8:9],
4402 },
4403 },
4404 Tokens: tk[8:9],
4405 },
4406 },
4407 File: File{
4408 Lines: []Line{
4409 {
4410 Statements: []Statement{
4411 {
4412 Pipeline: Pipeline{
4413 CommandOrCompound: CommandOrCompound{
4414 Command: &Command{
4415 AssignmentsOrWords: []AssignmentOrWord{
4416 {
4417 Word: &Word{
4418 Parts: []WordPart{
4419 {
4420 Part: &tk[13],
4421 Tokens: tk[13:14],
4422 },
4423 },
4424 Tokens: tk[13:14],
4425 },
4426 Tokens: tk[13:14],
4427 },
4428 },
4429 Tokens: tk[13:14],
4430 },
4431 Tokens: tk[13:14],
4432 },
4433 Tokens: tk[13:14],
4434 },
4435 Tokens: tk[13:15],
4436 },
4437 },
4438 Tokens: tk[13:15],
4439 },
4440 },
4441 Tokens: tk[13:15],
4442 },
4443 Tokens: tk[:16],
4444 }
4445 }},
4446 {"for (( a=1; a<2; a++ )); do b;done", func(t *test, tk Tokens) { // 6
4447 t.Output = ForCompound{
4448 ArithmeticExpansion: &ArithmeticExpansion{
4449 Expression: true,
4450 WordsAndOperators: []WordOrOperator{
4451 {
4452 Word: &Word{
4453 Parts: []WordPart{
4454 {
4455 Part: &tk[4],
4456 Tokens: tk[4:5],
4457 },
4458 },
4459 Tokens: tk[4:5],
4460 },
4461 Tokens: tk[4:5],
4462 },
4463 {
4464 Operator: &tk[5],
4465 Tokens: tk[5:6],
4466 },
4467 {
4468 Word: &Word{
4469 Parts: []WordPart{
4470 {
4471 Part: &tk[6],
4472 Tokens: tk[6:7],
4473 },
4474 },
4475 Tokens: tk[6:7],
4476 },
4477 Tokens: tk[6:7],
4478 },
4479 {
4480 Operator: &tk[7],
4481 Tokens: tk[7:8],
4482 },
4483 {
4484 Word: &Word{
4485 Parts: []WordPart{
4486 {
4487 Part: &tk[9],
4488 Tokens: tk[9:10],
4489 },
4490 },
4491 Tokens: tk[9:10],
4492 },
4493 Tokens: tk[9:10],
4494 },
4495 {
4496 Operator: &tk[10],
4497 Tokens: tk[10:11],
4498 },
4499 {
4500 Word: &Word{
4501 Parts: []WordPart{
4502 {
4503 Part: &tk[11],
4504 Tokens: tk[11:12],
4505 },
4506 },
4507 Tokens: tk[11:12],
4508 },
4509 Tokens: tk[11:12],
4510 },
4511 {
4512 Operator: &tk[12],
4513 Tokens: tk[12:13],
4514 },
4515 {
4516 Word: &Word{
4517 Parts: []WordPart{
4518 {
4519 Part: &tk[14],
4520 Tokens: tk[14:15],
4521 },
4522 },
4523 Tokens: tk[14:15],
4524 },
4525 Tokens: tk[14:15],
4526 },
4527 {
4528 Operator: &tk[15],
4529 Tokens: tk[15:16],
4530 },
4531 },
4532 Tokens: tk[2:18],
4533 },
4534 File: File{
4535 Lines: []Line{
4536 {
4537 Statements: []Statement{
4538 {
4539 Pipeline: Pipeline{
4540 CommandOrCompound: CommandOrCompound{
4541 Command: &Command{
4542 AssignmentsOrWords: []AssignmentOrWord{
4543 {
4544 Word: &Word{
4545 Parts: []WordPart{
4546 {
4547 Part: &tk[22],
4548 Tokens: tk[22:23],
4549 },
4550 },
4551 Tokens: tk[22:23],
4552 },
4553 Tokens: tk[22:23],
4554 },
4555 },
4556 Tokens: tk[22:23],
4557 },
4558 Tokens: tk[22:23],
4559 },
4560 Tokens: tk[22:23],
4561 },
4562 Tokens: tk[22:24],
4563 },
4564 },
4565 Tokens: tk[22:24],
4566 },
4567 },
4568 Tokens: tk[22:24],
4569 },
4570 Tokens: tk[:25],
4571 }
4572 }},
4573 {"for a #comment\ndo b;done", func(t *test, tk Tokens) { // 7
4574 t.Output = ForCompound{
4575 Identifier: &tk[2],
4576 File: File{
4577 Lines: []Line{
4578 {
4579 Statements: []Statement{
4580 {
4581 Pipeline: Pipeline{
4582 CommandOrCompound: CommandOrCompound{
4583 Command: &Command{
4584 AssignmentsOrWords: []AssignmentOrWord{
4585 {
4586 Word: &Word{
4587 Parts: []WordPart{
4588 {
4589 Part: &tk[8],
4590 Tokens: tk[8:9],
4591 },
4592 },
4593 Tokens: tk[8:9],
4594 },
4595 Tokens: tk[8:9],
4596 },
4597 },
4598 Tokens: tk[8:9],
4599 },
4600 Tokens: tk[8:9],
4601 },
4602 Tokens: tk[8:9],
4603 },
4604 Tokens: tk[8:10],
4605 },
4606 },
4607 Tokens: tk[8:10],
4608 },
4609 },
4610 Tokens: tk[8:10],
4611 },
4612 Comments: [2]Comments{{tk[4]}},
4613 Tokens: tk[:11],
4614 }
4615 }},
4616 {"for a # comment\nin b #comment 2\ndo c;done", func(t *test, tk Tokens) { // 8
4617 t.Output = ForCompound{
4618 Identifier: &tk[2],
4619 Words: []Word{
4620 {
4621 Parts: []WordPart{
4622 {
4623 Part: &tk[8],
4624 Tokens: tk[8:9],
4625 },
4626 },
4627 Tokens: tk[8:9],
4628 },
4629 },
4630 File: File{
4631 Lines: []Line{
4632 {
4633 Statements: []Statement{
4634 {
4635 Pipeline: Pipeline{
4636 CommandOrCompound: CommandOrCompound{
4637 Command: &Command{
4638 AssignmentsOrWords: []AssignmentOrWord{
4639 {
4640 Word: &Word{
4641 Parts: []WordPart{
4642 {
4643 Part: &tk[14],
4644 Tokens: tk[14:15],
4645 },
4646 },
4647 Tokens: tk[14:15],
4648 },
4649 Tokens: tk[14:15],
4650 },
4651 },
4652 Tokens: tk[14:15],
4653 },
4654 Tokens: tk[14:15],
4655 },
4656 Tokens: tk[14:15],
4657 },
4658 Tokens: tk[14:16],
4659 },
4660 },
4661 Tokens: tk[14:16],
4662 },
4663 },
4664 Tokens: tk[14:16],
4665 },
4666 Comments: [2]Comments{{tk[4]}, {tk[10]}},
4667 Tokens: tk[:17],
4668 }
4669 }},
4670 {"for a in b #comment\ndo c;done", func(t *test, tk Tokens) { // 9
4671 t.Output = ForCompound{
4672 Identifier: &tk[2],
4673 Words: []Word{
4674 {
4675 Parts: []WordPart{
4676 {
4677 Part: &tk[6],
4678 Tokens: tk[6:7],
4679 },
4680 },
4681 Tokens: tk[6:7],
4682 },
4683 },
4684 File: File{
4685 Lines: []Line{
4686 {
4687 Statements: []Statement{
4688 {
4689 Pipeline: Pipeline{
4690 CommandOrCompound: CommandOrCompound{
4691 Command: &Command{
4692 AssignmentsOrWords: []AssignmentOrWord{
4693 {
4694 Word: &Word{
4695 Parts: []WordPart{
4696 {
4697 Part: &tk[12],
4698 Tokens: tk[12:13],
4699 },
4700 },
4701 Tokens: tk[12:13],
4702 },
4703 Tokens: tk[12:13],
4704 },
4705 },
4706 Tokens: tk[12:13],
4707 },
4708 Tokens: tk[12:13],
4709 },
4710 Tokens: tk[12:13],
4711 },
4712 Tokens: tk[12:14],
4713 },
4714 },
4715 Tokens: tk[12:14],
4716 },
4717 },
4718 Tokens: tk[12:14],
4719 },
4720 Comments: [2]Comments{nil, {tk[8]}},
4721 Tokens: tk[:15],
4722 }
4723 }},
4724 {"for (( a=1; a<2; a++ )) #comment\ndo b;done", func(t *test, tk Tokens) { // 10
4725 t.Output = ForCompound{
4726 ArithmeticExpansion: &ArithmeticExpansion{
4727 Expression: true,
4728 WordsAndOperators: []WordOrOperator{
4729 {
4730 Word: &Word{
4731 Parts: []WordPart{
4732 {
4733 Part: &tk[4],
4734 Tokens: tk[4:5],
4735 },
4736 },
4737 Tokens: tk[4:5],
4738 },
4739 Tokens: tk[4:5],
4740 },
4741 {
4742 Operator: &tk[5],
4743 Tokens: tk[5:6],
4744 },
4745 {
4746 Word: &Word{
4747 Parts: []WordPart{
4748 {
4749 Part: &tk[6],
4750 Tokens: tk[6:7],
4751 },
4752 },
4753 Tokens: tk[6:7],
4754 },
4755 Tokens: tk[6:7],
4756 },
4757 {
4758 Operator: &tk[7],
4759 Tokens: tk[7:8],
4760 },
4761 {
4762 Word: &Word{
4763 Parts: []WordPart{
4764 {
4765 Part: &tk[9],
4766 Tokens: tk[9:10],
4767 },
4768 },
4769 Tokens: tk[9:10],
4770 },
4771 Tokens: tk[9:10],
4772 },
4773 {
4774 Operator: &tk[10],
4775 Tokens: tk[10:11],
4776 },
4777 {
4778 Word: &Word{
4779 Parts: []WordPart{
4780 {
4781 Part: &tk[11],
4782 Tokens: tk[11:12],
4783 },
4784 },
4785 Tokens: tk[11:12],
4786 },
4787 Tokens: tk[11:12],
4788 },
4789 {
4790 Operator: &tk[12],
4791 Tokens: tk[12:13],
4792 },
4793 {
4794 Word: &Word{
4795 Parts: []WordPart{
4796 {
4797 Part: &tk[14],
4798 Tokens: tk[14:15],
4799 },
4800 },
4801 Tokens: tk[14:15],
4802 },
4803 Tokens: tk[14:15],
4804 },
4805 {
4806 Operator: &tk[15],
4807 Tokens: tk[15:16],
4808 },
4809 },
4810 Tokens: tk[2:18],
4811 },
4812 File: File{
4813 Lines: []Line{
4814 {
4815 Statements: []Statement{
4816 {
4817 Pipeline: Pipeline{
4818 CommandOrCompound: CommandOrCompound{
4819 Command: &Command{
4820 AssignmentsOrWords: []AssignmentOrWord{
4821 {
4822 Word: &Word{
4823 Parts: []WordPart{
4824 {
4825 Part: &tk[23],
4826 Tokens: tk[23:24],
4827 },
4828 },
4829 Tokens: tk[23:24],
4830 },
4831 Tokens: tk[23:24],
4832 },
4833 },
4834 Tokens: tk[23:24],
4835 },
4836 Tokens: tk[23:24],
4837 },
4838 Tokens: tk[23:24],
4839 },
4840 Tokens: tk[23:25],
4841 },
4842 },
4843 Tokens: tk[23:25],
4844 },
4845 },
4846 Tokens: tk[23:25],
4847 },
4848 Comments: [2]Comments{nil, {tk[19]}},
4849 Tokens: tk[:26],
4850 }
4851 }},
4852 {"for (( a=1; a<2; a++ )) ;#comment\ndo b;done", func(t *test, tk Tokens) { // 11
4853 t.Output = ForCompound{
4854 ArithmeticExpansion: &ArithmeticExpansion{
4855 Expression: true,
4856 WordsAndOperators: []WordOrOperator{
4857 {
4858 Word: &Word{
4859 Parts: []WordPart{
4860 {
4861 Part: &tk[4],
4862 Tokens: tk[4:5],
4863 },
4864 },
4865 Tokens: tk[4:5],
4866 },
4867 Tokens: tk[4:5],
4868 },
4869 {
4870 Operator: &tk[5],
4871 Tokens: tk[5:6],
4872 },
4873 {
4874 Word: &Word{
4875 Parts: []WordPart{
4876 {
4877 Part: &tk[6],
4878 Tokens: tk[6:7],
4879 },
4880 },
4881 Tokens: tk[6:7],
4882 },
4883 Tokens: tk[6:7],
4884 },
4885 {
4886 Operator: &tk[7],
4887 Tokens: tk[7:8],
4888 },
4889 {
4890 Word: &Word{
4891 Parts: []WordPart{
4892 {
4893 Part: &tk[9],
4894 Tokens: tk[9:10],
4895 },
4896 },
4897 Tokens: tk[9:10],
4898 },
4899 Tokens: tk[9:10],
4900 },
4901 {
4902 Operator: &tk[10],
4903 Tokens: tk[10:11],
4904 },
4905 {
4906 Word: &Word{
4907 Parts: []WordPart{
4908 {
4909 Part: &tk[11],
4910 Tokens: tk[11:12],
4911 },
4912 },
4913 Tokens: tk[11:12],
4914 },
4915 Tokens: tk[11:12],
4916 },
4917 {
4918 Operator: &tk[12],
4919 Tokens: tk[12:13],
4920 },
4921 {
4922 Word: &Word{
4923 Parts: []WordPart{
4924 {
4925 Part: &tk[14],
4926 Tokens: tk[14:15],
4927 },
4928 },
4929 Tokens: tk[14:15],
4930 },
4931 Tokens: tk[14:15],
4932 },
4933 {
4934 Operator: &tk[15],
4935 Tokens: tk[15:16],
4936 },
4937 },
4938 Tokens: tk[2:18],
4939 },
4940 File: File{
4941 Lines: []Line{
4942 {
4943 Statements: []Statement{
4944 {
4945 Pipeline: Pipeline{
4946 CommandOrCompound: CommandOrCompound{
4947 Command: &Command{
4948 AssignmentsOrWords: []AssignmentOrWord{
4949 {
4950 Word: &Word{
4951 Parts: []WordPart{
4952 {
4953 Part: &tk[24],
4954 Tokens: tk[24:25],
4955 },
4956 },
4957 Tokens: tk[24:25],
4958 },
4959 Tokens: tk[24:25],
4960 },
4961 },
4962 Tokens: tk[24:25],
4963 },
4964 Tokens: tk[24:25],
4965 },
4966 Tokens: tk[24:25],
4967 },
4968 Tokens: tk[24:26],
4969 },
4970 },
4971 Tokens: tk[24:26],
4972 },
4973 },
4974 Tokens: tk[24:26],
4975 },
4976 Comments: [2]Comments{nil, {tk[20]}},
4977 Tokens: tk[:27],
4978 }
4979 }},
4980 {"for a in $(||); do b;done", func(t *test, tk Tokens) { // 12
4981 t.Err = Error{
4982 Err: Error{
4983 Err: Error{
4984 Err: Error{
4985 Err: Error{
4986 Err: Error{
4987 Err: Error{
4988 Err: Error{
4989 Err: Error{
4990 Err: Error{
4991 Err: ErrMissingWord,
4992 Parsing: "Command",
4993 Token: tk[7],
4994 },
4995 Parsing: "CommandOrCompound",
4996 Token: tk[7],
4997 },
4998 Parsing: "Pipeline",
4999 Token: tk[7],
5000 },
5001 Parsing: "Statement",
5002 Token: tk[7],
5003 },
5004 Parsing: "Line",
5005 Token: tk[7],
5006 },
5007 Parsing: "File",
5008 Token: tk[7],
5009 },
5010 Parsing: "CommandSubstitution",
5011 Token: tk[7],
5012 },
5013 Parsing: "WordPart",
5014 Token: tk[6],
5015 },
5016 Parsing: "Word",
5017 Token: tk[6],
5018 },
5019 Parsing: "ForCompound",
5020 Token: tk[6],
5021 }
5022 }},
5023 {"for (( $(||) )); do b;done", func(t *test, tk Tokens) { // 13
5024 t.Err = Error{
5025 Err: Error{
5026 Err: Error{
5027 Err: Error{
5028 Err: Error{
5029 Err: Error{
5030 Err: Error{
5031 Err: Error{
5032 Err: Error{
5033 Err: Error{
5034 Err: Error{
5035 Err: Error{
5036 Err: ErrMissingWord,
5037 Parsing: "Command",
5038 Token: tk[5],
5039 },
5040 Parsing: "CommandOrCompound",
5041 Token: tk[5],
5042 },
5043 Parsing: "Pipeline",
5044 Token: tk[5],
5045 },
5046 Parsing: "Statement",
5047 Token: tk[5],
5048 },
5049 Parsing: "Line",
5050 Token: tk[5],
5051 },
5052 Parsing: "File",
5053 Token: tk[5],
5054 },
5055 Parsing: "CommandSubstitution",
5056 Token: tk[5],
5057 },
5058 Parsing: "WordPart",
5059 Token: tk[4],
5060 },
5061 Parsing: "Word",
5062 Token: tk[4],
5063 },
5064 Parsing: "WordOrOperator",
5065 Token: tk[4],
5066 },
5067 Parsing: "ArithmeticExpansion",
5068 Token: tk[4],
5069 },
5070 Parsing: "ForCompound",
5071 Token: tk[2],
5072 }
5073 }},
5074 {"for a; do ||;done", func(t *test, tk Tokens) { // 14
5075 t.Err = Error{
5076 Err: Error{
5077 Err: Error{
5078 Err: Error{
5079 Err: Error{
5080 Err: Error{
5081 Err: Error{
5082 Err: ErrMissingWord,
5083 Parsing: "Command",
5084 Token: tk[7],
5085 },
5086 Parsing: "CommandOrCompound",
5087 Token: tk[7],
5088 },
5089 Parsing: "Pipeline",
5090 Token: tk[7],
5091 },
5092 Parsing: "Statement",
5093 Token: tk[7],
5094 },
5095 Parsing: "Line",
5096 Token: tk[7],
5097 },
5098 Parsing: "File",
5099 Token: tk[7],
5100 },
5101 Parsing: "ForCompound",
5102 Token: tk[7],
5103 }
5104 }},
5105 }, func(t *test) (Type, error) {
5106 var f ForCompound
5107
5108 err := f.parse(t.Parser)
5109
5110 return f, err
5111 })
5112 }
5113
5114 func TestSelectCompound(t *testing.T) {
5115 doTests(t, []sourceFn{
5116 {"select a; do b;done", func(t *test, tk Tokens) { // 1
5117 t.Output = SelectCompound{
5118 Identifier: &tk[2],
5119 File: File{
5120 Lines: []Line{
5121 {
5122 Statements: []Statement{
5123 {
5124 Pipeline: Pipeline{
5125 CommandOrCompound: CommandOrCompound{
5126 Command: &Command{
5127 AssignmentsOrWords: []AssignmentOrWord{
5128 {
5129 Word: &Word{
5130 Parts: []WordPart{
5131 {
5132 Part: &tk[7],
5133 Tokens: tk[7:8],
5134 },
5135 },
5136 Tokens: tk[7:8],
5137 },
5138 Tokens: tk[7:8],
5139 },
5140 },
5141 Tokens: tk[7:8],
5142 },
5143 Tokens: tk[7:8],
5144 },
5145 Tokens: tk[7:8],
5146 },
5147 Tokens: tk[7:9],
5148 },
5149 },
5150 Tokens: tk[7:9],
5151 },
5152 },
5153 Tokens: tk[7:9],
5154 },
5155 Tokens: tk[:10],
5156 }
5157 }},
5158 {"select a\ndo b\ndone", func(t *test, tk Tokens) { // 2
5159 t.Output = SelectCompound{
5160 Identifier: &tk[2],
5161 File: File{
5162 Lines: []Line{
5163 {
5164 Statements: []Statement{
5165 {
5166 Pipeline: Pipeline{
5167 CommandOrCompound: CommandOrCompound{
5168 Command: &Command{
5169 AssignmentsOrWords: []AssignmentOrWord{
5170 {
5171 Word: &Word{
5172 Parts: []WordPart{
5173 {
5174 Part: &tk[6],
5175 Tokens: tk[6:7],
5176 },
5177 },
5178 Tokens: tk[6:7],
5179 },
5180 Tokens: tk[6:7],
5181 },
5182 },
5183 Tokens: tk[6:7],
5184 },
5185 Tokens: tk[6:7],
5186 },
5187 Tokens: tk[6:7],
5188 },
5189 Tokens: tk[6:7],
5190 },
5191 },
5192 Tokens: tk[6:7],
5193 },
5194 },
5195 Tokens: tk[6:7],
5196 },
5197 Tokens: tk[:9],
5198 }
5199 }},
5200 {"select a in; do b;done", func(t *test, tk Tokens) { // 3
5201 t.Output = SelectCompound{
5202 Identifier: &tk[2],
5203 Words: []Word{},
5204 File: File{
5205 Lines: []Line{
5206 {
5207 Statements: []Statement{
5208 {
5209 Pipeline: Pipeline{
5210 CommandOrCompound: CommandOrCompound{
5211 Command: &Command{
5212 AssignmentsOrWords: []AssignmentOrWord{
5213 {
5214 Word: &Word{
5215 Parts: []WordPart{
5216 {
5217 Part: &tk[9],
5218 Tokens: tk[9:10],
5219 },
5220 },
5221 Tokens: tk[9:10],
5222 },
5223 Tokens: tk[9:10],
5224 },
5225 },
5226 Tokens: tk[9:10],
5227 },
5228 Tokens: tk[9:10],
5229 },
5230 Tokens: tk[9:10],
5231 },
5232 Tokens: tk[9:11],
5233 },
5234 },
5235 Tokens: tk[9:11],
5236 },
5237 },
5238 Tokens: tk[9:11],
5239 },
5240 Tokens: tk[:12],
5241 }
5242 }},
5243 {"select a in b; do c;done", func(t *test, tk Tokens) { // 4
5244 t.Output = SelectCompound{
5245 Identifier: &tk[2],
5246 Words: []Word{
5247 {
5248 Parts: []WordPart{
5249 {
5250 Part: &tk[6],
5251 Tokens: tk[6:7],
5252 },
5253 },
5254 Tokens: tk[6:7],
5255 },
5256 },
5257 File: File{
5258 Lines: []Line{
5259 {
5260 Statements: []Statement{
5261 {
5262 Pipeline: Pipeline{
5263 CommandOrCompound: CommandOrCompound{
5264 Command: &Command{
5265 AssignmentsOrWords: []AssignmentOrWord{
5266 {
5267 Word: &Word{
5268 Parts: []WordPart{
5269 {
5270 Part: &tk[11],
5271 Tokens: tk[11:12],
5272 },
5273 },
5274 Tokens: tk[11:12],
5275 },
5276 Tokens: tk[11:12],
5277 },
5278 },
5279 Tokens: tk[11:12],
5280 },
5281 Tokens: tk[11:12],
5282 },
5283 Tokens: tk[11:12],
5284 },
5285 Tokens: tk[11:13],
5286 },
5287 },
5288 Tokens: tk[11:13],
5289 },
5290 },
5291 Tokens: tk[11:13],
5292 },
5293 Tokens: tk[:14],
5294 }
5295 }},
5296 {"select a in b c; do d;done", func(t *test, tk Tokens) { // 5
5297 t.Output = SelectCompound{
5298 Identifier: &tk[2],
5299 Words: []Word{
5300 {
5301 Parts: []WordPart{
5302 {
5303 Part: &tk[6],
5304 Tokens: tk[6:7],
5305 },
5306 },
5307 Tokens: tk[6:7],
5308 },
5309 {
5310 Parts: []WordPart{
5311 {
5312 Part: &tk[8],
5313 Tokens: tk[8:9],
5314 },
5315 },
5316 Tokens: tk[8:9],
5317 },
5318 },
5319 File: File{
5320 Lines: []Line{
5321 {
5322 Statements: []Statement{
5323 {
5324 Pipeline: Pipeline{
5325 CommandOrCompound: CommandOrCompound{
5326 Command: &Command{
5327 AssignmentsOrWords: []AssignmentOrWord{
5328 {
5329 Word: &Word{
5330 Parts: []WordPart{
5331 {
5332 Part: &tk[13],
5333 Tokens: tk[13:14],
5334 },
5335 },
5336 Tokens: tk[13:14],
5337 },
5338 Tokens: tk[13:14],
5339 },
5340 },
5341 Tokens: tk[13:14],
5342 },
5343 Tokens: tk[13:14],
5344 },
5345 Tokens: tk[13:14],
5346 },
5347 Tokens: tk[13:15],
5348 },
5349 },
5350 Tokens: tk[13:15],
5351 },
5352 },
5353 Tokens: tk[13:15],
5354 },
5355 Tokens: tk[:16],
5356 }
5357 }},
5358 {"select a #comment\ndo b;done", func(t *test, tk Tokens) { // 6
5359 t.Output = SelectCompound{
5360 Identifier: &tk[2],
5361 File: File{
5362 Lines: []Line{
5363 {
5364 Statements: []Statement{
5365 {
5366 Pipeline: Pipeline{
5367 CommandOrCompound: CommandOrCompound{
5368 Command: &Command{
5369 AssignmentsOrWords: []AssignmentOrWord{
5370 {
5371 Word: &Word{
5372 Parts: []WordPart{
5373 {
5374 Part: &tk[8],
5375 Tokens: tk[8:9],
5376 },
5377 },
5378 Tokens: tk[8:9],
5379 },
5380 Tokens: tk[8:9],
5381 },
5382 },
5383 Tokens: tk[8:9],
5384 },
5385 Tokens: tk[8:9],
5386 },
5387 Tokens: tk[8:9],
5388 },
5389 Tokens: tk[8:10],
5390 },
5391 },
5392 Tokens: tk[8:10],
5393 },
5394 },
5395 Tokens: tk[8:10],
5396 },
5397 Comments: [2]Comments{{tk[4]}},
5398 Tokens: tk[:11],
5399 }
5400 }},
5401 {"select a # comment\nin b #comment 2\ndo c;done", func(t *test, tk Tokens) { // 7
5402 t.Output = SelectCompound{
5403 Identifier: &tk[2],
5404 Words: []Word{
5405 {
5406 Parts: []WordPart{
5407 {
5408 Part: &tk[8],
5409 Tokens: tk[8:9],
5410 },
5411 },
5412 Tokens: tk[8:9],
5413 },
5414 },
5415 File: File{
5416 Lines: []Line{
5417 {
5418 Statements: []Statement{
5419 {
5420 Pipeline: Pipeline{
5421 CommandOrCompound: CommandOrCompound{
5422 Command: &Command{
5423 AssignmentsOrWords: []AssignmentOrWord{
5424 {
5425 Word: &Word{
5426 Parts: []WordPart{
5427 {
5428 Part: &tk[14],
5429 Tokens: tk[14:15],
5430 },
5431 },
5432 Tokens: tk[14:15],
5433 },
5434 Tokens: tk[14:15],
5435 },
5436 },
5437 Tokens: tk[14:15],
5438 },
5439 Tokens: tk[14:15],
5440 },
5441 Tokens: tk[14:15],
5442 },
5443 Tokens: tk[14:16],
5444 },
5445 },
5446 Tokens: tk[14:16],
5447 },
5448 },
5449 Tokens: tk[14:16],
5450 },
5451 Comments: [2]Comments{{tk[4]}, {tk[10]}},
5452 Tokens: tk[:17],
5453 }
5454 }},
5455 {"select a in b #comment\ndo c;done", func(t *test, tk Tokens) { // 8
5456 t.Output = SelectCompound{
5457 Identifier: &tk[2],
5458 Words: []Word{
5459 {
5460 Parts: []WordPart{
5461 {
5462 Part: &tk[6],
5463 Tokens: tk[6:7],
5464 },
5465 },
5466 Tokens: tk[6:7],
5467 },
5468 },
5469 File: File{
5470 Lines: []Line{
5471 {
5472 Statements: []Statement{
5473 {
5474 Pipeline: Pipeline{
5475 CommandOrCompound: CommandOrCompound{
5476 Command: &Command{
5477 AssignmentsOrWords: []AssignmentOrWord{
5478 {
5479 Word: &Word{
5480 Parts: []WordPart{
5481 {
5482 Part: &tk[12],
5483 Tokens: tk[12:13],
5484 },
5485 },
5486 Tokens: tk[12:13],
5487 },
5488 Tokens: tk[12:13],
5489 },
5490 },
5491 Tokens: tk[12:13],
5492 },
5493 Tokens: tk[12:13],
5494 },
5495 Tokens: tk[12:13],
5496 },
5497 Tokens: tk[12:14],
5498 },
5499 },
5500 Tokens: tk[12:14],
5501 },
5502 },
5503 Tokens: tk[12:14],
5504 },
5505 Comments: [2]Comments{nil, {tk[8]}},
5506 Tokens: tk[:15],
5507 }
5508 }},
5509 {"select a in $(||); do b;done", func(t *test, tk Tokens) { // 9
5510 t.Err = Error{
5511 Err: Error{
5512 Err: Error{
5513 Err: Error{
5514 Err: Error{
5515 Err: Error{
5516 Err: Error{
5517 Err: Error{
5518 Err: Error{
5519 Err: Error{
5520 Err: ErrMissingWord,
5521 Parsing: "Command",
5522 Token: tk[7],
5523 },
5524 Parsing: "CommandOrCompound",
5525 Token: tk[7],
5526 },
5527 Parsing: "Pipeline",
5528 Token: tk[7],
5529 },
5530 Parsing: "Statement",
5531 Token: tk[7],
5532 },
5533 Parsing: "Line",
5534 Token: tk[7],
5535 },
5536 Parsing: "File",
5537 Token: tk[7],
5538 },
5539 Parsing: "CommandSubstitution",
5540 Token: tk[7],
5541 },
5542 Parsing: "WordPart",
5543 Token: tk[6],
5544 },
5545 Parsing: "Word",
5546 Token: tk[6],
5547 },
5548 Parsing: "SelectCompound",
5549 Token: tk[6],
5550 }
5551 }},
5552 {"select a; do ||;done", func(t *test, tk Tokens) { // 10
5553 t.Err = Error{
5554 Err: Error{
5555 Err: Error{
5556 Err: Error{
5557 Err: Error{
5558 Err: Error{
5559 Err: Error{
5560 Err: ErrMissingWord,
5561 Parsing: "Command",
5562 Token: tk[7],
5563 },
5564 Parsing: "CommandOrCompound",
5565 Token: tk[7],
5566 },
5567 Parsing: "Pipeline",
5568 Token: tk[7],
5569 },
5570 Parsing: "Statement",
5571 Token: tk[7],
5572 },
5573 Parsing: "Line",
5574 Token: tk[7],
5575 },
5576 Parsing: "File",
5577 Token: tk[7],
5578 },
5579 Parsing: "SelectCompound",
5580 Token: tk[7],
5581 }
5582 }},
5583 }, func(t *test) (Type, error) {
5584 var s SelectCompound
5585
5586 err := s.parse(t.Parser)
5587
5588 return s, err
5589 })
5590 }
5591
5592 func TestTestCompound(t *testing.T) {
5593 doTests(t, []sourceFn{
5594 {"[[ a = b ]]", func(t *test, tk Tokens) { // 1
5595 t.Output = TestCompound{
5596 Tests: Tests{
5597 Test: TestOperatorStringsEqual,
5598 Word: &Word{
5599 Parts: []WordPart{
5600 {
5601 Part: &tk[2],
5602 Tokens: tk[2:3],
5603 },
5604 },
5605 Tokens: tk[2:3],
5606 },
5607 Pattern: &Pattern{
5608 Parts: []WordPart{
5609 {
5610 Part: &tk[6],
5611 Tokens: tk[6:7],
5612 },
5613 },
5614 Tokens: tk[6:7],
5615 },
5616 Tokens: tk[2:7],
5617 },
5618 Tokens: tk[:9],
5619 }
5620 }},
5621 {"[[ #comment A\n\n#comment B\na = b ]]", func(t *test, tk Tokens) { // 2
5622 t.Output = TestCompound{
5623 Tests: Tests{
5624 Test: TestOperatorStringsEqual,
5625 Word: &Word{
5626 Parts: []WordPart{
5627 {
5628 Part: &tk[6],
5629 Tokens: tk[6:7],
5630 },
5631 },
5632 Tokens: tk[6:7],
5633 },
5634 Pattern: &Pattern{
5635 Parts: []WordPart{
5636 {
5637 Part: &tk[10],
5638 Tokens: tk[10:11],
5639 },
5640 },
5641 Tokens: tk[10:11],
5642 },
5643 Comments: [5]Comments{{tk[4]}},
5644 Tokens: tk[4:11],
5645 },
5646 Comments: [2]Comments{{tk[2]}},
5647 Tokens: tk[:13],
5648 }
5649 }},
5650 {"[[ a = b # comment A\n\n#comment B\n]]", func(t *test, tk Tokens) { // 3
5651 t.Output = TestCompound{
5652 Tests: Tests{
5653 Test: TestOperatorStringsEqual,
5654 Word: &Word{
5655 Parts: []WordPart{
5656 {
5657 Part: &tk[2],
5658 Tokens: tk[2:3],
5659 },
5660 },
5661 Tokens: tk[2:3],
5662 },
5663 Pattern: &Pattern{
5664 Parts: []WordPart{
5665 {
5666 Part: &tk[6],
5667 Tokens: tk[6:7],
5668 },
5669 },
5670 Tokens: tk[6:7],
5671 },
5672 Comments: [5]Comments{nil, nil, nil, nil, {tk[8]}},
5673 Tokens: tk[2:9],
5674 },
5675 Comments: [2]Comments{nil, {tk[10]}},
5676 Tokens: tk[:13],
5677 }
5678 }},
5679 {"[[ -a $(||) ]]", func(t *test, tk Tokens) { // 4
5680 t.Err = Error{
5681 Err: Error{
5682 Err: Error{
5683 Err: Error{
5684 Err: Error{
5685 Err: Error{
5686 Err: Error{
5687 Err: Error{
5688 Err: Error{
5689 Err: Error{
5690 Err: Error{
5691 Err: ErrMissingWord,
5692 Parsing: "Command",
5693 Token: tk[5],
5694 },
5695 Parsing: "CommandOrCompound",
5696 Token: tk[5],
5697 },
5698 Parsing: "Pipeline",
5699 Token: tk[5],
5700 },
5701 Parsing: "Statement",
5702 Token: tk[5],
5703 },
5704 Parsing: "Line",
5705 Token: tk[5],
5706 },
5707 Parsing: "File",
5708 Token: tk[5],
5709 },
5710 Parsing: "CommandSubstitution",
5711 Token: tk[5],
5712 },
5713 Parsing: "WordPart",
5714 Token: tk[4],
5715 },
5716 Parsing: "Word",
5717 Token: tk[4],
5718 },
5719 Parsing: "Tests",
5720 Token: tk[4],
5721 },
5722 Parsing: "TestCompound",
5723 Token: tk[2],
5724 }
5725 }},
5726 }, func(t *test) (Type, error) {
5727 var tc TestCompound
5728
5729 err := tc.parse(t.Parser)
5730
5731 return tc, err
5732 })
5733 }
5734
5735 func TestTests(t *testing.T) {
5736 doTests(t, []sourceFn{
5737 {"[[ a = b ]]", func(t *test, tk Tokens) { // 1
5738 t.Output = Tests{
5739 Test: TestOperatorStringsEqual,
5740 Word: &Word{
5741 Parts: []WordPart{
5742 {
5743 Part: &tk[2],
5744 Tokens: tk[2:3],
5745 },
5746 },
5747 Tokens: tk[2:3],
5748 },
5749 Pattern: &Pattern{
5750 Parts: []WordPart{
5751 {
5752 Part: &tk[6],
5753 Tokens: tk[6:7],
5754 },
5755 },
5756 Tokens: tk[6:7],
5757 },
5758 Tokens: tk[2:7],
5759 }
5760 }},
5761 {"[[ a == b ]]", func(t *test, tk Tokens) { // 2
5762 t.Output = Tests{
5763 Test: TestOperatorStringsEqual,
5764 Word: &Word{
5765 Parts: []WordPart{
5766 {
5767 Part: &tk[2],
5768 Tokens: tk[2:3],
5769 },
5770 },
5771 Tokens: tk[2:3],
5772 },
5773 Pattern: &Pattern{
5774 Parts: []WordPart{
5775 {
5776 Part: &tk[6],
5777 Tokens: tk[6:7],
5778 },
5779 },
5780 Tokens: tk[6:7],
5781 },
5782 Tokens: tk[2:7],
5783 }
5784 }},
5785 {"[[ a != b ]]", func(t *test, tk Tokens) { // 3
5786 t.Output = Tests{
5787 Test: TestOperatorStringsNotEqual,
5788 Word: &Word{
5789 Parts: []WordPart{
5790 {
5791 Part: &tk[2],
5792 Tokens: tk[2:3],
5793 },
5794 },
5795 Tokens: tk[2:3],
5796 },
5797 Pattern: &Pattern{
5798 Parts: []WordPart{
5799 {
5800 Part: &tk[6],
5801 Tokens: tk[6:7],
5802 },
5803 },
5804 Tokens: tk[6:7],
5805 },
5806 Tokens: tk[2:7],
5807 }
5808 }},
5809 {"[[ a =~ b ]]", func(t *test, tk Tokens) { // 4
5810 t.Output = Tests{
5811 Test: TestOperatorStringsMatch,
5812 Word: &Word{
5813 Parts: []WordPart{
5814 {
5815 Part: &tk[2],
5816 Tokens: tk[2:3],
5817 },
5818 },
5819 Tokens: tk[2:3],
5820 },
5821 Pattern: &Pattern{
5822 Parts: []WordPart{
5823 {
5824 Part: &tk[6],
5825 Tokens: tk[6:7],
5826 },
5827 },
5828 Tokens: tk[6:7],
5829 },
5830 Tokens: tk[2:7],
5831 }
5832 }},
5833 {"[[ a < b ]]", func(t *test, tk Tokens) { // 5
5834 t.Output = Tests{
5835 Test: TestOperatorStringBefore,
5836 Word: &Word{
5837 Parts: []WordPart{
5838 {
5839 Part: &tk[2],
5840 Tokens: tk[2:3],
5841 },
5842 },
5843 Tokens: tk[2:3],
5844 },
5845 Pattern: &Pattern{
5846 Parts: []WordPart{
5847 {
5848 Part: &tk[6],
5849 Tokens: tk[6:7],
5850 },
5851 },
5852 Tokens: tk[6:7],
5853 },
5854 Tokens: tk[2:7],
5855 }
5856 }},
5857 {"[[ a > b ]]", func(t *test, tk Tokens) { // 6
5858 t.Output = Tests{
5859 Test: TestOperatorStringAfter,
5860 Word: &Word{
5861 Parts: []WordPart{
5862 {
5863 Part: &tk[2],
5864 Tokens: tk[2:3],
5865 },
5866 },
5867 Tokens: tk[2:3],
5868 },
5869 Pattern: &Pattern{
5870 Parts: []WordPart{
5871 {
5872 Part: &tk[6],
5873 Tokens: tk[6:7],
5874 },
5875 },
5876 Tokens: tk[6:7],
5877 },
5878 Tokens: tk[2:7],
5879 }
5880 }},
5881 {"[[ a>b ]]", func(t *test, tk Tokens) { // 7
5882 t.Output = Tests{
5883 Test: TestOperatorStringAfter,
5884 Word: &Word{
5885 Parts: []WordPart{
5886 {
5887 Part: &tk[2],
5888 Tokens: tk[2:3],
5889 },
5890 },
5891 Tokens: tk[2:3],
5892 },
5893 Pattern: &Pattern{
5894 Parts: []WordPart{
5895 {
5896 Part: &tk[4],
5897 Tokens: tk[4:5],
5898 },
5899 },
5900 Tokens: tk[4:5],
5901 },
5902 Tokens: tk[2:5],
5903 }
5904 }},
5905 {"[[ a -ef b ]]", func(t *test, tk Tokens) { // 8
5906 t.Output = Tests{
5907 Test: TestOperatorFilesAreSameInode,
5908 Word: &Word{
5909 Parts: []WordPart{
5910 {
5911 Part: &tk[2],
5912 Tokens: tk[2:3],
5913 },
5914 },
5915 Tokens: tk[2:3],
5916 },
5917 Pattern: &Pattern{
5918 Parts: []WordPart{
5919 {
5920 Part: &tk[6],
5921 Tokens: tk[6:7],
5922 },
5923 },
5924 Tokens: tk[6:7],
5925 },
5926 Tokens: tk[2:7],
5927 }
5928 }},
5929 {"[[ a -nt b ]]", func(t *test, tk Tokens) { // 9
5930 t.Output = Tests{
5931 Test: TestOperatorFileIsNewerThan,
5932 Word: &Word{
5933 Parts: []WordPart{
5934 {
5935 Part: &tk[2],
5936 Tokens: tk[2:3],
5937 },
5938 },
5939 Tokens: tk[2:3],
5940 },
5941 Pattern: &Pattern{
5942 Parts: []WordPart{
5943 {
5944 Part: &tk[6],
5945 Tokens: tk[6:7],
5946 },
5947 },
5948 Tokens: tk[6:7],
5949 },
5950 Tokens: tk[2:7],
5951 }
5952 }},
5953 {"[[ a -ot b ]]", func(t *test, tk Tokens) { // 10
5954 t.Output = Tests{
5955 Test: TestOperatorFileIsOlderThan,
5956 Word: &Word{
5957 Parts: []WordPart{
5958 {
5959 Part: &tk[2],
5960 Tokens: tk[2:3],
5961 },
5962 },
5963 Tokens: tk[2:3],
5964 },
5965 Pattern: &Pattern{
5966 Parts: []WordPart{
5967 {
5968 Part: &tk[6],
5969 Tokens: tk[6:7],
5970 },
5971 },
5972 Tokens: tk[6:7],
5973 },
5974 Tokens: tk[2:7],
5975 }
5976 }},
5977 {"[[ a -eq b ]]", func(t *test, tk Tokens) { // 11
5978 t.Output = Tests{
5979 Test: TestOperatorEqual,
5980 Word: &Word{
5981 Parts: []WordPart{
5982 {
5983 Part: &tk[2],
5984 Tokens: tk[2:3],
5985 },
5986 },
5987 Tokens: tk[2:3],
5988 },
5989 Pattern: &Pattern{
5990 Parts: []WordPart{
5991 {
5992 Part: &tk[6],
5993 Tokens: tk[6:7],
5994 },
5995 },
5996 Tokens: tk[6:7],
5997 },
5998 Tokens: tk[2:7],
5999 }
6000 }},
6001 {"[[ a -ne b ]]", func(t *test, tk Tokens) { // 12
6002 t.Output = Tests{
6003 Test: TestOperatorNotEqual,
6004 Word: &Word{
6005 Parts: []WordPart{
6006 {
6007 Part: &tk[2],
6008 Tokens: tk[2:3],
6009 },
6010 },
6011 Tokens: tk[2:3],
6012 },
6013 Pattern: &Pattern{
6014 Parts: []WordPart{
6015 {
6016 Part: &tk[6],
6017 Tokens: tk[6:7],
6018 },
6019 },
6020 Tokens: tk[6:7],
6021 },
6022 Tokens: tk[2:7],
6023 }
6024 }},
6025 {"[[ a -le b ]]", func(t *test, tk Tokens) { // 13
6026 t.Output = Tests{
6027 Test: TestOperatorLessThanEqual,
6028 Word: &Word{
6029 Parts: []WordPart{
6030 {
6031 Part: &tk[2],
6032 Tokens: tk[2:3],
6033 },
6034 },
6035 Tokens: tk[2:3],
6036 },
6037 Pattern: &Pattern{
6038 Parts: []WordPart{
6039 {
6040 Part: &tk[6],
6041 Tokens: tk[6:7],
6042 },
6043 },
6044 Tokens: tk[6:7],
6045 },
6046 Tokens: tk[2:7],
6047 }
6048 }},
6049 {"[[ a -lt b ]]", func(t *test, tk Tokens) { // 14
6050 t.Output = Tests{
6051 Test: TestOperatorLessThan,
6052 Word: &Word{
6053 Parts: []WordPart{
6054 {
6055 Part: &tk[2],
6056 Tokens: tk[2:3],
6057 },
6058 },
6059 Tokens: tk[2:3],
6060 },
6061 Pattern: &Pattern{
6062 Parts: []WordPart{
6063 {
6064 Part: &tk[6],
6065 Tokens: tk[6:7],
6066 },
6067 },
6068 Tokens: tk[6:7],
6069 },
6070 Tokens: tk[2:7],
6071 }
6072 }},
6073 {"[[ a -ge b ]]", func(t *test, tk Tokens) { // 15
6074 t.Output = Tests{
6075 Test: TestOperatorGreaterThanEqual,
6076 Word: &Word{
6077 Parts: []WordPart{
6078 {
6079 Part: &tk[2],
6080 Tokens: tk[2:3],
6081 },
6082 },
6083 Tokens: tk[2:3],
6084 },
6085 Pattern: &Pattern{
6086 Parts: []WordPart{
6087 {
6088 Part: &tk[6],
6089 Tokens: tk[6:7],
6090 },
6091 },
6092 Tokens: tk[6:7],
6093 },
6094 Tokens: tk[2:7],
6095 }
6096 }},
6097 {"[[ a -gt b ]]", func(t *test, tk Tokens) { // 16
6098 t.Output = Tests{
6099 Test: TestOperatorGreaterThan,
6100 Word: &Word{
6101 Parts: []WordPart{
6102 {
6103 Part: &tk[2],
6104 Tokens: tk[2:3],
6105 },
6106 },
6107 Tokens: tk[2:3],
6108 },
6109 Pattern: &Pattern{
6110 Parts: []WordPart{
6111 {
6112 Part: &tk[6],
6113 Tokens: tk[6:7],
6114 },
6115 },
6116 Tokens: tk[6:7],
6117 },
6118 Tokens: tk[2:7],
6119 }
6120 }},
6121 {"[[ -a a ]]", func(t *test, tk Tokens) { // 17
6122 t.Output = Tests{
6123 Test: TestOperatorFileExists,
6124 Word: &Word{
6125 Parts: []WordPart{
6126 {
6127 Part: &tk[4],
6128 Tokens: tk[4:5],
6129 },
6130 },
6131 Tokens: tk[4:5],
6132 },
6133 Tokens: tk[2:5],
6134 }
6135 }},
6136 {"[[ -e a ]]", func(t *test, tk Tokens) { // 18
6137 t.Output = Tests{
6138 Test: TestOperatorFileExists,
6139 Word: &Word{
6140 Parts: []WordPart{
6141 {
6142 Part: &tk[4],
6143 Tokens: tk[4:5],
6144 },
6145 },
6146 Tokens: tk[4:5],
6147 },
6148 Tokens: tk[2:5],
6149 }
6150 }},
6151 {"[[ -b a ]]", func(t *test, tk Tokens) { // 19
6152 t.Output = Tests{
6153 Test: TestOperatorFileIsBlock,
6154 Word: &Word{
6155 Parts: []WordPart{
6156 {
6157 Part: &tk[4],
6158 Tokens: tk[4:5],
6159 },
6160 },
6161 Tokens: tk[4:5],
6162 },
6163 Tokens: tk[2:5],
6164 }
6165 }},
6166 {"[[ -c a ]]", func(t *test, tk Tokens) { // 20
6167 t.Output = Tests{
6168 Test: TestOperatorFileIsCharacter,
6169 Word: &Word{
6170 Parts: []WordPart{
6171 {
6172 Part: &tk[4],
6173 Tokens: tk[4:5],
6174 },
6175 },
6176 Tokens: tk[4:5],
6177 },
6178 Tokens: tk[2:5],
6179 }
6180 }},
6181 {"[[ -d a ]]", func(t *test, tk Tokens) { // 21
6182 t.Output = Tests{
6183 Test: TestOperatorDirectoryExists,
6184 Word: &Word{
6185 Parts: []WordPart{
6186 {
6187 Part: &tk[4],
6188 Tokens: tk[4:5],
6189 },
6190 },
6191 Tokens: tk[4:5],
6192 },
6193 Tokens: tk[2:5],
6194 }
6195 }},
6196 {"[[ -f a ]]", func(t *test, tk Tokens) { // 22
6197 t.Output = Tests{
6198 Test: TestOperatorFileIsRegular,
6199 Word: &Word{
6200 Parts: []WordPart{
6201 {
6202 Part: &tk[4],
6203 Tokens: tk[4:5],
6204 },
6205 },
6206 Tokens: tk[4:5],
6207 },
6208 Tokens: tk[2:5],
6209 }
6210 }},
6211 {"[[ -g a ]]", func(t *test, tk Tokens) { // 23
6212 t.Output = Tests{
6213 Test: TestOperatorFileHasSetGroupID,
6214 Word: &Word{
6215 Parts: []WordPart{
6216 {
6217 Part: &tk[4],
6218 Tokens: tk[4:5],
6219 },
6220 },
6221 Tokens: tk[4:5],
6222 },
6223 Tokens: tk[2:5],
6224 }
6225 }},
6226 {"[[ -h a ]]", func(t *test, tk Tokens) { // 24
6227 t.Output = Tests{
6228 Test: TestOperatorFileIsSymbolic,
6229 Word: &Word{
6230 Parts: []WordPart{
6231 {
6232 Part: &tk[4],
6233 Tokens: tk[4:5],
6234 },
6235 },
6236 Tokens: tk[4:5],
6237 },
6238 Tokens: tk[2:5],
6239 }
6240 }},
6241 {"[[ -L a ]]", func(t *test, tk Tokens) { // 25
6242 t.Output = Tests{
6243 Test: TestOperatorFileIsSymbolic,
6244 Word: &Word{
6245 Parts: []WordPart{
6246 {
6247 Part: &tk[4],
6248 Tokens: tk[4:5],
6249 },
6250 },
6251 Tokens: tk[4:5],
6252 },
6253 Tokens: tk[2:5],
6254 }
6255 }},
6256 {"[[ -k a ]]", func(t *test, tk Tokens) { // 26
6257 t.Output = Tests{
6258 Test: TestOperatorFileHasStickyBit,
6259 Word: &Word{
6260 Parts: []WordPart{
6261 {
6262 Part: &tk[4],
6263 Tokens: tk[4:5],
6264 },
6265 },
6266 Tokens: tk[4:5],
6267 },
6268 Tokens: tk[2:5],
6269 }
6270 }},
6271 {"[[ -p a ]]", func(t *test, tk Tokens) { // 27
6272 t.Output = Tests{
6273 Test: TestOperatorFileIsPipe,
6274 Word: &Word{
6275 Parts: []WordPart{
6276 {
6277 Part: &tk[4],
6278 Tokens: tk[4:5],
6279 },
6280 },
6281 Tokens: tk[4:5],
6282 },
6283 Tokens: tk[2:5],
6284 }
6285 }},
6286 {"[[ -r a ]]", func(t *test, tk Tokens) { // 28
6287 t.Output = Tests{
6288 Test: TestOperatorFileIsReadable,
6289 Word: &Word{
6290 Parts: []WordPart{
6291 {
6292 Part: &tk[4],
6293 Tokens: tk[4:5],
6294 },
6295 },
6296 Tokens: tk[4:5],
6297 },
6298 Tokens: tk[2:5],
6299 }
6300 }},
6301 {"[[ -s a ]]", func(t *test, tk Tokens) { // 29
6302 t.Output = Tests{
6303 Test: TestOperatorFileIsNonZero,
6304 Word: &Word{
6305 Parts: []WordPart{
6306 {
6307 Part: &tk[4],
6308 Tokens: tk[4:5],
6309 },
6310 },
6311 Tokens: tk[4:5],
6312 },
6313 Tokens: tk[2:5],
6314 }
6315 }},
6316 {"[[ -t a ]]", func(t *test, tk Tokens) { // 30
6317 t.Output = Tests{
6318 Test: TestOperatorFileIsTerminal,
6319 Word: &Word{
6320 Parts: []WordPart{
6321 {
6322 Part: &tk[4],
6323 Tokens: tk[4:5],
6324 },
6325 },
6326 Tokens: tk[4:5],
6327 },
6328 Tokens: tk[2:5],
6329 }
6330 }},
6331 {"[[ -u a ]]", func(t *test, tk Tokens) { // 31
6332 t.Output = Tests{
6333 Test: TestOperatorFileHasSetUserID,
6334 Word: &Word{
6335 Parts: []WordPart{
6336 {
6337 Part: &tk[4],
6338 Tokens: tk[4:5],
6339 },
6340 },
6341 Tokens: tk[4:5],
6342 },
6343 Tokens: tk[2:5],
6344 }
6345 }},
6346 {"[[ -w a ]]", func(t *test, tk Tokens) { // 32
6347 t.Output = Tests{
6348 Test: TestOperatorFileIsWritable,
6349 Word: &Word{
6350 Parts: []WordPart{
6351 {
6352 Part: &tk[4],
6353 Tokens: tk[4:5],
6354 },
6355 },
6356 Tokens: tk[4:5],
6357 },
6358 Tokens: tk[2:5],
6359 }
6360 }},
6361 {"[[ -x a ]]", func(t *test, tk Tokens) { // 33
6362 t.Output = Tests{
6363 Test: TestOperatorFileIsExecutable,
6364 Word: &Word{
6365 Parts: []WordPart{
6366 {
6367 Part: &tk[4],
6368 Tokens: tk[4:5],
6369 },
6370 },
6371 Tokens: tk[4:5],
6372 },
6373 Tokens: tk[2:5],
6374 }
6375 }},
6376 {"[[ -G a ]]", func(t *test, tk Tokens) { // 34
6377 t.Output = Tests{
6378 Test: TestOperatorFileIsOwnedByEffectiveGroup,
6379 Word: &Word{
6380 Parts: []WordPart{
6381 {
6382 Part: &tk[4],
6383 Tokens: tk[4:5],
6384 },
6385 },
6386 Tokens: tk[4:5],
6387 },
6388 Tokens: tk[2:5],
6389 }
6390 }},
6391 {"[[ -N a ]]", func(t *test, tk Tokens) { // 35
6392 t.Output = Tests{
6393 Test: TestOperatorFileWasModifiedSinceLastRead,
6394 Word: &Word{
6395 Parts: []WordPart{
6396 {
6397 Part: &tk[4],
6398 Tokens: tk[4:5],
6399 },
6400 },
6401 Tokens: tk[4:5],
6402 },
6403 Tokens: tk[2:5],
6404 }
6405 }},
6406 {"[[ -O a ]]", func(t *test, tk Tokens) { // 36
6407 t.Output = Tests{
6408 Test: TestOperatorFileIsOwnedByEffectiveUser,
6409 Word: &Word{
6410 Parts: []WordPart{
6411 {
6412 Part: &tk[4],
6413 Tokens: tk[4:5],
6414 },
6415 },
6416 Tokens: tk[4:5],
6417 },
6418 Tokens: tk[2:5],
6419 }
6420 }},
6421 {"[[ -S a ]]", func(t *test, tk Tokens) { // 37
6422 t.Output = Tests{
6423 Test: TestOperatorFileIsSocket,
6424 Word: &Word{
6425 Parts: []WordPart{
6426 {
6427 Part: &tk[4],
6428 Tokens: tk[4:5],
6429 },
6430 },
6431 Tokens: tk[4:5],
6432 },
6433 Tokens: tk[2:5],
6434 }
6435 }},
6436 {"[[ -o a ]]", func(t *test, tk Tokens) { // 38
6437 t.Output = Tests{
6438 Test: TestOperatorOptNameIsEnabled,
6439 Word: &Word{
6440 Parts: []WordPart{
6441 {
6442 Part: &tk[4],
6443 Tokens: tk[4:5],
6444 },
6445 },
6446 Tokens: tk[4:5],
6447 },
6448 Tokens: tk[2:5],
6449 }
6450 }},
6451 {"[[ -v a ]]", func(t *test, tk Tokens) { // 39
6452 t.Output = Tests{
6453 Test: TestOperatorVarNameIsSet,
6454 Word: &Word{
6455 Parts: []WordPart{
6456 {
6457 Part: &tk[4],
6458 Tokens: tk[4:5],
6459 },
6460 },
6461 Tokens: tk[4:5],
6462 },
6463 Tokens: tk[2:5],
6464 }
6465 }},
6466 {"[[ -R a ]]", func(t *test, tk Tokens) { // 40
6467 t.Output = Tests{
6468 Test: TestOperatorVarnameIsRef,
6469 Word: &Word{
6470 Parts: []WordPart{
6471 {
6472 Part: &tk[4],
6473 Tokens: tk[4:5],
6474 },
6475 },
6476 Tokens: tk[4:5],
6477 },
6478 Tokens: tk[2:5],
6479 }
6480 }},
6481 {"[[ -z a ]]", func(t *test, tk Tokens) { // 41
6482 t.Output = Tests{
6483 Test: TestOperatorStringIsZero,
6484 Word: &Word{
6485 Parts: []WordPart{
6486 {
6487 Part: &tk[4],
6488 Tokens: tk[4:5],
6489 },
6490 },
6491 Tokens: tk[4:5],
6492 },
6493 Tokens: tk[2:5],
6494 }
6495 }},
6496 {"[[ -n a ]]", func(t *test, tk Tokens) { // 42
6497 t.Output = Tests{
6498 Test: TestOperatorStringIsNonZero,
6499 Word: &Word{
6500 Parts: []WordPart{
6501 {
6502 Part: &tk[4],
6503 Tokens: tk[4:5],
6504 },
6505 },
6506 Tokens: tk[4:5],
6507 },
6508 Tokens: tk[2:5],
6509 }
6510 }},
6511 {"[[ ! -z a ]]", func(t *test, tk Tokens) { // 43
6512 t.Output = Tests{
6513 Not: true,
6514 Test: TestOperatorStringIsZero,
6515 Word: &Word{
6516 Parts: []WordPart{
6517 {
6518 Part: &tk[6],
6519 Tokens: tk[6:7],
6520 },
6521 },
6522 Tokens: tk[6:7],
6523 },
6524 Tokens: tk[2:7],
6525 }
6526 }},
6527 {"[[ (a = b) ]]", func(t *test, tk Tokens) { // 44
6528 t.Output = Tests{
6529 Parens: &Tests{
6530 Test: TestOperatorStringsEqual,
6531 Word: &Word{
6532 Parts: []WordPart{
6533 {
6534 Part: &tk[3],
6535 Tokens: tk[3:4],
6536 },
6537 },
6538 Tokens: tk[3:4],
6539 },
6540 Pattern: &Pattern{
6541 Parts: []WordPart{
6542 {
6543 Part: &tk[7],
6544 Tokens: tk[7:8],
6545 },
6546 },
6547 Tokens: tk[7:8],
6548 },
6549 Tokens: tk[3:8],
6550 },
6551 Tokens: tk[2:9],
6552 }
6553 }},
6554 {"[[ a ]]", func(t *test, tk Tokens) { // 45
6555 t.Output = Tests{
6556 Test: TestOperatorNone,
6557 Word: &Word{
6558 Parts: []WordPart{
6559 {
6560 Part: &tk[2],
6561 Tokens: tk[2:3],
6562 },
6563 },
6564 Tokens: tk[2:3],
6565 },
6566 Tokens: tk[2:3],
6567 }
6568 }},
6569 {"[[ a || b ]]", func(t *test, tk Tokens) { // 46
6570 t.Output = Tests{
6571 Test: TestOperatorNone,
6572 Word: &Word{
6573 Parts: []WordPart{
6574 {
6575 Part: &tk[2],
6576 Tokens: tk[2:3],
6577 },
6578 },
6579 Tokens: tk[2:3],
6580 },
6581 LogicalOperator: LogicalOperatorOr,
6582 Tests: &Tests{
6583 Word: &Word{
6584 Parts: []WordPart{
6585 {
6586 Part: &tk[6],
6587 Tokens: tk[6:7],
6588 },
6589 },
6590 Tokens: tk[6:7],
6591 },
6592 Tokens: tk[6:7],
6593 },
6594 Tokens: tk[2:7],
6595 }
6596 }},
6597 {"[[ a && b ]]", func(t *test, tk Tokens) { // 47
6598 t.Output = Tests{
6599 Test: TestOperatorNone,
6600 Word: &Word{
6601 Parts: []WordPart{
6602 {
6603 Part: &tk[2],
6604 Tokens: tk[2:3],
6605 },
6606 },
6607 Tokens: tk[2:3],
6608 },
6609 LogicalOperator: LogicalOperatorAnd,
6610 Tests: &Tests{
6611 Word: &Word{
6612 Parts: []WordPart{
6613 {
6614 Part: &tk[6],
6615 Tokens: tk[6:7],
6616 },
6617 },
6618 Tokens: tk[6:7],
6619 },
6620 Tokens: tk[6:7],
6621 },
6622 Tokens: tk[2:7],
6623 }
6624 }},
6625 {"[[\n#comment\na = b ]]", func(t *test, tk Tokens) { // 48
6626 t.Output = Tests{
6627 Test: TestOperatorStringsEqual,
6628 Word: &Word{
6629 Parts: []WordPart{
6630 {
6631 Part: &tk[4],
6632 Tokens: tk[4:5],
6633 },
6634 },
6635 Tokens: tk[4:5],
6636 },
6637 Pattern: &Pattern{
6638 Parts: []WordPart{
6639 {
6640 Part: &tk[8],
6641 Tokens: tk[8:9],
6642 },
6643 },
6644 Tokens: tk[8:9],
6645 },
6646 Comments: [5]Comments{{tk[2]}},
6647 Tokens: tk[2:9],
6648 }
6649 }},
6650 {"[[ a = b # comment\n ]]", func(t *test, tk Tokens) { // 49
6651 t.Output = Tests{
6652 Test: TestOperatorStringsEqual,
6653 Word: &Word{
6654 Parts: []WordPart{
6655 {
6656 Part: &tk[2],
6657 Tokens: tk[2:3],
6658 },
6659 },
6660 Tokens: tk[2:3],
6661 },
6662 Pattern: &Pattern{
6663 Parts: []WordPart{
6664 {
6665 Part: &tk[6],
6666 Tokens: tk[6:7],
6667 },
6668 },
6669 Tokens: tk[6:7],
6670 },
6671 Comments: [5]Comments{nil, nil, nil, nil, {tk[8]}},
6672 Tokens: tk[2:9],
6673 }
6674 }},
6675 {"[[ #comment A\n! #comment B\n-z a ]]", func(t *test, tk Tokens) { // 50
6676 t.Output = Tests{
6677 Not: true,
6678 Test: TestOperatorStringIsZero,
6679 Word: &Word{
6680 Parts: []WordPart{
6681 {
6682 Part: &tk[10],
6683 Tokens: tk[10:11],
6684 },
6685 },
6686 Tokens: tk[10:11],
6687 },
6688 Comments: [5]Comments{{tk[2]}, {tk[6]}},
6689 Tokens: tk[2:11],
6690 }
6691 }},
6692 {"[[ ( #comment A\n\n#comment B\na = b #comment C\n\n#comment D\n) ]]", func(t *test, tk Tokens) { // 51
6693 t.Output = Tests{
6694 Parens: &Tests{
6695 Test: TestOperatorStringsEqual,
6696 Word: &Word{
6697 Parts: []WordPart{
6698 {
6699 Part: &tk[8],
6700 Tokens: tk[8:9],
6701 },
6702 },
6703 Tokens: tk[8:9],
6704 },
6705 Pattern: &Pattern{
6706 Parts: []WordPart{
6707 {
6708 Part: &tk[12],
6709 Tokens: tk[12:13],
6710 },
6711 },
6712 Tokens: tk[12:13],
6713 },
6714 Comments: [5]Comments{{tk[6]}, nil, nil, nil, {tk[14]}},
6715 Tokens: tk[6:15],
6716 },
6717 Comments: [5]Comments{nil, nil, {tk[4]}, {tk[16]}},
6718 Tokens: tk[2:19],
6719 }
6720 }},
6721 {"[[ -a $(||) ]]", func(t *test, tk Tokens) { // 52
6722 t.Err = Error{
6723 Err: Error{
6724 Err: Error{
6725 Err: Error{
6726 Err: Error{
6727 Err: Error{
6728 Err: Error{
6729 Err: Error{
6730 Err: Error{
6731 Err: Error{
6732 Err: ErrMissingWord,
6733 Parsing: "Command",
6734 Token: tk[5],
6735 },
6736 Parsing: "CommandOrCompound",
6737 Token: tk[5],
6738 },
6739 Parsing: "Pipeline",
6740 Token: tk[5],
6741 },
6742 Parsing: "Statement",
6743 Token: tk[5],
6744 },
6745 Parsing: "Line",
6746 Token: tk[5],
6747 },
6748 Parsing: "File",
6749 Token: tk[5],
6750 },
6751 Parsing: "CommandSubstitution",
6752 Token: tk[5],
6753 },
6754 Parsing: "WordPart",
6755 Token: tk[4],
6756 },
6757 Parsing: "Word",
6758 Token: tk[4],
6759 },
6760 Parsing: "Tests",
6761 Token: tk[4],
6762 }
6763 }},
6764 {"[[ $(||) = a ]]", func(t *test, tk Tokens) { // 53
6765 t.Err = Error{
6766 Err: Error{
6767 Err: Error{
6768 Err: Error{
6769 Err: Error{
6770 Err: Error{
6771 Err: Error{
6772 Err: Error{
6773 Err: Error{
6774 Err: Error{
6775 Err: ErrMissingWord,
6776 Parsing: "Command",
6777 Token: tk[3],
6778 },
6779 Parsing: "CommandOrCompound",
6780 Token: tk[3],
6781 },
6782 Parsing: "Pipeline",
6783 Token: tk[3],
6784 },
6785 Parsing: "Statement",
6786 Token: tk[3],
6787 },
6788 Parsing: "Line",
6789 Token: tk[3],
6790 },
6791 Parsing: "File",
6792 Token: tk[3],
6793 },
6794 Parsing: "CommandSubstitution",
6795 Token: tk[3],
6796 },
6797 Parsing: "WordPart",
6798 Token: tk[2],
6799 },
6800 Parsing: "Word",
6801 Token: tk[2],
6802 },
6803 Parsing: "Tests",
6804 Token: tk[2],
6805 }
6806 }},
6807 {"[[ a = $(||) ]]", func(t *test, tk Tokens) { // 54
6808 t.Err = Error{
6809 Err: Error{
6810 Err: Error{
6811 Err: Error{
6812 Err: Error{
6813 Err: Error{
6814 Err: Error{
6815 Err: Error{
6816 Err: Error{
6817 Err: Error{
6818 Err: ErrMissingWord,
6819 Parsing: "Command",
6820 Token: tk[7],
6821 },
6822 Parsing: "CommandOrCompound",
6823 Token: tk[7],
6824 },
6825 Parsing: "Pipeline",
6826 Token: tk[7],
6827 },
6828 Parsing: "Statement",
6829 Token: tk[7],
6830 },
6831 Parsing: "Line",
6832 Token: tk[7],
6833 },
6834 Parsing: "File",
6835 Token: tk[7],
6836 },
6837 Parsing: "CommandSubstitution",
6838 Token: tk[7],
6839 },
6840 Parsing: "WordPart",
6841 Token: tk[6],
6842 },
6843 Parsing: "Pattern",
6844 Token: tk[6],
6845 },
6846 Parsing: "Tests",
6847 Token: tk[6],
6848 }
6849 }},
6850 {"[[ a -eq $(||) ]]", func(t *test, tk Tokens) { // 55
6851 t.Err = Error{
6852 Err: Error{
6853 Err: Error{
6854 Err: Error{
6855 Err: Error{
6856 Err: Error{
6857 Err: Error{
6858 Err: Error{
6859 Err: Error{
6860 Err: Error{
6861 Err: ErrMissingWord,
6862 Parsing: "Command",
6863 Token: tk[7],
6864 },
6865 Parsing: "CommandOrCompound",
6866 Token: tk[7],
6867 },
6868 Parsing: "Pipeline",
6869 Token: tk[7],
6870 },
6871 Parsing: "Statement",
6872 Token: tk[7],
6873 },
6874 Parsing: "Line",
6875 Token: tk[7],
6876 },
6877 Parsing: "File",
6878 Token: tk[7],
6879 },
6880 Parsing: "CommandSubstitution",
6881 Token: tk[7],
6882 },
6883 Parsing: "WordPart",
6884 Token: tk[6],
6885 },
6886 Parsing: "Pattern",
6887 Token: tk[6],
6888 },
6889 Parsing: "Tests",
6890 Token: tk[6],
6891 }
6892 }},
6893 {"[[ ( $(||) ) ]]", func(t *test, tk Tokens) { // 56
6894 t.Err = Error{
6895 Err: Error{
6896 Err: Error{
6897 Err: Error{
6898 Err: Error{
6899 Err: Error{
6900 Err: Error{
6901 Err: Error{
6902 Err: Error{
6903 Err: Error{
6904 Err: Error{
6905 Err: ErrMissingWord,
6906 Parsing: "Command",
6907 Token: tk[5],
6908 },
6909 Parsing: "CommandOrCompound",
6910 Token: tk[5],
6911 },
6912 Parsing: "Pipeline",
6913 Token: tk[5],
6914 },
6915 Parsing: "Statement",
6916 Token: tk[5],
6917 },
6918 Parsing: "Line",
6919 Token: tk[5],
6920 },
6921 Parsing: "File",
6922 Token: tk[5],
6923 },
6924 Parsing: "CommandSubstitution",
6925 Token: tk[5],
6926 },
6927 Parsing: "WordPart",
6928 Token: tk[4],
6929 },
6930 Parsing: "Word",
6931 Token: tk[4],
6932 },
6933 Parsing: "Tests",
6934 Token: tk[4],
6935 },
6936 Parsing: "Tests",
6937 Token: tk[4],
6938 }
6939 }},
6940 {"[[ ( a b ) ]]", func(t *test, tk Tokens) { // 57
6941 t.Err = Error{
6942 Err: ErrMissingClosingParen,
6943 Parsing: "Tests",
6944 Token: tk[6],
6945 }
6946 }},
6947 {"[[ a || $(||) ]]", func(t *test, tk Tokens) { // 58
6948 t.Err = Error{
6949 Err: Error{
6950 Err: Error{
6951 Err: Error{
6952 Err: Error{
6953 Err: Error{
6954 Err: Error{
6955 Err: Error{
6956 Err: Error{
6957 Err: Error{
6958 Err: Error{
6959 Err: ErrMissingWord,
6960 Parsing: "Command",
6961 Token: tk[7],
6962 },
6963 Parsing: "CommandOrCompound",
6964 Token: tk[7],
6965 },
6966 Parsing: "Pipeline",
6967 Token: tk[7],
6968 },
6969 Parsing: "Statement",
6970 Token: tk[7],
6971 },
6972 Parsing: "Line",
6973 Token: tk[7],
6974 },
6975 Parsing: "File",
6976 Token: tk[7],
6977 },
6978 Parsing: "CommandSubstitution",
6979 Token: tk[7],
6980 },
6981 Parsing: "WordPart",
6982 Token: tk[6],
6983 },
6984 Parsing: "Word",
6985 Token: tk[6],
6986 },
6987 Parsing: "Tests",
6988 Token: tk[6],
6989 },
6990 Parsing: "Tests",
6991 Token: tk[6],
6992 }
6993 }},
6994 }, func(t *test) (Type, error) {
6995 var ts Tests
6996
6997 t.Parser.Tokens = t.Parser.Tokens[2:2]
6998 err := ts.parse(t.Parser)
6999
7000 return ts, err
7001 })
7002 }
7003
7004 func TestPattern(t *testing.T) {
7005 doTests(t, []sourceFn{
7006 {"[[ z = a ]]", func(t *test, tk Tokens) { // 1
7007 t.Output = Pattern{
7008 Parts: []WordPart{
7009 {
7010 Part: &tk[6],
7011 Tokens: tk[6:7],
7012 },
7013 },
7014 Tokens: tk[6:7],
7015 }
7016 }},
7017 {"[[ z = a$b ]]", func(t *test, tk Tokens) { // 2
7018 t.Output = Pattern{
7019 Parts: []WordPart{
7020 {
7021 Part: &tk[6],
7022 Tokens: tk[6:7],
7023 },
7024 {
7025 Part: &tk[7],
7026 Tokens: tk[7:8],
7027 },
7028 },
7029 Tokens: tk[6:8],
7030 }
7031 }},
7032 {"[[ z = $(||) ]]", func(t *test, tk Tokens) { // 3
7033 t.Err = Error{
7034 Err: Error{
7035 Err: Error{
7036 Err: Error{
7037 Err: Error{
7038 Err: Error{
7039 Err: Error{
7040 Err: Error{
7041 Err: Error{
7042 Err: ErrMissingWord,
7043 Parsing: "Command",
7044 Token: tk[7],
7045 },
7046 Parsing: "CommandOrCompound",
7047 Token: tk[7],
7048 },
7049 Parsing: "Pipeline",
7050 Token: tk[7],
7051 },
7052 Parsing: "Statement",
7053 Token: tk[7],
7054 },
7055 Parsing: "Line",
7056 Token: tk[7],
7057 },
7058 Parsing: "File",
7059 Token: tk[7],
7060 },
7061 Parsing: "CommandSubstitution",
7062 Token: tk[7],
7063 },
7064 Parsing: "WordPart",
7065 Token: tk[6],
7066 },
7067 Parsing: "Pattern",
7068 Token: tk[6],
7069 }
7070 }},
7071 }, func(t *test) (Type, error) {
7072 var p Pattern
7073
7074 t.Parser.Tokens = t.Parser.Tokens[6:6]
7075 err := p.parse(t.Parser)
7076
7077 return p, err
7078 })
7079 }
7080
7081 func TestGroupingCompound(t *testing.T) {
7082 doTests(t, []sourceFn{
7083 {"(a)", func(t *test, tk Tokens) { // 1
7084 t.Output = GroupingCompound{
7085 SubShell: true,
7086 File: File{
7087 Lines: []Line{
7088 {
7089 Statements: []Statement{
7090 {
7091 Pipeline: Pipeline{
7092 CommandOrCompound: CommandOrCompound{
7093 Command: &Command{
7094 AssignmentsOrWords: []AssignmentOrWord{
7095 {
7096 Word: &Word{
7097 Parts: []WordPart{
7098 {
7099 Part: &tk[1],
7100 Tokens: tk[1:2],
7101 },
7102 },
7103 Tokens: tk[1:2],
7104 },
7105 Tokens: tk[1:2],
7106 },
7107 },
7108 Tokens: tk[1:2],
7109 },
7110 Tokens: tk[1:2],
7111 },
7112 Tokens: tk[1:2],
7113 },
7114 Tokens: tk[1:2],
7115 },
7116 },
7117 Tokens: tk[1:2],
7118 },
7119 },
7120 Tokens: tk[1:2],
7121 },
7122 Tokens: tk[:3],
7123 }
7124 }},
7125 {"( a )", func(t *test, tk Tokens) { // 2
7126 t.Output = GroupingCompound{
7127 SubShell: true,
7128 File: File{
7129 Lines: []Line{
7130 {
7131 Statements: []Statement{
7132 {
7133 Pipeline: Pipeline{
7134 CommandOrCompound: CommandOrCompound{
7135 Command: &Command{
7136 AssignmentsOrWords: []AssignmentOrWord{
7137 {
7138 Word: &Word{
7139 Parts: []WordPart{
7140 {
7141 Part: &tk[2],
7142 Tokens: tk[2:3],
7143 },
7144 },
7145 Tokens: tk[2:3],
7146 },
7147 Tokens: tk[2:3],
7148 },
7149 },
7150 Tokens: tk[2:3],
7151 },
7152 Tokens: tk[2:3],
7153 },
7154 Tokens: tk[2:3],
7155 },
7156 Tokens: tk[2:3],
7157 },
7158 },
7159 Tokens: tk[2:3],
7160 },
7161 },
7162 Tokens: tk[2:3],
7163 },
7164 Tokens: tk[:5],
7165 }
7166 }},
7167 {"(\na\n)", func(t *test, tk Tokens) { // 3
7168 t.Output = GroupingCompound{
7169 SubShell: true,
7170 File: File{
7171 Lines: []Line{
7172 {
7173 Statements: []Statement{
7174 {
7175 Pipeline: Pipeline{
7176 CommandOrCompound: CommandOrCompound{
7177 Command: &Command{
7178 AssignmentsOrWords: []AssignmentOrWord{
7179 {
7180 Word: &Word{
7181 Parts: []WordPart{
7182 {
7183 Part: &tk[2],
7184 Tokens: tk[2:3],
7185 },
7186 },
7187 Tokens: tk[2:3],
7188 },
7189 Tokens: tk[2:3],
7190 },
7191 },
7192 Tokens: tk[2:3],
7193 },
7194 Tokens: tk[2:3],
7195 },
7196 Tokens: tk[2:3],
7197 },
7198 Tokens: tk[2:3],
7199 },
7200 },
7201 Tokens: tk[2:3],
7202 },
7203 },
7204 Tokens: tk[2:3],
7205 },
7206 Tokens: tk[:5],
7207 }
7208 }},
7209 {"(\na;\n)", func(t *test, tk Tokens) { // 4
7210 t.Output = GroupingCompound{
7211 SubShell: true,
7212 File: File{
7213 Lines: []Line{
7214 {
7215 Statements: []Statement{
7216 {
7217 Pipeline: Pipeline{
7218 CommandOrCompound: CommandOrCompound{
7219 Command: &Command{
7220 AssignmentsOrWords: []AssignmentOrWord{
7221 {
7222 Word: &Word{
7223 Parts: []WordPart{
7224 {
7225 Part: &tk[2],
7226 Tokens: tk[2:3],
7227 },
7228 },
7229 Tokens: tk[2:3],
7230 },
7231 Tokens: tk[2:3],
7232 },
7233 },
7234 Tokens: tk[2:3],
7235 },
7236 Tokens: tk[2:3],
7237 },
7238 Tokens: tk[2:3],
7239 },
7240 Tokens: tk[2:4],
7241 },
7242 },
7243 Tokens: tk[2:4],
7244 },
7245 },
7246 Tokens: tk[2:4],
7247 },
7248 Tokens: tk[:6],
7249 }
7250 }},
7251 {"{\na\n}", func(t *test, tk Tokens) { // 5
7252 t.Output = GroupingCompound{
7253 File: File{
7254 Lines: []Line{
7255 {
7256 Statements: []Statement{
7257 {
7258 Pipeline: Pipeline{
7259 CommandOrCompound: CommandOrCompound{
7260 Command: &Command{
7261 AssignmentsOrWords: []AssignmentOrWord{
7262 {
7263 Word: &Word{
7264 Parts: []WordPart{
7265 {
7266 Part: &tk[2],
7267 Tokens: tk[2:3],
7268 },
7269 },
7270 Tokens: tk[2:3],
7271 },
7272 Tokens: tk[2:3],
7273 },
7274 },
7275 Tokens: tk[2:3],
7276 },
7277 Tokens: tk[2:3],
7278 },
7279 Tokens: tk[2:3],
7280 },
7281 Tokens: tk[2:3],
7282 },
7283 },
7284 Tokens: tk[2:3],
7285 },
7286 },
7287 Tokens: tk[2:3],
7288 },
7289 Tokens: tk[:5],
7290 }
7291 }},
7292 {"{ a; }", func(t *test, tk Tokens) { // 6
7293 t.Output = GroupingCompound{
7294 File: File{
7295 Lines: []Line{
7296 {
7297 Statements: []Statement{
7298 {
7299 Pipeline: Pipeline{
7300 CommandOrCompound: CommandOrCompound{
7301 Command: &Command{
7302 AssignmentsOrWords: []AssignmentOrWord{
7303 {
7304 Word: &Word{
7305 Parts: []WordPart{
7306 {
7307 Part: &tk[2],
7308 Tokens: tk[2:3],
7309 },
7310 },
7311 Tokens: tk[2:3],
7312 },
7313 Tokens: tk[2:3],
7314 },
7315 },
7316 Tokens: tk[2:3],
7317 },
7318 Tokens: tk[2:3],
7319 },
7320 Tokens: tk[2:3],
7321 },
7322 Tokens: tk[2:4],
7323 },
7324 },
7325 Tokens: tk[2:4],
7326 },
7327 },
7328 Tokens: tk[2:4],
7329 },
7330 Tokens: tk[:6],
7331 }
7332 }},
7333 {"( # comment A\n\n# comment B\na # comment C\n\n# comment D\n)", func(t *test, tk Tokens) { // 7
7334 t.Output = GroupingCompound{
7335 SubShell: true,
7336 File: File{
7337 Lines: []Line{
7338 {
7339 Statements: []Statement{
7340 {
7341 Pipeline: Pipeline{
7342 CommandOrCompound: CommandOrCompound{
7343 Command: &Command{
7344 AssignmentsOrWords: []AssignmentOrWord{
7345 {
7346 Word: &Word{
7347 Parts: []WordPart{
7348 {
7349 Part: &tk[6],
7350 Tokens: tk[6:7],
7351 },
7352 },
7353 Tokens: tk[6:7],
7354 },
7355 Tokens: tk[6:7],
7356 },
7357 },
7358 Tokens: tk[6:7],
7359 },
7360 Tokens: tk[6:7],
7361 },
7362 Tokens: tk[6:7],
7363 },
7364 Tokens: tk[6:7],
7365 },
7366 },
7367 Comments: [2]Comments{{tk[4]}, {tk[8]}},
7368 Tokens: tk[4:9],
7369 },
7370 },
7371 Comments: [2]Comments{{tk[2]}, {tk[10]}},
7372 Tokens: tk[2:11],
7373 },
7374 Tokens: tk[:13],
7375 }
7376 }},
7377 {"{ # comment A\n\n# comment B\na # comment C\n\n# comment D\n}", func(t *test, tk Tokens) { // 8
7378 t.Output = GroupingCompound{
7379 File: File{
7380 Lines: []Line{
7381 {
7382 Statements: []Statement{
7383 {
7384 Pipeline: Pipeline{
7385 CommandOrCompound: CommandOrCompound{
7386 Command: &Command{
7387 AssignmentsOrWords: []AssignmentOrWord{
7388 {
7389 Word: &Word{
7390 Parts: []WordPart{
7391 {
7392 Part: &tk[6],
7393 Tokens: tk[6:7],
7394 },
7395 },
7396 Tokens: tk[6:7],
7397 },
7398 Tokens: tk[6:7],
7399 },
7400 },
7401 Tokens: tk[6:7],
7402 },
7403 Tokens: tk[6:7],
7404 },
7405 Tokens: tk[6:7],
7406 },
7407 Tokens: tk[6:7],
7408 },
7409 },
7410 Comments: [2]Comments{{tk[4]}, {tk[8]}},
7411 Tokens: tk[4:9],
7412 },
7413 },
7414 Comments: [2]Comments{{tk[2]}, {tk[10]}},
7415 Tokens: tk[2:11],
7416 },
7417 Tokens: tk[:13],
7418 }
7419 }},
7420 {"(||)", func(t *test, tk Tokens) { // 9
7421 t.Err = Error{
7422 Err: Error{
7423 Err: Error{
7424 Err: Error{
7425 Err: Error{
7426 Err: Error{
7427 Err: Error{
7428 Err: ErrMissingWord,
7429 Parsing: "Command",
7430 Token: tk[1],
7431 },
7432 Parsing: "CommandOrCompound",
7433 Token: tk[1],
7434 },
7435 Parsing: "Pipeline",
7436 Token: tk[1],
7437 },
7438 Parsing: "Statement",
7439 Token: tk[1],
7440 },
7441 Parsing: "Line",
7442 Token: tk[1],
7443 },
7444 Parsing: "File",
7445 Token: tk[1],
7446 },
7447 Parsing: "GroupingCompound",
7448 Token: tk[1],
7449 }
7450 }},
7451 }, func(t *test) (Type, error) {
7452 var g GroupingCompound
7453
7454 err := g.parse(t.Parser)
7455
7456 return g, err
7457 })
7458 }
7459
7460 func TestFunctionCompound(t *testing.T) {
7461 doTests(t, []sourceFn{
7462 {"function a() { b; }", func(t *test, tk Tokens) { // 1
7463 t.Output = FunctionCompound{
7464 HasKeyword: true,
7465 Identifier: &tk[2],
7466 Body: Compound{
7467 GroupingCompound: &GroupingCompound{
7468 File: File{
7469 Lines: []Line{
7470 {
7471 Statements: []Statement{
7472 {
7473 Pipeline: Pipeline{
7474 CommandOrCompound: CommandOrCompound{
7475 Command: &Command{
7476 AssignmentsOrWords: []AssignmentOrWord{
7477 {
7478 Word: &Word{
7479 Parts: []WordPart{
7480 {
7481 Part: &tk[8],
7482 Tokens: tk[8:9],
7483 },
7484 },
7485 Tokens: tk[8:9],
7486 },
7487 Tokens: tk[8:9],
7488 },
7489 },
7490 Tokens: tk[8:9],
7491 },
7492 Tokens: tk[8:9],
7493 },
7494 Tokens: tk[8:9],
7495 },
7496 Tokens: tk[8:10],
7497 },
7498 },
7499 Tokens: tk[8:10],
7500 },
7501 },
7502 Tokens: tk[8:10],
7503 },
7504 Tokens: tk[6:12],
7505 },
7506 Tokens: tk[6:12],
7507 },
7508 Tokens: tk[:12],
7509 }
7510 }},
7511 {"function a ( ) { b; }", func(t *test, tk Tokens) { // 2
7512 t.Output = FunctionCompound{
7513 HasKeyword: true,
7514 Identifier: &tk[2],
7515 Body: Compound{
7516 GroupingCompound: &GroupingCompound{
7517 File: File{
7518 Lines: []Line{
7519 {
7520 Statements: []Statement{
7521 {
7522 Pipeline: Pipeline{
7523 CommandOrCompound: CommandOrCompound{
7524 Command: &Command{
7525 AssignmentsOrWords: []AssignmentOrWord{
7526 {
7527 Word: &Word{
7528 Parts: []WordPart{
7529 {
7530 Part: &tk[10],
7531 Tokens: tk[10:11],
7532 },
7533 },
7534 Tokens: tk[10:11],
7535 },
7536 Tokens: tk[10:11],
7537 },
7538 },
7539 Tokens: tk[10:11],
7540 },
7541 Tokens: tk[10:11],
7542 },
7543 Tokens: tk[10:11],
7544 },
7545 Tokens: tk[10:12],
7546 },
7547 },
7548 Tokens: tk[10:12],
7549 },
7550 },
7551 Tokens: tk[10:12],
7552 },
7553 Tokens: tk[8:14],
7554 },
7555 Tokens: tk[8:14],
7556 },
7557 Tokens: tk[:14],
7558 }
7559 }},
7560 {"a() { b; }", func(t *test, tk Tokens) { // 3
7561 t.Output = FunctionCompound{
7562 Identifier: &tk[0],
7563 Body: Compound{
7564 GroupingCompound: &GroupingCompound{
7565 File: File{
7566 Lines: []Line{
7567 {
7568 Statements: []Statement{
7569 {
7570 Pipeline: Pipeline{
7571 CommandOrCompound: CommandOrCompound{
7572 Command: &Command{
7573 AssignmentsOrWords: []AssignmentOrWord{
7574 {
7575 Word: &Word{
7576 Parts: []WordPart{
7577 {
7578 Part: &tk[6],
7579 Tokens: tk[6:7],
7580 },
7581 },
7582 Tokens: tk[6:7],
7583 },
7584 Tokens: tk[6:7],
7585 },
7586 },
7587 Tokens: tk[6:7],
7588 },
7589 Tokens: tk[6:7],
7590 },
7591 Tokens: tk[6:7],
7592 },
7593 Tokens: tk[6:8],
7594 },
7595 },
7596 Tokens: tk[6:8],
7597 },
7598 },
7599 Tokens: tk[6:8],
7600 },
7601 Tokens: tk[4:10],
7602 },
7603 Tokens: tk[4:10],
7604 },
7605 Tokens: tk[:10],
7606 }
7607 }},
7608 {"a ( ) { b; }", func(t *test, tk Tokens) { // 4
7609 t.Output = FunctionCompound{
7610 Identifier: &tk[0],
7611 Body: Compound{
7612 GroupingCompound: &GroupingCompound{
7613 File: File{
7614 Lines: []Line{
7615 {
7616 Statements: []Statement{
7617 {
7618 Pipeline: Pipeline{
7619 CommandOrCompound: CommandOrCompound{
7620 Command: &Command{
7621 AssignmentsOrWords: []AssignmentOrWord{
7622 {
7623 Word: &Word{
7624 Parts: []WordPart{
7625 {
7626 Part: &tk[8],
7627 Tokens: tk[8:9],
7628 },
7629 },
7630 Tokens: tk[8:9],
7631 },
7632 Tokens: tk[8:9],
7633 },
7634 },
7635 Tokens: tk[8:9],
7636 },
7637 Tokens: tk[8:9],
7638 },
7639 Tokens: tk[8:9],
7640 },
7641 Tokens: tk[8:10],
7642 },
7643 },
7644 Tokens: tk[8:10],
7645 },
7646 },
7647 Tokens: tk[8:10],
7648 },
7649 Tokens: tk[6:12],
7650 },
7651 Tokens: tk[6:12],
7652 },
7653 Tokens: tk[:12],
7654 }
7655 }},
7656 {"function a # comment\n{ b; }", func(t *test, tk Tokens) { // 5
7657 t.Output = FunctionCompound{
7658 HasKeyword: true,
7659 Identifier: &tk[2],
7660 Body: Compound{
7661 GroupingCompound: &GroupingCompound{
7662 File: File{
7663 Lines: []Line{
7664 {
7665 Statements: []Statement{
7666 {
7667 Pipeline: Pipeline{
7668 CommandOrCompound: CommandOrCompound{
7669 Command: &Command{
7670 AssignmentsOrWords: []AssignmentOrWord{
7671 {
7672 Word: &Word{
7673 Parts: []WordPart{
7674 {
7675 Part: &tk[8],
7676 Tokens: tk[8:9],
7677 },
7678 },
7679 Tokens: tk[8:9],
7680 },
7681 Tokens: tk[8:9],
7682 },
7683 },
7684 Tokens: tk[8:9],
7685 },
7686 Tokens: tk[8:9],
7687 },
7688 Tokens: tk[8:9],
7689 },
7690 Tokens: tk[8:10],
7691 },
7692 },
7693 Tokens: tk[8:10],
7694 },
7695 },
7696 Tokens: tk[8:10],
7697 },
7698 Tokens: tk[6:12],
7699 },
7700 Tokens: tk[6:12],
7701 },
7702 Comments: Comments{tk[4]},
7703 Tokens: tk[:12],
7704 }
7705 }},
7706 {"function a() # comment\n{ b; }", func(t *test, tk Tokens) { // 6
7707 t.Output = FunctionCompound{
7708 HasKeyword: true,
7709 Identifier: &tk[2],
7710 Body: Compound{
7711 GroupingCompound: &GroupingCompound{
7712 File: File{
7713 Lines: []Line{
7714 {
7715 Statements: []Statement{
7716 {
7717 Pipeline: Pipeline{
7718 CommandOrCompound: CommandOrCompound{
7719 Command: &Command{
7720 AssignmentsOrWords: []AssignmentOrWord{
7721 {
7722 Word: &Word{
7723 Parts: []WordPart{
7724 {
7725 Part: &tk[10],
7726 Tokens: tk[10:11],
7727 },
7728 },
7729 Tokens: tk[10:11],
7730 },
7731 Tokens: tk[10:11],
7732 },
7733 },
7734 Tokens: tk[10:11],
7735 },
7736 Tokens: tk[10:11],
7737 },
7738 Tokens: tk[10:11],
7739 },
7740 Tokens: tk[10:12],
7741 },
7742 },
7743 Tokens: tk[10:12],
7744 },
7745 },
7746 Tokens: tk[10:12],
7747 },
7748 Tokens: tk[8:14],
7749 },
7750 Tokens: tk[8:14],
7751 },
7752 Comments: Comments{tk[6]},
7753 Tokens: tk[:14],
7754 }
7755 }},
7756 {"a() #comment\n{ b; }", func(t *test, tk Tokens) { // 7
7757 t.Output = FunctionCompound{
7758 Identifier: &tk[0],
7759 Body: Compound{
7760 GroupingCompound: &GroupingCompound{
7761 File: File{
7762 Lines: []Line{
7763 {
7764 Statements: []Statement{
7765 {
7766 Pipeline: Pipeline{
7767 CommandOrCompound: CommandOrCompound{
7768 Command: &Command{
7769 AssignmentsOrWords: []AssignmentOrWord{
7770 {
7771 Word: &Word{
7772 Parts: []WordPart{
7773 {
7774 Part: &tk[8],
7775 Tokens: tk[8:9],
7776 },
7777 },
7778 Tokens: tk[8:9],
7779 },
7780 Tokens: tk[8:9],
7781 },
7782 },
7783 Tokens: tk[8:9],
7784 },
7785 Tokens: tk[8:9],
7786 },
7787 Tokens: tk[8:9],
7788 },
7789 Tokens: tk[8:10],
7790 },
7791 },
7792 Tokens: tk[8:10],
7793 },
7794 },
7795 Tokens: tk[8:10],
7796 },
7797 Tokens: tk[6:12],
7798 },
7799 Tokens: tk[6:12],
7800 },
7801 Comments: Comments{tk[4]},
7802 Tokens: tk[:12],
7803 }
7804 }},
7805 {"function a() { || }", func(t *test, tk Tokens) { // 8
7806 t.Err = Error{
7807 Err: Error{
7808 Err: Error{
7809 Err: Error{
7810 Err: Error{
7811 Err: Error{
7812 Err: Error{
7813 Err: Error{
7814 Err: Error{
7815 Err: ErrMissingWord,
7816 Parsing: "Command",
7817 Token: tk[8],
7818 },
7819 Parsing: "CommandOrCompound",
7820 Token: tk[8],
7821 },
7822 Parsing: "Pipeline",
7823 Token: tk[8],
7824 },
7825 Parsing: "Statement",
7826 Token: tk[8],
7827 },
7828 Parsing: "Line",
7829 Token: tk[8],
7830 },
7831 Parsing: "File",
7832 Token: tk[8],
7833 },
7834 Parsing: "GroupingCompound",
7835 Token: tk[8],
7836 },
7837 Parsing: "Compound",
7838 Token: tk[6],
7839 },
7840 Parsing: "FunctionCompound",
7841 Token: tk[6],
7842 }
7843 }},
7844 }, func(t *test) (Type, error) {
7845 var f FunctionCompound
7846
7847 err := f.parse(t.Parser)
7848
7849 return f, err
7850 })
7851 }
7852
7853 func TestCommandSubstitution(t *testing.T) {
7854 doTests(t, []sourceFn{
7855 {"$()", func(t *test, tk Tokens) { // 1
7856 t.Output = CommandSubstitution{
7857 SubstitutionType: SubstitutionNew,
7858 Command: File{
7859 Tokens: tk[1:1],
7860 },
7861 Tokens: tk[:2],
7862 }
7863 }},
7864 {"``", func(t *test, tk Tokens) { // 2
7865 t.Output = CommandSubstitution{
7866 SubstitutionType: SubstitutionBacktick,
7867 Backtick: &tk[0],
7868 Command: File{
7869 Tokens: tk[1:1],
7870 },
7871 Tokens: tk[:2],
7872 }
7873 }},
7874 {"<()", func(t *test, tk Tokens) { // 3
7875 t.Output = CommandSubstitution{
7876 SubstitutionType: SubstitutionProcessInput,
7877 Command: File{
7878 Tokens: tk[1:1],
7879 },
7880 Tokens: tk[:2],
7881 }
7882 }},
7883 {">()", func(t *test, tk Tokens) { // 4
7884 t.Output = CommandSubstitution{
7885 SubstitutionType: SubstitutionProcessOutput,
7886 Command: File{
7887 Tokens: tk[1:1],
7888 },
7889 Tokens: tk[:2],
7890 }
7891 }},
7892 {"$(``)", func(t *test, tk Tokens) { // 5
7893 t.Output = CommandSubstitution{
7894 SubstitutionType: SubstitutionNew,
7895 Command: File{
7896 Lines: []Line{
7897 {
7898 Statements: []Statement{
7899 {
7900 Pipeline: Pipeline{
7901 CommandOrCompound: CommandOrCompound{
7902 Command: &Command{
7903 AssignmentsOrWords: []AssignmentOrWord{
7904 {
7905 Word: &Word{
7906 Parts: []WordPart{
7907 {
7908 CommandSubstitution: &CommandSubstitution{
7909 SubstitutionType: SubstitutionBacktick,
7910 Backtick: &tk[1],
7911 Command: File{
7912 Tokens: tk[2:2],
7913 },
7914 Tokens: tk[1:3],
7915 },
7916 Tokens: tk[1:3],
7917 },
7918 },
7919 Tokens: tk[1:3],
7920 },
7921 Tokens: tk[1:3],
7922 },
7923 },
7924 Tokens: tk[1:3],
7925 },
7926 Tokens: tk[1:3],
7927 },
7928 Tokens: tk[1:3],
7929 },
7930 Tokens: tk[1:3],
7931 },
7932 },
7933 Tokens: tk[1:3],
7934 },
7935 },
7936 Tokens: tk[1:3],
7937 },
7938 Tokens: tk[:4],
7939 }
7940 }},
7941 {"`\\`\\``", func(t *test, tk Tokens) { // 6
7942 t.Output = CommandSubstitution{
7943 SubstitutionType: SubstitutionBacktick,
7944 Backtick: &tk[0],
7945 Command: File{
7946 Lines: []Line{
7947 {
7948 Statements: []Statement{
7949 {
7950 Pipeline: Pipeline{
7951 CommandOrCompound: CommandOrCompound{
7952 Command: &Command{
7953 AssignmentsOrWords: []AssignmentOrWord{
7954 {
7955 Word: &Word{
7956 Parts: []WordPart{
7957 {
7958 CommandSubstitution: &CommandSubstitution{
7959 SubstitutionType: SubstitutionBacktick,
7960 Backtick: &tk[1],
7961 Command: File{
7962 Tokens: tk[2:2],
7963 },
7964 Tokens: tk[1:3],
7965 },
7966 Tokens: tk[1:3],
7967 },
7968 },
7969 Tokens: tk[1:3],
7970 },
7971 Tokens: tk[1:3],
7972 },
7973 },
7974 Tokens: tk[1:3],
7975 },
7976 Tokens: tk[1:3],
7977 },
7978 Tokens: tk[1:3],
7979 },
7980 Tokens: tk[1:3],
7981 },
7982 },
7983 Tokens: tk[1:3],
7984 },
7985 },
7986 Tokens: tk[1:3],
7987 },
7988 Tokens: tk[:4],
7989 }
7990 }},
7991 {"$(||)", func(t *test, tk Tokens) { // 7
7992 t.Err = Error{
7993 Err: Error{
7994 Err: Error{
7995 Err: Error{
7996 Err: Error{
7997 Err: Error{
7998 Err: Error{
7999 Err: ErrMissingWord,
8000 Parsing: "Command",
8001 Token: tk[1],
8002 },
8003 Parsing: "CommandOrCompound",
8004 Token: tk[1],
8005 },
8006 Parsing: "Pipeline",
8007 Token: tk[1],
8008 },
8009 Parsing: "Statement",
8010 Token: tk[1],
8011 },
8012 Parsing: "Line",
8013 Token: tk[1],
8014 },
8015 Parsing: "File",
8016 Token: tk[1],
8017 },
8018 Parsing: "CommandSubstitution",
8019 Token: tk[1],
8020 }
8021 }},
8022 }, func(t *test) (Type, error) {
8023 var c CommandSubstitution
8024
8025 err := c.parse(t.Parser)
8026
8027 return c, err
8028 })
8029 }
8030
8031 func TestArithmeticExpansion(t *testing.T) {
8032 doTests(t, []sourceFn{
8033 {"$((a))", func(t *test, tk Tokens) { // 1
8034 t.Output = ArithmeticExpansion{
8035 WordsAndOperators: []WordOrOperator{
8036 {
8037 Word: &Word{
8038 Parts: []WordPart{
8039 {
8040 Part: &tk[1],
8041 Tokens: tk[1:2],
8042 },
8043 },
8044 Tokens: tk[1:2],
8045 },
8046 Tokens: tk[1:2],
8047 },
8048 },
8049 Tokens: tk[:3],
8050 }
8051 }},
8052 {"(( a ))", func(t *test, tk Tokens) { // 2
8053 t.Output = ArithmeticExpansion{
8054 Expression: true,
8055 WordsAndOperators: []WordOrOperator{
8056 {
8057 Word: &Word{
8058 Parts: []WordPart{
8059 {
8060 Part: &tk[2],
8061 Tokens: tk[2:3],
8062 },
8063 },
8064 Tokens: tk[2:3],
8065 },
8066 Tokens: tk[2:3],
8067 },
8068 },
8069 Tokens: tk[:5],
8070 }
8071 }},
8072 {"$(( a ))", func(t *test, tk Tokens) { // 3
8073 t.Output = ArithmeticExpansion{
8074 WordsAndOperators: []WordOrOperator{
8075 {
8076 Word: &Word{
8077 Parts: []WordPart{
8078 {
8079 Part: &tk[2],
8080 Tokens: tk[2:3],
8081 },
8082 },
8083 Tokens: tk[2:3],
8084 },
8085 Tokens: tk[2:3],
8086 },
8087 },
8088 Tokens: tk[:5],
8089 }
8090 }},
8091 {"$(( a$b ))", func(t *test, tk Tokens) { // 4
8092 t.Output = ArithmeticExpansion{
8093 WordsAndOperators: []WordOrOperator{
8094 {
8095 Word: &Word{
8096 Parts: []WordPart{
8097 {
8098 Part: &tk[2],
8099 Tokens: tk[2:3],
8100 },
8101 {
8102 Part: &tk[3],
8103 Tokens: tk[3:4],
8104 },
8105 },
8106 Tokens: tk[2:4],
8107 },
8108 Tokens: tk[2:4],
8109 },
8110 },
8111 Tokens: tk[:6],
8112 }
8113 }},
8114 {"$((a+b))", func(t *test, tk Tokens) { // 5
8115 t.Output = ArithmeticExpansion{
8116 WordsAndOperators: []WordOrOperator{
8117 {
8118 Word: &Word{
8119 Parts: []WordPart{
8120 {
8121 Part: &tk[1],
8122 Tokens: tk[1:2],
8123 },
8124 },
8125 Tokens: tk[1:2],
8126 },
8127 Tokens: tk[1:2],
8128 },
8129 {
8130 Operator: &tk[2],
8131 Tokens: tk[2:3],
8132 },
8133 {
8134 Word: &Word{
8135 Parts: []WordPart{
8136 {
8137 Part: &tk[3],
8138 Tokens: tk[3:4],
8139 },
8140 },
8141 Tokens: tk[3:4],
8142 },
8143 Tokens: tk[3:4],
8144 },
8145 },
8146 Tokens: tk[:5],
8147 }
8148 }},
8149 {"$(($(||)))", func(t *test, tk Tokens) { // 6
8150 t.Err = Error{
8151 Err: Error{
8152 Err: Error{
8153 Err: Error{
8154 Err: Error{
8155 Err: Error{
8156 Err: Error{
8157 Err: Error{
8158 Err: Error{
8159 Err: Error{
8160 Err: Error{
8161 Err: ErrMissingWord,
8162 Parsing: "Command",
8163 Token: tk[2],
8164 },
8165 Parsing: "CommandOrCompound",
8166 Token: tk[2],
8167 },
8168 Parsing: "Pipeline",
8169 Token: tk[2],
8170 },
8171 Parsing: "Statement",
8172 Token: tk[2],
8173 },
8174 Parsing: "Line",
8175 Token: tk[2],
8176 },
8177 Parsing: "File",
8178 Token: tk[2],
8179 },
8180 Parsing: "CommandSubstitution",
8181 Token: tk[2],
8182 },
8183 Parsing: "WordPart",
8184 Token: tk[1],
8185 },
8186 Parsing: "Word",
8187 Token: tk[1],
8188 },
8189 Parsing: "WordOrOperator",
8190 Token: tk[1],
8191 },
8192 Parsing: "ArithmeticExpansion",
8193 Token: tk[1],
8194 }
8195 }},
8196 }, func(t *test) (Type, error) {
8197 var ae ArithmeticExpansion
8198
8199 err := ae.parse(t.Parser)
8200
8201 return ae, err
8202 })
8203 }
8204