1#[macro_use]
2extern crate pest;
3#[macro_use]
4extern crate pest_derive;
5extern crate rand;
6
7use std::cell::RefCell;
8use std::rc::Rc;
9use std::fs::File;
10use std::io::prelude::*;
11use std::fmt;
12use std::fmt::Write;
13use std::collections::HashMap;
14use pest::Parser;
15use pest::error::{Error, ErrorVariant};
16use pest::iterators::Pair;
17use rand::prelude::*;
18
19#[derive(Parser)]
20#[grammar = "grammar.pest"]
21pub struct PseudocodeParser;
22
23pub struct Program {
24 instructions: Vec<Instruction>
25}
26
27impl Program {
28 fn new(insts: Vec<Instruction>) -> Self {
29 Program{
30 instructions: insts,
31 }
32 }
33}
34
35#[derive(Clone, Debug)]
36pub enum Op {
37 NEQ,
38 EQ,
39 GT,
40 LT,
41 GTE,
42 LTE,
43 MULT,
44 DIV,
45 PLUS,
46 MINUS,
47 MOD
48}
49
50#[derive(Clone, Debug)]
51pub enum Expr {
52 ProcedureCall(String, Vec<Expr>),
53 Number(f64),
54 String(String),
55 Boolean(bool),
56 Identifier(String),
57 BinaryExpr(Box<Expr>, Op, Box<Expr>),
58 Negate(Box<Expr>),
59 Not(Box<Expr>),
60 List(Vec<Expr>),
61 Index(String, Box<Expr>)
62}
63
64#[derive(Clone, Debug)]
65pub enum Instruction {
66 ProcedureDef(String, Vec<String>, Vec<Instruction>),
67 RepeatUntilBlock(Expr, Vec<Instruction>),
68 RepeatTimes(Expr, Vec<Instruction>),
69 ForEach(String, String, Vec<Instruction>),
70 IfSelection(Expr, Vec<Instruction>),
71 IfElseSelection(Expr, Vec<Instruction>, Vec<Instruction>),
72 ReturnStmt(Expr),
73 DisplayStmt(Expr),
74 ProcedureCall(String, Vec<Expr>),
75 IdentAssignment(String, Expr),
76 IndexAssignment(String, Expr, Expr) }
78
79#[derive(Clone, Debug)]
80pub enum Value {
81 Number(f64),
82 String(String),
83 Boolean(bool),
84 List(Rc<RefCell<Vec<Rc<RefCell<Value>>>>>)
85}
86
87impl fmt::Display for Value {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Value::Number(val) => write!(f, "{}", val),
91 Value::String(val) => write!(f, "{}", val),
92 Value::Boolean(val) => write!(f, "{}", val),
93 Value::List(list) => {
94 write!(f, "[")?;
95 let numvals = list.borrow().len();
96 for (idx, val) in list.borrow().iter().enumerate() {
97 if idx < numvals-1 {
98 write!(f, "{}, ", *val.borrow())?;
99 } else {
100 write!(f, "{}", *val.borrow())?;
101 }
102 }
103 write!(f, "]")
104 }
105 }
106 }
107}
108
109pub struct Procedure {
110 arglist: Vec<String>,
111 body: Vec<Instruction>,
112 native: Option<Box<dyn Fn(Rc<RefCell<Scope>>) -> Result<Vec<Instruction>, String>>>
113}
114
115impl Procedure {
116 fn new(arglist: Vec<String>, body: Vec<Instruction>, native: Option<Box<dyn Fn(Rc<RefCell<Scope>>) -> Result<Vec<Instruction>, String>>>) -> Self {
117 Procedure { arglist: arglist, body: body, native: native}
118 }
119}
120
121fn call_proc(scope: Rc<RefCell<Scope>>, name: String, args: Vec<Expr>, output: Rc<RefCell<String>>) -> Result<Option<Rc<RefCell<Value>>>, String> {
122 if let Some(_proc) = scope.clone().borrow().get_proc(&name) {
123 let proc = _proc.clone();
124 let func_scope = Rc::new(RefCell::new(Scope::new(scope.clone())));
125 for (idx, varname) in proc.borrow().arglist.iter().enumerate() {
126 let expr = &args[idx];
127 let evaluated = expr.eval(scope.clone(), output.clone())?;
128 func_scope.borrow_mut().variables.insert(varname.to_string(), evaluated);
129 }
130 if let Some(native_impl) = &proc.borrow().native {
131 let instructions = native_impl(func_scope.clone())?;
133 return run_instructions(instructions, func_scope, output.clone());
134 }
135 return run_instructions(proc.borrow().body.clone(), func_scope, output.clone());
136 } else {
137 return Err(format!("No procedure named {}", name));
138 }
139}
140
141pub struct Scope<'a> {
142 variables: HashMap<String, Rc<RefCell<Value>>>,
143 procedures: HashMap<String, Rc<RefCell<Procedure>>>,
144 parent: Option<Rc<RefCell<Scope<'a>>>>,
145}
146
147impl<'a> Scope<'a> {
148 fn new(parent: Rc<RefCell<Scope<'a>>>) -> Self {
149 Scope {
150 variables: HashMap::new(),
151 procedures: HashMap::new(),
152 parent: Some(parent),
153 }
154 }
155
156 fn new_base_scope() -> Self {
157 let mut s = Scope {
158 variables: HashMap::new(),
159 procedures: HashMap::new(),
160 parent: None,
161 };
162
163 let random_func = Procedure::new(vec!["a".to_string(), "b".to_string()], vec![], Some(Box::new(|scope| {
165 let mut rng = rand::thread_rng();
166 let a = scope.borrow().resolve("a".to_string()).ok_or("a is undefined")?;
167 let b = scope.borrow().resolve("b".to_string()).ok_or("a is undefined")?;
168 let val = match (a.borrow().clone(), b.borrow().clone()) {
169 (Value::Number(a), Value::Number(b)) => {
170 rng.gen_range(a as i64, (b as i64)+1)
171 },
172 _ => {
173 return Err("a and b most both be integers".to_string())
174 }
175 };
176 Ok(vec![
177 Instruction::ReturnStmt(Expr::Number(val as f64)),
178 ])
179 })));
180 s.procedures.insert("RANDOM".to_string(), Rc::new(RefCell::new(random_func)));
181
182 let concat_func = Procedure::new(vec!["a".to_string(), "b".to_string()], vec![], Some(Box::new(|scope| {
183 let a = scope.borrow().resolve("a".to_string()).ok_or("a is undefined")?;
184 let b = scope.borrow().resolve("b".to_string()).ok_or("a is undefined")?;
185 let val = match (a.borrow().clone(), b.borrow().clone()) {
186 (Value::String(a), Value::String(b)) => {
187 format!("{}{}", a, b)
188 },
189 _ => {
190 return Err("a and b most both be strings".to_string())
191 }
192 };
193 Ok(vec![
194 Instruction::ReturnStmt(Expr::String(val)),
195 ])
196 })));
197 s.procedures.insert("CONCAT".to_string(), Rc::new(RefCell::new(concat_func)));
198
199 let length_func = Procedure::new(vec!["l".to_string()], vec![], Some(Box::new(|scope| {
200 let list_val = scope.borrow().resolve("l".to_string()).ok_or("list is undefined")?;
201 let val = match list_val.borrow().clone() {
202 Value::List(list) => list.borrow().len() as f64,
203 _ => return Err("Argument to LENGTH must be a list".to_string())
204 };
205 Ok(vec![Instruction::ReturnStmt(Expr::Number(val))])
206 })));
207 s.procedures.insert("LENGTH".to_string(), Rc::new(RefCell::new(length_func)));
208
209 let insert_func = Procedure::new(vec!["list".to_string(), "i".to_string(), "value".to_string()], vec![], Some(Box::new(|scope| {
210 let list_val = scope.borrow().resolve("list".to_string()).ok_or("list is undefined")?;
211 let list = match list_val.borrow().clone() {
212 Value::List(list) => list,
213 _ => return Err("First argument to INSERT must be a list".to_string())
214 };
215 let idx_val = scope.borrow().resolve("i".to_string()).ok_or("i is undefined")?;
216 let idx = match *idx_val.borrow() {
217 Value::Number(idx) => if idx.fract() != 0.0 {
218 return Err("Second argument to INSERT must be an integer".to_string())
219 } else if idx < 1.0 || idx > list.borrow().len() as f64 {
220 return Err("Second argument to INSERT must be between 1 and the length of the list".to_string())
221 } else {
222 idx as usize
223 },
224 _ => return Err("First argument to INDEX must be a list".to_string())
225 };
226 let value = scope.borrow().resolve("value".to_string()).ok_or("value is undefined")?;
227 list.borrow_mut().insert(idx - 1, value);
228 Ok(vec![])
229 })));
230 s.procedures.insert("INSERT".to_string(), Rc::new(RefCell::new(insert_func)));
231
232 let remove_func = Procedure::new(vec!["list".to_string(), "i".to_string()], vec![], Some(Box::new(|scope| {
233 let list_val = scope.borrow().resolve("list".to_string()).ok_or("list is undefined")?;
234 let list = match list_val.borrow().clone() {
235 Value::List(list) => list,
236 _ => return Err("First argument to REMOVE must be a list".to_string())
237 };
238 let idx_val = scope.borrow().resolve("i".to_string()).ok_or("i is undefined")?;
239 let idx = match *idx_val.borrow() {
240 Value::Number(idx) => if idx.fract() != 0.0 {
241 return Err("Second argument to REMOVE must be an integer".to_string())
242 } else {
243 idx as usize
244 },
245 _ => return Err("First argument to REMOVE must be a list".to_string())
246 };
247 list.borrow_mut().remove(idx);
248 Ok(vec![])
249 })));
250 s.procedures.insert("REMOVE".to_string(), Rc::new(RefCell::new(remove_func)));
251
252 let append_func = Procedure::new(vec!["list".to_string(), "value".to_string()], vec![], Some(Box::new(|scope| {
253 let list_val = scope.borrow().resolve("list".to_string()).ok_or("list is undefined")?;
254 let list = match list_val.borrow().clone() {
255 Value::List(list) => list,
256 _ => return Err("First argument to APPEND must be a list".to_string())
257 };
258 let value = scope.borrow().resolve("value".to_string()).ok_or("value is undefined")?;
259 list.borrow_mut().push(value);
260 Ok(vec![])
261 })));
262 s.procedures.insert("APPEND".to_string(), Rc::new(RefCell::new(append_func)));
263
264 return s
265 }
266
267 fn define_proc(&mut self, name: String, arglist: Vec<String>, body: Vec<Instruction>) {
268 self.procedures.insert(name,
269 Rc::new(RefCell::new(Procedure::new(arglist, body, None))));
270 }
271
272 fn defined_in_parent(&self, ident: &String) -> bool {
273 if let Some(parent_scope) = &self.parent {
274 if parent_scope.borrow().variables.contains_key(ident) {
275 return true
276 } else {
277 parent_scope.borrow().defined_in_parent(ident)
278 }
279 } else {
280 false
281 }
282 }
283
284 fn assign(&mut self, ident: String, value: Rc<RefCell<Value>>) {
285 if self.variables.contains_key(&ident) {
286 self.variables.insert(ident, value);
287 } else if self.defined_in_parent(&ident) {
288 if let Some(parent_scope) = &self.parent {
289 parent_scope.borrow_mut().assign(ident, value);
290 }
291 } else {
292 self.variables.insert(ident, value);
293 }
294 }
295
296
297 fn resolve(&self, ident: String) -> Option<Rc<RefCell<Value>>> {
298 match self.variables.get(&ident) {
299 Some(val) => Some(val.clone()),
300 None => match &self.parent {
301 Some(parent_scope) => parent_scope.borrow().resolve(ident),
302 None => None
303 }
304 }
305 }
306
307 fn get_proc(&self, ident: &String) -> Option<Rc<RefCell<Procedure>>> {
308 match self.procedures.get(ident) {
309 Some(val) => Some(val.clone()),
310 None => match &self.parent {
311 Some(parent_scope) => parent_scope.borrow().get_proc(ident),
312 None => None
313 }
314 }
315 }
316
317 fn dump(&self) {
318 println!("### DUMPING SCOPE ###");
319 for (var, val) in self.variables.iter() {
320 println!("{} => {:?}", var, val);
321 }
322 }
323}
324
325impl Expr {
326 fn eval(&self, scope: Rc<RefCell<Scope>>, output: Rc<RefCell<String>>) -> Result<Rc<RefCell<Value>>, String> {
327 match self {
328 Expr::Number(val) => Ok(Rc::new(RefCell::new(Value::Number(*val)))),
329 Expr::String(val) => Ok(Rc::new(RefCell::new(Value::String(val.clone())))),
330 Expr::Boolean(val) => Ok(Rc::new(RefCell::new(Value::Boolean(val.clone())))),
331 Expr::Identifier(ident) => match scope.borrow().resolve(ident.to_string()) {
332 Some(val) => Ok(val),
333 None => Err(format!("Variable {} is not defined", ident))
334 },
335 Expr::Negate(expr) => {
336 let val = expr.eval(scope.clone(), output.clone())?.borrow().clone();
337 match val {
338 Value::Number(n) => Ok(Rc::new(RefCell::new(Value::Number(-n)))),
339 _ => Err(format!("Value {} must be a number", val))
340 }
341 },
342 Expr::Not(expr) => {
343 let val = expr.eval(scope.clone(), output.clone())?.borrow().clone();
344 match val {
345 Value::Boolean(n) => Ok(Rc::new(RefCell::new(Value::Boolean(!n)))),
346 _ => Err(format!("Value {} must be a boolean value but was a {:?}", val, val)),
347 }
348 },
349 Expr::BinaryExpr(lhs, op, rhs) => {
350 let lhsval = lhs.eval(scope.clone(), output.clone())?;
351 let rhsval = rhs.eval(scope.clone(), output.clone())?;
352 match op {
353 Op::PLUS => {
354 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
355 (Value::Number(f1), Value::Number(f2)) => {
356 Ok(Rc::new(RefCell::new(Value::Number(f1 + f2))))
357 },
358 (_, _) => {
359 Err(format!("{:?} and {:?} must both be numbers", lhsval, rhsval))
360 }
361 }
362 },
363 Op::MINUS => {
364 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
365 (Value::Number(f1), Value::Number(f2)) => {
366 Ok(Rc::new(RefCell::new(Value::Number(f1 - f2))))
367 },
368 (_, _) => {
369 Err(format!("{:?} and {:?} must both be numbers", lhsval, rhsval))
370 }
371 }
372 },
373 Op::MULT => {
374 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
375 (Value::Number(f1), Value::Number(f2)) => {
376 Ok(Rc::new(RefCell::new(Value::Number(f1 * f2))))
377 },
378 (_, _) => {
379 Err(format!("{:?} and {:?} must both be numbers", lhsval, rhsval))
380 }
381 }
382 },
383 Op::DIV => {
384 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
385 (Value::Number(f1), Value::Number(f2)) => {
386 Ok(Rc::new(RefCell::new(Value::Number(f1 / f2))))
387 },
388 (_, _) => {
389 Err(format!("{:?} and {:?} must both be numbers", lhsval, rhsval))
390 }
391 }
392 },
393 Op::MOD => {
394 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
395 (Value::Number(f1), Value::Number(f2)) => {
396 Ok(Rc::new(RefCell::new(Value::Number(f1 % f2))))
397 },
398 (_, _) => {
399 Err(format!("{:?} and {:?} must both be numbers", lhsval, rhsval))
400 }
401 }
402 },
403 Op::EQ => {
404 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
405 (Value::Number(f1), Value::Number(f2)) => {
406 Ok(Rc::new(RefCell::new(Value::Boolean(f1 == f2))))
407 },
408 (Value::String(f1), Value::String(f2)) => {
409 Ok(Rc::new(RefCell::new(Value::Boolean(f1 == f2))))
410 },
411 (Value::Boolean(f1), Value::Boolean(f2)) => {
412 Ok(Rc::new(RefCell::new(Value::Boolean(f1 == f2))))
413 },
414 (_, _) => {
415 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
416 }
417 }
418 },
419 Op::NEQ => {
420 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
421 (Value::Number(f1), Value::Number(f2)) => {
422 Ok(Rc::new(RefCell::new(Value::Boolean(f1 != f2))))
423 },
424 (Value::String(f1), Value::String(f2)) => {
425 Ok(Rc::new(RefCell::new(Value::Boolean(f1 != f2))))
426 },
427 (Value::Boolean(f1), Value::Boolean(f2)) => {
428 Ok(Rc::new(RefCell::new(Value::Boolean(f1 != f2))))
429 },
430 (_, _) => {
431 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
432 }
433 }
434 },
435 Op::GT => {
436 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
437 (Value::Number(f1), Value::Number(f2)) => {
438 Ok(Rc::new(RefCell::new(Value::Boolean(f1 > f2))))
439 },
440 (_, _) => {
441 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
442 }
443 }
444 },
445 Op::LT => {
446 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
447 (Value::Number(f1), Value::Number(f2)) => {
448 Ok(Rc::new(RefCell::new(Value::Boolean(f1 < f2))))
449 },
450 (_, _) => {
451 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
452 }
453 }
454 },
455 Op::GTE => {
456 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
457 (Value::Number(f1), Value::Number(f2)) => {
458 Ok(Rc::new(RefCell::new(Value::Boolean(f1 >= f2))))
459 },
460 (_, _) => {
461 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
462 }
463 }
464 },
465 Op::LTE => {
466 match (lhsval.borrow().clone(), rhsval.borrow().clone()) {
467 (Value::Number(f1), Value::Number(f2)) => {
468 Ok(Rc::new(RefCell::new(Value::Boolean(f1 <= f2))))
469 },
470 (_, _) => {
471 Err(format!("{:?} and {:?} must be same type", lhsval, rhsval))
472 }
473 }
474 },
475 }
476 },
477 Expr::ProcedureCall(procname, arglist) => {
478 let value = call_proc(scope.clone(), procname.to_string(), arglist.clone(), output.clone())?;
479 if let Some(value) = value {
480 Ok(value)
481 } else {
482 Ok(Rc::new(RefCell::new(Value::Number(-1.0))))
483 }
484 },
485 Expr::List(list) => {
486 let mut list_val: Vec<Rc<RefCell<Value>>> = Vec::new();
487 for vexpr in list.iter() {
488 let val = vexpr.eval(scope.clone(), output.clone())?;
490 list_val.push(val)
491 }
492 let l = Rc::new(RefCell::new(list_val));
493 Ok(Rc::new(RefCell::new(Value::List(l))))
494 },
495 Expr::Index(list_ident, index_expr) => {
496 let list_val = scope.borrow().resolve(list_ident.to_string())
497 .expect(&format!("List variable {} is not defined", list_ident)).borrow().clone();
498 if let Value::List(list) = list_val {
499 let index_val = index_expr.eval(scope.clone(), output.clone())?;
500 if let Value::Number(index) = *index_val.borrow() {
501 if index.fract() != 0.0 {
502 return Err(format!("Index {} must be an integer", *index_val.borrow()))
503 }
504 match list.borrow().get(index as usize-1) {
505 Some(val) => return Ok(val.clone()),
506 None => return Err(format!("List index {} is out of range {:?}", index, list))
507 };
508 } else {
509 return Err(format!("Index {} must be an integer", *index_val.borrow()));
510 };
511 } else {
512 return Err(format!("Variable {} must be a list", list_ident))
513 }
514 }
515 }
516 }
517}
518
519pub fn parse_op(pair: Pair<Rule>) -> Op {
520 let op = pair.into_inner().next().unwrap();
521 match op.as_rule() {
522 Rule::neq => Op::NEQ,
523 Rule::eq => Op::EQ,
524 Rule::gt => Op::GT,
525 Rule::lt => Op::LT,
526 Rule::gte => Op::GTE,
527 Rule::lte => Op::LTE,
528 Rule::mult => Op::MULT,
529 Rule::div => Op::DIV,
530 Rule::plus => Op::PLUS,
531 Rule::minus => Op::MINUS,
532 Rule::modop => Op::MOD,
533 _ => { panic!("{:#?} is unknown", op); }
534 }
535}
536
537fn parse_value_inner(val: Pair<Rule>) -> Expr {
538 match val.as_rule() {
539 Rule::procedure_call => {
540 let mut block = val.into_inner();
541 let ident = block.next().unwrap().as_str().to_string();
542 let arg_list: Vec<Expr> = block.next().unwrap().into_inner().map(parse_expr).collect();
543 Expr::ProcedureCall(ident, arg_list)
544 },
545 Rule::number => {
546 let val: f64 = val.as_str().parse().unwrap();
547 Expr::Number(val)
548 },
549 Rule::string => {
550 Expr::String(val.into_inner().next().unwrap().as_str().to_string())
552 },
553 Rule::boolean => {
554 Expr::Boolean(val.as_str() == "true")
555 },
556 Rule::identifier => {
557 Expr::Identifier(val.as_str().trim().to_string())
558 },
559 Rule::expression => {
560 parse_expr(val)
561 },
562 Rule::list => {
563 let x: Vec<Expr> = val.into_inner().map(|v| {
564 parse_expr(v)
565 }).collect();
566 Expr::List(x)
567 },
568 Rule::index => {
569 let mut block = val.into_inner();
570 let ident = block.next().unwrap().as_str().to_string();
571 let index = parse_expr(block.next().unwrap());
572 Expr::Index(ident, Box::new(index))
573 },
574 _ => {
575 panic!("UNEXPECTED VALUE parse_value_inner {:?}", val);
576 }
577 }
578}
579
580pub fn parse_value(pair: Pair<Rule>) -> Expr {
581 let mut block = pair.into_inner();
582 let val = block.next().unwrap();
583 match val.as_rule() {
584 Rule::prefix_op => {
585 let inner_val = parse_value_inner(block.next().unwrap());
586 match val.into_inner().next().unwrap().as_rule() {
587 Rule::minus => Expr::Negate(Box::new(inner_val)),
588 Rule::not => Expr::Not(Box::new(inner_val)),
589 _ => unreachable!()
590 }
591 }
592 _ => parse_value_inner(val)
593 }
594}
595
596pub fn parse_expr(pair: Pair<Rule>) -> Expr {
597 match pair.as_rule() {
598 Rule::value => parse_value(pair),
599 Rule::expression => {
600 let mut parts = pair.into_inner();
601 let mut lhs = parse_expr(parts.next().unwrap());
602 while let Some(_) = parts.peek() {
603 let op = parse_op(parts.next().unwrap());
604 let rhs = parse_expr(parts.next().unwrap());
605 lhs = Expr::BinaryExpr(Box::new(lhs), op, Box::new(rhs));
606 }
607 return lhs;
608 },
609 _ => {
610 panic!("other {:?}", pair);
611 }
612 }
613}
614
615pub fn parse_block(block: Pair<Rule>) -> Vec<Instruction> {
616 let mut instructions: Vec<Instruction> = Vec::new();
617 for inst in block.into_inner() {
619 let bi = inst.into_inner().next().unwrap();
620 match bi.as_rule() {
621 Rule::selection_block => {
622 if let Some(sel_block) = parse_selection(bi) {
623 instructions.push(sel_block);
624 }
625 },
626 Rule::assignment => {
627 let mut block = bi.into_inner();
628 let symbol = block.next().unwrap();
629 block.next(); match symbol.as_rule() {
631 Rule::identifier => {
632 let ident = symbol.as_str().trim().to_string();
633 let expr = block.next().unwrap();
634 instructions.push(Instruction::IdentAssignment(ident, parse_expr(expr)));
635 },
636 _ => {
637 panic!("UNEXPECTED parse_block {:?}", symbol);
638 }
639 }
640 },
642 Rule::return_statement => {
643 let expr = parse_expr(bi.into_inner().next().unwrap());
644 instructions.push(Instruction::ReturnStmt(expr));
645 }
646 Rule::display => {
647 let expr = parse_expr(bi.into_inner().next().unwrap());
648 instructions.push(Instruction::DisplayStmt(expr));
649 }
650 _ => {
651 panic!("other {:?}", bi);
652 }
653 }
654 }
655 return instructions;
656}
657
658pub fn parse_selection(sel: Pair<Rule>) -> Option<Instruction> {
659 let inst = sel.into_inner().next().unwrap();
660 match inst.as_rule() {
661 Rule::if_expr => {
662 let mut block = inst.into_inner();
663 let cond_expr = parse_expr(block.next().unwrap());
664 let cond_inst = parse_block(block.next().unwrap());
665 Some(Instruction::IfSelection(cond_expr, cond_inst))
666 },
667 Rule::if_else_expr => {
668 let mut block = inst.into_inner();
669 let cond_expr = parse_expr(block.next().unwrap());
670 let cond_inst = parse_block(block.next().unwrap());
671 let else_inst = parse_block(block.next().unwrap());
672 Some(Instruction::IfElseSelection(cond_expr, cond_inst, else_inst))
673 },
674 _ => { None }
675 }
676}
677
678pub fn parse_prog(prog: &str) -> Result<Program, Error<Rule>> {
679 if let Err(a) = PseudocodeParser::parse(Rule::program, prog) {
680 println!("syntax error at {:?}", a.location);
681 println!("syntax error at line col: {:?}", a.line_col);
682 match a.variant {
683 ErrorVariant::ParsingError{positives, negatives: _} => {
684 println!("positive? {:?}", positives.get(0).unwrap());
685 },
686 ErrorVariant::CustomError{message: _} => {},
687 }
688 };
689
690 let parsed = PseudocodeParser::parse(Rule::program, prog)?;
691 let mut instructions: Vec<Instruction> = Vec::new();
692 for inst in parsed {
693 match inst.as_rule() {
694 Rule::selection_block => {
695 if let Some(sel_block) = parse_selection(inst) {
696 instructions.push(sel_block);
697 }
698 },
699 Rule::iteration_block => {
700 let block = inst.into_inner().next().unwrap();
701 match block.as_rule() {
702 Rule::repeat_until => {
703 let mut ib = block.into_inner();
704 let expr = parse_expr(ib.next().unwrap());
705 let inst = parse_block(ib.next().unwrap());
706 instructions.push(Instruction::RepeatUntilBlock(expr, inst));
707 },
708 Rule::repeat_times => {
709 let mut ib = block.into_inner();
710 let times = parse_expr(ib.next().unwrap());
711 let inst = parse_block(ib.next().unwrap());
712 instructions.push(Instruction::RepeatTimes(times, inst));
713 },
714 Rule::for_each => {
715 let mut ib = block.into_inner();
716 let ident = ib.next().unwrap().as_str().trim().to_string();
717 let loopvar = ib.next().unwrap().as_str().trim().to_string(); let inst = parse_block(ib.next().unwrap());
719 instructions.push(Instruction::ForEach(loopvar, ident, inst));
720 },
721 _ => {
722 panic!("other {:?}", block);
723 }
724 }
725 },
726 Rule::procedure_def => {
727 let mut block = inst.into_inner();
728 let proc_name = block.next().unwrap().as_str().to_string();
729 let arg_list: Vec<String> = block.next().unwrap().into_inner().map(|pair|
730 pair.as_str().to_string()
731 ).collect();
732 let proc_list = parse_block(block.next().unwrap());
733 instructions.push(Instruction::ProcedureDef(proc_name, arg_list, proc_list));
734 },
735 Rule::assignment => {
736 let mut block = inst.into_inner();
737 let symbol = block.next().unwrap();
738 block.next(); match symbol.as_rule() {
740 Rule::identifier => {
741 let ident = symbol.as_str().trim().to_string();
742 let expr = block.next().unwrap();
743 instructions.push(Instruction::IdentAssignment(ident, parse_expr(expr)));
744 },
745 Rule::index => {
746 let mut index_sym = symbol.into_inner();
747 let list_ident = index_sym.next().unwrap().as_str().trim().to_string();
748 let list_index = index_sym.next().unwrap();
749 let list_value = block.next().unwrap();
750 instructions.push(Instruction::IndexAssignment(list_ident, parse_expr(list_index), parse_expr(list_value)));
751 },
752 _ => {
753 panic!("UNEXPECTED parse_block {:?}", symbol);
754 }
755 }
756 },
757 Rule::display => {
758 let inner = inst.into_inner().next().unwrap();
759 let expr = parse_expr(inner);
760 instructions.push(Instruction::DisplayStmt(expr));
761 }
762 Rule::expression => {
763 let inner = inst.into_inner().next().unwrap().into_inner().next().unwrap();
764 match inner.as_rule() {
765 Rule::procedure_call => {
766 let mut call = inner.into_inner();
767 let ident = call.next().unwrap().as_str().trim().to_string();
768 let arg_list: Vec<Expr> = call.next().unwrap().into_inner().map(parse_expr).collect();
769 instructions.push(Instruction::ProcedureCall(ident, arg_list));
770 },
771 _ => {}
772 }
773 },
774 _ => {}
775 }
776 }
777 Ok(Program::new(instructions))
778}
779
780fn run_instructions(instructions: Vec<Instruction>, scope: Rc<RefCell<Scope>>, output: Rc<RefCell<String>>) -> Result<Option<Rc<RefCell<Value>>>, String> {
782 let mut return_value: Option<Rc<RefCell<Value>>> = None;
783 for instruction in instructions.iter() {
784 match instruction {
785 Instruction::ProcedureDef(name, arglist, block) => {
786 scope.borrow_mut().define_proc(name.to_string(), arglist.to_vec(), block.to_vec());
787 },
788 Instruction::RepeatUntilBlock(expr, block) => {
789 loop {
790 if let Value::Boolean(doloop) = *expr.eval(scope.clone(), output.clone())?.borrow() {
791 if !doloop {
792 run_instructions(block.to_vec(), scope.clone(), output.clone())?;
793 } else {
794 break
795 }
796 }
797 }
798 },
799 Instruction::RepeatTimes(expr, block) => {
800 if let Value::Number(ntimes) = *expr.eval(scope.clone(), output.clone())?.borrow() {
801 for _ in 0..(ntimes as u64) {
802 run_instructions(block.to_vec(), scope.clone(), output.clone())?;
803 }
804 }
805 },
806 Instruction::ForEach(list_ident, loopvar, block) => {
808 if let Value::List(list) = scope.borrow().resolve(list_ident.to_string())
809 .expect(&format!("List variable {} is not defined", list_ident)).borrow().clone() {
810
811 for item in list.borrow().iter() {
812 let loop_scope = Rc::new(RefCell::new(Scope::new(scope.clone())));
813 loop_scope.borrow_mut().variables.insert(loopvar.to_string(), item.clone());
814 run_instructions(block.to_vec(), loop_scope, output.clone())?;
815 }
816 }
817
818 },
819 Instruction::IfSelection(cond, block) => {
820 if let Value::Boolean(expr) = *cond.eval(scope.clone(), output.clone())?.borrow() {
821 if expr {
823 return_value = run_instructions(block.to_vec(), scope.clone(), output.clone())?;
824 }
825 }
826 },
827 Instruction::IfElseSelection(cond, block, elseblock) => {
828 if let Value::Boolean(expr) = *cond.eval(scope.clone(), output.clone())?.borrow() {
829 if expr {
831 return_value = run_instructions(block.to_vec(), scope.clone(), output.clone())?;
832 } else {
833 return_value = run_instructions(elseblock.to_vec(), scope.clone(), output.clone())?;
834 }
835 }
836 },
837 Instruction::ProcedureCall(procname, arglist) => {
838 return_value = call_proc(scope.clone(), procname.to_string(), arglist.clone(), output.clone())?;
839 }
840 Instruction::DisplayStmt(expr) => {
841 let value = expr.eval(scope.clone(), output.clone())?;
842 match write!(&mut output.borrow_mut(), "{} ", *value.borrow()) {
843 Err(e) => panic!("Could not print to output: {}", e),
844 _ => {}
845 };
846 },
847 Instruction::IdentAssignment(ident, expr) => {
848 let value = expr.eval(scope.clone(), output.clone())?;
849 scope.borrow_mut().assign(ident.to_string(), value);
850 },
851 Instruction::IndexAssignment(list_ident, list_index, list_value) => {
852 let list_val = scope.borrow().resolve(list_ident.to_string())
853 .expect(&format!("List variable {} is not defined", list_ident));
854 if let Value::List(list) = list_val.borrow().clone() {
856 let index_val = list_index.eval(scope.clone(), output.clone())?;
857 if let Value::Number(index) = *index_val.borrow() {
858 if index.fract() != 0.0 {
859 return Err(format!("Index {} must be an integer", index))
860 }
861 if (index) < 1.0 || (index as usize) > list.borrow().len() {
862 return Err(format!("Index {} is out of range", index))
863 }
864 let value = list_value.eval(scope.clone(), output.clone())?;
865 list.borrow_mut()[index as usize - 1] = value;
866 let l = Rc::new(RefCell::new(Value::List(list)));
868 scope.borrow_mut().assign(list_ident.to_string(), l);
869 };
870 };
871 },
872 Instruction::ReturnStmt(expr) => {
873 let value = expr.eval(scope.clone(), output.clone())?;
874 return_value = Some(value);
875 }
876 }
877 }
878 Ok(return_value)
879}
880
881pub fn eval(prog: &str) -> Result<String, String> {
882 let output = Rc::new(RefCell::new(String::new()));
883 match parse_prog(prog) {
884 Ok(program) => {
885 let scope = Rc::new(RefCell::new(Scope::new_base_scope()));
886 run_instructions(program.instructions, scope.clone(), output.clone())?;
887 Ok(output.borrow().to_string())
889 },
890 Err(err) => Err(format!("Parse Error: {}", err.to_string()))
891 }
892}
893
894pub fn eval_file(filename: &str) -> Result<String, String> {
895 let mut file = File::open(filename).expect("Problem opening file");
896 let mut prog = String::new();
897 file.read_to_string(&mut prog).expect("Problem reading file");
898 eval(&prog)
899}
900
901#[cfg(test)]
902mod tests {
903 use super::*;
904 use pest::parses_to;
905
906 macro_rules! map(
907 { $($key:expr => $value:expr),+ } => {
908 {
909 let mut m = ::std::collections::HashMap::new();
910 $(
911 m.insert($key, $value);
912 )+
913 m
914 }
915 };
916 );
917
918 #[test]
919 fn test_parse() {
920 let success = PseudocodeParser::parse(Rule::program, "abc ← 3.0").unwrap();
921 println!("{:?}", success);
922 }
923
924 #[test]
925 fn test_parse_binary_expr() {
926 let success = PseudocodeParser::parse(Rule::expression, "(3 * 2) < (4 * 10.3)").unwrap();
927 println!("{:?}", success);
928 }
929
930 #[test]
931 fn test_parse_assignment_expr() {
932 let success = PseudocodeParser::parse(Rule::expression, "a ← 1 + 2").unwrap();
933 println!("{:#?}", success);
934 }
935
936 #[test]
937 fn test_file_output() -> Result<(), String> {
938 let file_output = map!(
939 "test_programs/assignment.ap" => "a is 3 b is 10.5 string_val is hello",
940 "test_programs/expr.ap" => "1 2 3 4 5 6 7 8 9 10",
941 "test_programs/loops.ap" => "1 2 3 x is even 2 x is odd 3 x is even 4 x is odd 5",
942 "test_programs/procedure.ap" => "inside did func work? true",
943 "test_programs/negate.ap" => "-1 -3 -6 -6 false true false true",
944 "test_programs/ops.ap" => "true false true",
945 "test_programs/list.ap" => "[] [1, 2, 3] [abc, def] [[1, 2, 3], [4, 5, 6]] [2, 7, 17.5]",
946 "test_programs/list2.ap" => "[1, 2, 3] [a, 1, 2, 3] [a, 1, b, 2, 3]",
947 "test_programs/recursion.ap" => "1 720"
948 );
949 for (file, expected_output) in file_output.iter() {
950 let output = eval_file(file).unwrap().trim().to_string();
951 assert!(output.eq(expected_output))
952 }
953 Ok(())
954 }
955
956 #[test]
957 fn test_parses_to() {
958 parses_to! {
959 parser: PseudocodeParser,
960 input: "my_variable",
961 rule: Rule::identifier,
962 tokens: [identifier(0, 11)]
963 }
964
965 parses_to! {
966 parser: PseudocodeParser,
967 input: "\"hello world\"",
968 rule: Rule::string,
969 tokens: [string(0, 13, [inner(1, 12)])]
970 }
971 }
972}