diff --git a/rust_compiler/Cargo.lock b/rust_compiler/Cargo.lock index 7a9df42..3d8cef8 100644 --- a/rust_compiler/Cargo.lock +++ b/rust_compiler/Cargo.lock @@ -1071,18 +1071,18 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.8.30" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.30" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", diff --git a/rust_compiler/libs/parser/src/lib.rs b/rust_compiler/libs/parser/src/lib.rs index 3789894..c655634 100644 --- a/rust_compiler/libs/parser/src/lib.rs +++ b/rust_compiler/libs/parser/src/lib.rs @@ -129,17 +129,62 @@ impl<'a> Parser<'a> { /// Parses all the input from the tokenizer buffer and returns the resulting expression /// Expressions are returned in a root block expression node pub fn parse_all(&mut self) -> Result, Error> { - let mut expressions = Vec::::new(); + // peek at what the first token would be and extract the line and col + let (start_line, start_col) = self + .tokenizer + .peek()? + .map(|tok| (tok.line, tok.column)) + .unwrap_or((1, 1)); + + let mut expressions = Vec::>::new(); while let Some(expression) = self.parse()? { expressions.push(expression); } - Ok(Some(Expression::Block(BlockExpression(expressions)))) + if expressions.is_empty() { + let span = Span { + start_line, + end_line: start_line, + start_col, + end_col: start_col, + }; + + return Ok(Some(Expression::Block(Spanned { + node: BlockExpression(expressions), + span, + }))); + } + + self.tokenizer.seek(SeekFrom::Current(-1))?; + + // Ignore the EOF, we want the previous token to define what the end of the source is. + let (end_line, end_col) = self + .tokenizer + .peek()? + .map(|tok| { + ( + tok.line, + tok.column + tok.original_string.unwrap_or_default().len(), + ) + }) + .unwrap_or((start_line, start_col)); + + let span = Span { + start_line, + end_line, + start_col, + end_col, + }; + + Ok(Some(Expression::Block(Spanned { + node: BlockExpression(expressions), + span, + }))) } /// Parses the input from the tokenizer buffer and returns the resulting expression - pub fn parse(&mut self) -> Result, Error> { + pub fn parse(&mut self) -> Result>, Error> { self.assign_next()?; let expr = self.expression()?; @@ -163,7 +208,12 @@ impl<'a> Parser<'a> { } /// Parses an expression, handling binary operations with correct precedence. - fn expression(&mut self) -> Result, Error> { + fn expression(&mut self) -> Result>, Error> { + let (start_line, end_line) = self + .current_token + .map(|tok| (tok.line, tok.column)) + .ok_or(Error::UnexpectedEOF)?; + // Parse the Left Hand Side (unary/primary expression) let lhs = self.unary()?; diff --git a/rust_compiler/libs/parser/src/tree_node.rs b/rust_compiler/libs/parser/src/tree_node.rs index 3e49e09..21588d2 100644 --- a/rust_compiler/libs/parser/src/tree_node.rs +++ b/rust_compiler/libs/parser/src/tree_node.rs @@ -1,3 +1,5 @@ +use std::ops::Deref; + use super::sys_call::SysCall; use tokenizer::token::Number; @@ -20,12 +22,12 @@ impl std::fmt::Display for Literal { #[derive(Debug, PartialEq, Eq)] pub enum BinaryExpression { - Add(Box, Box), - Multiply(Box, Box), - Divide(Box, Box), - Subtract(Box, Box), - Exponent(Box, Box), - Modulo(Box, Box), + Add(Box>, Box>), + Multiply(Box>, Box>), + Divide(Box>, Box>), + Subtract(Box>, Box>), + Exponent(Box>, Box>), + Modulo(Box>, Box>), } impl std::fmt::Display for BinaryExpression { @@ -43,15 +45,15 @@ impl std::fmt::Display for BinaryExpression { #[derive(Debug, PartialEq, Eq)] pub enum LogicalExpression { - And(Box, Box), - Or(Box, Box), - Not(Box), - Equal(Box, Box), - NotEqual(Box, Box), - GreaterThan(Box, Box), - GreaterThanOrEqual(Box, Box), - LessThan(Box, Box), - LessThanOrEqual(Box, Box), + And(Box>, Box>), + Or(Box>, Box>), + Not(Box>), + Equal(Box>, Box>), + NotEqual(Box>, Box>), + GreaterThan(Box>, Box>), + GreaterThanOrEqual(Box>, Box>), + LessThan(Box>, Box>), + LessThanOrEqual(Box>, Box>), } impl std::fmt::Display for LogicalExpression { @@ -73,7 +75,7 @@ impl std::fmt::Display for LogicalExpression { #[derive(Debug, PartialEq, Eq)] pub struct AssignmentExpression { pub identifier: String, - pub expression: Box, + pub expression: Box>, } impl std::fmt::Display for AssignmentExpression { @@ -102,7 +104,7 @@ impl std::fmt::Display for FunctionExpression { } #[derive(Debug, PartialEq, Eq)] -pub struct BlockExpression(pub Vec); +pub struct BlockExpression(pub Vec>); impl std::fmt::Display for BlockExpression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -170,9 +172,9 @@ impl std::fmt::Display for DeviceDeclarationExpression { #[derive(Debug, PartialEq, Eq)] pub struct IfExpression { - pub condition: Box, - pub body: BlockExpression, - pub else_branch: Option>, + pub condition: Box>, + pub body: Spanned, + pub else_branch: Option>>, } impl std::fmt::Display for IfExpression { @@ -187,7 +189,7 @@ impl std::fmt::Display for IfExpression { #[derive(Debug, PartialEq, Eq)] pub struct LoopExpression { - pub body: BlockExpression, + pub body: Spanned, } impl std::fmt::Display for LoopExpression { @@ -198,7 +200,7 @@ impl std::fmt::Display for LoopExpression { #[derive(Debug, PartialEq, Eq)] pub struct WhileExpression { - pub condition: Box, + pub condition: Box>, pub body: BlockExpression, } @@ -208,27 +210,58 @@ impl std::fmt::Display for WhileExpression { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Span { + pub start_line: usize, + pub end_line: usize, + pub start_col: usize, + pub end_col: usize, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Spanned { + pub span: Span, + pub node: T, +} + +impl std::fmt::Display for Spanned +where + T: std::fmt::Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.node) + } +} + +impl Deref for Spanned { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.node + } +} + #[derive(Debug, PartialEq, Eq)] pub enum Expression { - Assignment(AssignmentExpression), - Binary(BinaryExpression), - Block(BlockExpression), - Break, - Continue, - Declaration(String, Box), - DeviceDeclaration(DeviceDeclarationExpression), - Function(FunctionExpression), - If(IfExpression), - Invocation(InvocationExpression), - Literal(Literal), - Logical(LogicalExpression), - Loop(LoopExpression), - Negation(Box), - Priority(Box), - Return(Box), - Syscall(SysCall), - Variable(String), - While(WhileExpression), + Assignment(Spanned), + Binary(Spanned), + Block(Spanned), + Break(Span), + Continue(Span), + Declaration(String, Box>), + DeviceDeclaration(Spanned), + Function(Spanned), + If(Spanned), + Invocation(Spanned), + Literal(Spanned), + Logical(Spanned), + Loop(Spanned), + Negation(Box>), + Priority(Box>), + Return(Box>), + Syscall(Spanned), + Variable(Spanned), + While(Spanned), } impl std::fmt::Display for Expression { @@ -237,8 +270,8 @@ impl std::fmt::Display for Expression { Expression::Assignment(e) => write!(f, "{}", e), Expression::Binary(e) => write!(f, "{}", e), Expression::Block(e) => write!(f, "{}", e), - Expression::Break => write!(f, "break"), - Expression::Continue => write!(f, "continue"), + Expression::Break(_) => write!(f, "break"), + Expression::Continue(_) => write!(f, "continue"), Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e), Expression::DeviceDeclaration(e) => write!(f, "{}", e), Expression::Function(e) => write!(f, "{}", e),