1use crate::span::Span;
5
6#[derive(Debug, Clone)]
7pub struct File {
8 pub header: Option<Header>,
10 pub stmts: Vec<Stmt>,
11}
12
13#[derive(Debug, Clone)]
14pub struct Header {
15 pub version: String,
16 pub span: Span,
17}
18
19#[derive(Debug, Clone, PartialEq)]
20pub struct Ident {
21 pub name: String,
22 pub span: Span,
23}
24
25#[derive(Debug, Clone, Default)]
28pub struct Trivia {
29 pub leading: Vec<String>,
30 pub trailing: Option<String>,
31 pub blank_before: bool,
33}
34
35#[derive(Debug, Clone)]
36pub struct Stmt {
37 pub kind: StmtKind,
38 pub span: Span,
39 pub trivia: Trivia,
40}
41
42#[derive(Debug, Clone)]
43pub enum StmtKind {
44 Canvas(Block),
46 Def(Def),
48 Group(Group),
50 Class(Class),
52 Constrain(Vec<Constraint>),
54 Pin(Pin),
56 For(For),
58 Port(Port),
60 Prop(Prop),
62 Node(Node),
64 Edge(Edge),
66}
67
68#[derive(Debug, Clone)]
69pub struct Block {
70 pub stmts: Vec<Stmt>,
71 pub span: Span,
72}
73
74#[derive(Debug, Clone)]
75pub struct Def {
76 pub name: Ident,
77 pub params: Vec<Ident>,
78 pub body: Block,
79}
80
81#[derive(Debug, Clone)]
82pub struct Group {
83 pub name: Ident,
84 pub label: Option<StrLit>,
85 pub body: Block,
86}
87
88#[derive(Debug, Clone)]
89pub struct Class {
90 pub name: Ident,
91 pub body: Block,
92}
93
94#[derive(Debug, Clone)]
95pub struct Constraint {
96 pub name: Ident,
98 pub args: Vec<ConstraintArg>,
99 pub span: Span,
100 pub trivia: Trivia,
101}
102
103#[derive(Debug, Clone)]
104pub enum ConstraintArg {
105 Path(PathRef),
108 Num(f64, Span),
109}
110
111impl ConstraintArg {
112 pub fn span(&self) -> Span {
113 match self {
114 ConstraintArg::Path(p) => p.span,
115 ConstraintArg::Num(_, s) => *s,
116 }
117 }
118}
119
120#[derive(Debug, Clone)]
121pub struct Pin {
122 pub target: PathRef,
123 pub x: Expr,
124 pub y: Expr,
125}
126
127#[derive(Debug, Clone)]
128pub struct For {
129 pub var: Ident,
130 pub start: Expr,
131 pub end: Expr,
132 pub body: Block,
133}
134
135#[derive(Debug, Clone)]
136pub struct Port {
137 pub name: Ident,
138 pub body: Block,
139}
140
141#[derive(Debug, Clone)]
142pub struct Prop {
143 pub key: Vec<Ident>,
145 pub value: Value,
146 pub span: Span,
147}
148
149#[derive(Debug, Clone)]
150pub enum Value {
151 Str(StrLit),
152 Num(f64, Span),
153 Word(Ident),
155 ThemeToken(Ident),
157 Color(String, Span),
159}
160
161impl Value {
162 pub fn span(&self) -> Span {
163 match self {
164 Value::Str(s) => s.span,
165 Value::Num(_, s) => *s,
166 Value::Word(i) | Value::ThemeToken(i) => i.span,
167 Value::Color(_, s) => *s,
168 }
169 }
170}
171
172#[derive(Debug, Clone)]
173pub struct Node {
174 pub name: Option<Ident>,
176 pub kind: NodeKind,
177}
178
179#[derive(Debug, Clone)]
180pub enum NodeKind {
181 Plain { body: Block },
183 Container {
185 ctype: ContainerType,
186 ctype_span: Span,
187 body: Block,
188 },
189 Call {
191 callee: Ident,
192 args: Vec<Expr>,
193 body: Option<Block>,
194 },
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub enum ContainerType {
199 Row,
200 Column,
201 Grid { cols: u32, rows: u32 },
202}
203
204#[derive(Debug, Clone)]
205pub struct Edge {
206 pub from: PathRef,
207 pub op: EdgeOp,
208 pub op_span: Span,
209 pub to: PathRef,
210 pub label: Option<StrLit>,
211 pub props: Option<Block>,
212}
213
214#[derive(Debug, Clone, Copy, PartialEq, Eq)]
215pub enum EdgeOp {
216 Forward,
218 Bidirectional,
220}
221
222#[derive(Debug, Clone)]
224pub struct PathRef {
225 pub segments: Vec<PathSeg>,
226 pub span: Span,
227}
228
229#[derive(Debug, Clone)]
230pub enum PathSeg {
231 Name(Ident),
232 Index(Expr),
233 Wildcard(Span),
235}
236
237impl PathRef {
238 pub fn display(&self) -> String {
240 let mut out = String::new();
241 for (i, seg) in self.segments.iter().enumerate() {
242 match seg {
243 PathSeg::Name(id) => {
244 if i > 0 {
245 out.push('.');
246 }
247 out.push_str(&id.name);
248 }
249 PathSeg::Index(_) => out.push_str("[..]"),
250 PathSeg::Wildcard(_) => out.push_str("[*]"),
251 }
252 }
253 out
254 }
255}
256
257#[derive(Debug, Clone)]
259pub struct StrLit {
260 pub parts: Vec<StrPart>,
261 pub span: Span,
262}
263
264#[derive(Debug, Clone)]
265pub enum StrPart {
266 Text(String),
267 Expr(Expr),
268}
269
270impl StrLit {
271 pub fn as_plain(&self) -> Option<String> {
273 match self.parts.as_slice() {
274 [] => Some(String::new()),
275 [StrPart::Text(t)] => Some(t.clone()),
276 _ => None,
277 }
278 }
279}
280
281#[derive(Debug, Clone)]
282pub struct Expr {
283 pub kind: ExprKind,
284 pub span: Span,
285}
286
287#[derive(Debug, Clone)]
288pub enum ExprKind {
289 Num(f64),
290 Str(Box<StrLit>),
291 Var(Ident),
292 Unary(UnOp, Box<Expr>),
293 Binary(BinOp, Box<Expr>, Box<Expr>),
294}
295
296#[derive(Debug, Clone, Copy, PartialEq, Eq)]
297pub enum UnOp {
298 Neg,
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302pub enum BinOp {
303 Add,
304 Sub,
305 Mul,
306 Div,
307 Mod,
308}
309
310impl BinOp {
311 pub fn symbol(self) -> &'static str {
312 match self {
313 BinOp::Add => "+",
314 BinOp::Sub => "-",
315 BinOp::Mul => "*",
316 BinOp::Div => "/",
317 BinOp::Mod => "%",
318 }
319 }
320}