Added let statement parser

This commit is contained in:
Ishan Jain 2019-09-07 19:32:44 +05:30
parent 142b34edc4
commit 20a4907153
3 changed files with 118 additions and 39 deletions

View File

@ -1,5 +1,6 @@
use super::ParserError;
use crate::lexer::Lexer;
use super::ParseError;
use crate::lexer::Token;
use crate::parser::Parser;
use std::error::Error;
pub trait Node {
@ -7,8 +8,8 @@ pub trait Node {
fn validate(&self) -> Result<(), Box<dyn Error>>;
}
pub trait Statement: Node {
fn parse(&mut Lexer) -> Self
pub(crate) trait Statement: Node {
fn parse(&mut Parser) -> Result<Self, Box<dyn Error>>
where
Self: Sized;
}
@ -21,11 +22,16 @@ pub struct LetStatement {
// value: dyn Expression,
}
impl LetStatement {
pub fn new(identifier: Identifier) -> LetStatement {
LetStatement { name: identifier }
}
}
impl Node for LetStatement {
fn validate(&self) -> Result<(), Box<dyn Error>> {
if self.token_literal() != "let" {
return Err(Box::new(ParserError::new(
"self.token_literal is not set, got=".to_owned() + self.token_literal(),
return Err(Box::new(ParseError::new(
&("self.token_literal is not set, got=".to_owned() + self.token_literal()),
)));
}
Ok(())
@ -37,19 +43,52 @@ impl Node for LetStatement {
}
impl Statement for LetStatement {
fn parse(lexer: &mut Lexer) -> LetStatement {
LetStatement {
name: Identifier { name: "potato" },
// value: "",
fn parse(parser: &mut Parser) -> Result<LetStatement, Box<dyn Error>> {
let name;
//TODO: Add expression parser
match parser.lexer.next() {
Some(v) => match v {
Token::Ident(q) => name = Identifier { name: q },
n @ _ => {
return Err(Box::new(ParseError::new(&format!(
"expected IDENT, Found {:?}",
n
))))
}
},
None => {
return Err(Box::new(ParseError::new(
"expected IDENT after let, Could not find it",
)))
}
};
if !parser.expect_peek(Token::Assign) {
return Err(Box::new(ParseError::new("expected =, Could not find it")));
}
while !parser.current_token_is(Token::Semicolon) {
println!("prev_token={:?}", parser.current_token);
parser.current_token = parser.lexer.next();
println!("current_token={:?}", parser.current_token);
}
Ok(LetStatement { name })
}
}
#[derive(Debug)]
pub struct Identifier {
name: &'static str,
name: String,
}
impl Identifier {
pub fn new(name: &str) -> Identifier {
Identifier {
name: name.to_owned(),
}
}
}
impl Node for Identifier {
fn validate(&self) -> Result<(), Box<dyn Error>> {
Ok(())

View File

@ -5,37 +5,76 @@ pub use self::program::Program;
use self::ast::{LetStatement, Statement};
use crate::lexer::{Lexer, Token};
use std::iter::Peekable;
struct Parser {}
pub(crate) struct Parser<'a> {
lexer: Peekable<Lexer<'a>>,
current_token: Option<Token>,
}
impl Parser {
fn parse_statement(token: Token, lexer: &mut Lexer) -> Option<Box<dyn ast::Statement>> {
match token {
Token::Let => Some(Box::new(LetStatement::parse(lexer))),
_ => unimplemented!(),
impl<'a> Parser<'a> {
fn new(lexer: Lexer<'a>) -> Parser {
Parser {
lexer: lexer.peekable(),
current_token: None,
}
}
fn parse_statement(&mut self, token: Token) -> Option<Box<dyn ast::Statement>> {
match token {
Token::Let => {
let stmt = match LetStatement::parse(self) {
Ok(v) => v,
Err(_) => return None, //TODO: Return appropriate error
};
Some(Box::new(stmt))
}
n @ _ => {
println!("{:?}", n);
None
}
}
}
fn expect_peek(&mut self, token: Token) -> bool {
if let Some(v) = self.lexer.peek() {
if v == &token {
self.lexer.next();
true
} else {
false
}
} else {
false
}
}
fn current_token_is(&self, token: Token) -> bool {
self.current_token == Some(token)
}
}
#[derive(Debug)]
struct ParserError {
struct ParseError {
desc: String,
}
impl std::fmt::Display for ParserError {
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "ParserError: ")
write!(f, "ParseError: {}", self)
}
}
impl std::error::Error for ParserError {
impl std::error::Error for ParseError {
fn description(&self) -> &str {
&self.desc
}
}
impl ParserError {
fn new(desc: String) -> ParserError {
ParserError { desc }
impl ParseError {
fn new(desc: &str) -> ParseError {
ParseError {
desc: desc.to_owned(),
}
}
}

View File

@ -1,5 +1,5 @@
use crate::lexer::{Lexer, Token};
use crate::parser::ast::{LetStatement, Statement};
use crate::parser::ast::Statement;
use crate::parser::Parser;
pub struct Program {
@ -7,24 +7,16 @@ pub struct Program {
}
impl Program {
pub fn token_literal(&self) -> &'static str {
if self.statements.len() > 0 {
self.statements[0].token_literal()
} else {
""
}
}
pub fn parse(mut lexer: Lexer) -> Program {
pub fn parse(lexer: Lexer) -> Program {
let mut statements = vec![];
let mut parser = Parser::new(lexer);
loop {
if let Some(token) = lexer.next() {
if let Some(token) = parser.lexer.next() {
if token == Token::EOF {
break;
}
if let Some(stmt) = Parser::parse_statement(token, &mut lexer) {
if let Some(stmt) = parser.parse_statement(token) {
statements.push(stmt);
} else {
continue;
@ -41,8 +33,8 @@ impl Program {
#[cfg(test)]
mod tests {
use crate::lexer::Lexer;
use crate::parser::ast::{Identifier, LetStatement};
use crate::parser::Program;
#[test]
fn let_statements() {
let ip = "
@ -50,12 +42,21 @@ mod tests {
let qq = 10;
let foobar = 8388383;
";
let out = Program {
statements: vec![
Box::new(LetStatement::new(Identifier::new("yr"))),
Box::new(LetStatement::new(Identifier::new("qq"))),
Box::new(LetStatement::new(Identifier::new("foobar"))),
],
};
let lexer = Lexer::new(ip);
let ast_tree = Program::parse(lexer);
if ast_tree.statements.len() != 3 {
assert_eq!(ast_tree.statements.len(), 3);
}
for (out, expected_out) in ast_tree.statements.iter().zip(out.statements.iter()) {
// assert!(out, expected_out);
}
}
}