duckyscript/script/
parser.rs

1pub use pest::error::Error;
2pub use pest::iterators::{Pair, Pairs};
3use pest::Parser;
4
5pub type DuckyScriptTokens<'a> = Pair<'a, ducky::Rule>;
6pub type DuckyScriptError = Error<ducky::Rule>;
7
8#[allow(missing_docs)]
9pub mod ducky {
10    use pest_derive::Parser;
11    #[derive(Parser)]
12    #[grammar = "grammars/duckyscript.pest"]
13    pub struct DuckyScriptParser;
14}
15
16#[derive(Debug, Clone)]
17pub enum Lit {
18    Int(u32),
19    Str(String),
20    Bool(bool),
21}
22
23#[derive(Debug, Clone)]
24pub enum Variable {
25    Script(String),
26    Builtin(String),
27}
28
29#[derive(Debug, Clone)]
30pub enum Value {
31    Lit(Lit),
32    Variable(Variable),
33}
34
35#[derive(Debug, Clone)]
36pub enum Operator {
37    Add,
38    Subtract,
39    GreaterThan,
40    LessThan,
41    Equals,
42}
43
44#[derive(Debug, Clone)]
45pub enum Expr {
46    Value(Value),
47    OperationalExpr(Value, Operator, Value),
48}
49
50#[derive(Debug, Clone)]
51pub enum BuiltinFn {
52    LedOn,
53    LedOff,
54    LedG,
55    LedR,
56    Delay(Value),
57    StopPayload,
58}
59
60#[derive(Debug, Clone)]
61pub enum Function {
62    Builtin(BuiltinFn),
63    UserDefined(String),
64}
65
66pub type Statements = Vec<Statement>;
67
68#[derive(Debug, Clone)]
69pub enum Statement {
70    ButtonDef(Statements),
71    CallFn(Function),
72    WhileBlock(Expr, Statements),
73    VariableDef(String, Expr),
74}
75
76pub fn get_duckyscript_tokens(script: &str) -> Result<DuckyScriptTokens, Error<ducky::Rule>> {
77    Ok(
78        ducky::DuckyScriptParser::parse(ducky::Rule::script, script)?
79            .next()
80            .unwrap(),
81    )
82}
83
84#[derive(Debug, Clone, Default)]
85pub struct DuckyScript(pub Statements);
86
87impl DuckyScript {
88    pub fn parse_str(script: &str) -> Result<Self, Error<ducky::Rule>> {
89        let tokens = get_duckyscript_tokens(script)?;
90        Ok(Self::parse_tokens(tokens))
91    }
92    pub fn parse_tokens(script: DuckyScriptTokens) -> Self {
93        Self(Self::parse_statements(script.into_inner()))
94    }
95}
96
97impl DuckyScript {
98    fn parse_statements(tokens: Pairs<ducky::Rule>) -> Vec<Statement> {
99        tokens.map_while(Self::parse_single_statement).collect()
100    }
101    fn parse_single_statement(statement: Pair<ducky::Rule>) -> Option<Statement> {
102        let rule = statement.as_rule();
103        let mut inner = statement.into_inner();
104
105        let s = match rule {
106            ducky::Rule::button_def => Statement::ButtonDef(Self::parse_statements(inner)),
107            ducky::Rule::builtin_fn => Self::parse_statement_fn_builtin(inner.next().unwrap()),
108            ducky::Rule::while_block => Self::parse_statement_while_block(inner),
109            ducky::Rule::variable_def => Self::parse_statement_variable_def(inner),
110
111            ducky::Rule::EOI => return None,
112            s => unreachable!("parse_single_statement {:?}", s),
113        };
114        Some(s)
115    }
116
117    fn parse_statement_fn_builtin(statement: Pair<ducky::Rule>) -> Statement {
118        let f = match statement.as_rule() {
119            ducky::Rule::led_on => BuiltinFn::LedOn,
120            ducky::Rule::led_off => BuiltinFn::LedOff,
121            ducky::Rule::led_g => BuiltinFn::LedG,
122            ducky::Rule::led_r => BuiltinFn::LedR,
123            ducky::Rule::delay => {
124                BuiltinFn::Delay(Self::parse_value(statement.into_inner().next().unwrap()))
125            }
126            ducky::Rule::stop_payload => BuiltinFn::StopPayload,
127            s => unreachable!("parse_builtin_fn {:?}", s),
128        };
129        Statement::CallFn(Function::Builtin(f))
130    }
131    fn parse_statement_while_block(mut statements: Pairs<ducky::Rule>) -> Statement {
132        let expr = Self::parse_expr(statements.next().unwrap());
133        let inner_statements = Self::parse_statements(statements);
134        Statement::WhileBlock(expr, inner_statements)
135    }
136
137    fn parse_statement_variable_def(mut statements: Pairs<ducky::Rule>) -> Statement {
138        let name = statements.next().unwrap().as_str();
139        let value = Self::parse_expr(statements.next().unwrap());
140        Statement::VariableDef(name.into(), value)
141    }
142
143    fn parse_expr(statement: Pair<ducky::Rule>) -> Expr {
144        let rule = statement.as_rule();
145        let mut inner = statement.into_inner();
146        match rule {
147            ducky::Rule::expr_value => Expr::Value(Self::parse_value(inner.next().unwrap())),
148            ducky::Rule::expr_conditional => {
149                let lval = Self::parse_value(inner.next().unwrap());
150                let operator = match inner.next().unwrap().as_str() {
151                    "+" => Operator::Add,
152                    ">" => Operator::GreaterThan,
153                    "<" => Operator::LessThan,
154                    "==" => Operator::Equals,
155                    o => unreachable!("operator {}", o),
156                };
157                let rval = Self::parse_value(inner.next().unwrap());
158                Expr::OperationalExpr(lval, operator, rval)
159            }
160            e => unreachable!("parse_expr {:?}", e),
161        }
162    }
163
164    fn parse_value(statement: Pair<ducky::Rule>) -> Value {
165        let rule = statement.as_rule();
166        match rule {
167            ducky::Rule::lit_int => Self::parse_value_lit_int(statement),
168            ducky::Rule::lit_bool => Self::parse_value_lit_bool(statement),
169            ducky::Rule::script_variable => {
170                Value::Variable(Variable::Script(statement.as_str().into()))
171            }
172            s => unreachable!("parse_value {:?}", s),
173        }
174    }
175
176    fn parse_value_lit_int(statement: Pair<ducky::Rule>) -> Value {
177        Value::Lit(Lit::Int(statement.as_str().parse().unwrap()))
178    }
179    fn parse_value_lit_bool(statement: Pair<ducky::Rule>) -> Value {
180        Value::Lit(Lit::Bool(
181            statement.as_str().to_lowercase().parse().unwrap(),
182        ))
183    }
184}