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