49 lines
1.4 KiB
Rust
49 lines
1.4 KiB
Rust
use nom::Parser;
|
|
use super::{
|
|
SpanRef,
|
|
PResult,
|
|
Token,
|
|
Number,
|
|
IResultExt,
|
|
SpannedData,
|
|
SpanExt,
|
|
};
|
|
|
|
// should come after path
|
|
fn parse_number_span(span: SpanRef) -> PResult<()> {
|
|
// if not a path, everything that starts with an optional '-', optional '.'
|
|
// followed by digits is a number.
|
|
|
|
let (span, _) = nom::sequence::tuple((
|
|
nom::combinator::opt(nom::bytes::complete::tag("-")),
|
|
nom::combinator::opt(nom::bytes::complete::tag(".")),
|
|
nom::character::complete::digit1,
|
|
))(span)?;
|
|
|
|
// if we fail now, fail hard (upstream nix parses something crazy here).
|
|
// take up all alpha characters too, should be separated by something.
|
|
let (span, _) = nom::multi::many0_count(nom::branch::alt((
|
|
nom::character::complete::alphanumeric1.map(|_| ()),
|
|
nom::bytes::complete::tag(".").map(|_| ()),
|
|
nom::bytes::complete::tag("e").map(|_| ()),
|
|
)))(span).unrecoverable()?;
|
|
|
|
Ok((span, ()))
|
|
}
|
|
|
|
impl Number {
|
|
// should come after path
|
|
pub(super) fn parse(span: SpanRef) -> PResult<SpannedData<Token>> {
|
|
let (rem_span, num_span) = nom::combinator::recognize(parse_number_span)(span)?;
|
|
let num_s = num_span.as_str();
|
|
let num = if let Ok(num) = num_s.parse() {
|
|
Number::Integer(num)
|
|
} else if let Ok(num) = num_s.parse() {
|
|
Number::Float(num)
|
|
} else {
|
|
return nom::combinator::fail(span).unrecoverable();
|
|
};
|
|
Ok((rem_span, num_span.data(Token::Number(num))))
|
|
}
|
|
}
|