Add block parsing
Right now evaluating a block reduces it to just the last AST in it, will fix later with environments
This commit is contained in:
parent
dd2b4893a4
commit
fc11ee753d
@ -42,6 +42,12 @@ fn reduce_full(ast: AST) -> EvaluatorResult<AST> {
|
|||||||
fn reduce_step(ast: AST) -> EvaluatorResult<AST> {
|
fn reduce_step(ast: AST) -> EvaluatorResult<AST> {
|
||||||
use parser::AST::*;
|
use parser::AST::*;
|
||||||
match 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) => {
|
BinOp(left, op, right) => {
|
||||||
let left = try!(reduce_full(*left));
|
let left = try!(reduce_full(*left));
|
||||||
let op = try!(reduce_full(*op));
|
let op = try!(reduce_full(*op));
|
||||||
|
@ -9,6 +9,7 @@ pub enum AST {
|
|||||||
BinOp(Box<AST>, Box<AST>, Box<AST>),
|
BinOp(Box<AST>, Box<AST>, Box<AST>),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Name(String),
|
Name(String),
|
||||||
|
Block(Vec<AST>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for AST {
|
impl fmt::Display for AST {
|
||||||
@ -30,6 +31,10 @@ pub type ParseResult<T> = Result<T, ParseError>;
|
|||||||
|
|
||||||
/* grammar
|
/* grammar
|
||||||
|
|
||||||
|
program : block EOF
|
||||||
|
block : (statement sep)+
|
||||||
|
sep : NEWLINE | SEMICOLON
|
||||||
|
statement: expr
|
||||||
expr : term ((PLUS|MIMUS) term)*
|
expr : term ((PLUS|MIMUS) term)*
|
||||||
term : factor ((MUL | DIV) factor)*
|
term : factor ((MUL | DIV) factor)*
|
||||||
factor : NUM | LPAREN expr RPAREN
|
factor : NUM | LPAREN expr RPAREN
|
||||||
@ -98,12 +103,36 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse(&mut self) -> ParseResult<AST> {
|
fn parse(&mut self) -> ParseResult<AST> {
|
||||||
let r = self.expr();
|
let r = self.block();
|
||||||
try!(self.expect(Token::Newline));
|
|
||||||
try!(self.expect(Token::EOF));
|
try!(self.expect(Token::EOF));
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn block(&mut self) -> ParseResult<AST> {
|
||||||
|
use tokenizer::Token::*;
|
||||||
|
let mut block_nodes: Vec<AST> = 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<AST> {
|
||||||
|
let r = try!(self.expr());
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
fn expr(&mut self) -> ParseResult<AST> {
|
fn expr(&mut self) -> ParseResult<AST> {
|
||||||
use tokenizer::Token::*;
|
use tokenizer::Token::*;
|
||||||
let mut lhs = try!(self.term());
|
let mut lhs = try!(self.term());
|
||||||
@ -157,7 +186,7 @@ impl Parser {
|
|||||||
self.next();
|
self.next();
|
||||||
Ok(AST::Number(n))
|
Ok(AST::Number(n))
|
||||||
},
|
},
|
||||||
_ => parse_error!("Expected LParen or NumLiteral")
|
x => parse_error!("Expected LParen or NumLiteral, got {:?}", x )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user