1use std::{collections::HashMap, fmt::Display};
2
3use cypress::prelude::*;
4
5#[derive(PartialEq, Clone, Debug, Eq, Hash)]
17enum Expr {
18 Str(String),
19 Num(i32),
20 Var(String),
21 Assignment(String, Box<Expr>),
22 Print(Box<Expr>),
23 Seq(Vec<Expr>),
24}
25
26impl Display for Expr {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Expr::Str(str) => write!(f, "\"{}\"", str),
30 Expr::Num(num) => write!(f, "{}", num),
31 Expr::Var(var) => write!(f, "{}", var),
32 Expr::Assignment(name, expr) => write!(f, "{} = {}", name, expr),
33 Expr::Print(expr) => write!(f, "{}", expr),
34 Expr::Seq(exprs) => write!(
35 f,
36 "{}\n",
37 exprs
38 .iter()
39 .map(|expr| format!("{}", expr))
40 .collect::<String>()
41 ),
42 }
43 }
44}
45
46fn num<'a>() -> impl Parser<'a, u8, i32> {
47 pnum()
48 .many()
49 .map(|xs| String::from_utf8(xs).unwrap().parse::<i32>().unwrap())
50}
51
52fn str_<'a>() -> impl Parser<'a, u8, String> {
53 pbetween(just('\"'), pletter().many(), just('\"')).map(|val| String::from_utf8(val).unwrap())
54}
55
56fn ident<'a>() -> impl Parser<'a, u8, String> {
57 let start = choice!(pletter(), just('_'));
58 let valid_idents = choice!(pnum(), just('_'), pletter());
59
60 let ident = start.then(valid_idents.many()).map(|(s, mut rest)| {
61 let mut all = vec![s];
62 all.append(&mut rest);
63 all
64 });
65
66 ident.map(|val| String::from_utf8(val).unwrap())
67}
68
69fn var_assignment<'a>(expr: impl Parser<'a, u8, Expr>) -> impl Parser<'a, u8, Expr> {
73 sequence!(
74 (ident()) > (just('=').padded_by(pws())) > expr
75 => |(name, (_, val))| Expr::Assignment(name, Box::new(val))
76 )
77}
78
79fn print<'a>(expr: impl Parser<'a, u8, Expr>) -> impl Parser<'a, u8, Expr> {
81 let print_ident = pident("print");
82
83 print_ident
84 .padded_by(pws())
85 .then(expr)
86 .map(|(_, val)| Expr::Print(Box::new(val)))
87}
88
89fn expr<'a>() -> impl Parser<'a, u8, Expr> {
90 recursive(|expr| {
91 Box::new(
92 choice!(
93 var_assignment(expr.clone()),
94 print(expr),
95 ident().map(Expr::Var),
96 str_().map(Expr::Str),
97 num().map(Expr::Num)
98 )
99 .map(|expr| expr),
100 )
101 })
102}
103
104fn parser<'a>() -> impl Parser<'a, u8, Expr> {
105 (expr().delimited_by(just('\n'))).until_end().map(Expr::Seq)
106}
107
108fn eval<'a>(expr: Expr, var_map: &mut HashMap<String, Expr>) -> Result<Expr, String> {
109 match expr {
110 Expr::Str(_) | Expr::Num(_) => Ok(expr),
111 Expr::Var(name) => match var_map.get(&name) {
112 Some(val) => eval(val.clone(), var_map),
113 None => Err(format!("No value associated with key: \"{}\"", name)),
114 },
115 Expr::Assignment(name, expr) => {
116 let eval_expr = eval(*expr, var_map)?;
117 var_map.insert(name, eval_expr.clone());
118 Ok(eval_expr)
119 }
120 Expr::Print(expr) => {
121 let eval_expr = eval(*expr, var_map)?;
122 println!("{}", eval_expr);
123 Ok(eval_expr)
124 }
125 Expr::Seq(exprs) => {
126 let mut res = vec![];
127 for expr in exprs {
128 let expr_res = eval(expr.clone(), var_map);
129 match expr_res {
130 Ok(eval_expr) => res.push(eval_expr),
131 Err(err) => return Err(err),
132 }
133 }
134
135 Ok(Expr::Seq(res))
136 }
137 }
138}
139
140fn main() {
141 let input = b"y = print z = 4
142x = print y
143y = 10
144print y
145print x
146print z";
147
148 match parser().parse(input.into_input()) {
149 Ok(PSuccess { val, rest: _ }) => {
150 print!("{:?}", val);
151 let res = eval(val, &mut HashMap::new());
152 match res {
153 Ok(ret) => println!("{:?}", ret),
154 Err(err) => println!("Evaluation Error: {}", err),
155 }
156 }
157 Err(e) => {
158 println!("{}", e)
159 }
160 }
161}