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 fa12c7701d34e8d5ff0cf3c289b17f43b8642f83..7c4028c92b57fcf06416d6841e21e1359e928f6a 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 0000000000000000000000000000000000000000..32a6f608d8f91e47acdf9763df87009c8524692b --- /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 0000000000000000000000000000000000000000..598d762a1ff5cadf9465ccbc9609da1615fd63d0 --- /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 1dc5c4853e9ff3780577039ea9243d8048585b9a..c3d4d7b87a891e57886afddc4cf32a442e1b8df6 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 6c129bcce1f571c12b06517abf15206a8336acea..9ac891d8d7d94635892d374fec3c7c698891e13a 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 2f0b272801955f26e8c3674de085f5adfc94f2eb..ee6c32d5454fd7ccebc6ff9d69a2481ff59d2270 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 3bfe1ad4778a7b51b29279d1fdd8997b9b9937ac..ae08a5fff924cca8609d0eddf086aba0ded5dbe1 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 ca8516ddc4b9d7192e1738eb4f9050db8121c3aa..075a319901162720459b3e05212907b56e5d5177 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 32807b726c1512e748d092d49cd6a1db5931ba14..bf623816ddc4d3f2411d2f038ac945d30138da0e 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.