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 {
|
pub enum BinaryOperation {
|
||||||
Multiply,
|
Multiply,
|
||||||
Divide,
|
Divide,
|
||||||
|
Modulo,
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
|
LeftShift,
|
||||||
|
RightShift,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BinaryExpression {
|
pub struct BinaryExpression {
|
||||||
@ -137,6 +140,9 @@ impl BinaryExpression {
|
|||||||
BinaryOperation::Divide => {
|
BinaryOperation::Divide => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
BinaryOperation::Modulo => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
BinaryOperation::Add => {
|
BinaryOperation::Add => {
|
||||||
handle_diagnostic!(
|
handle_diagnostic!(
|
||||||
self.check_op(
|
self.check_op(
|
||||||
@ -160,6 +166,8 @@ impl BinaryExpression {
|
|||||||
diagnostics
|
diagnostics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
BinaryOperation::LeftShift => todo!(),
|
||||||
|
BinaryOperation::RightShift => todo!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics_result!(diagnostics)
|
diagnostics_result!(diagnostics)
|
||||||
@ -183,10 +191,13 @@ impl BinaryExpression {
|
|||||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
|
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
|
||||||
}
|
}
|
||||||
BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
|
BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
|
||||||
|
BinaryOperation::Modulo => todo!(),
|
||||||
BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add),
|
BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add),
|
||||||
BinaryOperation::Subtract => {
|
BinaryOperation::Subtract => {
|
||||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract)
|
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract)
|
||||||
}
|
}
|
||||||
|
BinaryOperation::LeftShift => todo!(),
|
||||||
|
BinaryOperation::RightShift => todo!(),
|
||||||
};
|
};
|
||||||
IrOperation::Binary(ir_binary_operation)
|
IrOperation::Binary(ir_binary_operation)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,8 +46,18 @@ impl<'a> Lexer<'a> {
|
|||||||
self.position + 1,
|
self.position + 1,
|
||||||
TokenKind::RightParentheses,
|
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("+") {
|
} else if chunk.starts_with("+") {
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Plus)
|
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("=") {
|
} else if chunk.starts_with("=") {
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
||||||
} else if chunk.starts_with(",") {
|
} else if chunk.starts_with(",") {
|
||||||
|
|||||||
@ -662,17 +662,52 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
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>> {
|
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() {
|
while self.current.is_some() {
|
||||||
let current = self.get_current();
|
let current = self.get_current();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Plus => {
|
TokenKind::Plus => {
|
||||||
self.advance(); // plus
|
self.advance(); // plus
|
||||||
let rhs = self.prefix_expression()?;
|
let rhs = self.multiplicative_expression()?;
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
result = Expression::Binary(BinaryExpression::new(
|
||||||
@ -684,7 +719,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
self.advance(); // minus
|
self.advance(); // minus
|
||||||
let rhs = self.prefix_expression()?;
|
let rhs = self.multiplicative_expression()?;
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
result = Expression::Binary(BinaryExpression::new(
|
||||||
@ -700,6 +735,53 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(result)
|
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>> {
|
fn prefix_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||||
// first, collect all consecutive operators
|
// first, collect all consecutive operators
|
||||||
let mut operator_tokens = vec![];
|
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)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -42,6 +42,11 @@ pub enum TokenKind {
|
|||||||
RightArrow,
|
RightArrow,
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
|
Star,
|
||||||
|
Slash,
|
||||||
|
Modulo,
|
||||||
|
LeftShift,
|
||||||
|
RightShift,
|
||||||
Class,
|
Class,
|
||||||
Dot,
|
Dot,
|
||||||
SelfKw,
|
SelfKw,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user