expr/ast/
program.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use crate::ast::node::Node;
use crate::Rule;
use pest::iterators::{Pair, Pairs};

/// A parsed expr program that can be run
#[derive(Debug, Clone, Default)]
pub struct Program {
    pub(crate) lines: Vec<(String, Node)>,
    pub(crate) expr: Node,
}

impl<'i> From<Pairs<'i, Rule>> for Program {
    fn from(pairs: Pairs<'i, Rule>) -> Self {
        let mut program = Program::default();
        for pair in pairs {
            if let Rule::EOI = pair.as_rule() {
                continue;
            }
            let p = Program::from(pair);
            program.lines.extend(p.lines);
            program.expr = p.expr;
        }
        program
    }
}

impl From<Pair<'_, Rule>> for Program {
    fn from(pair: Pair<'_, Rule>) -> Self {
        let mut lines = Vec::new();
        let mut expr = None;
        match pair.as_rule() {
            Rule::program => return pair.into_inner().into(),
            Rule::stmt => {
                let mut inner = pair.into_inner();
                let line = inner.next().unwrap().as_str().to_string();
                let node = Node::from(inner);
                lines.push((line, node));
            }
            Rule::expr => {
                expr = Some(Node::from(pair.into_inner()));
            }
            // means it's a predicate
            Rule::ident => {
                expr = Some(Node::Ident(pair.as_str().to_string()));
            }
            Rule::EOI => {}
            rule => unreachable!("Unexpected rule: {rule:?}"),
        }

        Program {
            lines,
            expr: expr.unwrap_or(Node::Value(crate::Value::Nil)),
        }
    }
}