Parsing and lexing multiply, divide, modulo, shift operators.
This commit is contained in:
parent
4a0a6b8425
commit
f0c84fe0c8
@ -18,8 +18,11 @@ use std::rc::Rc;
|
||||
pub enum BinaryOperation {
|
||||
Multiply,
|
||||
Divide,
|
||||
Modulo,
|
||||
Add,
|
||||
Subtract,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
}
|
||||
|
||||
pub struct BinaryExpression {
|
||||
@ -137,6 +140,9 @@ impl BinaryExpression {
|
||||
BinaryOperation::Divide => {
|
||||
todo!()
|
||||
}
|
||||
BinaryOperation::Modulo => {
|
||||
todo!()
|
||||
}
|
||||
BinaryOperation::Add => {
|
||||
handle_diagnostic!(
|
||||
self.check_op(
|
||||
@ -160,6 +166,8 @@ impl BinaryExpression {
|
||||
diagnostics
|
||||
)
|
||||
}
|
||||
BinaryOperation::LeftShift => todo!(),
|
||||
BinaryOperation::RightShift => todo!(),
|
||||
}
|
||||
|
||||
diagnostics_result!(diagnostics)
|
||||
@ -183,10 +191,13 @@ impl BinaryExpression {
|
||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
|
||||
}
|
||||
BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
|
||||
BinaryOperation::Modulo => todo!(),
|
||||
BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add),
|
||||
BinaryOperation::Subtract => {
|
||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract)
|
||||
}
|
||||
BinaryOperation::LeftShift => todo!(),
|
||||
BinaryOperation::RightShift => todo!(),
|
||||
};
|
||||
IrOperation::Binary(ir_binary_operation)
|
||||
}
|
||||
|
||||
@ -46,8 +46,18 @@ impl<'a> Lexer<'a> {
|
||||
self.position + 1,
|
||||
TokenKind::RightParentheses,
|
||||
)
|
||||
} else if chunk.starts_with("*") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Star)
|
||||
} else if chunk.starts_with("/") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Slash)
|
||||
} else if chunk.starts_with("%") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Modulo)
|
||||
} else if chunk.starts_with("+") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Plus)
|
||||
} else if chunk.starts_with("<<") {
|
||||
Token::new(self.position, self.position + 2, TokenKind::LeftShift)
|
||||
} else if chunk.starts_with(">>") {
|
||||
Token::new(self.position, self.position + 2, TokenKind::RightShift)
|
||||
} else if chunk.starts_with("=") {
|
||||
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
||||
} else if chunk.starts_with(",") {
|
||||
|
||||
@ -662,17 +662,52 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||
self.additive_expression()
|
||||
self.shift_expression()
|
||||
}
|
||||
|
||||
fn shift_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||
let mut result = self.additive_expression()?;
|
||||
while self.current.is_some() {
|
||||
let current = self.get_current();
|
||||
match current.kind() {
|
||||
TokenKind::LeftShift => {
|
||||
self.advance(); // left shift
|
||||
let rhs = self.additive_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
result,
|
||||
rhs,
|
||||
BinaryOperation::LeftShift,
|
||||
source_range,
|
||||
));
|
||||
}
|
||||
TokenKind::RightShift => {
|
||||
self.advance(); // right shift
|
||||
let rhs = self.additive_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
result,
|
||||
rhs,
|
||||
BinaryOperation::RightShift,
|
||||
source_range,
|
||||
));
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn additive_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||
let mut result = self.prefix_expression()?;
|
||||
let mut result = self.multiplicative_expression()?;
|
||||
while self.current.is_some() {
|
||||
let current = self.get_current();
|
||||
match current.kind() {
|
||||
TokenKind::Plus => {
|
||||
self.advance(); // plus
|
||||
let rhs = self.prefix_expression()?;
|
||||
let rhs = self.multiplicative_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
@ -684,7 +719,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
TokenKind::Minus => {
|
||||
self.advance(); // minus
|
||||
let rhs = self.prefix_expression()?;
|
||||
let rhs = self.multiplicative_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
@ -700,6 +735,53 @@ impl<'a> Parser<'a> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn multiplicative_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||
let mut result = self.prefix_expression()?;
|
||||
while self.current.is_some() {
|
||||
let current = self.get_current();
|
||||
match current.kind() {
|
||||
TokenKind::Star => {
|
||||
self.advance(); // multiply
|
||||
let rhs = self.prefix_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
result,
|
||||
rhs,
|
||||
BinaryOperation::Multiply,
|
||||
source_range,
|
||||
));
|
||||
}
|
||||
TokenKind::Slash => {
|
||||
self.advance(); // slash
|
||||
let rhs = self.prefix_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
result,
|
||||
rhs,
|
||||
BinaryOperation::Divide,
|
||||
source_range,
|
||||
))
|
||||
}
|
||||
TokenKind::Modulo => {
|
||||
self.advance(); // modulo
|
||||
let rhs = self.prefix_expression()?;
|
||||
let source_range =
|
||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||
result = Expression::Binary(BinaryExpression::new(
|
||||
result,
|
||||
rhs,
|
||||
BinaryOperation::Modulo,
|
||||
source_range,
|
||||
));
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn prefix_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||
// first, collect all consecutive operators
|
||||
let mut operator_tokens = vec![];
|
||||
@ -960,6 +1042,31 @@ mod smoke_tests {
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_multiply() {
|
||||
smoke_test("fn main() 1 * 2 end");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_divide() {
|
||||
smoke_test("fn main() 1 / 2 end");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_modulo() {
|
||||
smoke_test("fn main() 1 % 2 end");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_left_shift() {
|
||||
smoke_test("fn main() 2 << 1 end");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_right_shift() {
|
||||
smoke_test("fn main() 4 >> 1 end");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -42,6 +42,11 @@ pub enum TokenKind {
|
||||
RightArrow,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
Modulo,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
Class,
|
||||
Dot,
|
||||
SelfKw,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user