blob: acd81b504b36a009708f9442d28c604f416e5093 [file] [log] [blame]
use combine::parser::char::{char, digit, hex_digit, oct_digit, string};
use combine::parser::range::{range, recognize};
use combine::stream::RangeStream;
use combine::*;
// ;; Boolean
// boolean = true / false
parse!(boolean() -> bool, {
choice((
(char('t'), range("rue"),),
(char('f'), range("alse"),),
)).map(|p| p.0 == 't')
});
// ;; Integer
// integer = [ "-" / "+" ] int
// int = [1-9] 1*( DIGIT / _ DIGIT ) / DIGIT
// modified: int = 0 / [1-9] *( DIGIT / _ DIGIT )
parse!(parse_integer() -> &'a str, {
recognize((
optional(choice([char('-'), char('+')])),
choice((
char('0'),
(
satisfy(|c| ('1'..='9').contains(&c)),
skip_many((
optional(char('_')),
skip_many1(digit()),
)),
).map(|t| t.0),
)),
))
});
parse!(integer() -> i64, {
choice!(
attempt(parse_hex_integer()),
attempt(parse_octal_integer()),
attempt(parse_binary_integer()),
parse_integer()
.and_then(|s| s.replace("_", "").parse())
.message("While parsing an Integer")
)
});
// hex-int = "0x" HEXDIGIT *( HEXDIGIT / _ HEXDIGIT )
parse!(parse_hex_integer() -> i64, {
string("0x").with(
recognize((
hex_digit(),
skip_many((
optional(char('_')),
skip_many1(hex_digit()),
)),
).map(|t| t.0)
)).and_then(|s: &str| i64::from_str_radix(&s.replace("_", ""), 16))
.message("While parsing a hexadecimal Integer")
});
// oct-int = "0o" digit0-7 *( digit0-7 / _ digit0-7 )
parse!(parse_octal_integer() -> i64, {
string("0o").with(
recognize((
oct_digit(),
skip_many((
optional(char('_')),
skip_many1(oct_digit()),
)),
).map(|t| t.0)
)).and_then(|s: &str| i64::from_str_radix(&s.replace("_", ""), 8))
.message("While parsing an octal Integer")
});
// bin-int = "0b" digit0-1 *( digit0-1 / _ digit0-1 )
parse!(parse_binary_integer() -> i64, {
string("0b").with(
recognize((
satisfy(|c: char| c.is_digit(0x2)),
skip_many((
optional(char('_')),
skip_many1(satisfy(|c: char| c.is_digit(0x2))),
)),
).map(|t| t.0)
)).and_then(|s: &str| i64::from_str_radix(&s.replace("_", ""), 2))
.message("While parsing a binary Integer")
});
// ;; Float
// frac = decimal-point zero-prefixable-int
// decimal-point = %x2E ; .
// zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT )
parse!(frac() -> &'a str, {
recognize((
char('.'),
skip_many1(digit()),
skip_many((
optional(char('_')),
skip_many1(digit()),
)),
))
});
// exp = e integer
// e = %x65 / %x45 ; e E
parse!(exp() -> &'a str, {
recognize((
one_of("eE".chars()),
parse_integer(),
))
});
// float = integer ( frac / ( frac exp ) / exp )
parse!(parse_float() -> &'a str, {
recognize((
attempt((parse_integer(), look_ahead(one_of("eE.".chars())))),
choice((
exp(),
(
frac(),
optional(exp()),
).map(|_| "")
)),
))
});
parse!(float() -> f64, {
parse_float()
.and_then(|s| s.replace("_", "").parse())
.message("While parsing a Float")
});