diff --git a/grimoire/src/parser/span.rs b/grimoire/src/parser/span.rs index 74a74c1a52af32665b797512a6955ed27c6c2c3a..432b9f90aebc383968b90a3fb3447e68150bb38e 100644 --- a/grimoire/src/parser/span.rs +++ b/grimoire/src/parser/span.rs @@ -1,5 +1,5 @@ use crate::ast::Location; -use nom::{Compare, FindSubstring, Input, Offset as _}; +use nom::{Compare, FindSubstring, Input, Offset}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Span<'a> { @@ -23,6 +23,18 @@ impl<'a> core::ops::Deref for Span<'a> { } } +impl From<Span<'_>> for String { + fn from(value: Span<'_>) -> Self { + value.fragment().to_string() + } +} + +impl<'a> From<Span<'a>> for &'a str { + fn from(value: Span<'a>) -> Self { + value.fragment + } +} + impl<'a> Span<'a> { pub fn new(fragment: &'a str) -> Span<'a> { Self { @@ -85,6 +97,12 @@ impl<'a> Span<'a> { } } +impl Offset for Span<'_> { + fn offset(&self, second: &Self) -> usize { + second.fragment().as_ptr() as usize - self.fragment().as_ptr() as usize + } +} + impl<'a> Input for Span<'a> { type Item = <&'a str as Input>::Item; type Iter = <&'a str as Input>::Iter; @@ -138,6 +156,6 @@ impl Compare<&str> for Span<'_> { impl FindSubstring<&str> for Span<'_> { fn find_substring(&self, substr: &str) -> Option<usize> { - todo!() + self.fragment().find_substring(substr) } } diff --git a/grimoire/src/parser/utils.rs b/grimoire/src/parser/utils.rs index e528b9c3e93db3cd56cfb11645c6ee59c5a6b4a0..6f5c7c61a6ceb104351d76b0124dabca9a2a5bc6 100644 --- a/grimoire/src/parser/utils.rs +++ b/grimoire/src/parser/utils.rs @@ -9,16 +9,16 @@ use nom::{ complete::{tag, take_while_m_n}, take_until, }, - character::complete::{char, digit1, multispace0, multispace1}, - combinator::{peek, value, verify}, - multi::fold, - sequence::{delimited, preceded}, + character::complete::{alpha1, alphanumeric1, char, digit1, multispace0, multispace1}, + combinator::{opt, peek, recognize, value, verify}, + multi::{fold, many0}, + sequence::{delimited, pair, preceded}, }; pub fn parse_paren<'a, T>( inner: impl Parser<Span<'a>, Output = T, Error = ParserError>, ) -> impl Parser<Span<'a>, Output = T, Error = ParserError> { - preceded(multispace0, delimited(tag("("), inner, tag(")"))) + preceded(multispace0, delimited(char('('), inner, char(')'))) } pub fn with_location<'a, O>( @@ -52,18 +52,30 @@ pub fn keyword<'a>( } pub fn float<'a>(s: Span<'a>) -> ParserResult<'a, f32> { - digit1 - .map_res(|s: Span<'a>| str::parse::<f32>(s.fragment())) - .parse(s) + let s = multispace0(s)?.0; + let parse_f32 = |s: Span<'a>| str::parse::<f32>(s.into()); + pair( + digit1.map_res(parse_f32), + opt(recognize((char('.'), digit1)).map_res(parse_f32)), + ) + .map(|(intp, fltp)| intp + fltp.unwrap_or_default()) + .parse(s) } pub fn identifier(s: Span) -> ParserResult<String> { - todo!() + let s = multispace0(s)?.0; + recognize(pair( + alt((alpha1, tag("_"))), + many0(alt((alphanumeric1, tag("_")))), + )) + .map(String::from) + .parse(s) } pub fn number<'a>(s: Span<'a>) -> ParserResult<'a, i32> { + let s = multispace0(s)?.0; digit1 - .map_res(|s: Span<'a>| str::parse::<i32>(s.fragment())) + .map_res(|s: Span<'a>| str::parse::<i32>(s.into())) .parse(s) }