bash - ast_word_test.go
1 package bash
2
3 import "testing"
4
5 func TestAssignmentOrWord(t *testing.T) {
6 doTests(t, []sourceFn{
7 {"a", func(t *test, tk Tokens) { // 1
8 t.Output = AssignmentOrWord{
9 Word: &Word{
10 Parts: []WordPart{
11 {
12 Part: &tk[0],
13 Tokens: tk[:1],
14 },
15 },
16 Tokens: tk[:1],
17 },
18 Tokens: tk[:1],
19 }
20 }},
21 {"a=b", func(t *test, tk Tokens) { // 2
22 t.Output = AssignmentOrWord{
23 Assignment: &Assignment{
24 Identifier: ParameterAssign{
25 Identifier: &tk[0],
26 Tokens: tk[:1],
27 },
28 Assignment: AssignmentAssign,
29 Value: &Value{
30 Word: &Word{
31 Parts: []WordPart{
32 {
33 Part: &tk[2],
34 Tokens: tk[2:3],
35 },
36 },
37 Tokens: tk[2:3],
38 },
39 Tokens: tk[2:3],
40 },
41 Tokens: tk[:3],
42 },
43 Tokens: tk[:3],
44 }
45 }},
46 {"$(||)", func(t *test, tk Tokens) { // 3
47 t.Err = Error{
48 Err: Error{
49 Err: Error{
50 Err: Error{
51 Err: Error{
52 Err: Error{
53 Err: Error{
54 Err: Error{
55 Err: Error{
56 Err: Error{
57 Err: ErrMissingWord,
58 Parsing: "Command",
59 Token: tk[1],
60 },
61 Parsing: "CommandOrCompound",
62 Token: tk[1],
63 },
64 Parsing: "Pipeline",
65 Token: tk[1],
66 },
67 Parsing: "Statement",
68 Token: tk[1],
69 },
70 Parsing: "Line",
71 Token: tk[1],
72 },
73 Parsing: "File",
74 Token: tk[1],
75 },
76 Parsing: "CommandSubstitution",
77 Token: tk[1],
78 },
79 Parsing: "WordPart",
80 Token: tk[0],
81 },
82 Parsing: "Word",
83 Token: tk[0],
84 },
85 Parsing: "AssignmentOrWord",
86 Token: tk[0],
87 }
88 }},
89 {"a=$(||)", func(t *test, tk Tokens) { // 4
90 t.Err = Error{
91 Err: Error{
92 Err: Error{
93 Err: Error{
94 Err: Error{
95 Err: Error{
96 Err: Error{
97 Err: Error{
98 Err: Error{
99 Err: Error{
100 Err: Error{
101 Err: Error{
102 Err: ErrMissingWord,
103 Parsing: "Command",
104 Token: tk[3],
105 },
106 Parsing: "CommandOrCompound",
107 Token: tk[3],
108 },
109 Parsing: "Pipeline",
110 Token: tk[3],
111 },
112 Parsing: "Statement",
113 Token: tk[3],
114 },
115 Parsing: "Line",
116 Token: tk[3],
117 },
118 Parsing: "File",
119 Token: tk[3],
120 },
121 Parsing: "CommandSubstitution",
122 Token: tk[3],
123 },
124 Parsing: "WordPart",
125 Token: tk[2],
126 },
127 Parsing: "Word",
128 Token: tk[2],
129 },
130 Parsing: "Value",
131 Token: tk[2],
132 },
133 Parsing: "Assignment",
134 Token: tk[2],
135 },
136 Parsing: "AssignmentOrWord",
137 Token: tk[0],
138 }
139 }},
140 }, func(t *test) (Type, error) {
141 var a AssignmentOrWord
142
143 err := a.parse(t.Parser)
144
145 return a, err
146 })
147 }
148
149 func TestValue(t *testing.T) {
150 doTests(t, []sourceFn{
151 {"a=b", func(t *test, tk Tokens) { // 1
152 t.Output = Value{
153 Word: &Word{
154 Parts: []WordPart{
155 {
156 Part: &tk[2],
157 Tokens: tk[2:3],
158 },
159 },
160 Tokens: tk[2:3],
161 },
162 Tokens: tk[2:3],
163 }
164 }},
165 {"a=()", func(t *test, tk Tokens) { // 2
166 t.Output = Value{
167 Array: []ArrayWord{},
168 Tokens: tk[2:4],
169 }
170 }},
171 {"a=(b)", func(t *test, tk Tokens) { // 3
172 t.Output = Value{
173 Array: []ArrayWord{
174 {
175 Word: Word{
176 Parts: []WordPart{
177 {
178 Part: &tk[3],
179 Tokens: tk[3:4],
180 },
181 },
182 Tokens: tk[3:4],
183 },
184 Tokens: tk[3:4],
185 },
186 },
187 Tokens: tk[2:5],
188 }
189 }},
190 {"a=( b )", func(t *test, tk Tokens) { // 4
191 t.Output = Value{
192 Array: []ArrayWord{
193 {
194 Word: Word{
195 Parts: []WordPart{
196 {
197 Part: &tk[4],
198 Tokens: tk[4:5],
199 },
200 },
201 Tokens: tk[4:5],
202 },
203 Tokens: tk[4:5],
204 },
205 },
206 Tokens: tk[2:7],
207 }
208 }},
209 {"a=( b c )", func(t *test, tk Tokens) { // 5
210 t.Output = Value{
211 Array: []ArrayWord{
212 {
213 Word: Word{
214 Parts: []WordPart{
215 {
216 Part: &tk[4],
217 Tokens: tk[4:5],
218 },
219 },
220 Tokens: tk[4:5],
221 },
222 Tokens: tk[4:5],
223 },
224 {
225 Word: Word{
226 Parts: []WordPart{
227 {
228 Part: &tk[6],
229 Tokens: tk[6:7],
230 },
231 },
232 Tokens: tk[6:7],
233 },
234 Tokens: tk[6:7],
235 },
236 },
237 Tokens: tk[2:9],
238 }
239 }},
240 {"a=( # comment\n)", func(t *test, tk Tokens) { // 6
241 t.Output = Value{
242 Array: []ArrayWord{},
243 Comments: [2]Comments{{tk[4]}},
244 Tokens: tk[2:7],
245 }
246 }},
247 {"a=( # comment A\n\n# b comment B\n)", func(t *test, tk Tokens) { // 7
248 t.Output = Value{
249 Array: []ArrayWord{},
250 Comments: [2]Comments{{tk[4]}, {tk[6]}},
251 Tokens: tk[2:9],
252 }
253 }},
254 {"a=(\n# comment\n)", func(t *test, tk Tokens) { // 8
255 t.Output = Value{
256 Array: []ArrayWord{},
257 Comments: [2]Comments{nil, {tk[4]}},
258 Tokens: tk[2:7],
259 }
260 }},
261 {"a=( # comment A\nb\n# comment B\n)", func(t *test, tk Tokens) { // 9
262 t.Output = Value{
263 Array: []ArrayWord{
264 {
265 Word: Word{
266 Parts: []WordPart{
267 {
268 Part: &tk[6],
269 Tokens: tk[6:7],
270 },
271 },
272 Tokens: tk[6:7],
273 },
274 Tokens: tk[6:7],
275 },
276 },
277 Comments: [2]Comments{{tk[4]}, {tk[8]}},
278 Tokens: tk[2:11],
279 }
280 }},
281 {"a=$(||)", func(t *test, tk Tokens) { // 10
282 t.Err = Error{
283 Err: Error{
284 Err: Error{
285 Err: Error{
286 Err: Error{
287 Err: Error{
288 Err: Error{
289 Err: Error{
290 Err: Error{
291 Err: Error{
292 Err: ErrMissingWord,
293 Parsing: "Command",
294 Token: tk[3],
295 },
296 Parsing: "CommandOrCompound",
297 Token: tk[3],
298 },
299 Parsing: "Pipeline",
300 Token: tk[3],
301 },
302 Parsing: "Statement",
303 Token: tk[3],
304 },
305 Parsing: "Line",
306 Token: tk[3],
307 },
308 Parsing: "File",
309 Token: tk[3],
310 },
311 Parsing: "CommandSubstitution",
312 Token: tk[3],
313 },
314 Parsing: "WordPart",
315 Token: tk[2],
316 },
317 Parsing: "Word",
318 Token: tk[2],
319 },
320 Parsing: "Value",
321 Token: tk[2],
322 }
323 }},
324 {"a=($(||))", func(t *test, tk Tokens) { // 11
325 t.Err = Error{
326 Err: Error{
327 Err: Error{
328 Err: Error{
329 Err: Error{
330 Err: Error{
331 Err: Error{
332 Err: Error{
333 Err: Error{
334 Err: Error{
335 Err: Error{
336 Err: ErrMissingWord,
337 Parsing: "Command",
338 Token: tk[4],
339 },
340 Parsing: "CommandOrCompound",
341 Token: tk[4],
342 },
343 Parsing: "Pipeline",
344 Token: tk[4],
345 },
346 Parsing: "Statement",
347 Token: tk[4],
348 },
349 Parsing: "Line",
350 Token: tk[4],
351 },
352 Parsing: "File",
353 Token: tk[4],
354 },
355 Parsing: "CommandSubstitution",
356 Token: tk[4],
357 },
358 Parsing: "WordPart",
359 Token: tk[3],
360 },
361 Parsing: "Word",
362 Token: tk[3],
363 },
364 Parsing: "ArrayWord",
365 Token: tk[3],
366 },
367 Parsing: "Value",
368 Token: tk[3],
369 }
370 }},
371 }, func(t *test) (Type, error) {
372 var v Value
373
374 t.Parser.Tokens = t.Parser.Tokens[2:2]
375 err := v.parse(t.Parser)
376
377 return v, err
378 })
379 }
380
381 func TestArrayWord(t *testing.T) {
382 doTests(t, []sourceFn{
383 {"a", func(t *test, tk Tokens) { // 1
384 t.Output = ArrayWord{
385 Word: Word{
386 Parts: []WordPart{
387 {
388 Part: &tk[0],
389 Tokens: tk[:1],
390 },
391 },
392 Tokens: tk[:1],
393 },
394 Tokens: tk[:1],
395 }
396 }},
397 {"# comment\na", func(t *test, tk Tokens) { // 2
398 t.Output = ArrayWord{
399 Word: Word{
400 Parts: []WordPart{
401 {
402 Part: &tk[2],
403 Tokens: tk[2:3],
404 },
405 },
406 Tokens: tk[2:3],
407 },
408 Comments: [2]Comments{{tk[0]}},
409 Tokens: tk[:3],
410 }
411 }},
412 {"a # comment", func(t *test, tk Tokens) { // 3
413 t.Output = ArrayWord{
414 Word: Word{
415 Parts: []WordPart{
416 {
417 Part: &tk[0],
418 Tokens: tk[:1],
419 },
420 },
421 Tokens: tk[:1],
422 },
423 Comments: [2]Comments{nil, {tk[2]}},
424 Tokens: tk[:3],
425 }
426 }},
427 {"# comment A\na # comment B", func(t *test, tk Tokens) { // 4
428 t.Output = ArrayWord{
429 Word: Word{
430 Parts: []WordPart{
431 {
432 Part: &tk[2],
433 Tokens: tk[2:3],
434 },
435 },
436 Tokens: tk[2:3],
437 },
438 Comments: [2]Comments{{tk[0]}, {tk[4]}},
439 Tokens: tk[:5],
440 }
441 }},
442 {"$(||)", func(t *test, tk Tokens) { // 5
443 t.Err = Error{
444 Err: Error{
445 Err: Error{
446 Err: Error{
447 Err: Error{
448 Err: Error{
449 Err: Error{
450 Err: Error{
451 Err: Error{
452 Err: Error{
453 Err: ErrMissingWord,
454 Parsing: "Command",
455 Token: tk[1],
456 },
457 Parsing: "CommandOrCompound",
458 Token: tk[1],
459 },
460 Parsing: "Pipeline",
461 Token: tk[1],
462 },
463 Parsing: "Statement",
464 Token: tk[1],
465 },
466 Parsing: "Line",
467 Token: tk[1],
468 },
469 Parsing: "File",
470 Token: tk[1],
471 },
472 Parsing: "CommandSubstitution",
473 Token: tk[1],
474 },
475 Parsing: "WordPart",
476 Token: tk[0],
477 },
478 Parsing: "Word",
479 Token: tk[0],
480 },
481 Parsing: "ArrayWord",
482 Token: tk[0],
483 }
484 }},
485 {"", func(t *test, tk Tokens) { // 6
486 t.Err = Error{
487 Err: ErrMissingWord,
488 Parsing: "ArrayWord",
489 Token: tk[0],
490 }
491 }},
492 }, func(t *test) (Type, error) {
493 var a ArrayWord
494
495 err := a.parse(t.Parser)
496
497 return a, err
498 })
499 }
500
501 func TestWord(t *testing.T) {
502 doTests(t, []sourceFn{
503 {"a", func(t *test, tk Tokens) { // 1
504 t.Output = Word{
505 Parts: []WordPart{
506 {
507 Part: &tk[0],
508 Tokens: tk[:1],
509 },
510 },
511 Tokens: tk[:1],
512 }
513 }},
514 {"a b", func(t *test, tk Tokens) { // 2
515 t.Output = Word{
516 Parts: []WordPart{
517 {
518 Part: &tk[0],
519 Tokens: tk[:1],
520 },
521 },
522 Tokens: tk[:1],
523 }
524 }},
525 {"a\nb", func(t *test, tk Tokens) { // 3
526 t.Output = Word{
527 Parts: []WordPart{
528 {
529 Part: &tk[0],
530 Tokens: tk[:1],
531 },
532 },
533 Tokens: tk[:1],
534 }
535 }},
536 {"a|b", func(t *test, tk Tokens) { // 4
537 t.Output = Word{
538 Parts: []WordPart{
539 {
540 Part: &tk[0],
541 Tokens: tk[:1],
542 },
543 },
544 Tokens: tk[:1],
545 }
546 }},
547 {"a$b", func(t *test, tk Tokens) { // 5
548 t.Output = Word{
549 Parts: []WordPart{
550 {
551 Part: &tk[0],
552 Tokens: tk[:1],
553 },
554 {
555 Part: &tk[1],
556 Tokens: tk[1:2],
557 },
558 },
559 Tokens: tk[:2],
560 }
561 }},
562 {"a$()", func(t *test, tk Tokens) { // 6
563 t.Output = Word{
564 Parts: []WordPart{
565 {
566 Part: &tk[0],
567 Tokens: tk[:1],
568 },
569 {
570 CommandSubstitution: &CommandSubstitution{
571 Command: File{
572 Tokens: tk[2:2],
573 },
574 Tokens: tk[1:3],
575 },
576 Tokens: tk[1:3],
577 },
578 },
579 Tokens: tk[:3],
580 }
581 }},
582 {"${a}b", func(t *test, tk Tokens) { // 7
583 t.Output = Word{
584 Parts: []WordPart{
585 {
586 ParameterExpansion: &ParameterExpansion{
587 Parameter: Parameter{
588 Parameter: &tk[1],
589 Tokens: tk[1:2],
590 },
591 Tokens: tk[:3],
592 },
593 Tokens: tk[:3],
594 },
595 {
596 Part: &tk[3],
597 Tokens: tk[3:4],
598 },
599 },
600 Tokens: tk[:4],
601 }
602 }},
603 {"a$(())", func(t *test, tk Tokens) { // 8
604 t.Output = Word{
605 Parts: []WordPart{
606 {
607 Part: &tk[0],
608 Tokens: tk[:1],
609 },
610 {
611 ArithmeticExpansion: &ArithmeticExpansion{
612 Tokens: tk[1:3],
613 },
614 Tokens: tk[1:3],
615 },
616 },
617 Tokens: tk[:3],
618 }
619 }},
620 {"$(||)", func(t *test, tk Tokens) { // 9
621 t.Err = Error{
622 Err: Error{
623 Err: Error{
624 Err: Error{
625 Err: Error{
626 Err: Error{
627 Err: Error{
628 Err: Error{
629 Err: Error{
630 Err: ErrMissingWord,
631 Parsing: "Command",
632 Token: tk[1],
633 },
634 Parsing: "CommandOrCompound",
635 Token: tk[1],
636 },
637 Parsing: "Pipeline",
638 Token: tk[1],
639 },
640 Parsing: "Statement",
641 Token: tk[1],
642 },
643 Parsing: "Line",
644 Token: tk[1],
645 },
646 Parsing: "File",
647 Token: tk[1],
648 },
649 Parsing: "CommandSubstitution",
650 Token: tk[1],
651 },
652 Parsing: "WordPart",
653 Token: tk[0],
654 },
655 Parsing: "Word",
656 Token: tk[0],
657 }
658 }},
659 }, func(t *test) (Type, error) {
660 var w Word
661
662 err := w.parse(t.Parser, false)
663
664 return w, err
665 })
666 }
667
668 func TestWordPart(t *testing.T) {
669 doTests(t, []sourceFn{
670 {"a", func(t *test, tk Tokens) { // 1
671 t.Output = WordPart{
672 Part: &tk[0],
673 Tokens: tk[:1],
674 }
675 }},
676 {"${a}", func(t *test, tk Tokens) { // 2
677 t.Output = WordPart{
678 ParameterExpansion: &ParameterExpansion{
679 Parameter: Parameter{
680 Parameter: &tk[1],
681 Tokens: tk[1:2],
682 },
683 Tokens: tk[:3],
684 },
685 Tokens: tk[:3],
686 }
687 }},
688 {"$()", func(t *test, tk Tokens) { // 3
689 t.Output = WordPart{
690 CommandSubstitution: &CommandSubstitution{
691 Command: File{
692 Tokens: tk[1:1],
693 },
694 Tokens: tk[:2],
695 },
696 Tokens: tk[:2],
697 }
698 }},
699 {"``", func(t *test, tk Tokens) { // 4
700 t.Output = WordPart{
701 CommandSubstitution: &CommandSubstitution{
702 SubstitutionType: SubstitutionBacktick,
703 Backtick: &tk[0],
704 Command: File{
705 Tokens: tk[1:1],
706 },
707 Tokens: tk[:2],
708 },
709 Tokens: tk[:2],
710 }
711 }},
712 {"$(())", func(t *test, tk Tokens) { // 5
713 t.Output = WordPart{
714 ArithmeticExpansion: &ArithmeticExpansion{
715 Tokens: tk[:2],
716 },
717 Tokens: tk[:2],
718 }
719 }},
720 {"{a,,\"b\"}", func(t *test, tk Tokens) { // 6
721 t.Output = WordPart{
722 BraceExpansion: &BraceExpansion{
723 BraceExpansionType: BraceExpansionWords,
724 Words: []Word{
725 {
726 Parts: []WordPart{
727 {
728 Part: &tk[1],
729 Tokens: tk[1:2],
730 },
731 },
732 Tokens: tk[1:2],
733 },
734 {
735 Tokens: tk[3:3],
736 },
737 {
738 Parts: []WordPart{
739 {
740 Part: &tk[4],
741 Tokens: tk[4:5],
742 },
743 },
744 Tokens: tk[4:5],
745 },
746 },
747 Tokens: tk[:6],
748 },
749 Tokens: tk[:6],
750 }
751 }},
752 {"{a..e}", func(t *test, tk Tokens) { // 7
753 t.Output = WordPart{
754 BraceExpansion: &BraceExpansion{
755 BraceExpansionType: BraceExpansionSequence,
756 Words: []Word{
757 {
758 Parts: []WordPart{
759 {
760 Part: &tk[1],
761 Tokens: tk[1:2],
762 },
763 },
764 Tokens: tk[1:2],
765 },
766 {
767 Parts: []WordPart{
768 {
769 Part: &tk[3],
770 Tokens: tk[3:4],
771 },
772 },
773 Tokens: tk[3:4],
774 },
775 },
776 Tokens: tk[:5],
777 },
778 Tokens: tk[:5],
779 }
780 }},
781 {"${a[$(||)]}", func(t *test, tk Tokens) { // 8
782 t.Err = Error{
783 Err: Error{
784 Err: Error{
785 Err: Error{
786 Err: Error{
787 Err: Error{
788 Err: Error{
789 Err: Error{
790 Err: Error{
791 Err: Error{
792 Err: Error{
793 Err: Error{
794 Err: Error{
795 Err: ErrMissingWord,
796 Parsing: "Command",
797 Token: tk[4],
798 },
799 Parsing: "CommandOrCompound",
800 Token: tk[4],
801 },
802 Parsing: "Pipeline",
803 Token: tk[4],
804 },
805 Parsing: "Statement",
806 Token: tk[4],
807 },
808 Parsing: "Line",
809 Token: tk[4],
810 },
811 Parsing: "File",
812 Token: tk[4],
813 },
814 Parsing: "CommandSubstitution",
815 Token: tk[4],
816 },
817 Parsing: "WordPart",
818 Token: tk[3],
819 },
820 Parsing: "Word",
821 Token: tk[3],
822 },
823 Parsing: "WordOrOperator",
824 Token: tk[3],
825 },
826 Parsing: "Parameter",
827 Token: tk[3],
828 },
829 Parsing: "ParameterExpansion",
830 Token: tk[1],
831 },
832 Parsing: "WordPart",
833 Token: tk[0],
834 }
835 }},
836 {"$(($(||)))", func(t *test, tk Tokens) { // 9
837 t.Err = Error{
838 Err: Error{
839 Err: Error{
840 Err: Error{
841 Err: Error{
842 Err: Error{
843 Err: Error{
844 Err: Error{
845 Err: Error{
846 Err: Error{
847 Err: Error{
848 Err: Error{
849 Err: ErrMissingWord,
850 Parsing: "Command",
851 Token: tk[2],
852 },
853 Parsing: "CommandOrCompound",
854 Token: tk[2],
855 },
856 Parsing: "Pipeline",
857 Token: tk[2],
858 },
859 Parsing: "Statement",
860 Token: tk[2],
861 },
862 Parsing: "Line",
863 Token: tk[2],
864 },
865 Parsing: "File",
866 Token: tk[2],
867 },
868 Parsing: "CommandSubstitution",
869 Token: tk[2],
870 },
871 Parsing: "WordPart",
872 Token: tk[1],
873 },
874 Parsing: "Word",
875 Token: tk[1],
876 },
877 Parsing: "WordOrOperator",
878 Token: tk[1],
879 },
880 Parsing: "ArithmeticExpansion",
881 Token: tk[1],
882 },
883 Parsing: "WordPart",
884 Token: tk[0],
885 }
886 }},
887 {"$(||)", func(t *test, tk Tokens) { // 10
888 t.Err = Error{
889 Err: Error{
890 Err: Error{
891 Err: Error{
892 Err: Error{
893 Err: Error{
894 Err: Error{
895 Err: Error{
896 Err: ErrMissingWord,
897 Parsing: "Command",
898 Token: tk[1],
899 },
900 Parsing: "CommandOrCompound",
901 Token: tk[1],
902 },
903 Parsing: "Pipeline",
904 Token: tk[1],
905 },
906 Parsing: "Statement",
907 Token: tk[1],
908 },
909 Parsing: "Line",
910 Token: tk[1],
911 },
912 Parsing: "File",
913 Token: tk[1],
914 },
915 Parsing: "CommandSubstitution",
916 Token: tk[1],
917 },
918 Parsing: "WordPart",
919 Token: tk[0],
920 }
921 }},
922 {"{\"$(||)\",}", func(t *test, tk Tokens) { // 11
923 t.Err = Error{
924 Err: Error{
925 Err: Error{
926 Err: Error{
927 Err: Error{
928 Err: Error{
929 Err: Error{
930 Err: Error{
931 Err: Error{
932 Err: Error{
933 Err: Error{
934 Err: ErrMissingWord,
935 Parsing: "Command",
936 Token: tk[3],
937 },
938 Parsing: "CommandOrCompound",
939 Token: tk[3],
940 },
941 Parsing: "Pipeline",
942 Token: tk[3],
943 },
944 Parsing: "Statement",
945 Token: tk[3],
946 },
947 Parsing: "Line",
948 Token: tk[3],
949 },
950 Parsing: "File",
951 Token: tk[3],
952 },
953 Parsing: "CommandSubstitution",
954 Token: tk[3],
955 },
956 Parsing: "WordPart",
957 Token: tk[2],
958 },
959 Parsing: "Word",
960 Token: tk[2],
961 },
962 Parsing: "BraceExpansion",
963 Token: tk[1],
964 },
965 Parsing: "WordPart",
966 Token: tk[0],
967 }
968 }},
969 }, func(t *test) (Type, error) {
970 var wp WordPart
971
972 err := wp.parse(t.Parser)
973
974 return wp, err
975 })
976 }
977
978 func TestBraceExpansion(t *testing.T) {
979 doTests(t, []sourceFn{
980 {"{a,b}", func(t *test, tk Tokens) { // 1
981 t.Output = BraceExpansion{
982 BraceExpansionType: BraceExpansionWords,
983 Words: []Word{
984 {
985 Parts: []WordPart{
986 {
987 Part: &tk[1],
988 Tokens: tk[1:2],
989 },
990 },
991 Tokens: tk[1:2],
992 },
993 {
994 Parts: []WordPart{
995 {
996 Part: &tk[3],
997 Tokens: tk[3:4],
998 },
999 },
1000 Tokens: tk[3:4],
1001 },
1002 },
1003 Tokens: tk[:5],
1004 }
1005 }},
1006 {"{\"a\",bc,123}", func(t *test, tk Tokens) { // 2
1007 t.Output = BraceExpansion{
1008 BraceExpansionType: BraceExpansionWords,
1009 Words: []Word{
1010 {
1011 Parts: []WordPart{
1012 {
1013 Part: &tk[1],
1014 Tokens: tk[1:2],
1015 },
1016 },
1017 Tokens: tk[1:2],
1018 },
1019 {
1020 Parts: []WordPart{
1021 {
1022 Part: &tk[3],
1023 Tokens: tk[3:4],
1024 },
1025 },
1026 Tokens: tk[3:4],
1027 },
1028 {
1029 Parts: []WordPart{
1030 {
1031 Part: &tk[5],
1032 Tokens: tk[5:6],
1033 },
1034 },
1035 Tokens: tk[5:6],
1036 },
1037 },
1038 Tokens: tk[:7],
1039 }
1040 }},
1041 {"{a..e}", func(t *test, tk Tokens) { // 3
1042 t.Output = BraceExpansion{
1043 BraceExpansionType: BraceExpansionSequence,
1044 Words: []Word{
1045 {
1046 Parts: []WordPart{
1047 {
1048 Part: &tk[1],
1049 Tokens: tk[1:2],
1050 },
1051 },
1052 Tokens: tk[1:2],
1053 },
1054 {
1055 Parts: []WordPart{
1056 {
1057 Part: &tk[3],
1058 Tokens: tk[3:4],
1059 },
1060 },
1061 Tokens: tk[3:4],
1062 },
1063 },
1064 Tokens: tk[:5],
1065 }
1066 }},
1067 {"{100..10..-1}", func(t *test, tk Tokens) { // 4
1068 t.Output = BraceExpansion{
1069 BraceExpansionType: BraceExpansionSequence,
1070 Words: []Word{
1071 {
1072 Parts: []WordPart{
1073 {
1074 Part: &tk[1],
1075 Tokens: tk[1:2],
1076 },
1077 },
1078 Tokens: tk[1:2],
1079 },
1080 {
1081 Parts: []WordPart{
1082 {
1083 Part: &tk[3],
1084 Tokens: tk[3:4],
1085 },
1086 },
1087 Tokens: tk[3:4],
1088 },
1089 {
1090 Parts: []WordPart{
1091 {
1092 Part: &tk[5],
1093 Tokens: tk[5:6],
1094 },
1095 },
1096 Tokens: tk[5:6],
1097 },
1098 },
1099 Tokens: tk[:7],
1100 }
1101 }},
1102 {"{\"$(||)\",bc,123}", func(t *test, tk Tokens) { // 5
1103 t.Err = Error{
1104 Err: Error{
1105 Err: Error{
1106 Err: Error{
1107 Err: Error{
1108 Err: Error{
1109 Err: Error{
1110 Err: Error{
1111 Err: Error{
1112 Err: Error{
1113 Err: ErrMissingWord,
1114 Parsing: "Command",
1115 Token: tk[3],
1116 },
1117 Parsing: "CommandOrCompound",
1118 Token: tk[3],
1119 },
1120 Parsing: "Pipeline",
1121 Token: tk[3],
1122 },
1123 Parsing: "Statement",
1124 Token: tk[3],
1125 },
1126 Parsing: "Line",
1127 Token: tk[3],
1128 },
1129 Parsing: "File",
1130 Token: tk[3],
1131 },
1132 Parsing: "CommandSubstitution",
1133 Token: tk[3],
1134 },
1135 Parsing: "WordPart",
1136 Token: tk[2],
1137 },
1138 Parsing: "Word",
1139 Token: tk[2],
1140 },
1141 Parsing: "BraceExpansion",
1142 Token: tk[1],
1143 }
1144 }},
1145 }, func(t *test) (Type, error) {
1146 var b BraceExpansion
1147
1148 err := b.parse(t.Parser)
1149
1150 return b, err
1151 })
1152 }
1153
1154 func TestParameterExpansion(t *testing.T) {
1155 doTests(t, []sourceFn{
1156 {"${a}", func(t *test, tk Tokens) { // 1
1157 t.Output = ParameterExpansion{
1158 Parameter: Parameter{
1159 Parameter: &tk[1],
1160 Tokens: tk[1:2],
1161 },
1162 Tokens: tk[:3],
1163 }
1164 }},
1165 {"${a[0]}", func(t *test, tk Tokens) { // 2
1166 t.Output = ParameterExpansion{
1167 Parameter: Parameter{
1168 Parameter: &tk[1],
1169 Array: []WordOrOperator{
1170 {
1171 Word: &Word{
1172 Parts: []WordPart{
1173 {
1174 Part: &tk[3],
1175 Tokens: tk[3:4],
1176 },
1177 },
1178 Tokens: tk[3:4],
1179 },
1180 Tokens: tk[3:4],
1181 },
1182 },
1183 Tokens: tk[1:5],
1184 },
1185 Tokens: tk[:6],
1186 }
1187 }},
1188 {"${@}", func(t *test, tk Tokens) { // 3
1189 t.Output = ParameterExpansion{
1190 Parameter: Parameter{
1191 Parameter: &tk[1],
1192 Tokens: tk[1:2],
1193 },
1194 Tokens: tk[:3],
1195 }
1196 }},
1197 {"${*}", func(t *test, tk Tokens) { // 4
1198 t.Output = ParameterExpansion{
1199 Parameter: Parameter{
1200 Parameter: &tk[1],
1201 Tokens: tk[1:2],
1202 },
1203 Tokens: tk[:3],
1204 }
1205 }},
1206 {"${!}", func(t *test, tk Tokens) { // 5
1207 t.Output = ParameterExpansion{
1208 Parameter: Parameter{
1209 Parameter: &tk[1],
1210 Tokens: tk[1:2],
1211 },
1212 Tokens: tk[:3],
1213 }
1214 }},
1215 {"${0}", func(t *test, tk Tokens) { // 6
1216 t.Output = ParameterExpansion{
1217 Parameter: Parameter{
1218 Parameter: &tk[1],
1219 Tokens: tk[1:2],
1220 },
1221 Tokens: tk[:3],
1222 }
1223 }},
1224 {"${99}", func(t *test, tk Tokens) { // 7
1225 t.Output = ParameterExpansion{
1226 Parameter: Parameter{
1227 Parameter: &tk[1],
1228 Tokens: tk[1:2],
1229 },
1230 Tokens: tk[:3],
1231 }
1232 }},
1233 {"${#a}", func(t *test, tk Tokens) { // 8
1234 t.Output = ParameterExpansion{
1235 Type: ParameterLength,
1236 Parameter: Parameter{
1237 Parameter: &tk[2],
1238 Tokens: tk[2:3],
1239 },
1240 Tokens: tk[:4],
1241 }
1242 }},
1243 {"${!a}", func(t *test, tk Tokens) { // 9
1244 t.Output = ParameterExpansion{
1245 Indirect: true,
1246 Parameter: Parameter{
1247 Parameter: &tk[2],
1248 Tokens: tk[2:3],
1249 },
1250 Tokens: tk[:4],
1251 }
1252 }},
1253 {"${a:=b}", func(t *test, tk Tokens) { // 10
1254 t.Output = ParameterExpansion{
1255 Type: ParameterSubstitution,
1256 Parameter: Parameter{
1257 Parameter: &tk[1],
1258 Tokens: tk[1:2],
1259 },
1260 BraceWord: &BraceWord{
1261 Parts: []WordPart{
1262 {
1263 Part: &tk[3],
1264 Tokens: tk[3:4],
1265 },
1266 },
1267 Tokens: tk[3:4],
1268 },
1269 Tokens: tk[:5],
1270 }
1271 }},
1272 {"${a:?b}", func(t *test, tk Tokens) { // 11
1273 t.Output = ParameterExpansion{
1274 Type: ParameterAssignment,
1275 Parameter: Parameter{
1276 Parameter: &tk[1],
1277 Tokens: tk[1:2],
1278 },
1279 BraceWord: &BraceWord{
1280 Parts: []WordPart{
1281 {
1282 Part: &tk[3],
1283 Tokens: tk[3:4],
1284 },
1285 },
1286 Tokens: tk[3:4],
1287 },
1288 Tokens: tk[:5],
1289 }
1290 }},
1291 {"${a:+b}", func(t *test, tk Tokens) { // 12
1292 t.Output = ParameterExpansion{
1293 Type: ParameterMessage,
1294 Parameter: Parameter{
1295 Parameter: &tk[1],
1296 Tokens: tk[1:2],
1297 },
1298 BraceWord: &BraceWord{
1299 Parts: []WordPart{
1300 {
1301 Part: &tk[3],
1302 Tokens: tk[3:4],
1303 },
1304 },
1305 Tokens: tk[3:4],
1306 },
1307 Tokens: tk[:5],
1308 }
1309 }},
1310 {"${a:+b c}", func(t *test, tk Tokens) { // 13
1311 t.Output = ParameterExpansion{
1312 Type: ParameterMessage,
1313 Parameter: Parameter{
1314 Parameter: &tk[1],
1315 Tokens: tk[1:2],
1316 },
1317 BraceWord: &BraceWord{
1318 Parts: []WordPart{
1319 {
1320 Part: &tk[3],
1321 Tokens: tk[3:4],
1322 },
1323 {
1324 Part: &tk[4],
1325 Tokens: tk[4:5],
1326 },
1327 {
1328 Part: &tk[5],
1329 Tokens: tk[5:6],
1330 },
1331 },
1332 Tokens: tk[3:6],
1333 },
1334 Tokens: tk[:7],
1335 }
1336 }},
1337 {"${a:-b}", func(t *test, tk Tokens) { // 14
1338 t.Output = ParameterExpansion{
1339 Type: ParameterSetAssign,
1340 Parameter: Parameter{
1341 Parameter: &tk[1],
1342 Tokens: tk[1:2],
1343 },
1344 BraceWord: &BraceWord{
1345 Parts: []WordPart{
1346 {
1347 Part: &tk[3],
1348 Tokens: tk[3:4],
1349 },
1350 },
1351 Tokens: tk[3:4],
1352 },
1353 Tokens: tk[:5],
1354 }
1355 }},
1356 {"${a=b}", func(t *test, tk Tokens) { // 15
1357 t.Output = ParameterExpansion{
1358 Type: ParameterUnsetSubstitution,
1359 Parameter: Parameter{
1360 Parameter: &tk[1],
1361 Tokens: tk[1:2],
1362 },
1363 BraceWord: &BraceWord{
1364 Parts: []WordPart{
1365 {
1366 Part: &tk[3],
1367 Tokens: tk[3:4],
1368 },
1369 },
1370 Tokens: tk[3:4],
1371 },
1372 Tokens: tk[:5],
1373 }
1374 }},
1375 {"${a?b}", func(t *test, tk Tokens) { // 16
1376 t.Output = ParameterExpansion{
1377 Type: ParameterUnsetAssignment,
1378 Parameter: Parameter{
1379 Parameter: &tk[1],
1380 Tokens: tk[1:2],
1381 },
1382 BraceWord: &BraceWord{
1383 Parts: []WordPart{
1384 {
1385 Part: &tk[3],
1386 Tokens: tk[3:4],
1387 },
1388 },
1389 Tokens: tk[3:4],
1390 },
1391 Tokens: tk[:5],
1392 }
1393 }},
1394 {"${a+b}", func(t *test, tk Tokens) { // 17
1395 t.Output = ParameterExpansion{
1396 Type: ParameterUnsetMessage,
1397 Parameter: Parameter{
1398 Parameter: &tk[1],
1399 Tokens: tk[1:2],
1400 },
1401 BraceWord: &BraceWord{
1402 Parts: []WordPart{
1403 {
1404 Part: &tk[3],
1405 Tokens: tk[3:4],
1406 },
1407 },
1408 Tokens: tk[3:4],
1409 },
1410 Tokens: tk[:5],
1411 }
1412 }},
1413 {"${a-b}", func(t *test, tk Tokens) { // 18
1414 t.Output = ParameterExpansion{
1415 Type: ParameterUnsetSetAssign,
1416 Parameter: Parameter{
1417 Parameter: &tk[1],
1418 Tokens: tk[1:2],
1419 },
1420 BraceWord: &BraceWord{
1421 Parts: []WordPart{
1422 {
1423 Part: &tk[3],
1424 Tokens: tk[3:4],
1425 },
1426 },
1427 Tokens: tk[3:4],
1428 },
1429 Tokens: tk[:5],
1430 }
1431 }},
1432 {"${a:1}", func(t *test, tk Tokens) { // 19
1433 t.Output = ParameterExpansion{
1434 Type: ParameterSubstring,
1435 Parameter: Parameter{
1436 Parameter: &tk[1],
1437 Tokens: tk[1:2],
1438 },
1439 SubstringStart: &tk[3],
1440 Tokens: tk[:5],
1441 }
1442 }},
1443 {"${a: 1}", func(t *test, tk Tokens) { // 20
1444 t.Output = ParameterExpansion{
1445 Type: ParameterSubstring,
1446 Parameter: Parameter{
1447 Parameter: &tk[1],
1448 Tokens: tk[1:2],
1449 },
1450 SubstringStart: &tk[4],
1451 Tokens: tk[:6],
1452 }
1453 }},
1454 {"${a: -1}", func(t *test, tk Tokens) { // 21
1455 t.Output = ParameterExpansion{
1456 Type: ParameterSubstring,
1457 Parameter: Parameter{
1458 Parameter: &tk[1],
1459 Tokens: tk[1:2],
1460 },
1461 SubstringStart: &tk[4],
1462 Tokens: tk[:6],
1463 }
1464 }},
1465 {"${a:1:2}", func(t *test, tk Tokens) { // 22
1466 t.Output = ParameterExpansion{
1467 Type: ParameterSubstring,
1468 Parameter: Parameter{
1469 Parameter: &tk[1],
1470 Tokens: tk[1:2],
1471 },
1472 SubstringStart: &tk[3],
1473 SubstringEnd: &tk[5],
1474 Tokens: tk[:7],
1475 }
1476 }},
1477 {"${a:1:-2}", func(t *test, tk Tokens) { // 23
1478 t.Output = ParameterExpansion{
1479 Type: ParameterSubstring,
1480 Parameter: Parameter{
1481 Parameter: &tk[1],
1482 Tokens: tk[1:2],
1483 },
1484 SubstringStart: &tk[3],
1485 SubstringEnd: &tk[5],
1486 Tokens: tk[:7],
1487 }
1488 }},
1489 {"${a:1: -2}", func(t *test, tk Tokens) { // 24
1490 t.Output = ParameterExpansion{
1491 Type: ParameterSubstring,
1492 Parameter: Parameter{
1493 Parameter: &tk[1],
1494 Tokens: tk[1:2],
1495 },
1496 SubstringStart: &tk[3],
1497 SubstringEnd: &tk[6],
1498 Tokens: tk[:8],
1499 }
1500 }},
1501 {"${a#b}", func(t *test, tk Tokens) { // 25
1502 t.Output = ParameterExpansion{
1503 Type: ParameterRemoveStartShortest,
1504 Parameter: Parameter{
1505 Parameter: &tk[1],
1506 Tokens: tk[1:2],
1507 },
1508 BraceWord: &BraceWord{
1509 Parts: []WordPart{
1510 {
1511 Part: &tk[3],
1512 Tokens: tk[3:4],
1513 },
1514 },
1515 Tokens: tk[3:4],
1516 },
1517 Tokens: tk[:5],
1518 }
1519 }},
1520 {"${a##b}", func(t *test, tk Tokens) { // 26
1521 t.Output = ParameterExpansion{
1522 Type: ParameterRemoveStartLongest,
1523 Parameter: Parameter{
1524 Parameter: &tk[1],
1525 Tokens: tk[1:2],
1526 },
1527 BraceWord: &BraceWord{
1528 Parts: []WordPart{
1529 {
1530 Part: &tk[3],
1531 Tokens: tk[3:4],
1532 },
1533 },
1534 Tokens: tk[3:4],
1535 },
1536 Tokens: tk[:5],
1537 }
1538 }},
1539 {"${a%b}", func(t *test, tk Tokens) { // 27
1540 t.Output = ParameterExpansion{
1541 Type: ParameterRemoveEndShortest,
1542 Parameter: Parameter{
1543 Parameter: &tk[1],
1544 Tokens: tk[1:2],
1545 },
1546 BraceWord: &BraceWord{
1547 Parts: []WordPart{
1548 {
1549 Part: &tk[3],
1550 Tokens: tk[3:4],
1551 },
1552 },
1553 Tokens: tk[3:4],
1554 },
1555 Tokens: tk[:5],
1556 }
1557 }},
1558 {"${a%%b}", func(t *test, tk Tokens) { // 28
1559 t.Output = ParameterExpansion{
1560 Type: ParameterRemoveEndLongest,
1561 Parameter: Parameter{
1562 Parameter: &tk[1],
1563 Tokens: tk[1:2],
1564 },
1565 BraceWord: &BraceWord{
1566 Parts: []WordPart{
1567 {
1568 Part: &tk[3],
1569 Tokens: tk[3:4],
1570 },
1571 },
1572 Tokens: tk[3:4],
1573 },
1574 Tokens: tk[:5],
1575 }
1576 }},
1577 {"${a/b}", func(t *test, tk Tokens) { // 29
1578 t.Output = ParameterExpansion{
1579 Type: ParameterReplace,
1580 Parameter: Parameter{
1581 Parameter: &tk[1],
1582 Tokens: tk[1:2],
1583 },
1584 Pattern: &tk[3],
1585 Tokens: tk[:5],
1586 }
1587 }},
1588 {"${a/b/c}", func(t *test, tk Tokens) { // 30
1589 t.Output = ParameterExpansion{
1590 Type: ParameterReplace,
1591 Parameter: Parameter{
1592 Parameter: &tk[1],
1593 Tokens: tk[1:2],
1594 },
1595 Pattern: &tk[3],
1596 String: &String{
1597 WordsOrTokens: []WordOrToken{
1598 {
1599 Word: &Word{
1600 Parts: []WordPart{
1601 {
1602 Part: &tk[5],
1603 Tokens: tk[5:6],
1604 },
1605 },
1606 Tokens: tk[5:6],
1607 },
1608 Tokens: tk[5:6],
1609 },
1610 },
1611 Tokens: tk[5:6],
1612 },
1613 Tokens: tk[:7],
1614 }
1615 }},
1616 {"${a//b}", func(t *test, tk Tokens) { // 31
1617 t.Output = ParameterExpansion{
1618 Type: ParameterReplaceAll,
1619 Parameter: Parameter{
1620 Parameter: &tk[1],
1621 Tokens: tk[1:2],
1622 },
1623 Pattern: &tk[3],
1624 Tokens: tk[:5],
1625 }
1626 }},
1627 {"${a//b/c}", func(t *test, tk Tokens) { // 32
1628 t.Output = ParameterExpansion{
1629 Type: ParameterReplaceAll,
1630 Parameter: Parameter{
1631 Parameter: &tk[1],
1632 Tokens: tk[1:2],
1633 },
1634 Pattern: &tk[3],
1635 String: &String{
1636 WordsOrTokens: []WordOrToken{
1637 {
1638 Word: &Word{
1639 Parts: []WordPart{
1640 {
1641 Part: &tk[5],
1642 Tokens: tk[5:6],
1643 },
1644 },
1645 Tokens: tk[5:6],
1646 },
1647 Tokens: tk[5:6],
1648 },
1649 },
1650 Tokens: tk[5:6],
1651 },
1652 Tokens: tk[:7],
1653 }
1654 }},
1655 {"${a/#b}", func(t *test, tk Tokens) { // 33
1656 t.Output = ParameterExpansion{
1657 Type: ParameterReplaceStart,
1658 Parameter: Parameter{
1659 Parameter: &tk[1],
1660 Tokens: tk[1:2],
1661 },
1662 Pattern: &tk[3],
1663 Tokens: tk[:5],
1664 }
1665 }},
1666 {"${a/#b/c}", func(t *test, tk Tokens) { // 34
1667 t.Output = ParameterExpansion{
1668 Type: ParameterReplaceStart,
1669 Parameter: Parameter{
1670 Parameter: &tk[1],
1671 Tokens: tk[1:2],
1672 },
1673 Pattern: &tk[3],
1674 String: &String{
1675 WordsOrTokens: []WordOrToken{
1676 {
1677 Word: &Word{
1678 Parts: []WordPart{
1679 {
1680 Part: &tk[5],
1681 Tokens: tk[5:6],
1682 },
1683 },
1684 Tokens: tk[5:6],
1685 },
1686 Tokens: tk[5:6],
1687 },
1688 },
1689 Tokens: tk[5:6],
1690 },
1691 Tokens: tk[:7],
1692 }
1693 }},
1694 {"${a/%b}", func(t *test, tk Tokens) { // 35
1695 t.Output = ParameterExpansion{
1696 Type: ParameterReplaceEnd,
1697 Parameter: Parameter{
1698 Parameter: &tk[1],
1699 Tokens: tk[1:2],
1700 },
1701 Pattern: &tk[3],
1702 Tokens: tk[:5],
1703 }
1704 }},
1705 {"${a/%b/c}", func(t *test, tk Tokens) { // 36
1706 t.Output = ParameterExpansion{
1707 Type: ParameterReplaceEnd,
1708 Parameter: Parameter{
1709 Parameter: &tk[1],
1710 Tokens: tk[1:2],
1711 },
1712 Pattern: &tk[3],
1713 String: &String{
1714 WordsOrTokens: []WordOrToken{
1715 {
1716 Word: &Word{
1717 Parts: []WordPart{
1718 {
1719 Part: &tk[5],
1720 Tokens: tk[5:6],
1721 },
1722 },
1723 Tokens: tk[5:6],
1724 },
1725 Tokens: tk[5:6],
1726 },
1727 },
1728 Tokens: tk[5:6],
1729 },
1730 Tokens: tk[:7],
1731 }
1732 }},
1733 {"${a^b}", func(t *test, tk Tokens) { // 37
1734 t.Output = ParameterExpansion{
1735 Type: ParameterUppercaseFirstMatch,
1736 Parameter: Parameter{
1737 Parameter: &tk[1],
1738 Tokens: tk[1:2],
1739 },
1740 Pattern: &tk[3],
1741 Tokens: tk[:5],
1742 }
1743 }},
1744 {"${a^^b}", func(t *test, tk Tokens) { // 38
1745 t.Output = ParameterExpansion{
1746 Type: ParameterUppercaseAllMatches,
1747 Parameter: Parameter{
1748 Parameter: &tk[1],
1749 Tokens: tk[1:2],
1750 },
1751 Pattern: &tk[3],
1752 Tokens: tk[:5],
1753 }
1754 }},
1755 {"${a,b}", func(t *test, tk Tokens) { // 39
1756 t.Output = ParameterExpansion{
1757 Type: ParameterLowercaseFirstMatch,
1758 Parameter: Parameter{
1759 Parameter: &tk[1],
1760 Tokens: tk[1:2],
1761 },
1762 Pattern: &tk[3],
1763 Tokens: tk[:5],
1764 }
1765 }},
1766 {"${a,,b}", func(t *test, tk Tokens) { // 40
1767 t.Output = ParameterExpansion{
1768 Type: ParameterLowercaseAllMatches,
1769 Parameter: Parameter{
1770 Parameter: &tk[1],
1771 Tokens: tk[1:2],
1772 },
1773 Pattern: &tk[3],
1774 Tokens: tk[:5],
1775 }
1776 }},
1777 {"${!a@}", func(t *test, tk Tokens) { // 41
1778 t.Output = ParameterExpansion{
1779 Type: ParameterPrefixSeperate,
1780 Parameter: Parameter{
1781 Parameter: &tk[2],
1782 Tokens: tk[2:3],
1783 },
1784 Tokens: tk[:5],
1785 }
1786 }},
1787 {"${!a*}", func(t *test, tk Tokens) { // 42
1788 t.Output = ParameterExpansion{
1789 Type: ParameterPrefix,
1790 Parameter: Parameter{
1791 Parameter: &tk[2],
1792 Tokens: tk[2:3],
1793 },
1794 Tokens: tk[:5],
1795 }
1796 }},
1797 {"${a@U}", func(t *test, tk Tokens) { // 43
1798 t.Output = ParameterExpansion{
1799 Type: ParameterUppercase,
1800 Parameter: Parameter{
1801 Parameter: &tk[1],
1802 Tokens: tk[1:2],
1803 },
1804 Tokens: tk[:5],
1805 }
1806 }},
1807 {"${a@u}", func(t *test, tk Tokens) { // 44
1808 t.Output = ParameterExpansion{
1809 Type: ParameterUppercaseFirst,
1810 Parameter: Parameter{
1811 Parameter: &tk[1],
1812 Tokens: tk[1:2],
1813 },
1814 Tokens: tk[:5],
1815 }
1816 }},
1817 {"${a@L}", func(t *test, tk Tokens) { // 45
1818 t.Output = ParameterExpansion{
1819 Type: ParameterLowercase,
1820 Parameter: Parameter{
1821 Parameter: &tk[1],
1822 Tokens: tk[1:2],
1823 },
1824 Tokens: tk[:5],
1825 }
1826 }},
1827 {"${a@Q}", func(t *test, tk Tokens) { // 46
1828 t.Output = ParameterExpansion{
1829 Type: ParameterQuoted,
1830 Parameter: Parameter{
1831 Parameter: &tk[1],
1832 Tokens: tk[1:2],
1833 },
1834 Tokens: tk[:5],
1835 }
1836 }},
1837 {"${a@E}", func(t *test, tk Tokens) { // 47
1838 t.Output = ParameterExpansion{
1839 Type: ParameterEscaped,
1840 Parameter: Parameter{
1841 Parameter: &tk[1],
1842 Tokens: tk[1:2],
1843 },
1844 Tokens: tk[:5],
1845 }
1846 }},
1847 {"${a@P}", func(t *test, tk Tokens) { // 48
1848 t.Output = ParameterExpansion{
1849 Type: ParameterPrompt,
1850 Parameter: Parameter{
1851 Parameter: &tk[1],
1852 Tokens: tk[1:2],
1853 },
1854 Tokens: tk[:5],
1855 }
1856 }},
1857 {"${a@A}", func(t *test, tk Tokens) { // 49
1858 t.Output = ParameterExpansion{
1859 Type: ParameterDeclare,
1860 Parameter: Parameter{
1861 Parameter: &tk[1],
1862 Tokens: tk[1:2],
1863 },
1864 Tokens: tk[:5],
1865 }
1866 }},
1867 {"${a@K}", func(t *test, tk Tokens) { // 50
1868 t.Output = ParameterExpansion{
1869 Type: ParameterQuotedArrays,
1870 Parameter: Parameter{
1871 Parameter: &tk[1],
1872 Tokens: tk[1:2],
1873 },
1874 Tokens: tk[:5],
1875 }
1876 }},
1877 {"${a@a}", func(t *test, tk Tokens) { // 51
1878 t.Output = ParameterExpansion{
1879 Type: ParameterAttributes,
1880 Parameter: Parameter{
1881 Parameter: &tk[1],
1882 Tokens: tk[1:2],
1883 },
1884 Tokens: tk[:5],
1885 }
1886 }},
1887 {"${a@k}", func(t *test, tk Tokens) { // 52
1888 t.Output = ParameterExpansion{
1889 Type: ParameterQuotedArraysSeperate,
1890 Parameter: Parameter{
1891 Parameter: &tk[1],
1892 Tokens: tk[1:2],
1893 },
1894 Tokens: tk[:5],
1895 }
1896 }},
1897 {"${a[$(||)]}", func(t *test, tk Tokens) { // 53
1898 t.Err = Error{
1899 Err: Error{
1900 Err: Error{
1901 Err: Error{
1902 Err: Error{
1903 Err: Error{
1904 Err: Error{
1905 Err: Error{
1906 Err: Error{
1907 Err: Error{
1908 Err: Error{
1909 Err: Error{
1910 Err: ErrMissingWord,
1911 Parsing: "Command",
1912 Token: tk[4],
1913 },
1914 Parsing: "CommandOrCompound",
1915 Token: tk[4],
1916 },
1917 Parsing: "Pipeline",
1918 Token: tk[4],
1919 },
1920 Parsing: "Statement",
1921 Token: tk[4],
1922 },
1923 Parsing: "Line",
1924 Token: tk[4],
1925 },
1926 Parsing: "File",
1927 Token: tk[4],
1928 },
1929 Parsing: "CommandSubstitution",
1930 Token: tk[4],
1931 },
1932 Parsing: "WordPart",
1933 Token: tk[3],
1934 },
1935 Parsing: "Word",
1936 Token: tk[3],
1937 },
1938 Parsing: "WordOrOperator",
1939 Token: tk[3],
1940 },
1941 Parsing: "Parameter",
1942 Token: tk[3],
1943 },
1944 Parsing: "ParameterExpansion",
1945 Token: tk[1],
1946 }
1947 }},
1948 {"${a:=$(||)}", func(t *test, tk Tokens) { // 54
1949 t.Err = Error{
1950 Err: Error{
1951 Err: Error{
1952 Err: Error{
1953 Err: Error{
1954 Err: Error{
1955 Err: Error{
1956 Err: Error{
1957 Err: Error{
1958 Err: Error{
1959 Err: ErrMissingWord,
1960 Parsing: "Command",
1961 Token: tk[4],
1962 },
1963 Parsing: "CommandOrCompound",
1964 Token: tk[4],
1965 },
1966 Parsing: "Pipeline",
1967 Token: tk[4],
1968 },
1969 Parsing: "Statement",
1970 Token: tk[4],
1971 },
1972 Parsing: "Line",
1973 Token: tk[4],
1974 },
1975 Parsing: "File",
1976 Token: tk[4],
1977 },
1978 Parsing: "CommandSubstitution",
1979 Token: tk[4],
1980 },
1981 Parsing: "WordPart",
1982 Token: tk[3],
1983 },
1984 Parsing: "BraceWord",
1985 Token: tk[3],
1986 },
1987 Parsing: "ParameterExpansion",
1988 Token: tk[3],
1989 }
1990 }},
1991 {"${a:1:2b}", func(t *test, tk Tokens) { // 55
1992 t.Err = Error{
1993 Err: ErrMissingClosingBrace,
1994 Parsing: "ParameterExpansion",
1995 Token: tk[6],
1996 }
1997 }},
1998 {"${a/b/$(||)}", func(t *test, tk Tokens) { // 56
1999 t.Err = Error{
2000 Err: Error{
2001 Err: Error{
2002 Err: Error{
2003 Err: Error{
2004 Err: Error{
2005 Err: Error{
2006 Err: Error{
2007 Err: Error{
2008 Err: Error{
2009 Err: Error{
2010 Err: Error{
2011 Err: ErrMissingWord,
2012 Parsing: "Command",
2013 Token: tk[6],
2014 },
2015 Parsing: "CommandOrCompound",
2016 Token: tk[6],
2017 },
2018 Parsing: "Pipeline",
2019 Token: tk[6],
2020 },
2021 Parsing: "Statement",
2022 Token: tk[6],
2023 },
2024 Parsing: "Line",
2025 Token: tk[6],
2026 },
2027 Parsing: "File",
2028 Token: tk[6],
2029 },
2030 Parsing: "CommandSubstitution",
2031 Token: tk[6],
2032 },
2033 Parsing: "WordPart",
2034 Token: tk[5],
2035 },
2036 Parsing: "Word",
2037 Token: tk[5],
2038 },
2039 Parsing: "WordOrToken",
2040 Token: tk[5],
2041 },
2042 Parsing: "String",
2043 Token: tk[5],
2044 },
2045 Parsing: "ParameterExpansion",
2046 Token: tk[5],
2047 }
2048 }},
2049 }, func(t *test) (Type, error) {
2050 var pe ParameterExpansion
2051
2052 err := pe.parse(t.Parser)
2053
2054 return pe, err
2055 })
2056 }
2057
2058 func TestBraceWord(t *testing.T) {
2059 doTests(t, []sourceFn{
2060 {"${a:-b}", func(t *test, tk Tokens) { // 1
2061 t.Output = BraceWord{
2062 Parts: []WordPart{
2063 {
2064 Part: &tk[3],
2065 Tokens: tk[3:4],
2066 },
2067 },
2068 Tokens: tk[3:4],
2069 }
2070 }},
2071 {"${a:-b c}", func(t *test, tk Tokens) { // 2
2072 t.Output = BraceWord{
2073 Parts: []WordPart{
2074 {
2075 Part: &tk[3],
2076 Tokens: tk[3:4],
2077 },
2078 {
2079 Part: &tk[4],
2080 Tokens: tk[4:5],
2081 },
2082 {
2083 Part: &tk[5],
2084 Tokens: tk[5:6],
2085 },
2086 },
2087 Tokens: tk[3:6],
2088 }
2089 }},
2090 {"${a:-$(||)}", func(t *test, tk Tokens) { // 3
2091 t.Err = Error{
2092 Err: Error{
2093 Err: Error{
2094 Err: Error{
2095 Err: Error{
2096 Err: Error{
2097 Err: Error{
2098 Err: Error{
2099 Err: Error{
2100 Err: ErrMissingWord,
2101 Parsing: "Command",
2102 Token: tk[4],
2103 },
2104 Parsing: "CommandOrCompound",
2105 Token: tk[4],
2106 },
2107 Parsing: "Pipeline",
2108 Token: tk[4],
2109 },
2110 Parsing: "Statement",
2111 Token: tk[4],
2112 },
2113 Parsing: "Line",
2114 Token: tk[4],
2115 },
2116 Parsing: "File",
2117 Token: tk[4],
2118 },
2119 Parsing: "CommandSubstitution",
2120 Token: tk[4],
2121 },
2122 Parsing: "WordPart",
2123 Token: tk[3],
2124 },
2125 Parsing: "BraceWord",
2126 Token: tk[3],
2127 }
2128 }},
2129 }, func(t *test) (Type, error) {
2130 var bw BraceWord
2131
2132 t.Parser.Tokens = t.Parser.Tokens[3:3]
2133 err := bw.parse(t.Parser)
2134
2135 return bw, err
2136 })
2137 }
2138
2139 func TestParameter(t *testing.T) {
2140 doTests(t, []sourceFn{
2141 {"${a}", func(t *test, tk Tokens) { // 1
2142 t.Output = Parameter{
2143 Parameter: &tk[1],
2144 Tokens: tk[1:2],
2145 }
2146 }},
2147 {"${0}", func(t *test, tk Tokens) { // 2
2148 t.Output = Parameter{
2149 Parameter: &tk[1],
2150 Tokens: tk[1:2],
2151 }
2152 }},
2153 {"${9}", func(t *test, tk Tokens) { // 3
2154 t.Output = Parameter{
2155 Parameter: &tk[1],
2156 Tokens: tk[1:2],
2157 }
2158 }},
2159 {"${@}", func(t *test, tk Tokens) { // 4
2160 t.Output = Parameter{
2161 Parameter: &tk[1],
2162 Tokens: tk[1:2],
2163 }
2164 }},
2165 {"${*}", func(t *test, tk Tokens) { // 5
2166 t.Output = Parameter{
2167 Parameter: &tk[1],
2168 Tokens: tk[1:2],
2169 }
2170 }},
2171 {"${a[0]}", func(t *test, tk Tokens) { // 6
2172 t.Output = Parameter{
2173 Parameter: &tk[1],
2174 Array: []WordOrOperator{
2175 {
2176 Word: &Word{
2177 Parts: []WordPart{
2178 {
2179 Part: &tk[3],
2180 Tokens: tk[3:4],
2181 },
2182 },
2183 Tokens: tk[3:4],
2184 },
2185 Tokens: tk[3:4],
2186 },
2187 },
2188 Tokens: tk[1:5],
2189 }
2190 }},
2191 {"${a[ 0 ]}", func(t *test, tk Tokens) { // 7
2192 t.Output = Parameter{
2193 Parameter: &tk[1],
2194 Array: []WordOrOperator{
2195 {
2196 Word: &Word{
2197 Parts: []WordPart{
2198 {
2199 Part: &tk[4],
2200 Tokens: tk[4:5],
2201 },
2202 },
2203 Tokens: tk[4:5],
2204 },
2205 Tokens: tk[4:5],
2206 },
2207 },
2208 Tokens: tk[1:7],
2209 }
2210 }},
2211 {"${a[@]}", func(t *test, tk Tokens) { // 8
2212 t.Output = Parameter{
2213 Parameter: &tk[1],
2214 Array: []WordOrOperator{
2215 {
2216 Word: &Word{
2217 Parts: []WordPart{
2218 {
2219 Part: &tk[3],
2220 Tokens: tk[3:4],
2221 },
2222 },
2223 Tokens: tk[3:4],
2224 },
2225 Tokens: tk[3:4],
2226 },
2227 },
2228 Tokens: tk[1:5],
2229 }
2230 }},
2231 {"${a[*]}", func(t *test, tk Tokens) { // 9
2232 t.Output = Parameter{
2233 Parameter: &tk[1],
2234 Array: []WordOrOperator{
2235 {
2236 Word: &Word{
2237 Parts: []WordPart{
2238 {
2239 Part: &tk[3],
2240 Tokens: tk[3:4],
2241 },
2242 },
2243 Tokens: tk[3:4],
2244 },
2245 Tokens: tk[3:4],
2246 },
2247 },
2248 Tokens: tk[1:5],
2249 }
2250 }},
2251 {"${a[$(||)]}", func(t *test, tk Tokens) { // 10
2252 t.Err = Error{
2253 Err: Error{
2254 Err: Error{
2255 Err: Error{
2256 Err: Error{
2257 Err: Error{
2258 Err: Error{
2259 Err: Error{
2260 Err: Error{
2261 Err: Error{
2262 Err: Error{
2263 Err: ErrMissingWord,
2264 Parsing: "Command",
2265 Token: tk[4],
2266 },
2267 Parsing: "CommandOrCompound",
2268 Token: tk[4],
2269 },
2270 Parsing: "Pipeline",
2271 Token: tk[4],
2272 },
2273 Parsing: "Statement",
2274 Token: tk[4],
2275 },
2276 Parsing: "Line",
2277 Token: tk[4],
2278 },
2279 Parsing: "File",
2280 Token: tk[4],
2281 },
2282 Parsing: "CommandSubstitution",
2283 Token: tk[4],
2284 },
2285 Parsing: "WordPart",
2286 Token: tk[3],
2287 },
2288 Parsing: "Word",
2289 Token: tk[3],
2290 },
2291 Parsing: "WordOrOperator",
2292 Token: tk[3],
2293 },
2294 Parsing: "Parameter",
2295 Token: tk[3],
2296 }
2297 }},
2298 }, func(t *test) (Type, error) {
2299 var p Parameter
2300
2301 t.Parser.Tokens = t.Parser.Tokens[1:1]
2302 err := p.parse(t.Parser)
2303
2304 return p, err
2305 })
2306 }
2307
2308 func TestString(t *testing.T) {
2309 doTests(t, []sourceFn{
2310 {"a", func(t *test, tk Tokens) { // 1
2311 t.Output = String{
2312 WordsOrTokens: []WordOrToken{
2313 {
2314 Word: &Word{
2315 Parts: []WordPart{
2316 {
2317 Part: &tk[0],
2318 Tokens: tk[:1],
2319 },
2320 },
2321 Tokens: tk[:1],
2322 },
2323 Tokens: tk[:1],
2324 },
2325 },
2326 Tokens: tk[:1],
2327 }
2328 }},
2329 {"a\t or b", func(t *test, tk Tokens) { // 2
2330 t.Output = String{
2331 WordsOrTokens: []WordOrToken{
2332 {
2333 Word: &Word{
2334 Parts: []WordPart{
2335 {
2336 Part: &tk[0],
2337 Tokens: tk[:1],
2338 },
2339 },
2340 Tokens: tk[:1],
2341 },
2342 Tokens: tk[:1],
2343 },
2344 {
2345 Token: &tk[1],
2346 Tokens: tk[1:2],
2347 },
2348 {
2349 Word: &Word{
2350 Parts: []WordPart{
2351 {
2352 Part: &tk[2],
2353 Tokens: tk[2:3],
2354 },
2355 },
2356 Tokens: tk[2:3],
2357 },
2358 Tokens: tk[2:3],
2359 },
2360 {
2361 Token: &tk[3],
2362 Tokens: tk[3:4],
2363 },
2364 {
2365 Word: &Word{
2366 Parts: []WordPart{
2367 {
2368 Part: &tk[4],
2369 Tokens: tk[4:5],
2370 },
2371 },
2372 Tokens: tk[4:5],
2373 },
2374 Tokens: tk[4:5],
2375 },
2376 },
2377 Tokens: tk[:5],
2378 }
2379 }},
2380 {"$a", func(t *test, tk Tokens) { // 3
2381 t.Output = String{
2382 WordsOrTokens: []WordOrToken{
2383 {
2384 Word: &Word{
2385 Parts: []WordPart{
2386 {
2387 Part: &tk[0],
2388 Tokens: tk[:1],
2389 },
2390 },
2391 Tokens: tk[:1],
2392 },
2393 Tokens: tk[:1],
2394 },
2395 },
2396 Tokens: tk[:1],
2397 }
2398 }},
2399 {"$(||)", func(t *test, tk Tokens) { // 4
2400 t.Err = Error{
2401 Err: Error{
2402 Err: Error{
2403 Err: Error{
2404 Err: Error{
2405 Err: Error{
2406 Err: Error{
2407 Err: Error{
2408 Err: Error{
2409 Err: Error{
2410 Err: Error{
2411 Err: ErrMissingWord,
2412 Parsing: "Command",
2413 Token: tk[1],
2414 },
2415 Parsing: "CommandOrCompound",
2416 Token: tk[1],
2417 },
2418 Parsing: "Pipeline",
2419 Token: tk[1],
2420 },
2421 Parsing: "Statement",
2422 Token: tk[1],
2423 },
2424 Parsing: "Line",
2425 Token: tk[1],
2426 },
2427 Parsing: "File",
2428 Token: tk[1],
2429 },
2430 Parsing: "CommandSubstitution",
2431 Token: tk[1],
2432 },
2433 Parsing: "WordPart",
2434 Token: tk[0],
2435 },
2436 Parsing: "Word",
2437 Token: tk[0],
2438 },
2439 Parsing: "WordOrToken",
2440 Token: tk[0],
2441 },
2442 Parsing: "String",
2443 Token: tk[0],
2444 }
2445 }},
2446 }, func(t *test) (Type, error) {
2447 var s String
2448
2449 err := s.parse(t.Parser)
2450
2451 return s, err
2452 })
2453 }
2454
2455 func TestWordOrToken(t *testing.T) {
2456 doTests(t, []sourceFn{
2457 {"a", func(t *test, tk Tokens) { // 1
2458 t.Output = WordOrToken{
2459 Word: &Word{
2460 Parts: []WordPart{
2461 {
2462 Part: &tk[0],
2463 Tokens: tk[:1],
2464 },
2465 },
2466 Tokens: tk[:1],
2467 },
2468 Tokens: tk[:1],
2469 }
2470 }},
2471 {" ", func(t *test, tk Tokens) { // 2
2472 t.Output = WordOrToken{
2473 Token: &tk[0],
2474 Tokens: tk[:1],
2475 }
2476 }},
2477 {"$(||)", func(t *test, tk Tokens) { // 3
2478 t.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: Error{
2487 Err: Error{
2488 Err: ErrMissingWord,
2489 Parsing: "Command",
2490 Token: tk[1],
2491 },
2492 Parsing: "CommandOrCompound",
2493 Token: tk[1],
2494 },
2495 Parsing: "Pipeline",
2496 Token: tk[1],
2497 },
2498 Parsing: "Statement",
2499 Token: tk[1],
2500 },
2501 Parsing: "Line",
2502 Token: tk[1],
2503 },
2504 Parsing: "File",
2505 Token: tk[1],
2506 },
2507 Parsing: "CommandSubstitution",
2508 Token: tk[1],
2509 },
2510 Parsing: "WordPart",
2511 Token: tk[0],
2512 },
2513 Parsing: "Word",
2514 Token: tk[0],
2515 },
2516 Parsing: "WordOrToken",
2517 Token: tk[0],
2518 }
2519 }},
2520 }, func(t *test) (Type, error) {
2521 var w WordOrToken
2522
2523 err := w.parse(t.Parser)
2524
2525 return w, err
2526 })
2527 }
2528
2529 func TestWordOrOperator(t *testing.T) {
2530 doTests(t, []sourceFn{
2531 {"a", func(t *test, tk Tokens) { // 1
2532 t.Output = WordOrOperator{
2533 Word: &Word{
2534 Parts: []WordPart{
2535 {
2536 Part: &tk[0],
2537 Tokens: tk[:1],
2538 },
2539 },
2540 Tokens: tk[:1],
2541 },
2542 Tokens: tk[:1],
2543 }
2544 }},
2545 {"a=b", func(t *test, tk Tokens) { // 2
2546 t.Output = WordOrOperator{
2547 Word: &Word{
2548 Parts: []WordPart{
2549 {
2550 Part: &tk[0],
2551 Tokens: tk[:1],
2552 },
2553 },
2554 Tokens: tk[:1],
2555 },
2556 Tokens: tk[:1],
2557 }
2558 }},
2559 {"$a", func(t *test, tk Tokens) { // 3
2560 t.Output = WordOrOperator{
2561 Word: &Word{
2562 Parts: []WordPart{
2563 {
2564 Part: &tk[0],
2565 Tokens: tk[:1],
2566 },
2567 },
2568 Tokens: tk[:1],
2569 },
2570 Tokens: tk[:1],
2571 }
2572 }},
2573 {">", func(t *test, tk Tokens) { // 4
2574 t.Output = WordOrOperator{
2575 Operator: &tk[0],
2576 Tokens: tk[:1],
2577 }
2578 }},
2579 {"&", func(t *test, tk Tokens) { // 5
2580 t.Output = WordOrOperator{
2581 Operator: &tk[0],
2582 Tokens: tk[:1],
2583 }
2584 }},
2585 {"$(||)", func(t *test, tk Tokens) { // 6
2586 t.Err = Error{
2587 Err: Error{
2588 Err: Error{
2589 Err: Error{
2590 Err: Error{
2591 Err: Error{
2592 Err: Error{
2593 Err: Error{
2594 Err: Error{
2595 Err: Error{
2596 Err: ErrMissingWord,
2597 Parsing: "Command",
2598 Token: tk[1],
2599 },
2600 Parsing: "CommandOrCompound",
2601 Token: tk[1],
2602 },
2603 Parsing: "Pipeline",
2604 Token: tk[1],
2605 },
2606 Parsing: "Statement",
2607 Token: tk[1],
2608 },
2609 Parsing: "Line",
2610 Token: tk[1],
2611 },
2612 Parsing: "File",
2613 Token: tk[1],
2614 },
2615 Parsing: "CommandSubstitution",
2616 Token: tk[1],
2617 },
2618 Parsing: "WordPart",
2619 Token: tk[0],
2620 },
2621 Parsing: "Word",
2622 Token: tk[0],
2623 },
2624 Parsing: "WordOrOperator",
2625 Token: tk[0],
2626 }
2627 }},
2628 }, func(t *test) (Type, error) {
2629 var wo WordOrOperator
2630
2631 err := wo.parse(t.Parser)
2632
2633 return wo, err
2634 })
2635 }
2636