blob: ebedd3062e9f8aa689a860ffd396290f59ac0fb8 [file] [log] [blame]
use nom::{
branch::alt,
bytes::complete::{tag, take_until, take_while},
character::complete::{alpha1, alphanumeric1, digit1, multispace1},
combinator::{map, map_res, opt, recognize, value},
error::{context, VerboseError},
multi::{many0, many0_count, many1},
sequence::{delimited, pair, tuple},
IResult, Parser,
};
use crate::string::parse_string;
/// Result type with verbose error
pub(crate) type VerboseResult<'a, T> = IResult<&'a str, T, VerboseError<&'a str>>;
pub(crate) fn comment(input: &str) -> VerboseResult<()> {
context(
"comment",
value(
(),
tuple((tag("//"), take_while(|c|c!='\n'))),
),
)(input)
}
pub(crate) fn multiline_comment(input: &str) -> VerboseResult<()> {
context(
"multiline comment",
value((), delimited(tag("/*"), take_until("*/"), tag("*/"))),
)(input)
}
pub(crate) fn space_or_comments(input: &str) -> VerboseResult<()> {
value(
(),
many0(alt((value((), multispace1), comment, multiline_comment))),
)(input)
}
pub(crate) fn space_or_comments1(input: &str) -> VerboseResult<()> {
value(
(),
many1(alt((value((), multispace1), comment, multiline_comment))),
)(input)
}
pub(crate)fn ws<'a, F, O>(inner: F) -> impl Parser<&'a str, O, VerboseError<&'a str>>
where
F: Parser<&'a str, O, VerboseError<&'a str>>,
{
delimited(
space_or_comments,
inner,
space_or_comments
)
}
pub(crate) fn identifier(input: &str) -> VerboseResult<&str> {
recognize(pair(
alt((alpha1, tag("_"))),
many0_count(alt((alphanumeric1, tag("_")))),
))(input)
}
pub(crate) fn string_literal(input: &str) -> VerboseResult<String> {
context(
"string",
parse_string
)(input)
}
pub(crate) fn comma(input: &str) -> VerboseResult<&str> {
ws(tag(",")).parse(input)
}
pub(crate) fn parse_bool(input: &str) -> VerboseResult<bool> {
alt((map(tag("true"), |_| true), map(tag("false"), |_| false)))(input)
}
pub(crate) fn parse_int(input: &str) -> VerboseResult<i64> {
map_res(
recognize(pair(opt(tag("-")), digit1)),
|x| i64::from_str_radix(x, 10),
)(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_bool() {
let input = "true";
let expected_output = Ok(("", true));
assert_eq!(parse_bool(input), expected_output);
}
#[test]
fn test_parse_int() {
let input = "123";
let expected_output = Ok(("", 123));
assert_eq!(parse_int(input), expected_output);
}
#[test]
fn test_parse_nint() {
let input: &str = "-123";
let expected_output = Ok(("", -123));
assert_eq!(parse_int(input), expected_output);
}
}