Implement some statements
- Impl. expression only statement (expr;)
- Impl. let binding ("let" ident "=" expr;)
- Impl. assignment (ident "=" expr;)
This commit is contained in:
parent
5be3fd5bbc
commit
41b7247ffd
@ -4,7 +4,7 @@ use plang2_lib::*;
|
|||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let code = r#"
|
let code = r#"
|
||||||
(-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30
|
a = 54 * sqrt(9);
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut lexer = Lexer::new(code);
|
let mut lexer = Lexer::new(code);
|
||||||
|
|||||||
@ -32,3 +32,10 @@ pub enum Expr {
|
|||||||
BinOp(BinOpType, Box<Expr>, Box<Expr>),
|
BinOp(BinOpType, Box<Expr>, Box<Expr>),
|
||||||
UnOp(UnOpType, Box<Expr>),
|
UnOp(UnOpType, Box<Expr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Statement {
|
||||||
|
Expr(Expr),
|
||||||
|
LetBinding(String, Expr),
|
||||||
|
Assignment(String, Expr),
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::{BinOpType, Expr, FnCall, UnOpType},
|
ast::{BinOpType, Expr, FnCall, Statement, UnOpType},
|
||||||
token::{Group, Op, Token, TokenStream},
|
token::{Group, Keyword, Op, Token, TokenStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -13,15 +13,22 @@ pub struct Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GRAMMAR
|
# GRAMMAR
|
||||||
|
## expressions
|
||||||
|
|
||||||
expr_literal = Literal
|
ident = IDENT
|
||||||
expr_fn_call = FnCall
|
expr_literal = LITERAL
|
||||||
expr_varibale = Variable
|
expr_fn_call = ident "(" expr_add? ( "," expr_add )* ")"
|
||||||
|
expr_varibale = ident
|
||||||
expr_value = expr_literal | expr_fn_call | expr_variable
|
expr_value = expr_literal | expr_fn_call | expr_variable
|
||||||
expr_term = "-" expr_term | "(" expr_add ")" | expr_literal
|
expr_term = "-" expr_term | "(" expr_add ")" | expr_literal
|
||||||
expr_mul = expr_term (("*"|"/") expr_term)*
|
expr_mul = expr_term (("*"|"/") expr_term)*
|
||||||
expr_add = expr_mul (("+"|"-") expr_mul)*
|
expr_add = expr_mul (("+"|"-") expr_mul)*
|
||||||
|
|
||||||
|
## statements
|
||||||
|
stmt_let = "let" ident "=" expr_add
|
||||||
|
stmt_assign = ident "=" expr_add
|
||||||
|
stmt = ( stmt_let | stmt_assign | expr_add ) ";"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
@ -41,8 +48,62 @@ impl Parser {
|
|||||||
self.tokens.advance()
|
self.tokens.advance()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> PRes<Expr> {
|
pub fn parse(&mut self) -> PRes<Statement> {
|
||||||
self.parse_expr_add()
|
self.parse_statement()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_statement(&mut self) -> PRes<Statement> {
|
||||||
|
let stmt = match self.curr() {
|
||||||
|
Some(Token::Keyword(Keyword::Let)) => self.parse_stmt_let(),
|
||||||
|
Some(Token::Ident(_)) if matches!(self.peek(), Some(Token::Op(Op::Assign))) => {
|
||||||
|
self.parse_stmt_assign()
|
||||||
|
}
|
||||||
|
_ => self.parse_expr_add().map(|expr| Statement::Expr(expr)),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !matches!(self.advance(), Some(Token::Semicolon)) {
|
||||||
|
panic!("Expected ';' while parsing statement");
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_stmt_let(&mut self) -> PRes<Statement> {
|
||||||
|
if !matches!(self.advance(), Some(Token::Keyword(Keyword::Let))) {
|
||||||
|
panic!("Unexpected token while parsing let statement. Expected 'let'");
|
||||||
|
}
|
||||||
|
|
||||||
|
let var_name = match self.advance() {
|
||||||
|
Some(Token::Ident(ident)) => ident.clone(),
|
||||||
|
_ => panic!("Unexpected token while parsing let statement. Expected ident"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !matches!(self.advance(), Some(Token::Op(Op::Assign))) {
|
||||||
|
panic!("Unexpected token while parsing let statement. Expected '='");
|
||||||
|
}
|
||||||
|
|
||||||
|
let rhs = self.parse_expr_add()?;
|
||||||
|
|
||||||
|
let let_binding = Statement::LetBinding(var_name, rhs);
|
||||||
|
|
||||||
|
Ok(let_binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_stmt_assign(&mut self) -> PRes<Statement> {
|
||||||
|
let var_name = match self.advance() {
|
||||||
|
Some(Token::Ident(ident)) => ident.clone(),
|
||||||
|
_ => panic!("Unexpected token while parsing assignment statement. Expected ident"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !matches!(self.advance(), Some(Token::Op(Op::Assign))) {
|
||||||
|
panic!("Unexpected token while parsing let assignment. Expected '='");
|
||||||
|
}
|
||||||
|
|
||||||
|
let rhs = self.parse_expr_add()?;
|
||||||
|
|
||||||
|
let let_binding = Statement::Assignment(var_name, rhs);
|
||||||
|
|
||||||
|
Ok(let_binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_expr_add(&mut self) -> PRes<Expr> {
|
pub fn parse_expr_add(&mut self) -> PRes<Expr> {
|
||||||
@ -94,7 +155,7 @@ impl Parser {
|
|||||||
self.advance();
|
self.advance();
|
||||||
let a = self.parse_expr_add()?;
|
let a = self.parse_expr_add()?;
|
||||||
if !matches!(self.advance(), Some(Token::Close(Group::Paren))) {
|
if !matches!(self.advance(), Some(Token::Close(Group::Paren))) {
|
||||||
panic!("Missing closing parentheses");
|
panic!("Missing closing parentheses while parsing term");
|
||||||
}
|
}
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
@ -114,7 +175,7 @@ impl Parser {
|
|||||||
self.parse_expr_fn_call()
|
self.parse_expr_fn_call()
|
||||||
}
|
}
|
||||||
Some(Token::Ident(_)) => self.parse_expr_varibale(),
|
Some(Token::Ident(_)) => self.parse_expr_varibale(),
|
||||||
_ => panic!("Expected value (literal, variable or function call)"),
|
_ => panic!("Expected value (literal, variable or function call) while parsing value"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,34 +242,34 @@ mod tests {
|
|||||||
|
|
||||||
// (-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30
|
// (-(-5+2)*-(2*-sqrt(9))+-(a-6)) % 30
|
||||||
let input_toks = vec![
|
let input_toks = vec![
|
||||||
Token::Open(Group::Paren), // (
|
Token::Open(Group::Paren), // (
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Open(Group::Paren), // (
|
Token::Open(Group::Paren), // (
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Literal(Literal::Int64(5)), // 5
|
Token::Literal(Literal::Int64(5)), // 5
|
||||||
Token::Op(Op::Add), // +
|
Token::Op(Op::Add), // +
|
||||||
Token::Literal(Literal::Int64(2)), // 2
|
Token::Literal(Literal::Int64(2)), // 2
|
||||||
Token::Close(Group::Paren), // )
|
Token::Close(Group::Paren), // )
|
||||||
Token::Op(Op::Mul), // *
|
Token::Op(Op::Mul), // *
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Open(Group::Paren), // (
|
Token::Open(Group::Paren), // (
|
||||||
Token::Literal(Literal::Int64(2)), // 2
|
Token::Literal(Literal::Int64(2)), // 2
|
||||||
Token::Op(Op::Mul), // *
|
Token::Op(Op::Mul), // *
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Ident(fn_name.clone()), // sqrt
|
Token::Ident(fn_name.clone()), // sqrt
|
||||||
Token::Open(Group::Paren), // (
|
Token::Open(Group::Paren), // (
|
||||||
Token::Literal(Literal::Int64(9)), // 9
|
Token::Literal(Literal::Int64(9)), // 9
|
||||||
Token::Close(Group::Paren), // )
|
Token::Close(Group::Paren), // )
|
||||||
Token::Close(Group::Paren), // )
|
Token::Close(Group::Paren), // )
|
||||||
Token::Op(Op::Add), // +
|
Token::Op(Op::Add), // +
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Open(Group::Paren), // (
|
Token::Open(Group::Paren), // (
|
||||||
Token::Ident(var_name.clone()), // a
|
Token::Ident(var_name.clone()), // a
|
||||||
Token::Op(Op::Sub), // -
|
Token::Op(Op::Sub), // -
|
||||||
Token::Literal(Literal::Int64(6)), // 6
|
Token::Literal(Literal::Int64(6)), // 6
|
||||||
Token::Close(Group::Paren), // )
|
Token::Close(Group::Paren), // )
|
||||||
Token::Close(Group::Paren), // )
|
Token::Close(Group::Paren), // )
|
||||||
Token::Op(Op::Mod), // %
|
Token::Op(Op::Mod), // %
|
||||||
Token::Literal(Literal::Int64(30)), // 30
|
Token::Literal(Literal::Int64(30)), // 30
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user