1use std::fmt::{self, Display, Formatter};
15
16#[derive(Debug, Default)]
19pub struct Program {
20 pub filename: String,
22 pub blocks: Vec<Block>,
24}
25
26#[derive(Debug, Default)]
29pub struct Block {
30 pub lineno: usize,
32 pub blockdel: bool,
36 pub words: Vec<Word>,
39 pub assignments: Vec<ParAssign>,
42}
43
44#[derive(Debug)]
46pub struct ParAssign {
47 pub id: ParId,
48 pub value: Expr,
49}
50
51#[derive(Debug)]
56pub enum ParId {
57 Named(String),
58 Numeric(u16),
59 Indirect(Box<Expr>),
60}
61
62#[derive(Debug)]
64pub enum Expr {
65 Num(f64),
69 Par(ParId),
71 Call(Call),
73 BinOp(Op, Box<Expr>, Box<Expr>),
75 UnOp(UnOp, Box<Expr>),
77}
78
79#[derive(Debug)]
84pub enum Word {
85 Gcode(Expr),
86 Mcode(Expr),
87 Feed(Expr),
88 Spindle(Expr),
89 Tool(Expr),
90 Arg(Arg, Expr),
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum Op {
99 Exp,
100 Mul,
101 Div,
102 Mod,
103 Add,
104 Sub,
105 Eq,
106 Ne,
107 Gt,
108 Ge,
109 Lt,
110 Le,
111 And,
112 Or,
113 Xor,
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum UnOp {
119 Plus,
120 Minus,
121}
122
123#[derive(Debug)]
125pub enum Call {
126 Exists(ParId),
127 Atan(Box<Expr>, Box<Expr>),
128 Abs(Box<Expr>),
129 Acos(Box<Expr>),
130 Asin(Box<Expr>),
131 Cos(Box<Expr>),
132 Exp(Box<Expr>),
133 Fix(Box<Expr>),
134 Fup(Box<Expr>),
135 Round(Box<Expr>),
136 Ln(Box<Expr>),
137 Sin(Box<Expr>),
138 Sqrt(Box<Expr>),
139 Tan(Box<Expr>),
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144pub enum Arg {
145 AxisA,
147 AxisB,
148 AxisC,
149 AxisU,
150 AxisV,
151 AxisW,
152 AxisX,
153 AxisY,
154 AxisZ,
155 OffsetI,
157 OffsetJ,
158 OffsetK,
159 ParamD,
161 ParamE,
162 ParamH,
163 ParamL,
164 ParamP,
165 ParamQ,
166 ParamR,
167}
168
169fn wrap_op(f: &mut Formatter, ex: &Expr) -> fmt::Result {
170 if let Expr::BinOp(..) = ex {
171 write!(f, "[{}]", ex)
172 } else {
173 Display::fmt(&ex, f)
174 }
175}
176
177
178impl Display for Program {
179 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
180 for block in &self.blocks {
181 write!(f, "{}\n", block)?;
182 }
183 Ok(())
184 }
185}
186
187impl Display for Block {
188 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
189 if self.blockdel {
190 write!(f, "/ ")?;
191 }
192 for ass in &self.assignments {
193 write!(f, "{} ", ass)?;
194 }
195 for word in &self.words {
196 write!(f, "{} ", word)?;
197 }
198 Ok(())
199 }
200}
201
202impl Display for ParAssign {
203 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
204 if let ParId::Indirect(id) = &self.id {
207 if let Expr::Call(..) = **id {
208 write!(f, "#[{}]=", self.id)?;
209 return wrap_op(f, &self.value);
210 }
211 }
212 write!(f, "#{}=", self.id)?;
213 wrap_op(f, &self.value)
214 }
215}
216
217impl Display for ParId {
218 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
219 match self {
220 ParId::Numeric(n) => Display::fmt(n, f),
221 ParId::Named(n) => write!(f, "<{}>", n),
222 ParId::Indirect(ex) => wrap_op(f, ex),
223 }
224 }
225}
226
227impl Display for Expr {
228 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
229 match self {
230 Expr::Num(n) => Display::fmt(n, f),
231 Expr::Par(id) => write!(f, "#{}", id),
232 Expr::Call(func) => Display::fmt(func, f),
233 Expr::BinOp(op, lhs, rhs) => {
234 wrap_op(f, lhs)?;
235 write!(f, " {} ", op)?;
236 wrap_op(f, rhs)
237 }
238 Expr::UnOp(op, rhs) => {
239 Display::fmt(op, f)?;
240 wrap_op(f, rhs)
241 }
242 }
243 }
244}
245
246impl Display for Op {
247 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
248 f.write_str(match self {
249 Op::Exp => "**",
250 Op::Mul => "*",
251 Op::Div => "/",
252 Op::Mod => "MOD",
253 Op::Add => "+",
254 Op::Sub => "-",
255 Op::Eq => "EQ",
256 Op::Ne => "NE",
257 Op::Gt => "GT",
258 Op::Ge => "GE",
259 Op::Lt => "LT",
260 Op::Le => "LE",
261 Op::And => "AND",
262 Op::Or => "OR",
263 Op::Xor => "XOR",
264 })
265 }
266}
267
268impl Display for UnOp {
269 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
270 f.write_str(match self {
271 UnOp::Plus => "+",
272 UnOp::Minus => "-",
273 })
274 }
275}
276
277impl Display for Word {
278 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
279 match self {
280 Word::Gcode(n) => { f.write_str("G")?; wrap_op(f, n) },
281 Word::Mcode(n) => { f.write_str("M")?; wrap_op(f, n) },
282 Word::Feed(n) => { f.write_str("F")?; wrap_op(f, n) },
283 Word::Spindle(n) => { f.write_str("S")?; wrap_op(f, n) },
284 Word::Tool(n) => { f.write_str("T")?; wrap_op(f, n) },
285 Word::Arg(a, n) => { Display::fmt(a, f)?; wrap_op(f, n) },
286 }
287 }
288}
289
290impl Display for Arg {
291 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
292 f.write_str(match self {
293 Arg::AxisA => "A",
294 Arg::AxisB => "B",
295 Arg::AxisC => "C",
296 Arg::AxisU => "U",
297 Arg::AxisV => "V",
298 Arg::AxisW => "W",
299 Arg::AxisX => "X",
300 Arg::AxisY => "Y",
301 Arg::AxisZ => "Z",
302 Arg::OffsetI => "I",
303 Arg::OffsetJ => "J",
304 Arg::OffsetK => "K",
305 Arg::ParamD => "D",
306 Arg::ParamE => "E",
307 Arg::ParamH => "H",
308 Arg::ParamL => "L",
309 Arg::ParamP => "P",
310 Arg::ParamQ => "Q",
311 Arg::ParamR => "R",
312 })
313 }
314}
315
316impl Display for Call {
317 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
318 match self {
319 Call::Atan(arg1, arg2) => write!(f, "ATAN[{}]/[{}]", arg1, arg2),
320 Call::Exists(par) => write!(f, "EXISTS[#{}]", par),
321 Call::Abs(arg) => write!(f, "ABS[{}]", arg),
322 Call::Acos(arg) => write!(f, "ACOS[{}]", arg),
323 Call::Asin(arg) => write!(f, "ASIN[{}]", arg),
324 Call::Cos(arg) => write!(f, "COS[{}]", arg),
325 Call::Exp(arg) => write!(f, "EXP[{}]", arg),
326 Call::Fix(arg) => write!(f, "FIX[{}]", arg),
327 Call::Fup(arg) => write!(f, "FUP[{}]", arg),
328 Call::Round(arg) => write!(f, "ROUND[{}]", arg),
329 Call::Ln(arg) => write!(f, "LN[{}]", arg),
330 Call::Sin(arg) => write!(f, "SIN[{}]", arg),
331 Call::Sqrt(arg) => write!(f, "SQRT[{}]", arg),
332 Call::Tan(arg) => write!(f, "TAN[{}]", arg),
333 }
334 }
335}