WIP -- Expressions should know what their span is

This commit is contained in:
2025-11-30 14:56:54 -07:00
parent e3ad024866
commit 50d8f90816
3 changed files with 134 additions and 51 deletions

View File

@@ -1071,18 +1071,18 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.30" version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.30" version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@@ -129,17 +129,62 @@ impl<'a> Parser<'a> {
/// Parses all the input from the tokenizer buffer and returns the resulting expression /// Parses all the input from the tokenizer buffer and returns the resulting expression
/// Expressions are returned in a root block expression node /// Expressions are returned in a root block expression node
pub fn parse_all(&mut self) -> Result<Option<tree_node::Expression>, Error> { pub fn parse_all(&mut self) -> Result<Option<tree_node::Expression>, Error> {
let mut expressions = Vec::<Expression>::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::<Spanned<Expression>>::new();
while let Some(expression) = self.parse()? { while let Some(expression) = self.parse()? {
expressions.push(expression); 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 /// Parses the input from the tokenizer buffer and returns the resulting expression
pub fn parse(&mut self) -> Result<Option<tree_node::Expression>, Error> { pub fn parse(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, Error> {
self.assign_next()?; self.assign_next()?;
let expr = self.expression()?; let expr = self.expression()?;
@@ -163,7 +208,12 @@ impl<'a> Parser<'a> {
} }
/// Parses an expression, handling binary operations with correct precedence. /// Parses an expression, handling binary operations with correct precedence.
fn expression(&mut self) -> Result<Option<tree_node::Expression>, Error> { fn expression(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, 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) // Parse the Left Hand Side (unary/primary expression)
let lhs = self.unary()?; let lhs = self.unary()?;

View File

@@ -1,3 +1,5 @@
use std::ops::Deref;
use super::sys_call::SysCall; use super::sys_call::SysCall;
use tokenizer::token::Number; use tokenizer::token::Number;
@@ -20,12 +22,12 @@ impl std::fmt::Display for Literal {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum BinaryExpression { pub enum BinaryExpression {
Add(Box<Expression>, Box<Expression>), Add(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Multiply(Box<Expression>, Box<Expression>), Multiply(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Divide(Box<Expression>, Box<Expression>), Divide(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Subtract(Box<Expression>, Box<Expression>), Subtract(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Exponent(Box<Expression>, Box<Expression>), Exponent(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Modulo(Box<Expression>, Box<Expression>), Modulo(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
} }
impl std::fmt::Display for BinaryExpression { impl std::fmt::Display for BinaryExpression {
@@ -43,15 +45,15 @@ impl std::fmt::Display for BinaryExpression {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum LogicalExpression { pub enum LogicalExpression {
And(Box<Expression>, Box<Expression>), And(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Or(Box<Expression>, Box<Expression>), Or(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Not(Box<Expression>), Not(Box<Spanned<Expression>>),
Equal(Box<Expression>, Box<Expression>), Equal(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
NotEqual(Box<Expression>, Box<Expression>), NotEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
GreaterThan(Box<Expression>, Box<Expression>), GreaterThan(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
GreaterThanOrEqual(Box<Expression>, Box<Expression>), GreaterThanOrEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
LessThan(Box<Expression>, Box<Expression>), LessThan(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
LessThanOrEqual(Box<Expression>, Box<Expression>), LessThanOrEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
} }
impl std::fmt::Display for LogicalExpression { impl std::fmt::Display for LogicalExpression {
@@ -73,7 +75,7 @@ impl std::fmt::Display for LogicalExpression {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct AssignmentExpression { pub struct AssignmentExpression {
pub identifier: String, pub identifier: String,
pub expression: Box<Expression>, pub expression: Box<Spanned<Expression>>,
} }
impl std::fmt::Display for AssignmentExpression { impl std::fmt::Display for AssignmentExpression {
@@ -102,7 +104,7 @@ impl std::fmt::Display for FunctionExpression {
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct BlockExpression(pub Vec<Expression>); pub struct BlockExpression(pub Vec<Spanned<Expression>>);
impl std::fmt::Display for BlockExpression { impl std::fmt::Display for BlockExpression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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)] #[derive(Debug, PartialEq, Eq)]
pub struct IfExpression { pub struct IfExpression {
pub condition: Box<Expression>, pub condition: Box<Spanned<Expression>>,
pub body: BlockExpression, pub body: Spanned<BlockExpression>,
pub else_branch: Option<Box<Expression>>, pub else_branch: Option<Box<Spanned<Expression>>>,
} }
impl std::fmt::Display for IfExpression { impl std::fmt::Display for IfExpression {
@@ -187,7 +189,7 @@ impl std::fmt::Display for IfExpression {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct LoopExpression { pub struct LoopExpression {
pub body: BlockExpression, pub body: Spanned<BlockExpression>,
} }
impl std::fmt::Display for LoopExpression { impl std::fmt::Display for LoopExpression {
@@ -198,7 +200,7 @@ impl std::fmt::Display for LoopExpression {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct WhileExpression { pub struct WhileExpression {
pub condition: Box<Expression>, pub condition: Box<Spanned<Expression>>,
pub body: BlockExpression, 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<T> {
pub span: Span,
pub node: T,
}
impl<T> std::fmt::Display for Spanned<T>
where
T: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.node)
}
}
impl<T> Deref for Spanned<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.node
}
}
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Expression { pub enum Expression {
Assignment(AssignmentExpression), Assignment(Spanned<AssignmentExpression>),
Binary(BinaryExpression), Binary(Spanned<BinaryExpression>),
Block(BlockExpression), Block(Spanned<BlockExpression>),
Break, Break(Span),
Continue, Continue(Span),
Declaration(String, Box<Expression>), Declaration(String, Box<Spanned<Expression>>),
DeviceDeclaration(DeviceDeclarationExpression), DeviceDeclaration(Spanned<DeviceDeclarationExpression>),
Function(FunctionExpression), Function(Spanned<FunctionExpression>),
If(IfExpression), If(Spanned<IfExpression>),
Invocation(InvocationExpression), Invocation(Spanned<InvocationExpression>),
Literal(Literal), Literal(Spanned<Literal>),
Logical(LogicalExpression), Logical(Spanned<LogicalExpression>),
Loop(LoopExpression), Loop(Spanned<LoopExpression>),
Negation(Box<Expression>), Negation(Box<Spanned<Expression>>),
Priority(Box<Expression>), Priority(Box<Spanned<Expression>>),
Return(Box<Expression>), Return(Box<Spanned<Expression>>),
Syscall(SysCall), Syscall(Spanned<SysCall>),
Variable(String), Variable(Spanned<String>),
While(WhileExpression), While(Spanned<WhileExpression>),
} }
impl std::fmt::Display for Expression { impl std::fmt::Display for Expression {
@@ -237,8 +270,8 @@ impl std::fmt::Display for Expression {
Expression::Assignment(e) => write!(f, "{}", e), Expression::Assignment(e) => write!(f, "{}", e),
Expression::Binary(e) => write!(f, "{}", e), Expression::Binary(e) => write!(f, "{}", e),
Expression::Block(e) => write!(f, "{}", e), Expression::Block(e) => write!(f, "{}", e),
Expression::Break => write!(f, "break"), Expression::Break(_) => write!(f, "break"),
Expression::Continue => write!(f, "continue"), Expression::Continue(_) => write!(f, "continue"),
Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e), Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e),
Expression::DeviceDeclaration(e) => write!(f, "{}", e), Expression::DeviceDeclaration(e) => write!(f, "{}", e),
Expression::Function(e) => write!(f, "{}", e), Expression::Function(e) => write!(f, "{}", e),