Skip to content

Commit

Permalink
feat(expr): cast expression
Browse files Browse the repository at this point in the history
  • Loading branch information
MilkeeyCat committed Jun 3, 2024
1 parent 339ad9e commit 0fdc786
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 17 deletions.
18 changes: 18 additions & 0 deletions src/parser/expr/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl TryFrom<&Token> for BinOp {
pub enum Expr {
Binary(ExprBinary),
Unary(ExprUnary),
Cast(ExprCast),
Lit(ExprLit),
Ident(String),
}
Expand All @@ -89,6 +90,7 @@ impl Expr {
{
Symbol::GlobalVar(global_var) => Ok(global_var.type_.clone()),
},
Self::Cast(cast) => Ok(cast.type_()),
}
}
}
Expand Down Expand Up @@ -156,3 +158,19 @@ impl ExprUnary {
Ok(expr_type)
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct ExprCast {
expr: Box<Expr>,
type_: Type,
}

impl ExprCast {
pub fn new(type_: Type, expr: Box<Expr>) -> Self {
Self { type_, expr }
}

pub fn type_(&self) -> Type {
self.type_.to_owned()
}
}
2 changes: 1 addition & 1 deletion src/parser/expr/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod expr;
mod int_repr;

pub use expr::{BinOp, Expr, ExprBinary, ExprLit, ExprUnary, OpParseError, UnOp};
pub use expr::{BinOp, Expr, ExprBinary, ExprCast, ExprLit, ExprUnary, OpParseError, UnOp};
pub use int_repr::{IntLitRepr, IntLitReprError};
62 changes: 46 additions & 16 deletions src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{
expr::{BinOp, ExprBinary, ExprLit, ExprUnary, IntLitRepr, UnOp},
precedence::Precedence,
type_::{Type, TypeError},
Expr, IntLitReprError, OpParseError, Stmt, StmtVarDecl,
Expr, ExprCast, IntLitReprError, OpParseError, Stmt, StmtVarDecl,
};
use crate::{
lexer::{Lexer, Token},
Expand All @@ -13,7 +13,7 @@ use crate::{

#[derive(Debug)]
pub enum ParserError {
UnexpectedPeek(Token, Token),
UnexpectedToken(Token, Token),
ParseType(Token),
Prefix(Token),
Infix(Token),
Expand All @@ -26,7 +26,7 @@ pub enum ParserError {
impl Display for ParserError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedPeek(expected, actual) => {
Self::UnexpectedToken(expected, actual) => {
write!(f, "Expected token {}, got {}", expected, actual)
}
Self::ParseType(token) => write!(f, "Failed to parse type, found {}", token),
Expand Down Expand Up @@ -80,13 +80,26 @@ impl Parser {
if self.peek_token_is(token.clone()) {
self.next_token();

return Ok(());
Ok(())
} else {
Err(ParserError::UnexpectedToken(
token,
self.peek_token.to_owned(),
))
}
}

fn expect(&mut self, token: Token) -> Result<(), ParserError> {
if self.cur_token_is(token.clone()) {
self.next_token();

Err(ParserError::UnexpectedPeek(
token,
self.peek_token.to_owned(),
))
Ok(())
} else {
Err(ParserError::UnexpectedToken(
token,
self.peek_token.to_owned(),
))
}
}

pub fn into_parts(mut self) -> (Result<Vec<Stmt>, ParserError>, SymbolTable) {
Expand All @@ -109,7 +122,7 @@ impl Parser {
Token::Ident(_) => self.ident(),
Token::Integer(_) => self.int_lit(),
Token::Minus | Token::Bang => self.unary_expr(),
Token::LParen => self.grouped_bin_expr(),
Token::LParen => self.grouped_expr(),
token => Err(ParserError::Prefix(token.to_owned())),
};

Expand Down Expand Up @@ -229,11 +242,24 @@ impl Parser {
Ok(expr)
}

fn grouped_bin_expr(&mut self) -> Result<Expr, ParserError> {
self.next_token();
fn grouped_expr(&mut self) -> Result<Expr, ParserError> {
self.expect(Token::LParen)?;

let expr = self.expr(Token::LParen.precedence());
self.expect_peek(Token::RParen)?;
let expr = match &self.cur_token {
Token::U8 | Token::I8 => {
let type_ = self.parse_type()?;
self.expect(Token::RParen)?;
let expr = self.expr(self.cur_token.precedence())?;

Ok(Expr::Cast(ExprCast::new(type_, Box::new(expr))))
}
_ => {
let expr = self.expr(Token::LParen.precedence());
self.expect_peek(Token::RParen)?;

expr
}
};

expr
}
Expand All @@ -245,13 +271,14 @@ mod test {
use crate::{
lexer::Lexer,
parser::{
precedence::Precedence, BinOp, Expr, ExprBinary, ExprLit, IntLitRepr, IntLitReprError,
precedence::Precedence, BinOp, Expr, ExprBinary, ExprCast, ExprLit, IntLitRepr,
IntLitReprError, Type,
},
};

#[test]
fn parse_arithmetic_expression() -> Result<(), IntLitReprError> {
let input = "1 * 2 + 3 / (4 + 1);";
let input = "1 * 2 + 3 / (4 + (u8)1);";
let mut parser = Parser::new(Lexer::new(input.to_string()));

assert_eq!(
Expand All @@ -269,7 +296,10 @@ mod test {
Box::new(Expr::Binary(ExprBinary::new(
BinOp::Add,
Box::new(Expr::Lit(ExprLit::Int(IntLitRepr::try_from("4")?))),
Box::new(Expr::Lit(ExprLit::Int(IntLitRepr::try_from("1")?))),
Box::new(Expr::Cast(ExprCast::new(
Type::U8,
Box::new(Expr::Lit(ExprLit::Int(IntLitRepr::try_from("1")?))),
))),
)))
)))
))
Expand Down

0 comments on commit 0fdc786

Please sign in to comment.