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::Redir;
29use crate::syntax::Scalar;
30use crate::syntax::SimpleCommand;
31use crate::syntax::Word;
32
33#[derive(Default)]
35struct Builder {
36 assigns: Vec<Assign>,
37 words: Vec<Word>,
38 redirs: Vec<Redir>,
39}
40
41impl Builder {
42 fn is_empty(&self) -> bool {
43 self.assigns.is_empty() && self.words.is_empty() && self.redirs.is_empty()
44 }
45}
46
47impl From<Builder> for SimpleCommand {
48 fn from(builder: Builder) -> Self {
49 SimpleCommand {
50 assigns: builder.assigns,
51 words: builder.words,
52 redirs: builder.redirs.into(),
53 }
54 }
55}
56
57impl Parser<'_, '_> {
58 pub async fn array_values(&mut self) -> Result<Option<Vec<Word>>> {
66 if self.peek_token().await?.id != Operator(OpenParen) {
67 return Ok(None);
68 }
69
70 let opening_location = self.take_token_raw().await?.word.location;
71 let mut words = vec![];
72
73 loop {
74 let next = self.take_token_auto(&[]).await?;
75 match next.id {
76 Operator(Newline) => continue,
77 Operator(CloseParen) => break,
78 Token(_keyword) => words.push(next.word),
79 _ => {
80 return Err(Error {
81 cause: SyntaxError::UnclosedArrayValue { opening_location }.into(),
82 location: next.word.location,
83 })
84 }
85 }
86 }
87
88 Ok(Some(words))
89 }
90
91 pub async fn simple_command(&mut self) -> Result<Rec<Option<SimpleCommand>>> {
96 let mut result = Builder::default();
97
98 loop {
99 if let Some(redir) = self.redirection().await? {
101 result.redirs.push(redir);
102 continue;
103 }
104
105 match self.peek_token().await?.id {
107 Token(Some(_keyword)) if result.is_empty() => break,
108 Token(_) => (),
109 _ => break,
110 }
111
112 let token = match self.take_token_manual(result.words.is_empty()).await? {
114 Rec::AliasSubstituted => {
115 if result.is_empty() {
116 return Ok(Rec::AliasSubstituted);
117 } else {
118 continue;
119 }
120 }
121 Rec::Parsed(token) => token,
122 };
123
124 if !result.words.is_empty() {
126 result.words.push(token.word);
127 continue;
128 }
129 let mut assign = match Assign::try_from(token.word) {
130 Ok(assign) => assign,
131 Err(word) => {
132 result.words.push(word);
133 continue;
134 }
135 };
136
137 let units = match &assign.value {
138 Scalar(Word { units, .. }) => units,
139 _ => panic!(
140 "Assign::try_from produced a non-scalar value {:?}",
141 assign.value
142 ),
143 };
144
145 if units.is_empty() && !self.has_blank().await? {
148 if let Some(words) = self.array_values().await? {
149 assign.value = Array(words);
150 }
151 }
152
153 result.assigns.push(assign);
154 }
155
156 Ok(Rec::Parsed(if result.is_empty() {
157 None
158 } else {
159 Some(result.into())
160 }))
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::super::error::ErrorCause;
167 use super::super::lex::Lexer;
168 use super::super::lex::TokenId::EndOfInput;
169 use super::*;
170 use crate::alias::EmptyGlossary;
171 use crate::source::Source;
172 use crate::syntax::RedirBody;
173 use crate::syntax::RedirOp;
174 use assert_matches::assert_matches;
175 use futures_util::FutureExt;
176
177 #[test]
178 fn parser_array_values_no_open_parenthesis() {
179 let mut lexer = Lexer::from_memory(")", Source::Unknown);
180 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
181 let result = parser.array_values().now_or_never().unwrap().unwrap();
182 assert_eq!(result, None);
183 }
184
185 #[test]
186 fn parser_array_values_empty() {
187 let mut lexer = Lexer::from_memory("()", Source::Unknown);
188 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
189 let result = parser.array_values().now_or_never().unwrap();
190 let words = result.unwrap().unwrap();
191 assert_eq!(words, []);
192
193 let next = parser.peek_token().now_or_never().unwrap().unwrap();
194 assert_eq!(next.id, EndOfInput);
195 }
196
197 #[test]
198 fn parser_array_values_many() {
199 let mut lexer = Lexer::from_memory("(a b c)", Source::Unknown);
200 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
201 let result = parser.array_values().now_or_never().unwrap();
202 let words = result.unwrap().unwrap();
203 assert_eq!(words.len(), 3);
204 assert_eq!(words[0].to_string(), "a");
205 assert_eq!(words[1].to_string(), "b");
206 assert_eq!(words[2].to_string(), "c");
207 }
208
209 #[test]
210 fn parser_array_values_newlines_and_comments() {
211 let mut lexer = Lexer::from_memory(
212 "(
213 a # b
214 c d
215 )",
216 Source::Unknown,
217 );
218 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
219 let result = parser.array_values().now_or_never().unwrap();
220 let words = result.unwrap().unwrap();
221 assert_eq!(words.len(), 3);
222 assert_eq!(words[0].to_string(), "a");
223 assert_eq!(words[1].to_string(), "c");
224 assert_eq!(words[2].to_string(), "d");
225 }
226
227 #[test]
228 fn parser_array_values_unclosed() {
229 let mut lexer = Lexer::from_memory("(a b", Source::Unknown);
230 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
231 let e = parser.array_values().now_or_never().unwrap().unwrap_err();
232 assert_matches!(e.cause,
233 ErrorCause::Syntax(SyntaxError::UnclosedArrayValue { opening_location }) => {
234 assert_eq!(*opening_location.code.value.borrow(), "(a b");
235 assert_eq!(opening_location.code.start_line_number.get(), 1);
236 assert_eq!(*opening_location.code.source, Source::Unknown);
237 assert_eq!(opening_location.range, 0..1);
238 });
239 assert_eq!(*e.location.code.value.borrow(), "(a b");
240 assert_eq!(e.location.code.start_line_number.get(), 1);
241 assert_eq!(*e.location.code.source, Source::Unknown);
242 assert_eq!(e.location.range, 4..4);
243 }
244
245 #[test]
246 fn parser_array_values_invalid_word() {
247 let mut lexer = Lexer::from_memory("(a;b)", Source::Unknown);
248 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
249 let e = parser.array_values().now_or_never().unwrap().unwrap_err();
250 assert_matches!(e.cause,
251 ErrorCause::Syntax(SyntaxError::UnclosedArrayValue { opening_location }) => {
252 assert_eq!(*opening_location.code.value.borrow(), "(a;b)");
253 assert_eq!(opening_location.code.start_line_number.get(), 1);
254 assert_eq!(*opening_location.code.source, Source::Unknown);
255 assert_eq!(opening_location.range, 0..1);
256 });
257 assert_eq!(*e.location.code.value.borrow(), "(a;b)");
258 assert_eq!(e.location.code.start_line_number.get(), 1);
259 assert_eq!(*e.location.code.source, Source::Unknown);
260 assert_eq!(e.location.range, 2..3);
261 }
262
263 #[test]
264 fn parser_simple_command_eof() {
265 let mut lexer = Lexer::from_memory("", Source::Unknown);
266 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
267
268 let result = parser.simple_command().now_or_never().unwrap();
269 assert_eq!(result, Ok(Rec::Parsed(None)));
270 }
271
272 #[test]
273 fn parser_simple_command_keyword() {
274 let mut lexer = Lexer::from_memory("then", Source::Unknown);
275 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
276
277 let result = parser.simple_command().now_or_never().unwrap();
278 assert_eq!(result, Ok(Rec::Parsed(None)));
279 }
280
281 #[test]
282 fn parser_simple_command_one_assignment() {
283 let mut lexer = Lexer::from_memory("my=assignment", Source::Unknown);
284 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
285
286 let result = parser.simple_command().now_or_never().unwrap();
287 let sc = result.unwrap().unwrap().unwrap();
288 assert_eq!(sc.words, []);
289 assert_eq!(*sc.redirs, []);
290 assert_eq!(sc.assigns.len(), 1);
291 assert_eq!(sc.assigns[0].name, "my");
292 assert_eq!(sc.assigns[0].value.to_string(), "assignment");
293 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "my=assignment");
294 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
295 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
296 assert_eq!(sc.assigns[0].location.range, 0..13);
297 }
298
299 #[test]
300 fn parser_simple_command_many_assignments() {
301 let mut lexer = Lexer::from_memory("a= b=! c=X", Source::Unknown);
302 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
303
304 let result = parser.simple_command().now_or_never().unwrap();
305 let sc = result.unwrap().unwrap().unwrap();
306 assert_eq!(sc.words, []);
307 assert_eq!(*sc.redirs, []);
308 assert_eq!(sc.assigns.len(), 3);
309 assert_eq!(sc.assigns[0].name, "a");
310 assert_eq!(sc.assigns[0].value.to_string(), "");
311 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a= b=! c=X");
312 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
313 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
314 assert_eq!(sc.assigns[0].location.range, 0..2);
315 assert_eq!(sc.assigns[1].name, "b");
316 assert_eq!(sc.assigns[1].value.to_string(), "!");
317 assert_eq!(*sc.assigns[1].location.code.value.borrow(), "a= b=! c=X");
318 assert_eq!(sc.assigns[1].location.code.start_line_number.get(), 1);
319 assert_eq!(*sc.assigns[1].location.code.source, Source::Unknown);
320 assert_eq!(sc.assigns[1].location.range, 3..6);
321 assert_eq!(sc.assigns[2].name, "c");
322 assert_eq!(sc.assigns[2].value.to_string(), "X");
323 assert_eq!(*sc.assigns[2].location.code.value.borrow(), "a= b=! c=X");
324 assert_eq!(sc.assigns[2].location.code.start_line_number.get(), 1);
325 assert_eq!(*sc.assigns[2].location.code.source, Source::Unknown);
326 assert_eq!(sc.assigns[2].location.range, 7..10);
327 }
328
329 #[test]
330 fn parser_simple_command_one_word() {
331 let mut lexer = Lexer::from_memory("word", Source::Unknown);
332 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
333
334 let result = parser.simple_command().now_or_never().unwrap();
335 let sc = result.unwrap().unwrap().unwrap();
336 assert_eq!(sc.assigns, []);
337 assert_eq!(*sc.redirs, []);
338 assert_eq!(sc.words.len(), 1);
339 assert_eq!(sc.words[0].to_string(), "word");
340 }
341
342 #[test]
343 fn parser_simple_command_many_words() {
344 let mut lexer = Lexer::from_memory(": if then", Source::Unknown);
345 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
346
347 let result = parser.simple_command().now_or_never().unwrap();
348 let sc = result.unwrap().unwrap().unwrap();
349 assert_eq!(sc.assigns, []);
350 assert_eq!(*sc.redirs, []);
351 assert_eq!(sc.words.len(), 3);
352 assert_eq!(sc.words[0].to_string(), ":");
353 assert_eq!(sc.words[1].to_string(), "if");
354 assert_eq!(sc.words[2].to_string(), "then");
355 }
356
357 #[test]
358 fn parser_simple_command_one_redirection() {
359 let mut lexer = Lexer::from_memory("<foo", Source::Unknown);
360 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
361
362 let result = parser.simple_command().now_or_never().unwrap();
363 let sc = result.unwrap().unwrap().unwrap();
364 assert_eq!(sc.assigns, []);
365 assert_eq!(sc.words, []);
366 assert_eq!(sc.redirs.len(), 1);
367 assert_eq!(sc.redirs[0].fd, None);
368 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
369 assert_eq!(operator, &RedirOp::FileIn);
370 assert_eq!(operand.to_string(), "foo")
371 });
372
373 let next = parser.peek_token().now_or_never().unwrap().unwrap();
374 assert_eq!(next.id, EndOfInput);
375 }
376
377 #[test]
378 fn parser_simple_command_many_redirections() {
379 let mut lexer = Lexer::from_memory("<one >two >>three", Source::Unknown);
380 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
381
382 let result = parser.simple_command().now_or_never().unwrap();
383 let sc = result.unwrap().unwrap().unwrap();
384 assert_eq!(sc.assigns, []);
385 assert_eq!(sc.words, []);
386 assert_eq!(sc.redirs.len(), 3);
387 assert_eq!(sc.redirs[0].fd, None);
388 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
389 assert_eq!(operator, &RedirOp::FileIn);
390 assert_eq!(operand.to_string(), "one")
391 });
392 assert_eq!(sc.redirs[1].fd, None);
393 assert_matches!(sc.redirs[1].body, RedirBody::Normal { ref operator, ref operand } => {
394 assert_eq!(operator, &RedirOp::FileOut);
395 assert_eq!(operand.to_string(), "two")
396 });
397 assert_eq!(sc.redirs[2].fd, None);
398 assert_matches!(sc.redirs[2].body, RedirBody::Normal { ref operator, ref operand } => {
399 assert_eq!(operator, &RedirOp::FileAppend);
400 assert_eq!(operand.to_string(), "three")
401 });
402
403 let next = parser.peek_token().now_or_never().unwrap().unwrap();
404 assert_eq!(next.id, EndOfInput);
405 }
406
407 #[test]
408 fn parser_simple_command_assignment_word() {
409 let mut lexer = Lexer::from_memory("if=then else", Source::Unknown);
410 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
411
412 let result = parser.simple_command().now_or_never().unwrap();
413 let sc = result.unwrap().unwrap().unwrap();
414 assert_eq!(*sc.redirs, []);
415 assert_eq!(sc.assigns.len(), 1);
416 assert_eq!(sc.words.len(), 1);
417 assert_eq!(sc.assigns[0].name, "if");
418 assert_eq!(sc.assigns[0].value.to_string(), "then");
419 assert_eq!(sc.words[0].to_string(), "else");
420 }
421
422 #[test]
423 fn parser_simple_command_word_redirection() {
424 let mut lexer = Lexer::from_memory("word <redirection", Source::Unknown);
425 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
426
427 let result = parser.simple_command().now_or_never().unwrap();
428 let sc = result.unwrap().unwrap().unwrap();
429 assert_eq!(sc.assigns, []);
430 assert_eq!(sc.words.len(), 1);
431 assert_eq!(sc.redirs.len(), 1);
432 assert_eq!(sc.words[0].to_string(), "word");
433 assert_eq!(sc.redirs[0].fd, None);
434 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
435 assert_eq!(operator, &RedirOp::FileIn);
436 assert_eq!(operand.to_string(), "redirection")
437 });
438 }
439
440 #[test]
441 fn parser_simple_command_redirection_assignment() {
442 let mut lexer = Lexer::from_memory("<foo a=b", Source::Unknown);
443 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
444
445 let result = parser.simple_command().now_or_never().unwrap();
446 let sc = result.unwrap().unwrap().unwrap();
447 assert_eq!(sc.words, []);
448 assert_eq!(sc.assigns.len(), 1);
449 assert_eq!(sc.redirs.len(), 1);
450 assert_eq!(sc.assigns[0].name, "a");
451 assert_eq!(sc.assigns[0].value.to_string(), "b");
452 assert_eq!(sc.redirs[0].fd, None);
453 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
454 assert_eq!(operator, &RedirOp::FileIn);
455 assert_eq!(operand.to_string(), "foo")
456 });
457 }
458
459 #[test]
460 fn parser_simple_command_assignment_redirection_word() {
461 let mut lexer = Lexer::from_memory("if=then <foo else", Source::Unknown);
462 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
463
464 let result = parser.simple_command().now_or_never().unwrap();
465 let sc = result.unwrap().unwrap().unwrap();
466 assert_eq!(sc.assigns.len(), 1);
467 assert_eq!(sc.words.len(), 1);
468 assert_eq!(sc.redirs.len(), 1);
469 assert_eq!(sc.assigns[0].name, "if");
470 assert_eq!(sc.assigns[0].value.to_string(), "then");
471 assert_eq!(sc.words[0].to_string(), "else");
472 assert_eq!(sc.redirs[0].fd, None);
473 assert_matches!(sc.redirs[0].body, RedirBody::Normal { ref operator, ref operand } => {
474 assert_eq!(operator, &RedirOp::FileIn);
475 assert_eq!(operand.to_string(), "foo")
476 });
477 }
478
479 #[test]
480 fn parser_simple_command_array_assignment() {
481 let mut lexer = Lexer::from_memory("a=()", Source::Unknown);
482 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
483
484 let result = parser.simple_command().now_or_never().unwrap();
485 let sc = result.unwrap().unwrap().unwrap();
486 assert_eq!(sc.assigns.len(), 1);
487 assert_eq!(sc.words, []);
488 assert_eq!(*sc.redirs, []);
489 assert_eq!(sc.assigns[0].name, "a");
490 assert_matches!(&sc.assigns[0].value, Array(words) => {
491 assert_eq!(words, &[]);
492 });
493
494 let next = parser.peek_token().now_or_never().unwrap().unwrap();
495 assert_eq!(next.id, EndOfInput);
496 }
497
498 #[test]
499 fn parser_simple_command_empty_assignment_followed_by_blank_and_parenthesis() {
500 let mut lexer = Lexer::from_memory("a= ()", Source::Unknown);
501 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
502
503 let result = parser.simple_command().now_or_never().unwrap();
504 let sc = result.unwrap().unwrap().unwrap();
505 assert_eq!(sc.assigns.len(), 1);
506 assert_eq!(sc.words, []);
507 assert_eq!(*sc.redirs, []);
508 assert_eq!(sc.assigns[0].name, "a");
509 assert_eq!(sc.assigns[0].value.to_string(), "");
510 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a= ()");
511 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
512 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
513 assert_eq!(sc.assigns[0].location.range, 0..2);
514
515 let next = parser.peek_token().now_or_never().unwrap().unwrap();
516 assert_eq!(next.id, Operator(OpenParen));
517 }
518
519 #[test]
520 fn parser_simple_command_non_empty_assignment_followed_by_parenthesis() {
521 let mut lexer = Lexer::from_memory("a=b()", Source::Unknown);
522 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
523
524 let result = parser.simple_command().now_or_never().unwrap();
525 let sc = result.unwrap().unwrap().unwrap();
526 assert_eq!(sc.assigns.len(), 1);
527 assert_eq!(sc.words, []);
528 assert_eq!(*sc.redirs, []);
529 assert_eq!(sc.assigns[0].name, "a");
530 assert_eq!(sc.assigns[0].value.to_string(), "b");
531 assert_eq!(*sc.assigns[0].location.code.value.borrow(), "a=b()");
532 assert_eq!(sc.assigns[0].location.code.start_line_number.get(), 1);
533 assert_eq!(*sc.assigns[0].location.code.source, Source::Unknown);
534 assert_eq!(sc.assigns[0].location.range, 0..3);
535
536 let next = parser.peek_token().now_or_never().unwrap().unwrap();
537 assert_eq!(next.id, Operator(OpenParen));
538 }
539}