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]]
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",

View File

@@ -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<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()? {
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<Option<tree_node::Expression>, Error> {
pub fn parse(&mut self) -> Result<Option<Spanned<tree_node::Expression>>, 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<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)
let lhs = self.unary()?;

View File

@@ -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<Expression>, Box<Expression>),
Multiply(Box<Expression>, Box<Expression>),
Divide(Box<Expression>, Box<Expression>),
Subtract(Box<Expression>, Box<Expression>),
Exponent(Box<Expression>, Box<Expression>),
Modulo(Box<Expression>, Box<Expression>),
Add(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Multiply(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Divide(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Subtract(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Exponent(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Modulo(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
}
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<Expression>, Box<Expression>),
Or(Box<Expression>, Box<Expression>),
Not(Box<Expression>),
Equal(Box<Expression>, Box<Expression>),
NotEqual(Box<Expression>, Box<Expression>),
GreaterThan(Box<Expression>, Box<Expression>),
GreaterThanOrEqual(Box<Expression>, Box<Expression>),
LessThan(Box<Expression>, Box<Expression>),
LessThanOrEqual(Box<Expression>, Box<Expression>),
And(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Or(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
Not(Box<Spanned<Expression>>),
Equal(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
NotEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
GreaterThan(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
GreaterThanOrEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
LessThan(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
LessThanOrEqual(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
}
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<Expression>,
pub expression: Box<Spanned<Expression>>,
}
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<Expression>);
pub struct BlockExpression(pub Vec<Spanned<Expression>>);
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<Expression>,
pub body: BlockExpression,
pub else_branch: Option<Box<Expression>>,
pub condition: Box<Spanned<Expression>>,
pub body: Spanned<BlockExpression>,
pub else_branch: Option<Box<Spanned<Expression>>>,
}
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<BlockExpression>,
}
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<Expression>,
pub condition: Box<Spanned<Expression>>,
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)]
pub enum Expression {
Assignment(AssignmentExpression),
Binary(BinaryExpression),
Block(BlockExpression),
Break,
Continue,
Declaration(String, Box<Expression>),
DeviceDeclaration(DeviceDeclarationExpression),
Function(FunctionExpression),
If(IfExpression),
Invocation(InvocationExpression),
Literal(Literal),
Logical(LogicalExpression),
Loop(LoopExpression),
Negation(Box<Expression>),
Priority(Box<Expression>),
Return(Box<Expression>),
Syscall(SysCall),
Variable(String),
While(WhileExpression),
Assignment(Spanned<AssignmentExpression>),
Binary(Spanned<BinaryExpression>),
Block(Spanned<BlockExpression>),
Break(Span),
Continue(Span),
Declaration(String, Box<Spanned<Expression>>),
DeviceDeclaration(Spanned<DeviceDeclarationExpression>),
Function(Spanned<FunctionExpression>),
If(Spanned<IfExpression>),
Invocation(Spanned<InvocationExpression>),
Literal(Spanned<Literal>),
Logical(Spanned<LogicalExpression>),
Loop(Spanned<LoopExpression>),
Negation(Box<Spanned<Expression>>),
Priority(Box<Spanned<Expression>>),
Return(Box<Spanned<Expression>>),
Syscall(Spanned<SysCall>),
Variable(Spanned<String>),
While(Spanned<WhileExpression>),
}
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),