From 2b8d155d5df7502c698bf7791504d20749fc1a8f Mon Sep 17 00:00:00 2001
From: Kubat <maelle.martin@proton.me>
Date: Mon, 28 Apr 2025 21:43:53 +0200
Subject: [PATCH] Parse the AST with a location span! for debug & info purpuses

---
 grimoire/src/{expr/mod.rs => ast/expr.rs} | 13 ++----
 grimoire/src/ast/location.rs              |  5 ++
 grimoire/src/ast/mod.rs                   |  4 ++
 grimoire/src/lib.rs                       |  2 +-
 grimoire/src/parser/error.rs              |  2 +-
 grimoire/src/parser/expr.rs               | 57 +++++++++++++++++------
 grimoire/src/parser/span.rs               |  7 +--
 grimoire/src/parser/utils.rs              | 35 +++++++++++++-
 grimoire/src/spell/arguments.rs           |  2 +-
 9 files changed, 94 insertions(+), 33 deletions(-)
 rename grimoire/src/{expr/mod.rs => ast/expr.rs} (87%)
 create mode 100644 grimoire/src/ast/location.rs
 create mode 100644 grimoire/src/ast/mod.rs

diff --git a/grimoire/src/expr/mod.rs b/grimoire/src/ast/expr.rs
similarity index 87%
rename from grimoire/src/expr/mod.rs
rename to grimoire/src/ast/expr.rs
index fa12c77..7c4028c 100644
--- a/grimoire/src/expr/mod.rs
+++ b/grimoire/src/ast/expr.rs
@@ -1,11 +1,8 @@
+use crate::ast::Location;
+
 #[derive(Debug)]
 pub enum VarOrConstant {
     Var(String),
-    Constant(Constant),
-}
-
-#[derive(Debug)]
-pub enum Constant {
     Int(i32),
     Flt(f32),
     Bool(bool),
@@ -14,9 +11,9 @@ pub enum Constant {
 
 #[derive(Debug)]
 pub enum Expression {
-    Binary(Box<Expression>, BinOp, Box<Expression>),
-    Unary(UnOp, Box<Expression>),
-    Leaf(VarOrConstant),
+    Binary(Location, Location, Box<Expression>, BinOp, Box<Expression>),
+    Unary(Location, Location, UnOp, Box<Expression>),
+    Leaf(Location, Location, VarOrConstant),
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/grimoire/src/ast/location.rs b/grimoire/src/ast/location.rs
new file mode 100644
index 0000000..32a6f60
--- /dev/null
+++ b/grimoire/src/ast/location.rs
@@ -0,0 +1,5 @@
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Location {
+    offset: usize,
+    line: u32,
+}
diff --git a/grimoire/src/ast/mod.rs b/grimoire/src/ast/mod.rs
new file mode 100644
index 0000000..598d762
--- /dev/null
+++ b/grimoire/src/ast/mod.rs
@@ -0,0 +1,4 @@
+pub mod expr;
+mod location;
+
+pub use location::Location;
diff --git a/grimoire/src/lib.rs b/grimoire/src/lib.rs
index 1dc5c48..c3d4d7b 100644
--- a/grimoire/src/lib.rs
+++ b/grimoire/src/lib.rs
@@ -1,5 +1,5 @@
+pub mod ast;
 pub mod error;
-pub mod expr;
 pub mod parser;
 pub mod spell;
 pub mod state;
diff --git a/grimoire/src/parser/error.rs b/grimoire/src/parser/error.rs
index 6c129bc..9ac891d 100644
--- a/grimoire/src/parser/error.rs
+++ b/grimoire/src/parser/error.rs
@@ -1,4 +1,4 @@
-use crate::parser::span::{Location, Span};
+use crate::{ast::Location, parser::Span};
 use nom::{IResult, error::*};
 use std::num::{ParseFloatError, ParseIntError};
 
diff --git a/grimoire/src/parser/expr.rs b/grimoire/src/parser/expr.rs
index 2f0b272..ee6c32d 100644
--- a/grimoire/src/parser/expr.rs
+++ b/grimoire/src/parser/expr.rs
@@ -1,20 +1,37 @@
 use crate::{
-    expr::{BinOp, Expression, UnOp},
+    ast::{Location, expr::*},
     parser::*,
 };
 
 use nom::{
-    Parser, branch::alt, bytes::complete::tag, character::complete::multispace0, combinator::map,
-    multi::many0, sequence::preceded,
+    Parser,
+    branch::alt,
+    bytes::complete::tag,
+    character::complete::{digit1, multispace0},
+    combinator::map,
+    multi::many0,
+    sequence::preceded,
 };
 
+fn var_or_constant(s: Span) -> ParserResult<Expression> {
+    utils::map_with_locaiton(
+        alt((
+            map(digit1, |digits| todo!()),
+            map(utils::identifier("true"), |_| todo!()),
+            map(utils::identifier("false"), |_| todo!()),
+        )),
+        |begin, end, var_or_constant| todo!(),
+    )
+    .parse(s)
+}
+
 fn leaf(s: Span) -> ParserResult<Expression> {
+    // Note: the order is important!
     alt((
-        // 1
         unop(UnOp::Not, expression),
         unop(UnOp::Neg, expression),
-        // 2
         utils::parse_paren(expression),
+        var_or_constant,
     ))
     .parse(s)
 }
@@ -23,27 +40,37 @@ fn unop<'a>(
     op: UnOp,
     next: impl Parser<Span<'a>, Output = Expression, Error = ParserError>,
 ) -> impl Parser<Span<'a>, Output = Expression, Error = ParserError> {
-    map((multispace0, tag(op.as_str()), next), move |(.., expr)| {
-        Expression::Unary(op, Box::new(expr))
-    })
+    utils::map_with_locaiton(
+        (multispace0, tag(op.as_str()), next),
+        move |begin, end, (.., expr)| Expression::Unary(begin, end, op, Box::new(expr)),
+    )
 }
 
 fn binop<'a>(
     op: BinOp,
     next: impl Parser<Span<'a>, Output = Expression, Error = ParserError>,
-) -> impl Parser<Span<'a>, Output = (BinOp, Expression), Error = ParserError> {
-    preceded(multispace0, (map(tag(op.as_str()), move |_| op), next))
+) -> impl Parser<Span<'a>, Output = (Location, Location, BinOp, Expression), Error = ParserError> {
+    preceded(
+        multispace0,
+        utils::with_location((map(tag(op.as_str()), move |_| op), next))
+            .map(|(begin, end, (op, expr))| (begin, end, op, expr)),
+    )
 }
 
-fn fold_exprs(initial: Expression, remainder: Vec<(BinOp, Expression)>) -> Expression {
-    remainder.into_iter().fold(initial, |acc, (op, expr)| {
-        Expression::Binary(Box::new(acc), op, Box::new(expr))
-    })
+fn fold_exprs(
+    initial: Expression,
+    remainder: Vec<(Location, Location, BinOp, Expression)>,
+) -> Expression {
+    remainder
+        .into_iter()
+        .fold(initial, |acc, (begin, end, op, expr)| {
+            Expression::Binary(begin, end, Box::new(acc), op, Box::new(expr))
+        })
 }
 
 fn terms(s: Span) -> ParserResult<Expression> {
     let (s, initial) = leaf(s)?;
-    let (s, remainder): (Span, Vec<(BinOp, Expression)>) = many0(alt((
+    let (s, remainder): (Span, Vec<_>) = many0(alt((
         binop(BinOp::Mul, leaf),
         binop(BinOp::Div, leaf),
         binop(BinOp::Mod, leaf),
diff --git a/grimoire/src/parser/span.rs b/grimoire/src/parser/span.rs
index 3bfe1ad..ae08a5f 100644
--- a/grimoire/src/parser/span.rs
+++ b/grimoire/src/parser/span.rs
@@ -1,11 +1,6 @@
+use crate::ast::Location;
 use nom::{Compare, Input, Offset as _};
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Location {
-    offset: usize,
-    line: u32,
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Span<'a> {
     /// The offset represents the position of the fragment relatively to
diff --git a/grimoire/src/parser/utils.rs b/grimoire/src/parser/utils.rs
index ca8516d..075a319 100644
--- a/grimoire/src/parser/utils.rs
+++ b/grimoire/src/parser/utils.rs
@@ -1,4 +1,7 @@
-use crate::parser::{error::*, span::*};
+use crate::{
+    ast::Location,
+    parser::{error::*, span::*},
+};
 use nom::{
     Parser,
     bytes::complete::tag,
@@ -11,3 +14,33 @@ pub fn parse_paren<'a, T>(
 ) -> impl Parser<Span<'a>, Output = T, Error = ParserError> {
     preceded(multispace0, delimited(tag("("), inner, tag(")")))
 }
+
+pub fn with_location<'a, O>(
+    mut parser: impl Parser<Span<'a>, Output = O, Error = ParserError>,
+) -> impl Parser<Span<'a>, Output = (Location, Location, O), Error = ParserError> {
+    move |span: Span<'a>| {
+        let begin_s = multispace0(span)?.0;
+        let (end_s, res) = parser.parse(span)?;
+        Ok((end_s, (begin_s.get_location(), end_s.get_location(), res)))
+    }
+}
+
+pub fn map_with_locaiton<'a, F, O>(
+    mut parser: F,
+    mut cb: impl FnMut(Location, Location, <F as Parser<Span<'a>>>::Output) -> O,
+) -> impl Parser<Span<'a>, Output = O, Error = ParserError>
+where
+    F: Parser<Span<'a>, Error = ParserError>,
+{
+    move |span: Span<'a>| {
+        let begin_s = multispace0(span)?.0;
+        let (end_s, res) = parser.parse(span)?;
+        Ok((end_s, cb(begin_s.get_location(), end_s.get_location(), res)))
+    }
+}
+
+pub fn identifier<'a>(
+    ident: &'static str,
+) -> impl Parser<Span<'a>, Output = Span<'a>, Error = ParserError> {
+    todo!()
+}
diff --git a/grimoire/src/spell/arguments.rs b/grimoire/src/spell/arguments.rs
index 32807b7..bf62381 100644
--- a/grimoire/src/spell/arguments.rs
+++ b/grimoire/src/spell/arguments.rs
@@ -1,4 +1,4 @@
-use crate::expr::Expression;
+use crate::ast::expr::Expression;
 use std::collections::HashMap;
 
 /// Allowed types for arguments.
-- 
GitLab