1use std::fmt;
2use std::io::prelude::*;
3use std::convert::{TryFrom, TryInto};
4
5use combinedfun as cf;
6use cf::types::VerboseError;
7use cf::str_parsers as sp;
8
9#[derive(Clone, Debug)]
10pub enum Value {
11 Str(String),
12 Int(i32),
13 Float(f32),
14 List(Vec<Value>),
15}
16
17impl fmt::Display for Value {
18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 match *self {
20 Value::Str(ref s) => write!(f, "{:?}", s),
21 Value::Int(ref i) => write!(f, "{:?}", i),
22 Value::Float(ref fl) => write!(f, "{:?}", fl),
23 Value::List(ref l) => {
24 write!(f, "(")?;
25 let mut first = true;
26 for i in l {
27 if first {
28 first = false;
29 } else {
30 write!(f, " ")?;
31 }
32 write!(f, "{}", i)?;
33 }
34 write!(f, ")")?;
35 Ok(())
36 },
37 }
38 }
39}
40
41type ParserInput<'a> = cf::Span<&'a str, cf::Pos>;
42pub type ParserError<'a> = VerboseError<'a, ParserInput<'a>, (), str>;
43
44type ParserResult<'a, Out> = Result<(ParserInput<'a>, Out), ParserError<'a>>;
45
46fn parse_partial(i: ParserInput) -> ParserResult<Value> {
47 fn string(i: ParserInput) -> ParserResult<String> {
48 (
49 -cf::tag("\"")
50 >> cf::record_while(|&c: &char| c != '"', ..)
51 >> -cf::tag("\"")
52 >> ToOwned::to_owned
53 ).parse_partial(i)
54 }
55
56 fn consume_digits<'a, R: cf::RangeLike>(range: R) -> cf::parser!(<ParserInput<'a>, (), ParserError<'a>>) {
57 cf::consume_while(|&c: &char| c.is_digit(10), range)
58 }
59
60 fn float_e(i: ParserInput) -> ParserResult<()> {
61 (
62 -cf::tag("e")
63 >> -(cf::tag("-") | ())
64 >> -consume_digits(1..)
65 >> cf::epsilon()
66 ).parse_partial(i)
67 }
68
69 fn float(i: ParserInput) -> ParserResult<f32> {
74 (
75 (
76 -(cf::tag("-") | ())
77 >> (
78 -cf::tag(".") >> -consume_digits(1..) >> cf::epsilon()
79 |
80 -consume_digits(1..) >> (
81 -cf::tag(".") >> -consume_digits(0..) >> -(cf::f(float_e) | ()) >> cf::epsilon()
82 |
83 -cf::f(float_e) >> cf::epsilon()
84 )
85 )
86 ).record()
87 >> (|s: &str| s.parse::<f32>().unwrap())
88 ).parse_partial(i)
89 }
90
91 fn int(i: ParserInput) -> ParserResult<i32> {
92 (
93 (
94 -(cf::tag("-") | ())
95 >> cf::consume_while(|&c: &char| c.is_digit(10), 1..)
96 ).record()
97 >> (|s: &str| s.parse::<i32>().unwrap())
98 ).parse_partial(i)
99 }
100
101 fn list(i: ParserInput) -> ParserResult<Vec<Value>> {
102 (
103 -cf::tag("(")
104 >> cf::f(parse_partial) / sp::ws(1..) * Vec::new * ..
105 >> -sp::ws(..)
106 >> -cf::tag(")")
107 ).parse_partial(i)
108 }
109
110 (
111 -sp::ws(..)
112 >> (
113 cf::f(string) >> Value::Str
114 | cf::f(float) >> Value::Float
115 | cf::f(int) >> Value::Int
116 | cf::f(list) >> Value::List
117 )
118 ).parse_partial(i)
119}
120
121pub fn parse(i: &str) -> Result<Value, ParserError> {
122 (cf::f(parse_partial) >> -sp::ws(..)).parse(ParserInput::new(i))
123}
124
125#[derive(Clone, Debug)]
126pub enum LispError {
127 EmptyCommand,
128 ExpectedCommand(Value),
129 ExpectedCommandWithArgs(Value),
130 ExpectedNumber(Value),
131 WrongArgCountDivision(Vec<Value>),
132 WrongArgCountQuote(Vec<Value>),
133 UndefinedFunction(String),
134}
135
136enum Number {
137 Int(i32),
138 Float(f32),
139}
140
141impl From<Number> for Value {
142 fn from(number: Number) -> Self {
143 match number {
144 Number::Int(i) => Value::Int(i),
145 Number::Float(f) => Value::Float(f),
146 }
147 }
148}
149
150impl<'a> TryFrom<&'a Value> for Number {
151 type Error = LispError;
152
153 fn try_from(value: &'a Value) -> Result<Number, LispError> {
154 match *value {
155 Value::Int(i) => Ok(Number::Int(i)),
156 Value::Float(f) => Ok(Number::Float(f)),
157 ref inp @ Value::List(_) => match evaluate(inp)? {
158 Value::Int(i) => Ok(Number::Int(i)),
159 Value::Float(f) => Ok(Number::Float(f)),
160 ref val => Err(LispError::ExpectedNumber(val.clone())),
161 },
162 ref val => Err(LispError::ExpectedNumber(val.clone())),
163 }
164 }
165}
166
167impl<'a> TryFrom<&'a Value> for f32 {
168 type Error = LispError;
169
170 fn try_from(value: &'a Value) -> Result<f32, LispError> {
171 match value.try_into()? {
172 Number::Float(f) => Ok(f),
173 Number::Int(i) => Ok(i as f32),
174 }
175 }
176}
177
178pub fn evaluate(v: &Value) -> Result<Value, LispError> {
179 macro_rules! cmd {
180 ($elements:expr, neutral = $neutral:expr, $op:tt) => {
181 $elements.iter().skip(1).fold(Ok(Number::Int($neutral)), |acc, next| match acc? { Number::Int(i) => match next.try_into()? {
183 Number::Int(i2) => Ok(Number::Int(i $op i2)),
184 Number::Float(f) => Ok(Number::Float(i as f32 $op f)),
185 },
186 Number::Float(f) => Ok(Number::Float(f $op f32::try_from(next)?)),
187 }).map(Into::into)
188 };
189 }
190
191 match *v {
192 Value::List(ref elements) => {
193 if let Some(first) = elements.first() {
194 match *first {
195 Value::Str(ref s) => match &**s {
196 "+" => cmd!(elements, neutral = 0, +),
197 "-" => cmd!(elements, neutral = 0, +),
198 "*" => cmd!(elements, neutral = 0, +),
199 "/" => if elements.len() == 3 {
200 Ok(Value::Float(f32::try_from(&elements[1])? / f32::try_from(&elements[2])?))
201 } else {
202 Err(LispError::WrongArgCountDivision(elements.clone()))
203 },
204 "quote" => if elements.len() == 2 {
205 Ok(elements[1].clone())
206 } else {
207 Err(LispError::WrongArgCountQuote(elements.clone()))
208 },
209 s => Err(LispError::UndefinedFunction(s.to_owned())),
210 },
211 ref x => Err(LispError::ExpectedCommand(x.clone())),
212 }
213 } else {
214 Err(LispError::EmptyCommand)
215 }
216 },
217 ref v => Err(LispError::ExpectedCommandWithArgs(v.clone())),
218 }
219}
220
221fn main() {
222 let mut input = String::new();
223 std::io::stdin().read_to_string(&mut input).unwrap();
224
225 let expression = match parse(&input) {
226 Ok(expression) => expression,
227 Err(error) => {
228 eprintln!("Encountered an error while parsing:\n{:#?}", error);
229 return;
230 },
231 };
232 let result = evaluate(&expression);
233 match result {
234 Ok(value) => println!("{}", value),
235 Err(error) => eprintln!("Encountered an error while evaluating:\n{:#?}", error),
236 }
237}