psi_lang/
lib.rs

1#![allow(clippy::upper_case_acronyms)]
2
3#[macro_use]
4extern crate quick_error;
5extern crate pest;
6
7#[global_allocator]
8static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
9
10mod enums;
11mod error;
12mod expr;
13mod interpreter;
14mod namespace;
15mod table;
16
17pub use crate::enums::{Action, Block, Identifier, Identifiers, IfPart};
18pub use crate::error::Error;
19pub use crate::expr::{Expr, Op};
20pub use crate::interpreter::Interpreter;
21use crate::namespace::Namespace;
22use crate::table::Table;
23use pest_consume::{match_nodes, Error as PCError, Parser};
24use smartstring::alias::String;
25
26#[derive(Parser)]
27#[grammar = "psi.pest"]
28pub struct PsiParser;
29
30type Pesult<T> = std::result::Result<T, PCError<Rule>>;
31type Node<'i> = pest_consume::Node<'i, Rule, ()>;
32
33pub fn do_walk(node: Node) -> Result<Vec<Action>, Error> {
34    let instructions = PsiParser::stmts(node)?;
35    Ok(instructions)
36}
37
38pub fn do_parse(src: &str) -> Result<Node, Error> {
39    let parse = PsiParser::parse(Rule::stmts, src)?;
40    let input = parse.single()?;
41    Ok(input)
42}
43
44#[pest_consume::parser]
45impl PsiParser {
46    fn EOI(_input: Node) -> Pesult<()> {
47        Ok(())
48    }
49    fn positive(_input: Node) -> Pesult<()> {
50        Ok(())
51    }
52    fn negative(_input: Node) -> Pesult<()> {
53        Ok(())
54    }
55    fn equals(_input: Node) -> Pesult<()> {
56        Ok(())
57    }
58    fn not_equals(_input: Node) -> Pesult<()> {
59        Ok(())
60    }
61    fn greater(_input: Node) -> Pesult<()> {
62        Ok(())
63    }
64    fn less(_input: Node) -> Pesult<()> {
65        Ok(())
66    }
67    fn greater_eq(_input: Node) -> Pesult<()> {
68        Ok(())
69    }
70    fn less_eq(_input: Node) -> Pesult<()> {
71        Ok(())
72    }
73    fn and(_input: Node) -> Pesult<()> {
74        Ok(())
75    }
76    fn or(_input: Node) -> Pesult<()> {
77        Ok(())
78    }
79    fn continue_stmt(_input: Node) -> Pesult<()> {
80        Ok(())
81    }
82    fn break_stmt(_input: Node) -> Pesult<()> {
83        Ok(())
84    }
85
86    fn identifier_part(input: Node) -> Pesult<&str> {
87        Ok(input.as_str())
88    }
89
90    fn identifier(input: Node) -> Pesult<Expr> {
91        Ok(match_nodes!(input.into_children();
92            [identifier_part(part)..] => Expr::Identifier(part.map(|x| x.into()).collect()),
93        ))
94    }
95
96    fn boolean(input: Node) -> Pesult<Expr> {
97        let data = input.as_str().parse().map_err(|e| input.error(e));
98        Ok(Expr::Boolean(data?))
99    }
100
101    fn float(input: Node) -> Pesult<Expr> {
102        let data = input.as_str().parse().map_err(|e| input.error(e));
103        Ok(Expr::Float(data?))
104    }
105
106    fn integer(input: Node) -> Pesult<Expr> {
107        let data = input.as_str().parse().map_err(|e| input.error(e));
108        Ok(Expr::Integer(data?))
109    }
110
111    fn string_esc(input: Node) -> Pesult<&str> {
112        Ok(match_nodes!(input.into_children();
113            [string_brack] => "{",
114            [string_quote] => "\"",
115        ))
116    }
117
118    fn string_expr(input: Node) -> Pesult<Expr> {
119        Ok(match_nodes!(input.into_children();
120            [expr(e)] => e,
121        ))
122    }
123
124    fn string_char(input: Node) -> Pesult<&str> {
125        Ok(input.as_str())
126    }
127
128    fn string_part(input: Node) -> Pesult<Expr> {
129        Ok(match_nodes!(input.into_children();
130            [string_esc(e)] => Expr::StringRaw(e.into()),
131            [string_expr(e)] => e,
132            [string_char(c)] => Expr::StringRaw(c.into()),
133        ))
134    }
135
136    fn string(input: Node) -> Pesult<Expr> {
137        Ok(match_nodes!(input.into_children();
138            [string_part(parts)..] => Expr::StringFmt(parts.collect()),
139        ))
140    }
141
142    fn exclusive(input: Node) -> Pesult<Expr> {
143        Ok(match_nodes!(input.into_children();
144            [bound(start), bound(end)] => Expr::Exclusive(Box::new(start), Box::new(end)),
145        ))
146    }
147
148    fn inclusive(input: Node) -> Pesult<Expr> {
149        Ok(match_nodes!(input.into_children();
150            [bound(start), bound(end)] => Expr::Inclusive(Box::new(start), Box::new(end)),
151        ))
152    }
153
154    fn table_pair(input: Node) -> Pesult<(Expr, Expr)> {
155        Ok(match_nodes!(input.into_children();
156            [datatype(d), expr(e)] => (d, e),
157        ))
158    }
159
160    fn table(input: Node) -> Pesult<Expr> {
161        Ok(match_nodes!(input.into_children();
162            [table_pair(a)..] => Expr::Table(Table::new(a.collect())),
163        ))
164    }
165
166    fn array(input: Node) -> Pesult<Expr> {
167        Ok(match_nodes!(input.into_children();
168            [expr(a)..] => Expr::Array(a.collect()),
169        ))
170    }
171
172    fn bound(input: Node) -> Pesult<Expr> {
173        // bound = { "(" ~ expr ~ ")" | sign | integer | identifier }
174        Ok(match_nodes!(input.into_children();
175            [expr(e)] => e,
176            [sign(s)] => s,
177            [integer(i)] => i,
178            [identifier(i)] => i,
179        ))
180    }
181
182    fn datatype(input: Node) -> Pesult<Expr> {
183        // datatype = { boolean | array | table | inclusive |
184        //              exclusive | float | integer | string }
185        Ok(match_nodes!(input.into_children();
186            [boolean(e)] => e,
187            [array(d)] => d,
188            [table(s)] => s,
189            [inclusive(i)] => i,
190            [exclusive(e)] => e,
191            [float(f)] => f,
192            [integer(i)] => i,
193            [string(s)] => s,
194        ))
195    }
196
197    fn var_index(input: Node) -> Pesult<Expr> {
198        // var_index = { atom ~ ("[" ~ expr ~ "]")* }
199        Ok(match_nodes!(input.into_children();
200            [atom(id)] => id,
201            [atom(id), expr(e)..] => Expr::VarIndex(Box::new(id), e.collect()),
202        ))
203    }
204
205    fn atom(input: Node) -> Pesult<Expr> {
206        // atom = { datatype | "(" ~ expr ~ ")" | sign | identifier }
207        Ok(match_nodes!(input.into_children();
208            [expr(e)] => e,
209            [datatype(d)] => d,
210            [sign(s)] => s,
211            [identifier(i)] => i,
212        ))
213    }
214
215    fn sign(input: Node) -> Pesult<Expr> {
216        // sign = { (positive | negative) ~ (float | integer | sign) }
217        Ok(match_nodes!(input.into_children();
218            [positive(_), float(f)] => f,
219            [positive(_), integer(i)] => i,
220            [positive(_), sign(s)] => s,
221            [negative(_), float(f)] =>
222                Expr::BinOp(Box::new(f), Op::Mul, Box::new(Expr::Integer(-1))),
223            [negative(_), integer(i)] =>
224                Expr::BinOp(Box::new(i), Op::Mul, Box::new(Expr::Integer(-1))),
225            [negative(_), sign(s)] =>
226                Expr::BinOp(Box::new(s), Op::Mul, Box::new(Expr::Integer(-1))),
227        ))
228    }
229
230    fn pow(input: Node) -> Pesult<Expr> {
231        // pow = { var_index ~ ("^" ~ var_index)* }
232        Ok(match_nodes!(input.into_children();
233            [var_index(left)] => left,
234            [var_index(mut nums)..] => {
235                let mut result: Option<Expr> = None;
236                while let Some(p) = nums.next_back() {
237                    if let Some(i) = result {
238                        result = Some(Expr::BinOp(Box::new(p), Op::Pow, Box::new(i)));
239                    } else {
240                        result = Some(p);
241                    }
242                }
243                result.unwrap()
244            }
245        ))
246    }
247
248    fn rem(input: Node) -> Pesult<Expr> {
249        // rem = { pow ~ ("%" ~ pow)* }
250        Ok(match_nodes!(input.into_children();
251            [pow(left)] => left,
252            [pow(mut nums)..] => {
253                let mut result = None;
254                while let Some(p) = nums.next() {
255                    if let Some(i) = result {
256                        result = Some(Expr::BinOp(Box::new(i), Op::Rem, Box::new(p)));
257                    } else {
258                        result = Some(p);
259                    }
260                }
261                result.unwrap()
262            }
263        ))
264    }
265
266    fn div(input: Node) -> Pesult<Expr> {
267        // div = { rem ~ ("/" ~ rem)* }
268        Ok(match_nodes!(input.into_children();
269            [rem(left)] => left,
270            [rem(mut nums)..] => {
271                let mut result = None;
272                while let Some(p) = nums.next() {
273                    if let Some(i) = result {
274                        result = Some(Expr::BinOp(Box::new(i), Op::Div, Box::new(p)));
275                    } else {
276                        result = Some(p);
277                    }
278                }
279                result.unwrap()
280            }
281        ))
282    }
283
284    fn mul(input: Node) -> Pesult<Expr> {
285        // mul = { div ~ ("*" ~ div)* }
286        Ok(match_nodes!(input.into_children();
287            [div(left)] => left,
288            [div(mut nums)..] => {
289                let mut result = None;
290                while let Some(p) = nums.next() {
291                    if let Some(i) = result {
292                        result = Some(Expr::BinOp(Box::new(i), Op::Mul, Box::new(p)));
293                    } else {
294                        result = Some(p);
295                    }
296                }
297                result.unwrap()
298            }
299        ))
300    }
301
302    fn add(input: Node) -> Pesult<Expr> {
303        // add = { mul ~ ("+" ~ mul)* }
304        Ok(match_nodes!(input.into_children();
305            [mul(left)] => left,
306            [mul(mut nums)..] => {
307                let mut result = None;
308                while let Some(p) = nums.next() {
309                    if let Some(i) = result {
310                        result = Some(Expr::BinOp(Box::new(i), Op::Add, Box::new(p)));
311                    } else {
312                        result = Some(p);
313                    }
314                }
315                result.unwrap()
316            }
317        ))
318    }
319
320    fn sub(input: Node) -> Pesult<Expr> {
321        // sub = { add ~ ("-" ~ add)* }
322        Ok(match_nodes!(input.into_children();
323            [add(left)] => left,
324            [add(mut nums)..] => {
325                let mut result = None;
326                while let Some(p) = nums.next() {
327                    if let Some(i) = result {
328                        result = Some(Expr::BinOp(Box::new(i), Op::Sub, Box::new(p)));
329                    } else {
330                        result = Some(p);
331                    }
332                }
333                result.unwrap()
334            }
335        ))
336    }
337
338    fn ss_add(input: Node) -> Pesult<Action> {
339        Ok(match_nodes!(input.into_children();
340            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Add, e)
341        ))
342    }
343
344    fn ss_sub(input: Node) -> Pesult<Action> {
345        Ok(match_nodes!(input.into_children();
346            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Sub, e)
347        ))
348    }
349
350    fn ss_mul(input: Node) -> Pesult<Action> {
351        Ok(match_nodes!(input.into_children();
352            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Mul, e)
353        ))
354    }
355
356    fn ss_div(input: Node) -> Pesult<Action> {
357        Ok(match_nodes!(input.into_children();
358            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Div, e)
359        ))
360    }
361
362    fn ss_rem(input: Node) -> Pesult<Action> {
363        Ok(match_nodes!(input.into_children();
364            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Rem, e)
365        ))
366    }
367
368    fn ss_pow(input: Node) -> Pesult<Action> {
369        Ok(match_nodes!(input.into_children();
370            [identifier(i), expr(e)] => Action::SingleShot(i, Op::Pow, e)
371        ))
372    }
373
374    fn single_shot(input: Node) -> Pesult<Action> {
375        Ok(match_nodes!(input.into_children();
376            [ss_add(e)] => e,
377            [ss_sub(e)] => e,
378            [ss_mul(e)] => e,
379            [ss_div(e)] => e,
380            [ss_rem(e)] => e,
381            [ss_pow(e)] => e,
382        ))
383    }
384
385    fn comp(input: Node) -> Pesult<Expr> {
386        // comp = { sub ~ ((greater_eq | less_eq | greater | less) ~ sub)? }
387        Ok(match_nodes!(input.into_children();
388            [sub(left)] => left,
389            [sub(left), greater_eq(_), sub(right)] =>
390                Expr::BinOp(Box::new(left), Op::GreaterEq, Box::new(right)),
391            [sub(left), less_eq(_), sub(right)] =>
392                Expr::BinOp(Box::new(left), Op::LessEq, Box::new(right)),
393            [sub(left), greater(_), sub(right)] =>
394                Expr::BinOp(Box::new(left), Op::Greater, Box::new(right)),
395            [sub(left), less(_), sub(right)] =>
396                Expr::BinOp(Box::new(left), Op::Less, Box::new(right)),
397        ))
398    }
399
400    fn eq(input: Node) -> Pesult<Expr> {
401        // eq = { comp ~ ((equals | not_equals) ~ comp)? }
402        Ok(match_nodes!(input.into_children();
403            [comp(left)] => left,
404            [comp(left), equals(_), comp(right)] =>
405                Expr::BinOp(Box::new(left), Op::Equals, Box::new(right)),
406            [comp(left), not_equals(_), comp(right)] =>
407                Expr::BinOp(Box::new(left), Op::NotEquals, Box::new(right)),
408        ))
409    }
410
411    fn comb(input: Node) -> Pesult<Expr> {
412        // comb = { eq ~ ((and | or) ~ eq)? }
413        Ok(match_nodes!(input.into_children();
414            [eq(left)] => left,
415            [eq(left), and(_), eq(right)] =>
416                Expr::BinOp(Box::new(left), Op::And, Box::new(right)),
417            [eq(left), or(_), eq(right)] =>
418                Expr::BinOp(Box::new(left), Op::Or, Box::new(right)),
419        ))
420    }
421
422    fn not(input: Node) -> Pesult<Expr> {
423        Ok(match_nodes!(input.into_children();
424            [expr(e)] => Expr::Not(Box::new(e)),
425        ))
426    }
427
428    fn iterable(input: Node) -> Pesult<Expr> {
429        // iterable = { array | table | var_index | inclusive | exclusive | identifier }
430        Ok(match_nodes!(input.into_children();
431            [array(a)] => a,
432            [table(t)] => t,
433            [var_index(v)] => v,
434            [inclusive(i)] => i,
435            [exclusive(e)] => e,
436            [identifier(i)] => i,
437        ))
438    }
439
440    fn contains(input: Node) -> Pesult<Expr> {
441        Ok(match_nodes!(input.into_children();
442            [atom(a), iterable(i)] => Expr::BinOp(Box::new(a), Op::In, Box::new(i)),
443        ))
444    }
445
446    fn expr(input: Node) -> Pesult<Expr> {
447        Ok(match_nodes!(input.into_children();
448            [integer(int)] => int,
449            [comb(com)] => com,
450            [not(no)] => no,
451            [contains(con)] => con,
452            [fn_call(call)] => call.to_expr(),
453        ))
454    }
455
456    fn comment(input: Node) -> Pesult<Action> {
457        Ok(Action::Comment(input.as_str().into()))
458    }
459
460    fn fn_call(input: Node) -> Pesult<Action> {
461        Ok(match_nodes!(input.into_children();
462            [identifier(i), expr(e)..] => Action::FnCall(i, e.collect()),
463        ))
464    }
465
466    fn var_assign(input: Node) -> Pesult<Action> {
467        Ok(match_nodes!(input.into_children();
468            [identifier(id), expr(exp)] => Action::VarAssign(id, exp),
469        ))
470    }
471
472    fn block(input: Node) -> Pesult<Vec<Action>> {
473        Ok(match_nodes!(input.into_children();
474            [stmt(s)..] => s.collect(),
475        ))
476    }
477
478    fn if_stmt(input: Node) -> Pesult<IfPart> {
479        Ok(match_nodes!(input.into_children();
480            [expr(e), block(b)] => IfPart::If(e, b),
481        ))
482    }
483
484    fn else_if_stmt(input: Node) -> Pesult<IfPart> {
485        Ok(match_nodes!(input.into_children();
486            [expr(e), block(b)] => IfPart::IfElse(e, b),
487        ))
488    }
489
490    fn else_stmt(input: Node) -> Pesult<IfPart> {
491        Ok(match_nodes!(input.into_children();
492            [block(b)] => IfPart::Else(b),
493        ))
494    }
495
496    fn ifs(input: Node) -> Pesult<Action> {
497        Ok(match_nodes!(input.into_children();
498            [if_stmt(first)] => Action::If(vec![first]),
499            [if_stmt(first), else_if_stmt(second)..] => {
500                let mut result = vec![first];
501                result.extend(second);
502                Action::If(result)
503            },
504            [if_stmt(first), else_if_stmt(second).., else_stmt(third)] => {
505                let mut result = vec![first];
506                result.extend(second);
507                result.push(third);
508                Action::If(result)
509            },
510            [if_stmt(first), else_stmt(third)] => Action::If(vec![first, third]),
511        ))
512    }
513
514    fn args(input: Node) -> Pesult<Vec<String>> {
515        Ok(match_nodes!(input.into_children();
516            [identifier_part(i)..] => i.map(|x| x.into()).collect(),
517        ))
518    }
519
520    fn fn_def(input: Node) -> Pesult<Action> {
521        Ok(match_nodes!(input.into_children();
522            [identifier(i), args(a), block(b)] => Action::FnDef(i, a, b),
523        ))
524    }
525
526    fn return_stmt(input: Node) -> Pesult<Action> {
527        Ok(match_nodes!(input.into_children();
528            [return_expr(e)] => Action::Return(e),
529        ))
530    }
531
532    fn return_expr(input: Node) -> Pesult<Option<Expr>> {
533        Ok(match_nodes!(input.into_children();
534            [expr(e)] => Some(e),
535            [] => None,
536        ))
537    }
538
539    fn for_stmt(input: Node) -> Pesult<Action> {
540        Ok(match_nodes!(input.into_children();
541            [args(a), iterable(i), block(b)] => Action::For(a, i, b),
542        ))
543    }
544
545    fn loop_stmt(input: Node) -> Pesult<Action> {
546        Ok(match_nodes!(input.into_children();
547            [block(b)] => Action::Loop(b),
548        ))
549    }
550
551    fn while_stmt(input: Node) -> Pesult<Action> {
552        Ok(match_nodes!(input.into_children();
553            [expr(c), block(b)] => Action::While(c, b),
554        ))
555    }
556
557    fn loop_control(input: Node) -> Pesult<Action> {
558        Ok(match_nodes!(input.into_children();
559            [break_stmt(_)] => Action::Break,
560            [continue_stmt(_)] => Action::Continue,
561        ))
562    }
563
564    fn import_stmt(input: Node) -> Pesult<Action> {
565        Ok(match_nodes!(input.into_children();
566            [identifier(from), identifier(into)] =>
567                Action::Import(from, Some(into)),
568            [identifier(from)] => Action::Import(from, None),
569        ))
570    }
571
572    fn stmt(input: Node) -> Pesult<Action> {
573        Ok(match_nodes!(input.into_children();
574            [var_assign(var)] => var,
575            [comment(com)] => com,
576            [fn_call(call)] => call,
577            [fn_def(def)] => def,
578            [return_stmt(ret)] => ret,
579            [ifs(if_s)] => if_s,
580            [for_stmt(for_s)] => for_s,
581            [loop_stmt(loop_s)] => loop_s,
582            [while_stmt(loop_s)] => loop_s,
583            [single_shot(ss)] => ss,
584            [loop_control(lc)] => lc,
585            [import_stmt(imp)] => imp,
586        ))
587    }
588
589    pub fn stmts(input: Node) -> Pesult<Vec<Action>> {
590        Ok(match_nodes!(input.into_children();
591            [stmt(act).., _] => act.collect(),
592        ))
593    }
594}