let statement parsing
This commit is contained in:
+13
-13
@@ -1,17 +1,17 @@
|
|||||||
use crate::token;
|
use crate::token;
|
||||||
|
|
||||||
trait NodeTrait {
|
pub trait NodeTrait {
|
||||||
fn token_literal(&self) -> String;
|
fn token_literal(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait StatementTrait: NodeTrait {
|
pub trait StatementTrait: NodeTrait {
|
||||||
fn statement_node(&self);
|
fn statement_node(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ExpressionTrait: NodeTrait {
|
trait ExpressionTrait: NodeTrait {
|
||||||
fn expression_node(&self);
|
fn expression_node(&self);
|
||||||
}
|
}
|
||||||
struct Expression {
|
pub struct Expression {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
impl NodeTrait for Expression {
|
impl NodeTrait for Expression {
|
||||||
@@ -20,7 +20,7 @@ impl NodeTrait for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Statement {
|
pub struct Statement {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
impl NodeTrait for Statement {
|
impl NodeTrait for Statement {
|
||||||
@@ -34,12 +34,12 @@ impl StatementTrait for Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
statements: Vec<Statement>,
|
pub statements: Vec<Box<dyn StatementTrait>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeTrait for Program {
|
impl NodeTrait for Program {
|
||||||
fn token_literal(&self) -> String {
|
fn token_literal(&self) -> String {
|
||||||
if self.statements.is_empty() {
|
if !self.statements.is_empty() {
|
||||||
self.statements[0].token_literal()
|
self.statements[0].token_literal()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
@@ -47,10 +47,10 @@ impl NodeTrait for Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LetStatement {
|
pub struct LetStatement {
|
||||||
token: token::Token,
|
pub token: token::Token,
|
||||||
name: Identifier,
|
pub name: Identifier,
|
||||||
value: Expression,
|
pub value: Expression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeTrait for LetStatement {
|
impl NodeTrait for LetStatement {
|
||||||
@@ -65,9 +65,9 @@ impl StatementTrait for LetStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Identifier {
|
pub struct Identifier {
|
||||||
token: token::Token,
|
pub token: token::Token,
|
||||||
value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeTrait for Identifier {
|
impl NodeTrait for Identifier {
|
||||||
|
|||||||
+102
-8
@@ -1,21 +1,30 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast,
|
ast::{self},
|
||||||
lexer::{self, LexerTraits},
|
lexer::{self, LexerTraits},
|
||||||
token,
|
token::{self, EOF},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
lexer: lexer::Lexer,
|
lexer: lexer::Lexer,
|
||||||
cur_token: token::Token,
|
cur_token: token::Token,
|
||||||
peek_token: token::Token,
|
peek_token: token::Token,
|
||||||
|
errors: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait PaserTrait {
|
pub trait ParserTrait {
|
||||||
fn next_token(&mut self);
|
fn next_token(&mut self);
|
||||||
fn parse_program(&self) -> ast::Program;
|
fn parse_program(&mut self) -> ast::Program;
|
||||||
|
fn parse_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>>;
|
||||||
|
fn parse_let_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>>;
|
||||||
|
|
||||||
|
fn cur_token_is(&self, t: String) -> bool;
|
||||||
|
fn peek_token_is(&self, t: String) -> bool;
|
||||||
|
fn expect_peek(&mut self, t: String) -> bool;
|
||||||
|
fn errors(&self) -> &Vec<String>;
|
||||||
|
fn peek_error(&mut self, t: String);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(l: lexer::Lexer) -> Parser {
|
pub fn new_parser(l: lexer::Lexer) -> Parser {
|
||||||
let mut p: Parser = Parser {
|
let mut p: Parser = Parser {
|
||||||
lexer: l,
|
lexer: l,
|
||||||
cur_token: token::Token {
|
cur_token: token::Token {
|
||||||
@@ -26,13 +35,14 @@ pub fn new(l: lexer::Lexer) -> Parser {
|
|||||||
literal: String::new(),
|
literal: String::new(),
|
||||||
type_: String::new(),
|
type_: String::new(),
|
||||||
},
|
},
|
||||||
|
errors: Vec::new(),
|
||||||
};
|
};
|
||||||
p.next_token();
|
p.next_token();
|
||||||
p.next_token();
|
p.next_token();
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaserTrait for Parser {
|
impl ParserTrait for Parser {
|
||||||
fn next_token(&mut self) {
|
fn next_token(&mut self) {
|
||||||
self.cur_token = token::Token {
|
self.cur_token = token::Token {
|
||||||
literal: String::from(&self.peek_token.literal),
|
literal: String::from(&self.peek_token.literal),
|
||||||
@@ -41,7 +51,91 @@ impl PaserTrait for Parser {
|
|||||||
self.peek_token = self.lexer.next_token();
|
self.peek_token = self.lexer.next_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_program(&self) -> ast::Program {
|
fn parse_program(&mut self) -> ast::Program {
|
||||||
todo!()
|
let mut program = ast::Program {
|
||||||
|
statements: Vec::new(),
|
||||||
|
};
|
||||||
|
while &self.cur_token.type_ != EOF {
|
||||||
|
if let Some(stmt) = self.parse_statement() {
|
||||||
|
program.statements.push(stmt);
|
||||||
|
}
|
||||||
|
self.next_token();
|
||||||
|
}
|
||||||
|
program
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>> {
|
||||||
|
match self.cur_token.type_.as_str() {
|
||||||
|
token::LET => self.parse_let_statement(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cur_token_is(&self, t: String) -> bool {
|
||||||
|
self.cur_token.type_ == t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek_token_is(&self, t: String) -> bool {
|
||||||
|
self.peek_token.type_ == t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect_peek(&mut self, t: String) -> bool {
|
||||||
|
if self.peek_token_is(t) {
|
||||||
|
self.next_token();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_let_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>> {
|
||||||
|
let mut stmt = ast::LetStatement {
|
||||||
|
token: token::Token {
|
||||||
|
literal: String::from(&self.cur_token.literal),
|
||||||
|
type_: String::from(&self.cur_token.type_),
|
||||||
|
},
|
||||||
|
name: ast::Identifier {
|
||||||
|
token: token::Token {
|
||||||
|
literal: String::new(),
|
||||||
|
type_: String::new(),
|
||||||
|
},
|
||||||
|
value: String::new(),
|
||||||
|
},
|
||||||
|
value: ast::Expression {},
|
||||||
|
};
|
||||||
|
|
||||||
|
if !self.expect_peek(token::IDENT.to_string()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt.name = ast::Identifier {
|
||||||
|
token: token::Token {
|
||||||
|
literal: String::from(&self.cur_token.literal),
|
||||||
|
type_: String::from(&self.cur_token.type_),
|
||||||
|
},
|
||||||
|
value: String::from(&self.cur_token.literal),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !self.expect_peek(token::ASSIGN.to_string()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
while !self.cur_token_is(token::SEMICOLON.to_string()) {
|
||||||
|
self.next_token();
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Box::from(stmt))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn errors(&self) -> &Vec<String> {
|
||||||
|
&self.errors
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek_error(&mut self, t: String) {
|
||||||
|
let msg = format!(
|
||||||
|
"expected next token to be {}, got {} instead",
|
||||||
|
t, self.peek_token.type_
|
||||||
|
);
|
||||||
|
self.errors.push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -1,5 +1,7 @@
|
|||||||
use crate::lexer::LexerTraits;
|
|
||||||
use crate::lexer::new;
|
use crate::lexer::new;
|
||||||
|
use crate::parser::Parser;
|
||||||
|
use crate::parser::ParserTrait;
|
||||||
|
use crate::parser::new_parser;
|
||||||
|
|
||||||
const PROMPT: &str = ">> ";
|
const PROMPT: &str = ">> ";
|
||||||
|
|
||||||
@@ -15,13 +17,11 @@ pub fn start_repl() {
|
|||||||
if input == "exit" {
|
if input == "exit" {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut lexer = new(input.to_string());
|
let lexer = new(input.to_string());
|
||||||
loop {
|
let mut parser: Parser = new_parser(lexer);
|
||||||
let token = lexer.next_token();
|
let program = parser.parse_program();
|
||||||
if token.type_ == "EOF" {
|
for stmt in program.statements {
|
||||||
break;
|
println!("{:?}", stmt.token_literal());
|
||||||
}
|
|
||||||
println!("Token: {:?}, Literal: {:?}", token.type_, token.literal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user