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)
 }