1use crate::{CollectionColumns, Type};
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub enum SyntaxShape {
14 Any,
16
17 Binary,
19
20 Block,
22
23 Boolean,
25
26 CellPath,
28
29 Closure(Option<Vec<SyntaxShape>>),
31
32 DateTime,
34
35 Directory,
37
38 Duration,
40
41 Error,
43
44 Expression,
46
47 ExternalArgument,
52
53 Filepath,
55
56 Filesize,
58
59 Float,
61
62 FullCellPath,
66
67 GlobPattern,
69
70 Int,
72
73 ImportPattern,
75
76 Keyword(Vec<u8>, Box<SyntaxShape>),
78
79 List(Box<SyntaxShape>),
81
82 MathExpression,
84
85 MatchBlock,
87
88 Nothing,
90
91 Number,
93
94 OneOf(Vec<SyntaxShape>),
96
97 Operator,
99
100 Range,
102
103 Record(CollectionColumns<SyntaxShape>),
105
106 RowCondition,
109
110 Signature,
112
113 ExternalSignature,
115
116 String,
118
119 Table(CollectionColumns<SyntaxShape>),
121
122 VarWithOptType,
124}
125
126impl SyntaxShape {
127 pub fn to_type(&self) -> Type {
138 match self {
139 SyntaxShape::Any => Type::Any,
140 SyntaxShape::Block => Type::Block,
141 SyntaxShape::Closure(_) => Type::Closure,
142 SyntaxShape::Binary => Type::Binary,
143 SyntaxShape::CellPath => Type::CellPath,
144 SyntaxShape::DateTime => Type::Date,
145 SyntaxShape::Duration => Type::Duration,
146 SyntaxShape::Expression => Type::Any,
147 SyntaxShape::ExternalArgument => Type::Any,
148 SyntaxShape::Filepath => Type::String,
149 SyntaxShape::Directory => Type::String,
150 SyntaxShape::Float => Type::Float,
151 SyntaxShape::Filesize => Type::Filesize,
152 SyntaxShape::FullCellPath => Type::Any,
153 SyntaxShape::GlobPattern => Type::Glob,
154 SyntaxShape::Error => Type::Error,
155 SyntaxShape::ImportPattern => Type::Any,
156 SyntaxShape::Int => Type::Int,
157 SyntaxShape::List(x) => {
158 let contents = x.to_type();
159 Type::List(Box::new(contents))
160 }
161 SyntaxShape::Keyword(_, expr) => expr.to_type(),
162 SyntaxShape::MatchBlock => Type::Any,
163 SyntaxShape::MathExpression => Type::Any,
164 SyntaxShape::Nothing => Type::Nothing,
165 SyntaxShape::Number => Type::Number,
166 SyntaxShape::OneOf(types) => Type::one_of(types.iter().map(SyntaxShape::to_type)),
167 SyntaxShape::Operator => Type::Any,
168 SyntaxShape::Range => Type::Range,
169 SyntaxShape::Record(entries) => Type::Record(entries.map(SyntaxShape::to_type)),
170 SyntaxShape::RowCondition => Type::Bool,
171 SyntaxShape::Boolean => Type::Bool,
172 SyntaxShape::Signature | SyntaxShape::ExternalSignature => Type::Any,
173 SyntaxShape::String => Type::String,
174 SyntaxShape::Table(columns) => Type::Table(columns.map(SyntaxShape::to_type)),
175 SyntaxShape::VarWithOptType => Type::Any,
176 }
177 }
178
179 pub fn record() -> Self {
180 Self::Record(Default::default())
181 }
182
183 pub fn table() -> Self {
184 Self::Table(Default::default())
185 }
186}
187
188impl Display for SyntaxShape {
189 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 match self {
191 SyntaxShape::Keyword(kw, shape) => {
192 write!(f, "\"{}\" {}", String::from_utf8_lossy(kw), shape)
193 }
194 SyntaxShape::Any => write!(f, "any"),
195 SyntaxShape::String => write!(f, "string"),
196 SyntaxShape::CellPath => write!(f, "cell-path"),
197 SyntaxShape::FullCellPath => write!(f, "cell-path"),
198 SyntaxShape::Number => write!(f, "number"),
199 SyntaxShape::Range => write!(f, "range"),
200 SyntaxShape::Int => write!(f, "int"),
201 SyntaxShape::Float => write!(f, "float"),
202 SyntaxShape::Filepath => write!(f, "path"),
203 SyntaxShape::Directory => write!(f, "directory"),
204 SyntaxShape::GlobPattern => write!(f, "glob"),
205 SyntaxShape::ImportPattern => write!(f, "import"),
206 SyntaxShape::Block => write!(f, "block"),
207 SyntaxShape::Closure(args) => {
208 if let Some(args) = args {
209 let arg_vec: Vec<_> = args.iter().map(|x| x.to_string()).collect();
210 let arg_string = arg_vec.join(", ");
211 write!(f, "closure({arg_string})")
212 } else {
213 write!(f, "closure()")
214 }
215 }
216 SyntaxShape::Binary => write!(f, "binary"),
217 SyntaxShape::List(x) => write!(f, "list<{x}>"),
218 SyntaxShape::Table(columns) => write!(f, "table{columns}"),
219 SyntaxShape::Record(columns) => write!(f, "record{columns}"),
220 SyntaxShape::Filesize => write!(f, "filesize"),
221 SyntaxShape::Duration => write!(f, "duration"),
222 SyntaxShape::DateTime => write!(f, "datetime"),
223 SyntaxShape::Operator => write!(f, "operator"),
224 SyntaxShape::RowCondition => write!(
225 f,
226 "oneof<condition, {}>",
227 SyntaxShape::Closure(Some(vec![SyntaxShape::Any]))
228 ),
229 SyntaxShape::MathExpression => write!(f, "variable"),
230 SyntaxShape::VarWithOptType => write!(f, "vardecl"),
231 SyntaxShape::Signature => write!(f, "signature"),
232 SyntaxShape::ExternalSignature => write!(f, "external-signature"),
233 SyntaxShape::MatchBlock => write!(f, "match-block"),
234 SyntaxShape::Expression => write!(f, "expression"),
235 SyntaxShape::ExternalArgument => write!(f, "external-argument"),
236 SyntaxShape::Boolean => write!(f, "bool"),
237 SyntaxShape::Error => write!(f, "error"),
238 SyntaxShape::OneOf(list) => {
239 write!(f, "oneof")?;
240 let [first, rest @ ..] = &**list else {
241 return Ok(());
242 };
243 write!(f, "<{first}")?;
244 for t in rest {
245 write!(f, ", {t}")?;
246 }
247 f.write_str(">")
248 }
249 SyntaxShape::Nothing => write!(f, "nothing"),
250 }
251 }
252}