From fc11ee753d1e8a64802ead089159236064a1c846 Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 1 Jan 2016 00:52:48 -0800 Subject: [PATCH] Add block parsing Right now evaluating a block reduces it to just the last AST in it, will fix later with environments --- src/evaluator.rs | 6 ++++++ src/parser.rs | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/evaluator.rs b/src/evaluator.rs index 40ee681..e75ae6b 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -42,6 +42,12 @@ fn reduce_full(ast: AST) -> EvaluatorResult { fn reduce_step(ast: AST) -> EvaluatorResult { use parser::AST::*; match ast { + Block(mut block_nodes) => { + match block_nodes.pop() { + None => Err(EvaluatorError { err: format!("Block with no statements") }), + Some(node) => reduce_full(node), + } + }, BinOp(left, op, right) => { let left = try!(reduce_full(*left)); let op = try!(reduce_full(*op)); diff --git a/src/parser.rs b/src/parser.rs index e53a7f6..3e95c9a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,6 +9,7 @@ pub enum AST { BinOp(Box, Box, Box), Number(f64), Name(String), + Block(Vec), } impl fmt::Display for AST { @@ -30,6 +31,10 @@ pub type ParseResult = Result; /* grammar + program : block EOF + block : (statement sep)+ + sep : NEWLINE | SEMICOLON + statement: expr expr : term ((PLUS|MIMUS) term)* term : factor ((MUL | DIV) factor)* factor : NUM | LPAREN expr RPAREN @@ -98,12 +103,36 @@ impl Parser { } fn parse(&mut self) -> ParseResult { - let r = self.expr(); - try!(self.expect(Token::Newline)); + let r = self.block(); try!(self.expect(Token::EOF)); r } + fn block(&mut self) -> ParseResult { + use tokenizer::Token::*; + let mut block_nodes: Vec = Vec::new(); + loop { + let s: AST = try!(self.statement()); + block_nodes.push(s); + match self.lookahead() { + Some(Semicolon) | Some(Newline) => { + self.next(); + if let Some(EOF) = self.lookahead() { + break + } + }, + _ => break + } + } + + Ok(AST::Block(block_nodes)) + } + + fn statement(&mut self) -> ParseResult { + let r = try!(self.expr()); + Ok(r) + } + fn expr(&mut self) -> ParseResult { use tokenizer::Token::*; let mut lhs = try!(self.term()); @@ -157,7 +186,7 @@ impl Parser { self.next(); Ok(AST::Number(n)) }, - _ => parse_error!("Expected LParen or NumLiteral") + x => parse_error!("Expected LParen or NumLiteral, got {:?}", x ) } } }