1use super::core::Parser;
20use super::core::Rec;
21use super::core::Result;
22use super::error::Error;
23use super::error::SyntaxError;
24use super::lex::Operator::{CloseParen, Newline, OpenParen};
25use super::lex::TokenId::{Operator, Token};
26use crate::syntax::Array;
27use crate::syntax::Assign;
28use crate::syntax::ExpansionMode;
29use crate::syntax::MaybeLiteral as _;
30use crate::syntax::Redir;
31use crate::syntax::Scalar;
32use crate::syntax::SimpleCommand;
33use crate::syntax::Word;
34
35fn determine_expansion_mode(word: Word) -> (Word, ExpansionMode) {
45 use crate::syntax::{TextUnit::Literal, WordUnit::Unquoted};
46 if let Some(eq) = word.units.iter().position(|u| *u == Unquoted(Literal('='))) {
47 if let Some(name) = word.units[..eq].to_string_if_literal() {
48 if !name.is_empty() {
49 let mut word = word;
50 word.parse_tilde_everywhere_after(eq + 1);
51 return (word, ExpansionMode::Single);
52 }
53 }
54 }
55 (word, ExpansionMode::Multiple)
56}
57
58#[derive(Default)]
60struct Builder {
61 assigns: Vec<Assign>,
62 words: Vec<(Word, ExpansionMode)>,
63 redirs: Vec<Redir>,
64}
65
66impl Builder {
67 fn is_empty(&self) -> bool {
68 self.assigns.is_empty() && self.words.is_empty() && self.redirs.is_empty()
69 }
70}
71
72impl From<Builder> for SimpleCommand {
73 fn from(builder: Builder) -> Self {
74 SimpleCommand {
75 assigns: builder.assigns,
76 words: builder.words,
77 redirs: builder.redirs.into(),
78 }
79 }
80}
81
82impl Parser<'_, '_> {
83 pub async fn array_values(&mut self) -> Result<Option<Vec<Word>>> {
91 if self.peek_token().await?.id != Operator(OpenParen) {
92 return Ok(None);
93 }
94
95 let opening_location = self.take_token_raw().await?.word.location;
96 let mut words = vec![];
97
98 loop {
99 let next = self.take_token_auto(&[]).await?;
100 match next.id {
101 Operator(Newline) => continue,
102 Operator(CloseParen) => break,
103 Token(_keyword) => words.push(next.word),
104 _ => {
105 return Err(Error {
106 cause: SyntaxError::UnclosedArrayValue { opening_location }.into(),
107 location: next.word.location,
108 });
109 }
110 }
111 }
112
113 Ok(Some(words))
114 }
115
116 pub async fn simple_command(&mut self) -> Result<Rec<Option<SimpleCommand>>> {
121 let mut is_declaration_utility = None;
122 let mut result = Builder::default();
123
124 loop {
125 if let Some(redir) = self.redirection().await? {
127 result.redirs.push(redir);
128 continue;
129 }
130
131 match self.peek_token().await?.id {
133 Token(Some(_keyword)) if result.is_empty() => break,
134 Token(_) => (),
135 _ => break,
136 }
137
138 let token = match self.take_token_manual(result.words.is_empty()).await? {
140 Rec::AliasSubstituted => {
141 if result.is_empty() {
142 return Ok(Rec::AliasSubstituted);
143 } else {
144 continue;
145 }
146 }
147 Rec::Parsed(token) => token,
148 };
149
150 if let Some(is_declaration_utility) = is_declaration_utility {
152 debug_assert!(!result.words.is_empty());
155
156 result.words.push(if is_declaration_utility {
157 determine_expansion_mode(token.word)
158 } else {
159 (token.word, ExpansionMode::Multiple)
160 });
161 continue;
162 }
163
164 let assign_or_word = if result.words.is_empty() {
166 Assign::try_from(token.word)
168 } else {
169 Err(token.word)
171 };
172 let mut assign = match assign_or_word {
173 Ok(assign) => assign,
174 Err(word) => {
175 debug_assert!(is_declaration_utility.is_none());
176 is_declaration_utility = self.word_names_declaration_utility(&word);
177 result.words.push((word, ExpansionMode::Multiple));
178 continue;
179 }
180 };
181
182 let units = match &assign.value {
183 Scalar(Word { units, .. }) => units,
184 _ => panic!(
185 "Assign::try_from produced a non-scalar value {:?}",
186 assign.value
187 ),
188 };
189
190 if units.is_empty() && !self.has_blank().await? {
193 if let Some(words) = self.array_values().await? {
194 assign.value = Array(words);
195 }
196 }
197
198 result.assigns.push(assign);
199 }
200
201 Ok(Rec::Parsed((!result.is_empty()).then(|| result.into())))
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::super::error::ErrorCause;
208 use super::super::lex::Lexer;
209 use super::super::lex::TokenId::EndOfInput;
210 use super::*;
211 use crate::decl_util::EmptyGlossary;
212 use crate::source::Source;
213 use crate::syntax::RedirBody;
214 use crate::syntax::RedirOp;
215 use crate::syntax::TextUnit;
216 use crate::syntax::WordUnit;
217 use assert_matches::assert_matches;
218 use futures_util::FutureExt as _;
219
220 #[test]
221 fn determine_expansion_mode_empty_name() {
222 let in_word = "=".parse::<Word>().unwrap();
223 let (out_word, mode) = determine_expansion_mode(in_word.clone());
224 assert_eq!(out_word, in_word);
225 assert_eq!(mode, ExpansionMode::Multiple);
226 }
227
228 #[test]
229 fn determine_expansion_mode_nonempty_name() {
230 let in_word = "foo=".parse::<Word>().unwrap();
231 let (out_word, mode) = determine_expansion_mode(in_word.clone());
232 assert_eq!(out_word, in_word);
233 assert_eq!(mode, ExpansionMode::Single);
234 }
235
236 #[test]
237 fn determine_expansion_mode_non_literal_name() {
238 let in_word = "${X}=".parse::<Word>().unwrap();
239 let (out_word, mode) = determine_expansion_mode(in_word.clone());
240 assert_eq!(out_word, in_word);
241 assert_eq!(mode, ExpansionMode::Multiple);
242 }
243
244 #[test]
245 fn determine_expansion_mode_tilde_expansions_after_equal() {
246 let word = "~=~:~b".parse().unwrap();
247 let (word, mode) = determine_expansion_mode(word);
248 assert_eq!(
249 word.units,
250 [
251 WordUnit::Unquoted(TextUnit::Literal('~')),
252 WordUnit::Unquoted(TextUnit::Literal('=')),
253 WordUnit::Tilde("".to_string()),
254 WordUnit::Unquoted(TextUnit::Literal(':')),
255 WordUnit::Tilde("b".to_string()),
256 ]
257 );
258 assert_eq!(mode, ExpansionMode::Single);
259 }
260
261 #[test]
262 fn parser_array_values_no_open_parenthesis() {
263 let mut lexer = Lexer::with_code(")");
264 let mut parser = Parser::new(&mut lexer);
265 let result = parser.array_values().now_or_never().unwrap().unwrap();
266 assert_eq!(result, None);
267 }
268
269 #[test]
270 fn parser_array_values_empty() {
271 let mut lexer = Lexer::with_code("()");
272 let mut parser = Parser::new(&mut lexer);
273 let result = parser.array_values().now_or_never().unwrap();
274 let words = result.unwrap().unwrap();
275 assert_eq!(words, []);
276
277 let next = parser.peek_token().now_or_never().unwrap().unwrap();
278 assert_eq!(next.id, EndOfInput);
279 }
280
281 #[test]
282 fn parser_array_values_many() {
283 let mut lexer = Lexer::with_code("(a b c)");
284 let mut parser = Parser::new(&mut lexer);
285 let result = parser.array_values().now_or_never().unwrap();
286 let words = result.unwrap().unwrap();
287 assert_eq!(words.len(), 3);
288 assert_eq!(words[0].to_string(), "a");
289 assert_eq!(words[1].to_string(), "b");
290 assert_eq!(words[2].to_string(), "c");
291 }
292
293 #[test]
294 fn parser_array_values_newlines_and_comments() {
295 let mut lexer = Lexer::with_code(
296 "(
297 a # b
298 c d
299 )",
300 );
301 let mut parser = Parser::new(&mut lexer);
302 let result = parser.array_values().now_or_never().unwrap();
303 let words = result.unwrap().unwrap();
304 assert_eq!(words.len(), 3);
305 assert_eq!(words[0].to_string(), "a");
306 assert_eq!(words[1].to_string(), "c");
307 assert_eq!(words[2].to_string(), "d");
308 }
309
310 #[test]
311 fn parser_array_values_unclosed() {
312 let mut lexer = Lexer::with_code("(a b");
313 let mut parser = Parser::new(&mut lexer);
314 let e = parser.array_values().now_or_never().unwrap().unwrap_err();
315 assert_matches!(e.cause,
316 ErrorCause::Syntax(SyntaxError::UnclosedArrayValue { opening_location }) => {
317 assert_eq!(*opening_location.code.value.borrow(), "(a b");
318 assert_eq!(opening_location.code.start_line_number.get(), 1);
319 assert_eq!(*opening_location.code.source, Source::Unknown);
320 assert_eq!(opening_location.range, 0..1);
321 });
322 assert_eq!(*e.location.code.value.borrow(), "(a b");
323 assert_eq!(e.location.code.start_line_number.get(), 1);
324 assert_eq!(*e.location.code.source, Source::Unknown);
325 assert_eq!(e.location.range, 4..4);
326 }
327
328 #[test]
329 fn parser_array_values_invalid_word() {
330 let mut lexer = Lexer::with_code("(a;b)");
331 let mut parser = Parser::new(&mut lexer);
332 let e = parser.array_values().now_or_never().unwrap().unwrap_err();
333 assert_matches!(e.cause,
334 ErrorCause::Syntax(SyntaxError::UnclosedArrayValue { opening_location }) => {
335 assert_eq!(*opening_location.code.value.borrow(), "(a;b)");
336 assert_eq!(opening_location.code.start_line_number.get(), 1);
337 assert_eq!(*opening_location.code.source, Source::Unknown);
338 assert_eq!(opening_location.range, 0..1);
339 });
340 assert_eq!(*e.location.code.value.borrow(), "(a;b)");
341 assert_eq!(e.location.code.start_line_number.get(), 1);
342 assert_eq!(*e.location.code.source, Source::Unknown);
343 assert_eq!(e.location.range, 2..3);
344 }
345
346 #[test]
347 fn parser_simple_command_eof() {
348 let mut lexer = Lexer::with_code("");
349 let mut parser = Parser::new(&mut lexer);
350
351 let result = parser.simple_command().now_or_never().unwrap();
352 assert_eq!(result, Ok(Rec::Parsed(None)));
353 }
354
355 #[test]
356 fn parser_simple_command_keyword() {
357 let mut lexer = Lexer::with_code("then");
358 let mut parser = Parser::new(&mut lexer);
359
360 let result = parser.simple_command().now_or_never().unwrap();
361 assert_eq!(result, Ok(Rec::Parsed(None)));
362 }
363
364 #[test]
365 fn parser_simple_command_one_assignment() {
366 let mut lexer = Lexer::with_code("my=assignment");
367 let mut parser = Parser::new(&mut lexer);
368
369 let result = parser.simple_command().now_or_never().unwrap();
370 let sc = result.unwrap().unwrap().unwrap();
371 assert_eq!(sc.words, []);
372 assert_eq!(*sc.redirs, []);
373 assert_eq!(sc.assigns.len(), 1);
374 assert_eq!(sc.assigns[0].name, "my");
375 assert_eq!(sc.assigns[0].value.to_string(), "assignment");
376 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "my=assignment");
377 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
378 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
379 assert_eq!(sc.assigns[0].location.range, 0..13);
380 }
381
382 #[test]
383 fn parser_simple_command_many_assignments() {
384 let mut lexer = Lexer::with_code("a= b=! c=X");
385 let mut parser = Parser::new(&mut lexer);
386
387 let result = parser.simple_command().now_or_never().unwrap();
388 let sc = result.unwrap().unwrap().unwrap();
389 assert_eq!(sc.words, []);
390 assert_eq!(*sc.redirs, []);
391 assert_eq!(sc.assigns.len(), 3);
392 assert_eq!(sc.assigns[0].name, "a");
393 assert_eq!(sc.assigns[0].value.to_string(), "");
394 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a= b=! c=X");
395 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
396 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
397 assert_eq!(sc.assigns[0].location.range, 0..2);
398 assert_eq!(sc.assigns[1].name, "b");
399 assert_eq!(sc.assigns[1].value.to_string(), "!");
400 assert_eq!(*sc.assigns[1].location.code.value.borrow(), "a= b=! c=X");
401 assert_eq!(sc.assigns[1].location.code.start_line_number.get(), 1);
402 assert_eq!(*sc.assigns[1].location.code.source, Source::Unknown);
403 assert_eq!(sc.assigns[1].location.range, 3..6);
404 assert_eq!(sc.assigns[2].name, "c");
405 assert_eq!(sc.assigns[2].value.to_string(), "X");
406 assert_eq!(*sc.assigns[2].location.code.value.borrow(), "a= b=! c=X");
407 assert_eq!(sc.assigns[2].location.code.start_line_number.get(), 1);
408 assert_eq!(*sc.assigns[2].location.code.source, Source::Unknown);
409 assert_eq!(sc.assigns[2].location.range, 7..10);
410 }
411
412 #[test]
413 fn parser_simple_command_one_word() {
414 let mut lexer = Lexer::with_code("word");
415 let mut parser = Parser::new(&mut lexer);
416
417 let result = parser.simple_command().now_or_never().unwrap();
418 let sc = result.unwrap().unwrap().unwrap();
419 assert_eq!(sc.assigns, []);
420 assert_eq!(*sc.redirs, []);
421 assert_eq!(sc.words.len(), 1);
422 assert_eq!(sc.words[0].0.to_string(), "word");
423 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
424 }
425
426 #[test]
427 fn parser_simple_command_many_words() {
428 let mut lexer = Lexer::with_code(": if then");
429 let mut parser = Parser::new(&mut lexer);
430
431 let result = parser.simple_command().now_or_never().unwrap();
432 let sc = result.unwrap().unwrap().unwrap();
433 assert_eq!(sc.assigns, []);
434 assert_eq!(*sc.redirs, []);
435 assert_eq!(sc.words.len(), 3);
436 assert_eq!(sc.words[0].0.to_string(), ":");
437 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
438 assert_eq!(sc.words[1].0.to_string(), "if");
439 assert_eq!(sc.words[1].1, ExpansionMode::Multiple);
440 assert_eq!(sc.words[2].0.to_string(), "then");
441 assert_eq!(sc.words[2].1, ExpansionMode::Multiple);
442 }
443
444 #[test]
445 fn parser_simple_command_one_redirection() {
446 let mut lexer = Lexer::with_code("<foo");
447 let mut parser = Parser::new(&mut lexer);
448
449 let result = parser.simple_command().now_or_never().unwrap();
450 let sc = result.unwrap().unwrap().unwrap();
451 assert_eq!(sc.assigns, []);
452 assert_eq!(sc.words, []);
453 assert_eq!(sc.redirs.len(), 1);
454 assert_eq!(sc.redirs[0].fd, None);
455 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
456 assert_eq!(operator, &RedirOp::FileIn);
457 assert_eq!(operand.to_string(), "foo")
458 });
459
460 let next = parser.peek_token().now_or_never().unwrap().unwrap();
461 assert_eq!(next.id, EndOfInput);
462 }
463
464 #[test]
465 fn parser_simple_command_many_redirections() {
466 let mut lexer = Lexer::with_code("<one >two >>three");
467 let mut parser = Parser::new(&mut lexer);
468
469 let result = parser.simple_command().now_or_never().unwrap();
470 let sc = result.unwrap().unwrap().unwrap();
471 assert_eq!(sc.assigns, []);
472 assert_eq!(sc.words, []);
473 assert_eq!(sc.redirs.len(), 3);
474 assert_eq!(sc.redirs[0].fd, None);
475 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
476 assert_eq!(operator, &RedirOp::FileIn);
477 assert_eq!(operand.to_string(), "one")
478 });
479 assert_eq!(sc.redirs[1].fd, None);
480 assert_matches!(sc.redirs[1].body, RedirBody::Normal { ref operator, ref operand } => {
481 assert_eq!(operator, &RedirOp::FileOut);
482 assert_eq!(operand.to_string(), "two")
483 });
484 assert_eq!(sc.redirs[2].fd, None);
485 assert_matches!(sc.redirs[2].body, RedirBody::Normal { ref operator, ref operand } => {
486 assert_eq!(operator, &RedirOp::FileAppend);
487 assert_eq!(operand.to_string(), "three")
488 });
489
490 let next = parser.peek_token().now_or_never().unwrap().unwrap();
491 assert_eq!(next.id, EndOfInput);
492 }
493
494 #[test]
495 fn parser_simple_command_assignment_word() {
496 let mut lexer = Lexer::with_code("if=then else");
497 let mut parser = Parser::new(&mut lexer);
498
499 let result = parser.simple_command().now_or_never().unwrap();
500 let sc = result.unwrap().unwrap().unwrap();
501 assert_eq!(*sc.redirs, []);
502 assert_eq!(sc.assigns.len(), 1);
503 assert_eq!(sc.words.len(), 1);
504 assert_eq!(sc.assigns[0].name, "if");
505 assert_eq!(sc.assigns[0].value.to_string(), "then");
506 assert_eq!(sc.words[0].0.to_string(), "else");
507 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
508 }
509
510 #[test]
511 fn parser_simple_command_word_redirection() {
512 let mut lexer = Lexer::with_code("word <redirection");
513 let mut parser = Parser::new(&mut lexer);
514
515 let result = parser.simple_command().now_or_never().unwrap();
516 let sc = result.unwrap().unwrap().unwrap();
517 assert_eq!(sc.assigns, []);
518 assert_eq!(sc.words.len(), 1);
519 assert_eq!(sc.redirs.len(), 1);
520 assert_eq!(sc.words[0].0.to_string(), "word");
521 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
522 assert_eq!(sc.redirs[0].fd, None);
523 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
524 assert_eq!(operator, &RedirOp::FileIn);
525 assert_eq!(operand.to_string(), "redirection")
526 });
527 }
528
529 #[test]
530 fn parser_simple_command_redirection_assignment() {
531 let mut lexer = Lexer::with_code("<foo a=b");
532 let mut parser = Parser::new(&mut lexer);
533
534 let result = parser.simple_command().now_or_never().unwrap();
535 let sc = result.unwrap().unwrap().unwrap();
536 assert_eq!(sc.words, []);
537 assert_eq!(sc.assigns.len(), 1);
538 assert_eq!(sc.redirs.len(), 1);
539 assert_eq!(sc.assigns[0].name, "a");
540 assert_eq!(sc.assigns[0].value.to_string(), "b");
541 assert_eq!(sc.redirs[0].fd, None);
542 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
543 assert_eq!(operator, &RedirOp::FileIn);
544 assert_eq!(operand.to_string(), "foo")
545 });
546 }
547
548 #[test]
549 fn parser_simple_command_assignment_redirection_word() {
550 let mut lexer = Lexer::with_code("if=then <foo else");
551 let mut parser = Parser::new(&mut lexer);
552
553 let result = parser.simple_command().now_or_never().unwrap();
554 let sc = result.unwrap().unwrap().unwrap();
555 assert_eq!(sc.assigns.len(), 1);
556 assert_eq!(sc.words.len(), 1);
557 assert_eq!(sc.redirs.len(), 1);
558 assert_eq!(sc.assigns[0].name, "if");
559 assert_eq!(sc.assigns[0].value.to_string(), "then");
560 assert_eq!(sc.words[0].0.to_string(), "else");
561 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
562 assert_eq!(sc.redirs[0].fd, None);
563 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
564 assert_eq!(operator, &RedirOp::FileIn);
565 assert_eq!(operand.to_string(), "foo")
566 });
567 }
568
569 #[test]
570 fn parser_simple_command_array_assignment() {
571 let mut lexer = Lexer::with_code("a=()");
572 let mut parser = Parser::new(&mut lexer);
573
574 let result = parser.simple_command().now_or_never().unwrap();
575 let sc = result.unwrap().unwrap().unwrap();
576 assert_eq!(sc.assigns.len(), 1);
577 assert_eq!(sc.words, []);
578 assert_eq!(*sc.redirs, []);
579 assert_eq!(sc.assigns[0].name, "a");
580 assert_matches!(&sc.assigns[0].value, Array(words) => {
581 assert_eq!(words, &[]);
582 });
583
584 let next = parser.peek_token().now_or_never().unwrap().unwrap();
585 assert_eq!(next.id, EndOfInput);
586 }
587
588 #[test]
589 fn parser_simple_command_empty_assignment_followed_by_blank_and_parenthesis() {
590 let mut lexer = Lexer::with_code("a= ()");
591 let mut parser = Parser::new(&mut lexer);
592
593 let result = parser.simple_command().now_or_never().unwrap();
594 let sc = result.unwrap().unwrap().unwrap();
595 assert_eq!(sc.assigns.len(), 1);
596 assert_eq!(sc.words, []);
597 assert_eq!(*sc.redirs, []);
598 assert_eq!(sc.assigns[0].name, "a");
599 assert_eq!(sc.assigns[0].value.to_string(), "");
600 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a= ()");
601 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
602 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
603 assert_eq!(sc.assigns[0].location.range, 0..2);
604
605 let next = parser.peek_token().now_or_never().unwrap().unwrap();
606 assert_eq!(next.id, Operator(OpenParen));
607 }
608
609 #[test]
610 fn parser_simple_command_non_empty_assignment_followed_by_parenthesis() {
611 let mut lexer = Lexer::with_code("a=b()");
612 let mut parser = Parser::new(&mut lexer);
613
614 let result = parser.simple_command().now_or_never().unwrap();
615 let sc = result.unwrap().unwrap().unwrap();
616 assert_eq!(sc.assigns.len(), 1);
617 assert_eq!(sc.words, []);
618 assert_eq!(*sc.redirs, []);
619 assert_eq!(sc.assigns[0].name, "a");
620 assert_eq!(sc.assigns[0].value.to_string(), "b");
621 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a=b()");
622 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
623 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
624 assert_eq!(sc.assigns[0].location.range, 0..3);
625
626 let next = parser.peek_token().now_or_never().unwrap().unwrap();
627 assert_eq!(next.id, Operator(OpenParen));
628 }
629
630 #[test]
631 fn word_with_single_expansion_mode_in_declaration_utility() {
632 let mut lexer = Lexer::with_code("export a=b");
635 let mut parser = Parser::new(&mut lexer);
636
637 let result = parser.simple_command().now_or_never().unwrap();
638 let sc = result.unwrap().unwrap().unwrap();
639 assert_eq!(sc.assigns, []);
640 assert_eq!(sc.words.len(), 2);
641 assert_eq!(*sc.redirs, []);
642 assert_eq!(sc.words[0].0.to_string(), "export");
643 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
644 assert_eq!(sc.words[1].0.to_string(), "a=b");
645 assert_eq!(sc.words[1].1, ExpansionMode::Single);
646 }
647
648 #[test]
649 fn word_with_multiple_expansion_mode_in_declaration_utility() {
650 let mut lexer = Lexer::with_code("export foo");
653 let mut parser = Parser::new(&mut lexer);
654
655 let result = parser.simple_command().now_or_never().unwrap();
656 let sc = result.unwrap().unwrap().unwrap();
657 assert_eq!(sc.assigns, []);
658 assert_eq!(sc.words.len(), 2);
659 assert_eq!(*sc.redirs, []);
660 assert_eq!(sc.words[0].0.to_string(), "export");
661 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
662 assert_eq!(sc.words[1].0.to_string(), "foo");
663 assert_eq!(sc.words[1].1, ExpansionMode::Multiple);
664 }
665
666 #[test]
667 fn word_with_multiple_expansion_mode_in_non_declaration_utility() {
668 let mut lexer = Lexer::with_code("foo a=b");
671 let mut parser = Parser::new(&mut lexer);
672
673 let result = parser.simple_command().now_or_never().unwrap();
674 let sc = result.unwrap().unwrap().unwrap();
675 assert_eq!(sc.assigns, []);
676 assert_eq!(sc.words.len(), 2);
677 assert_eq!(*sc.redirs, []);
678 assert_eq!(sc.words[0].0.to_string(), "foo");
679 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
680 assert_eq!(sc.words[1].0.to_string(), "a=b");
681 assert_eq!(sc.words[1].1, ExpansionMode::Multiple);
682 }
683
684 #[test]
685 fn declaration_utility_determined_by_non_first_word() {
686 let mut lexer = Lexer::with_code("command command export foo a=b");
689 let mut parser = Parser::new(&mut lexer);
690 let result = parser.simple_command().now_or_never().unwrap();
691 let sc = result.unwrap().unwrap().unwrap();
692 assert_eq!(sc.words[4].0.to_string(), "a=b");
693 assert_eq!(sc.words[4].1, ExpansionMode::Single);
694
695 let mut lexer = Lexer::with_code("command command foo export a=b");
696 let mut parser = Parser::new(&mut lexer);
697 let result = parser.simple_command().now_or_never().unwrap();
698 let sc = result.unwrap().unwrap().unwrap();
699 assert_eq!(sc.words[4].0.to_string(), "a=b");
700 assert_eq!(sc.words[4].1, ExpansionMode::Multiple);
701 }
702
703 #[test]
704 fn no_declaration_utilities_with_empty_glossary() {
705 let mut lexer = Lexer::with_code("export a=b");
707 let mut parser = Parser::config()
708 .declaration_utilities(&EmptyGlossary)
709 .input(&mut lexer);
710
711 let result = parser.simple_command().now_or_never().unwrap();
712 let sc = result.unwrap().unwrap().unwrap();
713 assert_eq!(sc.assigns, []);
714 assert_eq!(sc.words.len(), 2);
715 assert_eq!(*sc.redirs, []);
716 assert_eq!(sc.words[0].0.to_string(), "export");
717 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
718 assert_eq!(sc.words[1].0.to_string(), "a=b");
719 assert_eq!(sc.words[1].1, ExpansionMode::Multiple);
720 }
721
722 #[test]
723 fn custom_declaration_utility_glossary() {
724 #[derive(Debug)]
726 struct CustomGlossary;
727 impl crate::decl_util::Glossary for CustomGlossary {
728 fn is_declaration_utility(&self, name: &str) -> Option<bool> {
729 Some(name == "foo")
730 }
731 }
732
733 let mut lexer = Lexer::with_code("foo a=b");
734 let mut parser = Parser::config()
735 .declaration_utilities(&CustomGlossary)
736 .input(&mut lexer);
737
738 let result = parser.simple_command().now_or_never().unwrap();
739 let sc = result.unwrap().unwrap().unwrap();
740 assert_eq!(sc.assigns, []);
741 assert_eq!(sc.words.len(), 2);
742 assert_eq!(*sc.redirs, []);
743 assert_eq!(sc.words[0].0.to_string(), "foo");
744 assert_eq!(sc.words[0].1, ExpansionMode::Multiple);
745 assert_eq!(sc.words[1].0.to_string(), "a=b");
746 assert_eq!(sc.words[1].1, ExpansionMode::Single);
747 }
748
749 #[test]
750 fn assignment_is_not_considered_for_declaration_utility() {
751 #[derive(Debug)]
752 struct CustomGlossary;
753 impl crate::decl_util::Glossary for CustomGlossary {
754 fn is_declaration_utility(&self, _name: &str) -> Option<bool> {
755 unreachable!("is_declaration_utility should not be called for assignments");
756 }
757 }
758
759 let mut lexer = Lexer::with_code("a=b");
760 let mut parser = Parser::config()
761 .declaration_utilities(&CustomGlossary)
762 .input(&mut lexer);
763
764 let result = parser.simple_command().now_or_never().unwrap();
765 let sc = result.unwrap().unwrap().unwrap();
766 assert_eq!(sc.assigns.len(), 1);
767 assert_eq!(sc.words, []);
768 assert_eq!(*sc.redirs, [])
769 }
770}