better binop handling

This commit is contained in:
nora 2021-10-31 01:24:20 +02:00
parent 7f12eaee01
commit f6fcca589e

View file

@ -84,65 +84,74 @@ impl<'code> Parser<'code> {
} }
fn comparison(&mut self) -> ParseResult<'code, Expr> { fn comparison(&mut self) -> ParseResult<'code, Expr> {
todo!() let lhs = self.term()?;
match self.peek().map(|token| &token.kind) {
Some(TokenType::GreaterThan) => {
let _ = self.next();
let rhs = self.term()?;
self.binary_op(lhs, BinaryOpKind::Greater, rhs)
}
Some(TokenType::GreaterThanEqual) => {
let _ = self.next();
let rhs = self.term()?;
self.binary_op(lhs, BinaryOpKind::GreaterEqual, rhs)
}
Some(TokenType::LessThan) => {
let _ = self.next();
let rhs = self.term()?;
self.binary_op(lhs, BinaryOpKind::Less, rhs)
}
Some(TokenType::LessThanEqual) => {
let _ = self.next();
let rhs = self.term()?;
self.binary_op(lhs, BinaryOpKind::LessEqual, rhs)
}
_ => Ok(lhs),
}
} }
fn term(&mut self) -> ParseResult<'code, Expr> { fn term(&mut self) -> ParseResult<'code, Expr> {
todo!() let lhs = self.factor()?;
match self.peek().map(|token| &token.kind) {
Some(TokenType::Plus) => {
let _ = self.next();
let rhs = self.factor()?;
self.binary_op(lhs, BinaryOpKind::Add, rhs)
}
Some(TokenType::Minus) => {
let _ = self.next();
let rhs = self.factor()?;
self.binary_op(lhs, BinaryOpKind::Sub, rhs)
}
_ => Ok(lhs),
}
} }
fn factor(&mut self) -> ParseResult<'code, Expr> { fn factor(&mut self) -> ParseResult<'code, Expr> {
let lhs = self.unary()?; let lhs = self.unary()?;
match self.peek() { match self.peek().map(|token| &token.kind) {
Some(Token { Some(TokenType::Asterisk) => {
kind: TokenType::Asterisk,
..
}) => {
let _ = self.next(); let _ = self.next();
let rhs = self.unary()?; let rhs = self.unary()?;
Ok(Expr::BinaryOp(Box::new(BinaryOp { self.binary_op(lhs, BinaryOpKind::Mul, rhs)
span: lhs.span().extend(rhs.span()),
lhs,
rhs,
kind: BinaryOpKind::Mul,
})))
} }
Some(Token { Some(TokenType::Slash) => {
kind: TokenType::Slash,
..
}) => {
let _ = self.next(); let _ = self.next();
let rhs = self.unary()?; let rhs = self.unary()?;
Ok(Expr::BinaryOp(Box::new(BinaryOp { self.binary_op(lhs, BinaryOpKind::Div, rhs)
span: lhs.span().extend(rhs.span()),
lhs,
rhs,
kind: BinaryOpKind::Div,
})))
} }
Some(Token { Some(TokenType::Percent) => {
kind: TokenType::Percent,
..
}) => {
let _ = self.next(); let _ = self.next();
let rhs = self.unary()?; let rhs = self.unary()?;
Ok(Expr::BinaryOp(Box::new(BinaryOp { self.binary_op(lhs, BinaryOpKind::Mod, rhs)
span: lhs.span().extend(rhs.span()),
lhs,
rhs,
kind: BinaryOpKind::Mod,
})))
} }
_ => Ok(lhs), _ => Ok(lhs),
} }
} }
fn unary(&mut self) -> ParseResult<'code, Expr> { fn unary(&mut self) -> ParseResult<'code, Expr> {
match self.peek() { match self.peek().map(|token| &token.kind) {
Some(Token { Some(TokenType::Not) => {
kind: TokenType::Not,
..
}) => {
let unary_op_span = self.next().unwrap().span; let unary_op_span = self.next().unwrap().span;
let expr = self.expression()?; let expr = self.expression()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp { Ok(Expr::UnaryOp(Box::new(UnaryOp {
@ -151,10 +160,7 @@ impl<'code> Parser<'code> {
kind: UnaryOpKind::Not, kind: UnaryOpKind::Not,
}))) })))
} }
Some(Token { Some(TokenType::Minus) => {
kind: TokenType::Minus,
..
}) => {
let unary_op_span = self.next().unwrap().span; let unary_op_span = self.next().unwrap().span;
let expr = self.expression()?; let expr = self.expression()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp { Ok(Expr::UnaryOp(Box::new(UnaryOp {
@ -163,7 +169,8 @@ impl<'code> Parser<'code> {
kind: UnaryOpKind::Neg, kind: UnaryOpKind::Neg,
}))) })))
} }
_ => self.primary(), Some(_) => self.primary(),
None => todo!(),
} }
} }
@ -207,7 +214,18 @@ impl<'code> Parser<'code> {
todo!() todo!()
} }
// helpers // other helpers
fn binary_op(&mut self, lhs: Expr, kind: BinaryOpKind, rhs: Expr) -> ParseResult<'code, Expr> {
Ok(Expr::BinaryOp(Box::new(BinaryOp {
span: lhs.span().extend(rhs.span()),
lhs,
rhs,
kind,
})))
}
// token helpers
#[must_use] #[must_use]
fn next(&mut self) -> Option<Token<'code>> { fn next(&mut self) -> Option<Token<'code>> {
@ -235,6 +253,7 @@ impl<'code> Parser<'code> {
#[derive(Debug)] #[derive(Debug)]
pub enum ParseErr<'code> { pub enum ParseErr<'code> {
MismatchedKind { expected: TokenType<'code> }, MismatchedKind { expected: TokenType<'code> },
InvalidToken(TokenType<'code>),
EOF, EOF,
} }