yash_syntax/parser/
and_or.rs1use super::core::Parser;
20use super::core::Rec;
21use super::core::Result;
22use super::error::Error;
23use super::error::SyntaxError;
24use super::lex::Operator::{AndAnd, BarBar};
25use super::lex::TokenId::Operator;
26use crate::syntax::AndOr;
27use crate::syntax::AndOrList;
28
29impl Parser<'_, '_> {
30 pub async fn and_or_list(&mut self) -> Result<Rec<Option<AndOrList>>> {
35 let first = match self.pipeline().await? {
36 Rec::AliasSubstituted => return Ok(Rec::AliasSubstituted),
37 Rec::Parsed(None) => return Ok(Rec::Parsed(None)),
38 Rec::Parsed(Some(p)) => p,
39 };
40
41 let mut rest = vec![];
42 loop {
43 let condition = match self.peek_token().await?.id {
44 Operator(AndAnd) => AndOr::AndThen,
45 Operator(BarBar) => AndOr::OrElse,
46 _ => break,
47 };
48 self.take_token_raw().await?;
49
50 while self.newline_and_here_doc_contents().await? {}
51
52 let maybe_pipeline = loop {
53 if let Rec::Parsed(maybe_pipeline) = self.pipeline().await? {
54 break maybe_pipeline;
55 }
56 };
57 let pipeline = match maybe_pipeline {
58 None => {
59 let cause = SyntaxError::MissingPipeline(condition).into();
60 let location = self.peek_token().await?.word.location.clone();
61 return Err(Error { cause, location });
62 }
63 Some(pipeline) => pipeline,
64 };
65
66 rest.push((condition, pipeline));
67 }
68
69 Ok(Rec::Parsed(Some(AndOrList { first, rest })))
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::super::error::ErrorCause;
76 use super::super::lex::Lexer;
77 use super::*;
78 use crate::alias::EmptyGlossary;
79 use crate::source::Source;
80 use futures_util::FutureExt;
81
82 #[test]
83 fn parser_and_or_list_eof() {
84 let mut lexer = Lexer::from_memory("", Source::Unknown);
85 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
86
87 let result = parser.and_or_list().now_or_never().unwrap();
88 assert_eq!(result, Ok(Rec::Parsed(None)));
89 }
90
91 #[test]
92 fn parser_and_or_list_one() {
93 let mut lexer = Lexer::from_memory("foo", Source::Unknown);
94 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
95
96 let result = parser.and_or_list().now_or_never().unwrap();
97 let aol = result.unwrap().unwrap().unwrap();
98 assert_eq!(aol.first.to_string(), "foo");
99 assert_eq!(aol.rest, vec![]);
100 }
101
102 #[test]
103 fn parser_and_or_list_many() {
104 let mut lexer = Lexer::from_memory("first && second || \n\n third;", Source::Unknown);
105 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
106
107 let result = parser.and_or_list().now_or_never().unwrap();
108 let aol = result.unwrap().unwrap().unwrap();
109 assert_eq!(aol.first.to_string(), "first");
110 assert_eq!(aol.rest.len(), 2);
111 assert_eq!(aol.rest[0].0, AndOr::AndThen);
112 assert_eq!(aol.rest[0].1.to_string(), "second");
113 assert_eq!(aol.rest[1].0, AndOr::OrElse);
114 assert_eq!(aol.rest[1].1.to_string(), "third");
115 }
116
117 #[test]
118 fn parser_and_or_list_missing_command_after_and_and() {
119 let mut lexer = Lexer::from_memory("foo &&", Source::Unknown);
120 let mut parser = Parser::new(&mut lexer, &EmptyGlossary);
121
122 let e = parser.and_or_list().now_or_never().unwrap().unwrap_err();
123 assert_eq!(
124 e.cause,
125 ErrorCause::Syntax(SyntaxError::MissingPipeline(AndOr::AndThen))
126 );
127 assert_eq!(*e.location.code.value.borrow(), "foo &&");
128 assert_eq!(e.location.code.start_line_number.get(), 1);
129 assert_eq!(*e.location.code.source, Source::Unknown);
130 assert_eq!(e.location.range, 6..6);
131 }
132}