yash_syntax/parser/
command.rs1use super::core::Parser;
23use super::core::Rec;
24use super::core::Result;
25use super::lex::Keyword::{Function, OpenBracketBracket};
26use super::lex::TokenId::Token;
27use super::{Error, SyntaxError};
28use crate::syntax::Command;
29
30impl Parser<'_, '_> {
31 pub async fn command(&mut self) -> Result<Rec<Option<Command>>> {
36 match self.simple_command().await? {
37 Rec::AliasSubstituted => Ok(Rec::AliasSubstituted),
38
39 Rec::Parsed(None) => {
40 if let Some(compound) = self.full_compound_command().await? {
41 return Ok(Rec::Parsed(Some(Command::Compound(compound))));
42 }
43
44 let next = self.peek_token().await?;
45 match next.id {
46 Token(Some(Function)) => {
47 let cause = SyntaxError::UnsupportedFunctionDefinitionSyntax.into();
48 let location = next.word.location.clone();
49 Err(Error { cause, location })
50 }
51 Token(Some(OpenBracketBracket)) => {
52 let cause = SyntaxError::UnsupportedDoubleBracketCommand.into();
53 let location = next.word.location.clone();
54 Err(Error { cause, location })
55 }
56 _ => Ok(Rec::Parsed(None)),
57 }
58 }
59
60 Rec::Parsed(Some(c)) => self
61 .short_function_definition(c)
62 .await
63 .map(|c| Rec::Parsed(Some(c))),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::super::ErrorCause;
71 use super::super::lex::Lexer;
72 use super::super::lex::TokenId::EndOfInput;
73 use super::*;
74 use crate::source::Source;
75 use assert_matches::assert_matches;
76 use futures_util::FutureExt as _;
77
78 #[test]
79 fn parser_command_simple() {
80 let mut lexer = Lexer::with_code("foo < bar");
81 let mut parser = Parser::new(&mut lexer);
82
83 let result = parser.command().now_or_never().unwrap();
84 let command = result.unwrap().unwrap().unwrap();
85 assert_matches!(command, Command::Simple(c) => {
86 assert_eq!(c.to_string(), "foo <bar");
87 });
88
89 let next = parser.peek_token().now_or_never().unwrap().unwrap();
90 assert_eq!(next.id, EndOfInput);
91 }
92
93 #[test]
94 fn parser_command_compound() {
95 let mut lexer = Lexer::with_code("(foo) < bar");
96 let mut parser = Parser::new(&mut lexer);
97
98 let result = parser.command().now_or_never().unwrap();
99 let command = result.unwrap().unwrap().unwrap();
100 assert_matches!(command, Command::Compound(c) => {
101 assert_eq!(c.to_string(), "(foo) <bar");
102 });
103
104 let next = parser.peek_token().now_or_never().unwrap().unwrap();
105 assert_eq!(next.id, EndOfInput);
106 }
107
108 #[test]
109 fn parser_command_short_function() {
110 let mut lexer = Lexer::with_code("fun () ( echo )");
111 let mut parser = Parser::new(&mut lexer);
112
113 let result = parser.command().now_or_never().unwrap();
114 let command = result.unwrap().unwrap().unwrap();
115 assert_matches!(command, Command::Function(f) => {
116 assert_eq!(f.to_string(), "fun() (echo)");
117 });
118
119 let next = parser.peek_token().now_or_never().unwrap().unwrap();
120 assert_eq!(next.id, EndOfInput);
121 }
122
123 #[test]
124 fn parser_command_long_function() {
125 let mut lexer = Lexer::with_code(" function fun { echo; }");
126 let mut parser = Parser::new(&mut lexer);
127
128 let e = parser.command().now_or_never().unwrap().unwrap_err();
129 assert_eq!(
130 e.cause,
131 ErrorCause::Syntax(SyntaxError::UnsupportedFunctionDefinitionSyntax)
132 );
133 assert_eq!(*e.location.code.value.borrow(), " function fun { echo; }");
134 assert_eq!(e.location.code.start_line_number.get(), 1);
135 assert_eq!(*e.location.code.source, Source::Unknown);
136 assert_eq!(e.location.range, 2..10);
137 }
138
139 #[test]
140 fn parser_command_double_bracket() {
141 let mut lexer = Lexer::with_code(" [[ foo ]]");
142 let mut parser = Parser::new(&mut lexer);
143
144 let e = parser.command().now_or_never().unwrap().unwrap_err();
145 assert_eq!(
146 e.cause,
147 ErrorCause::Syntax(SyntaxError::UnsupportedDoubleBracketCommand)
148 );
149 assert_eq!(*e.location.code.value.borrow(), " [[ foo ]]");
150 assert_eq!(e.location.code.start_line_number.get(), 1);
151 assert_eq!(*e.location.code.source, Source::Unknown);
152 assert_eq!(e.location.range, 1..3);
153 }
154
155 #[test]
156 fn parser_command_eof() {
157 let mut lexer = Lexer::with_code("");
158 let mut parser = Parser::new(&mut lexer);
159
160 let result = parser.command().now_or_never().unwrap().unwrap();
161 assert_eq!(result, Rec::Parsed(None));
162 }
163}