13 changed files with 416 additions and 208 deletions
@ -1,7 +1,3 @@
|
||||
mod parser; |
||||
|
||||
pub use self::{ |
||||
parser::Datum, |
||||
}; |
||||
pub mod parser; |
||||
|
||||
// EOF
|
||||
|
@ -0,0 +1,69 @@
|
||||
use super::{space::{eof, line_ending, not_line_ending}, IResult}; |
||||
use nom::{ |
||||
branch::alt, |
||||
bytes::complete::tag, |
||||
character::complete::{anychar, char}, |
||||
combinator::recognize, |
||||
multi::many_till, |
||||
sequence::{pair, tuple}, |
||||
}; |
||||
|
||||
pub fn line(inp: &str) -> IResult<&str, &str> { |
||||
// <line comment> ->
|
||||
// | `;' <not line ending>* <line ending>
|
||||
recognize(tuple((char(';'), not_line_ending, alt((line_ending, eof)))))(inp) |
||||
} |
||||
|
||||
pub fn block(inp: &str) -> IResult<&str, &str> { |
||||
// <block comment> ->
|
||||
// | `#|' <block comment inner>* `|#'
|
||||
|
||||
// <block comment inner> ->
|
||||
// | <not `|#'>
|
||||
// | <block comment>
|
||||
recognize(pair( |
||||
tag("#|"), |
||||
many_till(alt((block, recognize(anychar))), tag("|#")), |
||||
))(inp) |
||||
} |
||||
|
||||
pub fn datum(inp: &str) -> IResult<&str, &str> { |
||||
// <datum comment> -> `#;' <datum>
|
||||
recognize(pair(tag("#;"), super::datum::parse))(inp) |
||||
} |
||||
|
||||
pub fn any(inp: &str) -> IResult<&str, &str> { |
||||
// <comment> ->
|
||||
// | <line comment>
|
||||
// | <block comment>
|
||||
// | <datum comment>
|
||||
alt((line, block, datum))(inp) |
||||
} |
||||
|
||||
#[test] |
||||
fn line_test() { |
||||
use nom::error::ErrorKind; |
||||
let inp = "; test"; |
||||
assert_eq!(line(inp), Ok(("", inp))); |
||||
let inp = "; test\n\r\n\r\n"; |
||||
assert_eq!(line(inp), Ok(("", inp))); |
||||
let inp = " test\n\r\n\r\n"; |
||||
assert!(line(inp).is_err()); |
||||
} |
||||
|
||||
#[test] |
||||
fn block_test() { |
||||
use nom::error::ErrorKind; |
||||
let inp = "#| test |#"; |
||||
assert_eq!(block(inp), Ok(("", inp))); |
||||
let inp = "#| #| test |# |#"; |
||||
assert_eq!(block(inp), Ok(("", inp))); |
||||
let inp = "#test |# |#"; |
||||
assert!(block(inp).is_err()); |
||||
let inp = "#| test #"; |
||||
assert!(block(inp).is_err()); |
||||
} |
||||
|
||||
// TODO: datum test
|
||||
|
||||
// EOF
|
@ -0,0 +1,53 @@
|
||||
use super::IResult; |
||||
use nom::{ |
||||
branch::alt, |
||||
combinator::all_consuming, |
||||
error::VerboseError, |
||||
multi::many0, |
||||
sequence::delimited, |
||||
}; |
||||
|
||||
#[derive(Debug, PartialEq)] |
||||
pub enum Datum { |
||||
BoolF, |
||||
BoolT, |
||||
Chara(char), |
||||
Integ(i64), |
||||
Listv(Box<Datum>, Box<Datum>), |
||||
Nullv, |
||||
Strng(String), |
||||
Symbl(String), |
||||
} |
||||
|
||||
impl Datum { |
||||
pub fn parse(inp: &str) -> Result<Vec<Self>, nom::Err<VerboseError<&str>>> { |
||||
match all_consuming(many0(self::parse))(inp) { |
||||
Ok((_, data)) => Ok(data), |
||||
Err(res) => Err(res), |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn parse(inp: &str) -> IResult<&str, Datum> { |
||||
// <datum> ->
|
||||
// | <boolean>
|
||||
// | <character>
|
||||
// | <symbol>
|
||||
// | <string>
|
||||
// | <integer>
|
||||
// | <list>
|
||||
delimited( |
||||
super::space::any0, |
||||
alt(( |
||||
super::boolv::parse, |
||||
super::chara::parse, |
||||
super::symbl::parse, |
||||
super::strng::parse, |
||||
super::integ::parse, |
||||
super::listv::parse, |
||||
)), |
||||
super::space::any0, |
||||
)(inp) |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,56 @@
|
||||
use super::IResult; |
||||
use nom::{ |
||||
branch::alt, |
||||
bytes::complete::{is_a, is_not}, |
||||
combinator::recognize, |
||||
error::{ErrorKind, VerboseErrorKind}, |
||||
multi::many0_count, |
||||
sequence::terminated, |
||||
}; |
||||
|
||||
fn space(inp: &str) -> IResult<&str, &str> { |
||||
// <space> -> <U+9> ... <U+D> | <U+20>
|
||||
is_a("\x09\x0a\x0b\x0c\x0d\x20")(inp) |
||||
} |
||||
|
||||
pub fn line_ending(inp: &str) -> IResult<&str, &str> { |
||||
// <line ending> -> <U+A> | <U+D> | <end of file>
|
||||
is_a("\x0a\x0d")(inp) |
||||
} |
||||
|
||||
pub fn not_line_ending(inp: &str) -> IResult<&str, &str> { |
||||
is_not("\x0a\x0d")(inp) |
||||
} |
||||
|
||||
fn any(inp: &str) -> IResult<&str, &str> { |
||||
// <any space kind> ->
|
||||
// | <space>
|
||||
// | <line ending>
|
||||
// | <comment>
|
||||
alt((space, line_ending, super::cment::any))(inp) |
||||
} |
||||
|
||||
pub fn any0(inp: &str) -> IResult<&str, &str> { |
||||
// <any space> -> <any space kind>*
|
||||
alt((eof, recognize(many0_count(any))))(inp) |
||||
} |
||||
|
||||
pub fn delim<'a, F, O>(mid: F) -> impl Fn(&'a str) -> IResult<&'a str, O> |
||||
where |
||||
F: Fn(&'a str) -> IResult<&'a str, O>, |
||||
{ |
||||
terminated(mid, any0) |
||||
} |
||||
|
||||
pub fn eof(inp: &str) -> IResult<&str, &str> { |
||||
// <end of file>
|
||||
if inp.is_empty() { |
||||
Ok((inp, inp)) |
||||
} else { |
||||
Err(nom::Err::Error(nom::error::VerboseError { |
||||
errors: vec![(inp, VerboseErrorKind::Nom(ErrorKind::Eof))], |
||||
})) |
||||
} |
||||
} |
||||
|
||||
// EOF
|
@ -0,0 +1,54 @@
|
||||
use super::{space, IResult}; |
||||
use nom::{ |
||||
branch::alt, |
||||
character::complete::char, |
||||
combinator::{cut, peek, recognize}, |
||||
sequence::terminated, |
||||
}; |
||||
|
||||
pub fn brk1o(inp: &str) -> IResult<&str, char> { |
||||
space::delim(char('('))(inp) |
||||
} |
||||
|
||||
pub fn brk1c(inp: &str) -> IResult<&str, char> { |
||||
space::delim(char(')'))(inp) |
||||
} |
||||
|
||||
pub fn brk3o(inp: &str) -> IResult<&str, char> { |
||||
space::delim(char('['))(inp) |
||||
} |
||||
|
||||
pub fn brk3c(inp: &str) -> IResult<&str, char> { |
||||
space::delim(char(']'))(inp) |
||||
} |
||||
|
||||
pub fn dotls(inp: &str) -> IResult<&str, char> { |
||||
delim(char('.'))(inp) |
||||
} |
||||
|
||||
pub fn delim<'a, F, O>(mid: F) -> impl Fn(&'a str) -> IResult<&'a str, O> |
||||
where |
||||
F: Fn(&'a str) -> IResult<&'a str, O>, |
||||
{ |
||||
// <* any> ->
|
||||
// | <any> <delimiter (not token yet)>
|
||||
// | <any> <any space>
|
||||
// <delimiter> -> `(' | `)' | `[' | `]' | `"' | `#'
|
||||
terminated( |
||||
mid, |
||||
cut(alt(( |
||||
space::eof, |
||||
space::any0, |
||||
peek(recognize(alt(( |
||||
char('('), |
||||
char(')'), |
||||
char('['), |
||||
char(']'), |
||||
char('"'), |
||||
char('#'), |
||||
)))), |
||||
))), |
||||
) |
||||
} |
||||
|
||||
// EOF
|
Loading…
Reference in new issue