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