Compare commits

..

10 Commits

16 changed files with 842 additions and 506 deletions

View File

@@ -9,7 +9,9 @@ use crate::combinators::left_right_parsers::{LeftParser, RightParser};
use crate::combinators::many_parsers::{
Many1Parser, Many1TillParser, ManyParser, ManyTillParser, Skip1Parser, SkipParser,
};
use crate::combinators::separated_parsers::{SeparateBy1Parser, SeparateOrEndBy1Parser};
use crate::combinators::separated_parsers::{
QuoteParser, SeparateBy1Parser, SeparateOrEndBy1Parser,
};
use crate::combinators::tuple_parser::{ParserTuple, TupleParser};
use crate::parser::{any, Parser};
use std::fmt::Debug;
@@ -190,7 +192,13 @@ where
PLeft: Parser<'a, TToken, TLeft, TContext>,
PRight: Parser<'a, TToken, TRight, TContext>,
{
left.right(parser.many_till(right))
QuoteParser {
left,
parser,
right,
left_data: PhantomData,
right_data: PhantomData,
}
}
pub fn separate_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
@@ -219,7 +227,7 @@ where
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{
separate_by1(parser, separator).next(|r| match r {
Err((input, _)) => Ok((input, vec![])),
Err(r) => Ok((r.input(), vec![])),
r => r,
})
}
@@ -274,7 +282,7 @@ where
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{
separate_or_end_by1(parser, separator).next(|r| match r {
Err((i, _)) => Ok((i, vec![])),
Err(r) => Ok((r.input(), vec![])),
r => r,
})
}

View File

@@ -17,7 +17,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
match self.first.parse(context.clone(), input) {
@@ -38,7 +38,7 @@ mod test {
#[test]
fn alternate_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, char> {
char_parser('a')
@@ -47,35 +47,35 @@ mod test {
.parse(context, input)
}
parser_test_helper(ParserContext::new_with_str("a", ()), &'a', parser);
parser_test_helper(ParserContext::new_with_str("b", ()), &'b', parser);
parser_test_helper(ParserContext::new_with_str("c", ()), &'c', parser);
parser_test_helper("a", &'a', parser);
parser_test_helper("b", &'b', parser);
parser_test_helper("c", &'c', parser);
}
#[test]
fn alternate_macro_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, char> {
alternate!(char_parser('a'), char_parser('b'), char_parser('c')).parse(context, input)
}
parser_test_helper(ParserContext::new_with_str("a", ()), &'a', parser);
parser_test_helper(ParserContext::new_with_str("b", ()), &'b', parser);
parser_test_helper(ParserContext::new_with_str("c", ()), &'c', parser);
parser_test_helper("a", &'a', parser);
parser_test_helper("b", &'b', parser);
parser_test_helper("c", &'c', parser);
}
#[test]
fn alternate_function_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, char> {
alternate!(char_parser('a'), char_parser('b')).parse(context, input)
}
parser_test_helper(ParserContext::new_with_str("a", ()), &'a', |c, i| {
parser_test_helper("a", &'a', |c, i| {
let parser = alternate!(parser, char_parser('c'));
let parser = alternate!(parser, char_parser('d'));
parser.parse(c, i)
@@ -85,27 +85,23 @@ mod test {
#[test]
fn alternate_pure_function_test() {
fn parser1(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, &[char]> {
alternate!(char_parser('a').literal(), char_parser('b').literal()).parse(context, input)
}
fn parser2(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, &[char]> {
alternate!(char_parser('c').literal(), char_parser('d').literal()).parse(context, input)
}
parser_test_helper(
ParserContext::new_with_str("a", ()),
&"a".to_owned(),
|c, i| {
parser_test_helper("a", &"a".to_owned(), |c, i| {
alternate!(parser1, parser2)
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
});
}
}

View File

@@ -19,7 +19,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
let (input, r) = self.left_parser.parse(context.clone(), input)?;
@@ -46,7 +46,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TRight> {
let (input, _) = self.left_parser.parse(context.clone(), input)?;
@@ -58,19 +58,19 @@ where
#[cfg(test)]
mod test {
use crate::combinators::ParserExt;
use crate::parser::{parser_test_helper, Parser, ParserContext};
use crate::parser::{parser_test_helper, Parser};
use crate::text::char_parser;
#[test]
fn left_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
parser_test_helper("abc", &'a', |c, i| {
char_parser('a').left(char_parser('b')).parse(c, i)
});
}
#[test]
fn right_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'b', |c, i| {
parser_test_helper("abc", &'b', |c, i| {
char_parser('a').right(char_parser('b')).parse(c, i)
})
}

View File

@@ -15,7 +15,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let mut result = vec![];
@@ -41,7 +41,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let (mut input, first_result) = self.parser.parse(context.clone(), input)?;
@@ -68,7 +68,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, ()> {
let mut input = input;
@@ -93,7 +93,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, ()> {
let (mut input, _) = self.parser.parse(context.clone(), input)?;
@@ -121,7 +121,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let mut input = input;
@@ -136,9 +136,9 @@ where
input = i;
result.push(r);
} else {
return Err((
return Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new("End with other elements.".to_owned()),
"End with other elements.",
));
}
}
@@ -159,7 +159,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let (mut input, r) = self.parser.parse(context.clone(), input)?;
@@ -174,9 +174,9 @@ where
result.push(r);
input = i;
} else {
return Err((
return Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new("End with other elements.".to_owned()),
"End with other elements.",
));
}
}
@@ -192,130 +192,112 @@ mod test {
#[test]
fn many_test() {
parser_test_helper(
ParserContext::new_with_str("aaa", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many().parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("aaabbaa", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many().parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("bbaa", ()), &vec![], |c, i| {
parser_test_helper("aaa", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many().parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("", ()), &vec![], |c, i| {
parser_test_helper("aaabbaa", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many().parse(c, i)
});
parser_test_helper("bbaa", &vec![], |c, i| char_parser('a').many().parse(c, i));
parser_test_helper("", &vec![], |c, i| char_parser('a').many().parse(c, i));
}
#[test]
fn many1_test() {
parser_test_helper(
ParserContext::new_with_str("aaa", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many1().parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("aaabbaa", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many1().parse(c, i),
);
failed_parser_test_helper(ParserContext::new_with_str("bbaa", ()), |c, i| {
parser_test_helper("aaa", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many1().parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("", ()), |c, i| {
parser_test_helper("aaabbaa", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many1().parse(c, i)
});
failed_parser_test_helper("bbaa", |c, i| char_parser('a').many1().parse(c, i));
failed_parser_test_helper("baa", |c, i| char_parser('a').many1().parse(c, i));
}
#[test]
fn skip_test() {
parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| {
parser_test_helper("aaab", &'b', |c, i| {
char_parser('a').skip().right(char_parser('b')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("b", ()), &'b', |c, i| {
parser_test_helper("b", &'b', |c, i| {
char_parser('a').skip().right(char_parser('b')).parse(c, i)
});
}
#[test]
fn skip1_test() {
parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| {
parser_test_helper("aaab", &'b', |c, i| {
char_parser('a').skip1().right(char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
failed_parser_test_helper("b", |c, i| {
char_parser('a').skip1().right(char_parser('b')).parse(c, i)
});
}
#[test]
fn many_till_test() {
parser_test_helper(
ParserContext::new_with_str("aaab", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many_till(char_parser('b')).parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("b", ()), &vec![], |c, i| {
parser_test_helper("aaab", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many_till(char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| {
parser_test_helper("b", &vec![], |c, i| {
char_parser('a').many_till(char_parser('b')).parse(c, i)
});
parser_test_helper("aaabc", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a')
.many_till(char_parser('b'))
.left(char_parser('b'))
.left(char_parser('c'))
.parse(c, i)
});
failed_parser_test_helper("aaacb", |c, i| {
char_parser('a').many_till(char_parser('b')).parse(c, i)
});
}
#[test]
fn many1_till_test() {
parser_test_helper(
ParserContext::new_with_str("aaab", ()),
&vec!['a', 'a', 'a'],
|c, i| char_parser('a').many1_till(char_parser('b')).parse(c, i),
);
failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
parser_test_helper("aaab", &vec!['a', 'a', 'a'], |c, i| {
char_parser('a').many1_till(char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| {
failed_parser_test_helper("b", |c, i| {
char_parser('a').many1_till(char_parser('b')).parse(c, i)
});
failed_parser_test_helper("aaacb", |c, i| {
char_parser('a').many1_till(char_parser('b')).parse(c, i)
});
}
#[test]
fn take_till_test() {
parser_test_helper(
ParserContext::new_with_str("aaab", ()),
&(vec!['a', 'a', 'a'], 'b'),
|c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i),
);
parser_test_helper("aaab", &(vec!['a', 'a', 'a'], 'b'), |c, i| {
tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("b", ()),
&(vec![], 'b'),
|c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i),
);
parser_test_helper("b", &(vec![], 'b'), |c, i| {
tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i)
});
}
#[test]
fn take1_till_test() {
parser_test_helper(
ParserContext::new_with_str("aaab", ()),
&(vec!['a', 'a', 'a'], 'b'),
|c, i| tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i),
);
parser_test_helper("aaab", &(vec!['a', 'a', 'a'], 'b'), |c, i| {
tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
failed_parser_test_helper("b", |c, i| {
tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i)
});
}

View File

@@ -1,9 +1,60 @@
use crate::parser::{Parser, ParserContext, ParserResult};
use crate::parser::{FailedParserResult, Parser, ParserContext, ParserResult};
use std::cell::RefCell;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::rc::Rc;
pub struct QuoteParser<P, PLeft, PRight, TLeft, TRight> {
pub(crate) parser: P,
pub(crate) left: PLeft,
pub(crate) right: PRight,
pub(crate) left_data: PhantomData<TLeft>,
pub(crate) right_data: PhantomData<TRight>,
}
impl<'a, TToken, T: 'a, TLeft: 'a, TRight: 'a, TContext, P, PLeft, PRight>
Parser<'a, TToken, Vec<T>, TContext> for QuoteParser<P, PLeft, PRight, TLeft, TRight>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
PLeft: Parser<'a, TToken, TLeft, TContext>,
PRight: Parser<'a, TToken, TRight, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let (mut input, _) = match self.left.parse(context.clone(), input) {
Err(r) => Err(FailedParserResult::new(
r.input(),
format!("Failed to parse left quote: {}", r.message()),
)),
r => r,
}?;
let mut result = vec![];
loop {
if let Ok((i, _)) = self.right.parse(context.clone(), input) {
input = i;
break;
}
if let Ok((i, r)) = self.parser.parse(context.clone(), input) {
input = i;
result.push(r);
} else {
return Err(FailedParserResult::new_with_str(
input,
"Quote without the right quote.",
));
}
}
Ok((input, result))
}
}
pub struct SeparateBy1Parser<P, PSeparator, TSeparator> {
pub(crate) parser: P,
pub(crate) separator: PSeparator,
@@ -19,7 +70,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let (mut input, first) = self.parser.parse(context.clone(), input)?;
@@ -54,7 +105,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<T>> {
let (mut input, first) = self.parser.parse(context.clone(), input)?;
@@ -82,6 +133,7 @@ mod test {
use super::*;
use crate::combinators::{
end_by, end_by1, quote, separate_by, separate_by1, separate_or_end_by, separate_or_end_by1,
ParserExt,
};
use crate::parser::{failed_parser_test_helper, parser_test_helper, satisfy};
use crate::text::char_parser;
@@ -89,7 +141,7 @@ mod test {
#[test]
fn quote_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, Vec<char>> {
quote(
@@ -100,140 +152,112 @@ mod test {
.parse(context, input)
}
parser_test_helper(
ParserContext::new_with_str("'abc'", ()),
&vec!['a', 'b', 'c'],
parser,
);
parser_test_helper(ParserContext::new_with_str("''", ()), &vec![], parser);
failed_parser_test_helper(ParserContext::new_with_str("asd", ()), parser)
parser_test_helper("'abc'", &vec!['a', 'b', 'c'], parser);
parser_test_helper("''", &vec![], parser);
failed_parser_test_helper("asd", parser);
parser_test_helper("'a'b", &vec!['a'], |c, i| {
quote(char_parser('\''), char_parser('a'), char_parser('\''))
.left(char_parser('b'))
.parse(c, i)
})
}
#[test]
fn separate_by1_test() {
parser_test_helper(
ParserContext::new_with_str("a,b,c", ()),
&vec!['a', 'b', 'c'],
|c, i| separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("a", ()), &vec!['a'], |c, i| {
parser_test_helper("a,b,c", &vec!['a', 'b', 'c'], |c, i| {
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper("a", &vec!['a'], |c, i| {
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper("bbc", &vec!['b'], |c, i| {
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("bbc", ()),
&vec!['b'],
|c, i| separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
}
#[test]
fn separate_by_test() {
parser_test_helper(
ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'],
|c, i| separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
parser_test_helper("1,2,3", &vec!['1', '2', '3'], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("", ()), &vec![], |c, i| {
parser_test_helper("1", &vec!['1'], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper("", &vec![], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper("abc", &vec!['a'], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a'],
|c, i| separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
}
#[test]
fn end_by1_test() {
parser_test_helper(
ParserContext::new_with_str("aab", ()),
&vec!['a', 'a'],
|c, i| end_by1(char_parser('a'), char_parser('b')).parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("ab", ()), &vec!['a'], |c, i| {
parser_test_helper("aab", &vec!['a', 'a'], |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
parser_test_helper("ab", &vec!['a'], |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("cd", ()), |c, i| {
failed_parser_test_helper("b", |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper("cd", |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
}
#[test]
fn end_by_test() {
parser_test_helper(
ParserContext::new_with_str("aab", ()),
&vec!['a', 'a'],
|c, i| end_by(char_parser('a'), char_parser('b')).parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("ab", ()), &vec!['a'], |c, i| {
parser_test_helper("aab", &vec!['a', 'a'], |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("b", ()), &vec![], |c, i| {
parser_test_helper("ab", &vec!['a'], |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("cd", ()), |c, i| {
parser_test_helper("b", &vec![], |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper("cd", |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
}
#[test]
fn separate_or_end_by1_test() {
parser_test_helper(
ParserContext::new_with_str("1,2,3,", ()),
&vec!['1', '2', '3'],
|c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(','))
.parse(c, i)
},
);
parser_test_helper(ParserContext::new_with_str("1,", ()), &vec!['1'], |c, i| {
parser_test_helper("1,2,3,", &vec!['1', '2', '3'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'],
|c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(','))
.parse(c, i)
},
);
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
parser_test_helper("1,", &vec!['1'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
parser_test_helper("1,2,3", &vec!['1', '2', '3'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper("1", &vec!['1'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
failed_parser_test_helper("abc", |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
}
#[test]
fn separate_or_end_by_test() {
parser_test_helper(
ParserContext::new_with_str("1,2,3,", ()),
&vec!['1', '2', '3'],
|c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
},
);
parser_test_helper(ParserContext::new_with_str("1,", ()), &vec!['1'], |c, i| {
parser_test_helper("1,2,3,", &vec!['1', '2', '3'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'],
|c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
},
);
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
parser_test_helper("1", &vec!['1'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("abc", ()), &vec![], |c, i| {
parser_test_helper("1,2,3", &vec!['1', '2', '3'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper("1,", &vec!['1'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper("abc", &vec![], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
}

View File

@@ -9,7 +9,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T>;
}
@@ -25,7 +25,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
self.parser.parse(context, input)
@@ -41,7 +41,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
@@ -61,7 +61,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
@@ -83,7 +83,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3, T4)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
@@ -107,7 +107,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3, T4, T5)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
@@ -120,6 +120,146 @@ where
}
}
impl<
'a,
TToken,
T1: 'a,
T2: 'a,
T3: 'a,
T4: 'a,
T5: 'a,
T6: 'a,
TContext,
P1,
P2,
P3,
P4,
P5,
P6,
> ParserTuple<'a, TToken, (T1, T2, T3, T4, T5, T6), TContext> for (P1, P2, P3, P4, P5, P6)
where
TToken: Debug + Clone,
P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<'a, TToken, T3, TContext>,
P4: Parser<'a, TToken, T4, TContext>,
P5: Parser<'a, TToken, T5, TContext>,
P6: Parser<'a, TToken, T6, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3, T4, T5, T6)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
let (input, r2) = self.1.parse(context.clone(), input)?;
let (input, r3) = self.2.parse(context.clone(), input)?;
let (input, r4) = self.3.parse(context.clone(), input)?;
let (input, r5) = self.4.parse(context.clone(), input)?;
let (input, r6) = self.5.parse(context.clone(), input)?;
Ok((input, (r1, r2, r3, r4, r5, r6)))
}
}
impl<
'a,
TToken,
T1: 'a,
T2: 'a,
T3: 'a,
T4: 'a,
T5: 'a,
T6: 'a,
T7: 'a,
TContext,
P1,
P2,
P3,
P4,
P5,
P6,
P7,
> ParserTuple<'a, TToken, (T1, T2, T3, T4, T5, T6, T7), TContext>
for (P1, P2, P3, P4, P5, P6, P7)
where
TToken: Debug + Clone,
P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<'a, TToken, T3, TContext>,
P4: Parser<'a, TToken, T4, TContext>,
P5: Parser<'a, TToken, T5, TContext>,
P6: Parser<'a, TToken, T6, TContext>,
P7: Parser<'a, TToken, T7, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3, T4, T5, T6, T7)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
let (input, r2) = self.1.parse(context.clone(), input)?;
let (input, r3) = self.2.parse(context.clone(), input)?;
let (input, r4) = self.3.parse(context.clone(), input)?;
let (input, r5) = self.4.parse(context.clone(), input)?;
let (input, r6) = self.5.parse(context.clone(), input)?;
let (input, r7) = self.6.parse(context.clone(), input)?;
Ok((input, (r1, r2, r3, r4, r5, r6, r7)))
}
}
impl<
'a,
TToken,
T1: 'a,
T2: 'a,
T3: 'a,
T4: 'a,
T5: 'a,
T6: 'a,
T7: 'a,
T8: 'a,
TContext,
P1,
P2,
P3,
P4,
P5,
P6,
P7,
P8,
> ParserTuple<'a, TToken, (T1, T2, T3, T4, T5, T6, T7, T8), TContext>
for (P1, P2, P3, P4, P5, P6, P7, P8)
where
TToken: Debug + Clone,
P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<'a, TToken, T3, TContext>,
P4: Parser<'a, TToken, T4, TContext>,
P5: Parser<'a, TToken, T5, TContext>,
P6: Parser<'a, TToken, T6, TContext>,
P7: Parser<'a, TToken, T7, TContext>,
P8: Parser<'a, TToken, T8, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, (T1, T2, T3, T4, T5, T6, T7, T8)> {
let (input, r1) = self.0.parse(context.clone(), input)?;
let (input, r2) = self.1.parse(context.clone(), input)?;
let (input, r3) = self.2.parse(context.clone(), input)?;
let (input, r4) = self.3.parse(context.clone(), input)?;
let (input, r5) = self.4.parse(context.clone(), input)?;
let (input, r6) = self.5.parse(context.clone(), input)?;
let (input, r7) = self.6.parse(context.clone(), input)?;
let (input, r8) = self.7.parse(context.clone(), input)?;
Ok((input, (r1, r2, r3, r4, r5, r6, r7, r8)))
}
}
#[cfg(test)]
mod test {
use super::*;
@@ -129,22 +269,15 @@ mod test {
#[test]
fn tuple_test() {
parser_test_helper(
ParserContext::new_with_str("ab", ()),
&('a', 'b'),
|c, i| tuple((char_parser('a'), char_parser('b'))).parse(c, i),
);
parser_test_helper("ab", &('a', 'b'), |c, i| {
tuple((char_parser('a'), char_parser('b'))).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&('a', 'b', 'c'),
|c, i| tuple((char_parser('a'), char_parser('b'), char_parser('c'))).parse(c, i),
);
parser_test_helper("abc", &('a', 'b', 'c'), |c, i| {
tuple((char_parser('a'), char_parser('b'), char_parser('c'))).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("abcd", ()),
&('a', 'b', 'c', 'd'),
|c, i| {
parser_test_helper("abcd", &('a', 'b', 'c', 'd'), |c, i| {
tuple((
char_parser('a'),
char_parser('b'),
@@ -152,7 +285,6 @@ mod test {
char_parser('d'),
))
.parse(c, i)
},
);
});
}
}

View File

@@ -2,72 +2,74 @@ mod modified_parsers;
mod primitive_parsers;
use crate::parser::modified_parsers::{
BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
NextParser, ReverseParser,
AndThenParser, BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser,
MapParser, NextParser, OptionalParser, ReverseParser, RunParser, TryParser,
};
use crate::parser::primitive_parsers::{
AnyParser, FailParser, FailWithMessageParser, SatisfyParser, SkipParser, SucceedParser,
TakeParser,
AnyParser, FailParser, FailWithMessageParser, SatifiedMapParser, SatisfyParser, SkipParser,
SucceedParser, TakeParser,
};
use std::cell::RefCell;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::marker::PhantomData;
use std::rc::Rc;
#[derive(Debug)]
pub struct FailedParserResult {
pub struct FailedParserResult<'a, TToken: Debug> {
input: &'a [TToken],
message: String,
}
impl FailedParserResult {
pub fn new(message: String) -> Self {
Self { message }
impl<'a, TToken: Debug> FailedParserResult<'a, TToken> {
pub fn new(input: &'a [TToken], message: String) -> Self {
Self { input, message }
}
pub fn new_with_str(input: &'a [TToken], message: &'static str) -> Self {
Self {
input,
message: message.to_owned(),
}
}
pub fn new_with_error(input: &'a [TToken], err: anyhow::Error) -> Self {
Self {
input,
message: format!("{}", err),
}
}
pub fn message(&self) -> &str {
self.message.as_str()
}
pub fn input(&self) -> &'a [TToken] {
self.input
}
}
impl Display for FailedParserResult {
impl<'a, TToken: Debug> Error for FailedParserResult<'a, TToken> {}
impl<'a, TToken: Debug> Display for FailedParserResult<'a, TToken> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Parse failed: {}.", self.message)
write!(
f,
"Parse failed: {}, the input is '{:?}'.",
self.message, self.input
)
}
}
pub type ParserResult<'a, TToken, T> =
Result<(&'a [TToken], T), (&'a [TToken], FailedParserResult)>;
pub type ParserResult<'a, TToken, T> = Result<(&'a [TToken], T), FailedParserResult<'a, TToken>>;
pub struct ParserContext<TToken, TContext>
where
TToken: Debug + Clone,
{
pub struct ParserContext<TContext> {
pub context: TContext,
input_array: Vec<TToken>,
}
impl<TToken, TContext> ParserContext<TToken, TContext>
where
TToken: Debug + Clone,
{
pub fn new(input: &[TToken], context: TContext) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
input_array: input.iter().map(|x| x.clone()).collect(),
context,
}))
}
pub fn input_slice(&self) -> &[TToken] {
self.input_array.as_slice()
}
}
impl<TContext> ParserContext<char, TContext> {
pub fn new_with_str(input: &str, context: TContext) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
input_array: input.chars().collect(),
context,
}))
impl<TContext> ParserContext<TContext> {
pub fn new(context: TContext) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self { context }))
}
}
@@ -78,7 +80,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T>;
@@ -160,6 +162,17 @@ where
}
}
fn try_parse(self, result: T) -> TryParser<Self, T>
where
Self: Sized,
T: Clone,
{
TryParser {
parser: self,
result,
}
}
fn reverse<TResult>(self, result: TResult) -> ReverseParser<Self, T, TResult>
where
Self: Sized,
@@ -171,19 +184,46 @@ where
phantom_data: PhantomData,
}
}
fn optional(self) -> OptionalParser<Self>
where
Self: Sized,
{
OptionalParser { parser: self }
}
fn run<F>(self, action: F) -> RunParser<Self, F>
where
Self: Sized,
F: Fn(&T) -> (),
{
RunParser {
parser: self,
action,
}
}
fn and_then<TResult, F>(self, mapper: F) -> AndThenParser<Self, F, T>
where
Self: Sized,
F: Fn(T) -> anyhow::Result<TResult>,
{
AndThenParser {
parser: self,
mapper,
phantom_data: PhantomData,
}
}
}
impl<'a, TToken, T: 'a, TContext, F> Parser<'a, TToken, T, TContext> for F
where
TToken: Debug + Clone + 'a,
F: Fn(
Rc<RefCell<ParserContext<TToken, TContext>>>,
&'a [TToken],
) -> ParserResult<'a, TToken, T>,
F: Fn(Rc<RefCell<ParserContext<TContext>>>, &'a [TToken]) -> ParserResult<'a, TToken, T>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
(*self)(context, input)
@@ -197,7 +237,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
(**self).parse(context, input)
@@ -241,6 +281,16 @@ where
SatisfyParser { predicate }
}
pub fn satified_map<'a, TToken, TContext, T: 'a, F>(
mapper: F,
) -> impl Parser<'a, TToken, T, TContext>
where
TToken: Debug + Clone,
F: Fn(&TToken) -> Option<T>,
{
SatifiedMapParser { mapper }
}
pub fn any<'a, TToken, TContext>() -> impl Parser<'a, TToken, TToken, TContext>
where
TToken: Debug + Clone + 'a,
@@ -263,32 +313,27 @@ where
}
#[cfg(test)]
pub fn parser_test_helper<T, P>(
context: Rc<RefCell<ParserContext<char, ()>>>,
excepted_node: &T,
test_parser: P,
) where
pub fn parser_test_helper<T, P>(input: &str, excepted_node: &T, test_parser: P)
where
T: PartialEq + Debug,
P: for<'a> Fn(Rc<RefCell<ParserContext<char, ()>>>, &'a [char]) -> ParserResult<'a, char, T>,
P: for<'a> Fn(Rc<RefCell<ParserContext<()>>>, &'a [char]) -> ParserResult<'a, char, T>,
{
let borrowed_context = context.borrow();
let input = borrowed_context.input_slice();
let (_, actual_result) = test_parser.parse(context.clone(), input).unwrap();
let word: Vec<char> = input.chars().collect();
let (_, actual_result) = test_parser
.parse(ParserContext::new(()), word.as_slice())
.unwrap();
assert_eq!(excepted_node, &actual_result);
}
#[cfg(test)]
pub fn failed_parser_test_helper<T, P>(
context: Rc<RefCell<ParserContext<char, ()>>>,
test_parser: P,
) where
pub fn failed_parser_test_helper<T, P>(input: &str, test_parser: P)
where
T: Debug,
P: for<'a> Fn(Rc<RefCell<ParserContext<char, ()>>>, &'a [char]) -> ParserResult<'a, char, T>,
P: for<'a> Fn(Rc<RefCell<ParserContext<()>>>, &'a [char]) -> ParserResult<'a, char, T>,
{
let borrowed_context = context.borrow();
let input = borrowed_context.input_slice();
let result = test_parser.parse(context.clone(), input);
let word: Vec<char> = input.chars().collect();
let result = test_parser.parse(ParserContext::new(()), word.as_slice());
assert!(result.is_err());
}

View File

@@ -19,7 +19,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T2> {
self.parser
@@ -44,7 +44,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T2> {
let (input, middle) = self.parser.parse(context.clone(), input)?;
@@ -68,7 +68,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T2> {
self.parser
@@ -92,7 +92,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TResult> {
let result = self.parser.parse(context, input);
@@ -114,18 +114,16 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, &'a [TToken]> {
let origin_input = input;
let (input, _) = self.parser.parse(context, input)?;
if origin_input.is_empty() {
return Err((
return Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new(
"Empty input, the 'literal' parser cann't get length of elememt.".to_owned(),
),
"Empty input, the 'literal' parser cann't get length of elememt.",
));
}
@@ -149,18 +147,16 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, usize> {
let origin_input = input;
let (input, _) = self.parser.parse(context, input)?;
if origin_input.is_empty() {
return Err((
return Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new(
"Empty input, the 'literal' parser cann't get length of elememt.".to_owned(),
),
"Empty input, the 'literal' parser cann't get length of elememt.",
));
}
@@ -183,7 +179,7 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
let original_input = input;
@@ -193,6 +189,29 @@ where
}
}
pub struct TryParser<P, T> {
pub(crate) parser: P,
pub(crate) result: T,
}
impl<'a, TToken, T, TContext, P> Parser<'a, TToken, T, TContext> for TryParser<P, T>
where
TToken: Debug + Clone,
T: Clone + 'a,
P: Parser<'a, TToken, T, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
match self.parser.parse(context, input) {
Err(r) => Ok((r.input, self.result.clone())),
r => r,
}
}
}
pub struct ReverseParser<P, T, TResult> {
pub(crate) parser: P,
pub(crate) result: TResult,
@@ -208,15 +227,91 @@ where
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TResult> {
match self.parser.parse(context, input) {
Ok((input, _)) => Err((
Ok(_) => Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new("Reverse failed succeeded.".to_owned()),
"Reverse successful parser.",
)),
Err((input, _)) => Ok((input, self.result.clone())),
Err(_) => Ok((input, self.result.clone())),
}
}
}
pub struct OptionalParser<P> {
pub(crate) parser: P,
}
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Option<T>, TContext> for OptionalParser<P>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Option<T>> {
match self.parser.parse(context, input) {
Ok(r) => Ok((r.0, Some(r.1))),
Err(r) => Ok((r.input, None)),
}
}
}
pub struct RunParser<P, F> {
pub(crate) parser: P,
pub(crate) action: F,
}
impl<'a, TToken, T: 'a, TContext, P, F> Parser<'a, TToken, T, TContext> for RunParser<P, F>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
F: Fn(&T) -> (),
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
match self.parser.parse(context, input) {
Ok(r) => {
(self.action)(&r.1);
Ok(r)
}
r => r,
}
}
}
pub struct AndThenParser<P, F, T> {
pub(crate) parser: P,
pub(crate) mapper: F,
pub(crate) phantom_data: PhantomData<T>,
}
impl<'a, TToken, T: 'a, TResult: 'a, TContext, P, F> Parser<'a, TToken, TResult, TContext>
for AndThenParser<P, F, T>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
F: Fn(T) -> anyhow::Result<TResult>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TResult> {
match self.parser.parse(context, input) {
Ok((i, r)) => match (self.mapper)(r) {
Ok(result) => Ok((i, result)),
Err(err) => Err(FailedParserResult::new_with_error(i, err)),
},
Err(r) => Err(r),
}
}
}
@@ -227,24 +322,20 @@ mod test {
use crate::parser::{
failed_parser_test_helper, parser_test_helper, satisfy, take, FailedParserResult,
};
use crate::text::char_parser;
use crate::text::{char_parser, char_satisfy};
#[test]
fn map_test() {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&(),
|c, i| take(5).map(|_| ()).parse(c, i),
)
parser_test_helper("hello, world!", &(), |c, i| take(5).map(|_| ()).parse(c, i))
}
#[test]
fn bind_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'b', |c, i| {
parser_test_helper("abc", &'b', |c, i| {
char_parser('a').bind(|_| char_parser('b')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("abc", ()), &'c', |c, i| {
parser_test_helper("abc", &'c', |c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.bind(|_| char_parser('c'))
@@ -263,30 +354,26 @@ mod test {
#[test]
fn convert_test() {
fn single_numer_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, Number> {
let (input, result) = satisfy(|c: &char| c.is_numeric()).parse(context, input)?;
match result.to_digit(10) {
None => Err((input, FailedParserResult::new("What?".to_string()))),
None => Err(FailedParserResult::new_with_str(input, "What?")),
Some(r) => Ok((input, Number(r as i32))),
}
}
parser_test_helper(
ParserContext::new_with_str("9", ()),
&"9".to_owned(),
|c, i| single_numer_parser.convert().parse(c, i),
);
parser_test_helper("9", &"9".to_owned(), |c, i| {
single_numer_parser.convert().parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("1", ()),
&"1".to_owned(),
|c, i| single_numer_parser.convert().parse(c, i),
);
parser_test_helper("1", &"1".to_owned(), |c, i| {
single_numer_parser.convert().parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
failed_parser_test_helper("abc", |c, i| {
single_numer_parser.convert::<String>().parse(c, i)
});
}
@@ -294,13 +381,13 @@ mod test {
#[test]
fn next_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, Number> {
satisfy(|c: &char| c.is_numeric())
.next(|r| match r {
Ok((input, result)) => match result.to_digit(10) {
None => Err((input, FailedParserResult::new("What?".to_string()))),
None => Err(FailedParserResult::new_with_str(input, "What?")),
Some(r) => Ok((input, Number(r as i32))),
},
Err(r) => Err(r),
@@ -308,65 +395,43 @@ mod test {
.parse(context, input)
}
parser_test_helper(
ParserContext::new_with_str("9", ()),
&"9".to_owned(),
|c, i| parser.convert().parse(c, i),
);
parser_test_helper("9", &"9".to_owned(), |c, i| parser.convert().parse(c, i));
parser_test_helper(
ParserContext::new_with_str("1", ()),
&"1".to_owned(),
|c, i| parser.convert().parse(c, i),
);
parser_test_helper("1", &"1".to_owned(), |c, i| parser.convert().parse(c, i));
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
parser.convert::<String>().parse(c, i)
});
failed_parser_test_helper("abc", |c, i| parser.convert::<String>().parse(c, i));
}
#[test]
fn literal_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a'],
|c, i| {
parser_test_helper("abc", &vec!['a'], |c, i| {
char_parser('a')
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
});
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a', 'b'],
|c, i| {
parser_test_helper("abc", &vec!['a', 'b'], |c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
});
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a', 'b', 'c'],
|c, i| {
parser_test_helper("abc", &vec!['a', 'b', 'c'], |c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.bind(|_| char_parser('c'))
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
});
}
#[test]
fn look_ahead_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
parser_test_helper("abc", &'a', |c, i| {
char_parser('a')
.look_ahead()
.bind(|_| char_parser('a'))
@@ -375,13 +440,47 @@ mod test {
}
#[test]
fn reverse_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
char_parser('b').reverse(()).parse(c, i)
fn try_parse_test() {
parser_test_helper("abc", &'a', |c, i| {
char_parser('a').try_parse('a').parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
char_parser('a').reverse(()).parse(c, i)
parser_test_helper("bc", &'a', |c, i| {
char_parser('a').try_parse('a').parse(c, i)
});
}
#[test]
fn reverse_test() {
parser_test_helper("abc", &(), |c, i| char_parser('b').reverse(()).parse(c, i));
failed_parser_test_helper("abc", |c, i| char_parser('a').reverse(()).parse(c, i));
}
#[test]
fn optional_test() {
parser_test_helper("abc", &Some('a'), |c, i| {
char_parser('a').optional().parse(c, i)
});
parser_test_helper("bc", &None, |c, i| char_parser('a').optional().parse(c, i));
}
#[test]
fn run_test() {
parser_test_helper("abc", &'a', |c, i| {
char_parser('a').run(|c| assert_eq!(c, &'a')).parse(c, i)
})
}
#[test]
fn and_then_test() {
parser_test_helper("123", &1, |c, i| {
char_satisfy(char::is_ascii_digit)
.and_then(|c| {
let word = c.to_string();
Ok(i32::from_str_radix(word.as_str(), 10)?)
})
.parse(c, i)
});
}
}

View File

@@ -15,7 +15,7 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
Ok((input, self.value.clone()))
@@ -32,12 +32,12 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
Err((
Err(FailedParserResult::new_with_str(
input,
FailedParserResult::new("Default failed parser.".to_owned()),
"Default failed parser.",
))
}
}
@@ -53,10 +53,10 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
Err((input, FailedParserResult::new(self.message.clone())))
Err(FailedParserResult::new(input, self.message.clone()))
}
}
@@ -71,20 +71,43 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TToken> {
if input.is_empty() {
return Err((input, FailedParserResult::new("Input is empty.".to_owned())));
return Err(FailedParserResult::new_with_str(input, "Input is empty"));
}
if (self.predicate)(&input[0]) {
Ok((&input[1..], input[0].clone()))
} else {
Err((
input,
FailedParserResult::new("Predicate failed.".to_owned()),
))
Err(FailedParserResult::new_with_str(input, "Predicate failed."))
}
}
}
pub struct SatifiedMapParser<F> {
pub(crate) mapper: F,
}
impl<'a, TToken, TContext, T: 'a, F> Parser<'a, TToken, T, TContext> for SatifiedMapParser<F>
where
TToken: Debug + Clone,
F: Fn(&TToken) -> Option<T>,
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
if input.is_empty() {
return Err(FailedParserResult::new_with_str(input, "Input is empty"));
}
if let Some(result) = (self.mapper)(&input[0]) {
Ok((&input[1..], result))
} else {
Err(FailedParserResult::new_with_str(input, "Predicate failed."))
}
}
}
@@ -97,11 +120,11 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, TToken> {
if input.is_empty() {
Err((input, FailedParserResult::new("Input is empty.".to_owned())))
Err(FailedParserResult::new_with_str(input, "Input is empty"))
} else {
Ok((&input[1..], input[0].clone()))
}
@@ -118,16 +141,16 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<TToken>> {
if input.len() < self.count {
Err((
Err(FailedParserResult::new(
input,
FailedParserResult::new(format!(
format!(
"The input doesn't contain enough {} elemements.",
self.count
)),
),
))
} else {
Ok((
@@ -148,16 +171,16 @@ where
{
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, ()> {
if input.len() < self.count {
Err((
Err(FailedParserResult::new(
input,
FailedParserResult::new(format!(
format!(
"The input doesn't contain enough {} elemements.",
self.count
)),
),
))
} else {
Ok((&input[self.count..], ()))
@@ -169,76 +192,69 @@ where
mod test {
use super::*;
use crate::parser::{
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satisfy, skip,
succeed, take,
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satified_map,
satisfy, skip, succeed, take,
};
#[test]
fn succeed_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
succeed(()).parse(c, i)
});
parser_test_helper("abc", &(), |c, i| succeed(()).parse(c, i));
}
#[test]
fn fail_test() {
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
fail::<char, (), ()>().parse(c, i)
});
failed_parser_test_helper("abc", |c, i| fail::<char, (), ()>().parse(c, i));
}
#[test]
fn fail_with_message_test() {
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
failed_parser_test_helper("abc", |c, i| {
fail_with_message::<char, (), ()>("Failed!").parse(c, i)
});
}
#[test]
fn satisfy_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
satisfy(|x| x == &'a').parse(c, i)
parser_test_helper("abc", &'a', |c, i| satisfy(|x| x == &'a').parse(c, i));
failed_parser_test_helper("abc", |c, i| satisfy(|x| x == &'b').parse(c, i));
}
#[test]
fn satified_map_test() {
parser_test_helper("123", &1, |c, i| {
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
satisfy(|x| x == &'b').parse(c, i)
parser_test_helper("23", &2, |c, i| {
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
});
parser_test_helper("3", &3, |c, i| {
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
});
}
#[test]
fn any_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
any().parse(c, i)
});
parser_test_helper("abc", &'a', |c, i| any().parse(c, i));
parser_test_helper(ParserContext::new_with_str("cde", ()), &'c', |c, i| {
any().parse(c, i)
});
parser_test_helper("cde", &'c', |c, i| any().parse(c, i));
}
#[test]
fn take_test() {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&("hello".chars().collect()),
|c, i| take(5).parse(c, i),
);
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), |c, i| {
parser_test_helper("hello, world!", &("hello".chars().collect()), |c, i| {
take(5).parse(c, i)
});
failed_parser_test_helper("abcd", |c, i| take(5).parse(c, i));
}
#[test]
fn skip_test() {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&(),
|c, i| skip(5).parse(c, i),
);
parser_test_helper("hello, world!", &(), |c, i| skip(5).parse(c, i));
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), |c, i| {
skip(5).parse(c, i)
});
failed_parser_test_helper("abcd", |c, i| skip(5).parse(c, i));
}
}

View File

@@ -1,23 +1,16 @@
use crate::parser::{satisfy, take, FailedParserResult, Parser};
mod string_parsers;
use crate::parser::{satisfy, Parser};
use crate::text::string_parsers::StringParser;
pub fn char_parser<'a, TContext>(c: char) -> impl Parser<'a, char, char, TContext> {
satisfy(move |x| *x == c)
}
pub fn string_parser<'a, TContext>(str: &'static str) -> impl Parser<'a, char, String, TContext> {
take::<char, TContext>(str.chars().count()).next(move |result| {
result.and_then(|(input, chars)| {
let chars: String = chars.iter().collect();
if chars == str {
Ok((input, chars))
} else {
Err((
input,
FailedParserResult::new(format!("Failed to parse '{}'.", str)),
))
}
})
})
pub fn string_parser<'a, TContext>(
str: &'static str,
) -> impl Parser<'a, char, &'a [char], TContext> {
StringParser { str }
}
pub fn one_of<'a, TContext>(str: &'static str) -> impl Parser<'a, char, char, TContext> {
@@ -25,6 +18,13 @@ pub fn one_of<'a, TContext>(str: &'static str) -> impl Parser<'a, char, char, TC
satisfy(move |c: &char| str.contains(c))
}
pub fn char_satisfy<'a, TContext, F>(condition: F) -> impl Parser<'a, char, char, TContext>
where
F: Fn(&char) -> bool,
{
satisfy(move |x: &char| condition(x))
}
#[cfg(test)]
mod test {
use super::*;
@@ -36,44 +36,44 @@ mod test {
#[test]
fn char_parser_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&'a',
|context, input| char_parser('a').parse(context, input),
);
parser_test_helper("abc", &'a', |context, input| {
char_parser('a').parse(context, input)
});
failed_parser_test_helper(ParserContext::new_with_str("bc", ()), |context, input| {
failed_parser_test_helper("bc", |context, input| {
char_parser('a').parse(context, input)
});
}
#[test]
fn string_parser_test() {
parser_test_helper(
ParserContext::new_with_str("Hello, world!", ()),
&"Hello".to_owned(),
|context, input| string_parser("Hello").parse(context, input),
);
parser_test_helper("Hello, world!", &"Hello".to_owned(), |context, input| {
string_parser("Hello")
.map(|x| x.iter().collect())
.parse(context, input)
});
fn test_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, String> {
let (input, first) = string_parser("hello, ").parse(context.clone(), input)?;
let (input, second) = string_parser("world!").parse(context.clone(), input)?;
Ok((input, first + second.as_str()))
Ok((
input,
first.iter().collect::<String>() + second.iter().collect::<String>().as_str(),
))
}
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&"hello, world!".to_owned(),
test_parser,
);
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&(),
|context, input| test_parser.map(|_| ()).parse(context, input),
)
parser_test_helper("hello, world!", &"hello, world!".to_owned(), test_parser);
parser_test_helper("hello, world!", &(), |context, input| {
test_parser.map(|_| ()).parse(context, input)
})
}
#[test]
fn char_satsify_test() {
parser_test_helper("abc", &'a', |c, i| char_satisfy(char::is_ascii).parse(c, i));
}
}

View File

@@ -0,0 +1,37 @@
use crate::parser::{FailedParserResult, Parser, ParserContext, ParserResult};
use std::cell::RefCell;
use std::rc::Rc;
pub struct StringParser {
pub(crate) str: &'static str,
}
impl<'a, TContext> Parser<'a, char, &'a [char], TContext> for StringParser {
fn parse(
&self,
_: Rc<RefCell<ParserContext<TContext>>>,
input: &'a [char],
) -> ParserResult<'a, char, &'a [char]> {
let length = self.str.chars().count();
if input.len() < length {
return Err(FailedParserResult::new(
input,
format!("Failed to get enough elements for string '{}'.", self.str),
));
}
if (&input[..length])
.iter()
.zip(self.str.chars())
.map(|(x, y)| *x == y)
.all(|x| x)
{
Ok((&input[length..], &input[..length]))
} else {
Err(FailedParserResult::new(
input,
format!("Input is not string '{}'", self.str),
))
}
}
}

View File

@@ -75,10 +75,10 @@ fn file_lexical_parser_test() -> anyhow::Result<()> {
let (_, nom_tokens) =
nom_lexical_parser(source_file.content.as_str()).or_else(|e| Err(e.to_owned()))?;
let context = ParserContext::new_with_str(source_file.content.as_str(), ());
let borrowed_context = context.borrow();
let (_, zero_tokens) = zero_lexical_parser(context.clone(), borrowed_context.input_slice())
.or_else(|e| Err(anyhow!("{}", e.1)))?;
let context = ParserContext::new(());
let word: Vec<char> = source_file.content.chars().collect();
let (_, zero_tokens) = zero_lexical_parser(context.clone(), word.as_slice())
.or_else(|e| Err(anyhow!("{}", e)))?;
assert_eq!(nom_tokens.len(), zero_tokens.len());

View File

@@ -5,11 +5,10 @@ use zero_parser::parser::ParserContext;
mod tokenizer;
fn validate_tokens(input: &'static str, tokens: Vec<LexicalTokenType>) {
let context = ParserContext::new_with_str(input, ());
let borrowed_context = context.borrow();
let context = ParserContext::new(());
let word: Vec<char> = input.chars().collect();
let (_, actual_tokens) =
zero_lexical_parser(context.clone(), borrowed_context.input_slice()).unwrap();
let (_, actual_tokens) = zero_lexical_parser(context.clone(), word.as_slice()).unwrap();
dbg!(&tokens, &actual_tokens);
assert_eq!(tokens.len(), actual_tokens.len());

View File

@@ -109,7 +109,7 @@ pub fn nom_lexical_parser(mut input: &str) -> IResult<&str, Vec<LexicalToken>> {
}
pub fn zero_lexical_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
mut input: &[char],
) -> ParserResult<char, Vec<NewLexicalToken>> {
let mut array = vec![];

View File

@@ -9,7 +9,7 @@ use zero_parser::text::{char_parser, one_of, string_parser};
use zero_parser::{alternate, parser::satisfy};
pub fn keyword_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -38,7 +38,7 @@ pub fn keyword_parser(
}
pub fn delimiter_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
alternate!(
@@ -60,7 +60,7 @@ pub fn delimiter_parser(
}
pub fn operator_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
alternate!(
@@ -89,7 +89,7 @@ pub fn operator_parser(
}
pub fn identifier_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -105,7 +105,7 @@ pub fn identifier_parser(
}
pub fn decimal_integer_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -126,7 +126,7 @@ pub fn decimal_integer_parser(
}
pub fn octal_integer_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -147,7 +147,7 @@ pub fn octal_integer_parser(
}
pub fn hexadecimal_integer_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -168,7 +168,7 @@ pub fn hexadecimal_integer_parser(
}
pub fn integer_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
alternate!(
@@ -180,7 +180,7 @@ pub fn integer_parser(
}
pub fn float_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
tuple((
@@ -202,7 +202,7 @@ pub fn float_parser(
}
pub fn literal_string_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
quote(char_parser('"'), any(), char_parser('"'))
@@ -211,14 +211,14 @@ pub fn literal_string_parser(
let length = x.len();
NewLexicalToken {
token_type: LexicalTokenType::LiteralString,
literal_value: &x[1..length],
literal_value: &x[1..length - 1],
}
})
.parse(context, input)
}
pub fn comments_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, ()> {
alternate!(
@@ -239,7 +239,7 @@ pub fn comments_parser(
}
pub fn junk_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, ()> {
alternate!(
@@ -250,7 +250,7 @@ pub fn junk_parser(
}
pub fn combine_parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
context: Rc<RefCell<ParserContext<()>>>,
input: &[char],
) -> ParserResult<char, NewLexicalToken> {
alternate!(

View File

@@ -1,3 +1,5 @@
extern crate core;
use crate::tokenizer::zero_parsers::{
combine_parser, comments_parser, decimal_integer_parser, delimiter_parser, float_parser,
hexadecimal_integer_parser, identifier_parser, integer_parser, keyword_parser,
@@ -13,16 +15,12 @@ mod tokenizer;
fn assert_lexical_parser(
except: LexicalToken,
parser: fn(
Rc<RefCell<ParserContext<char, ()>>>,
&[char],
) -> ParserResult<char, NewLexicalToken>,
parser: fn(Rc<RefCell<ParserContext<()>>>, &[char]) -> ParserResult<char, NewLexicalToken>,
input: &str,
) {
let context = ParserContext::new_with_str(input, ());
let borrowed_context = context.borrow();
let input = borrowed_context.input_slice();
let (_, token) = parser(context.clone(), input).unwrap();
let context = ParserContext::new(());
let word: Vec<char> = input.chars().collect();
let (_, token) = parser(context.clone(), word.as_slice()).unwrap();
assert_eq!(except, token);
}
@@ -30,11 +28,11 @@ fn assert_lexical_parser(
fn assert_parser<T, F>(except: T, parser: F, input: &str)
where
T: PartialEq + Debug,
F: Fn(Rc<RefCell<ParserContext<char, ()>>>, &[char]) -> ParserResult<char, T>,
F: Fn(Rc<RefCell<ParserContext<()>>>, &[char]) -> ParserResult<char, T>,
{
let context = ParserContext::new_with_str(input, ());
let borrowed_context = context.borrow();
let (_, token) = parser(context.clone(), borrowed_context.input_slice()).unwrap();
let context = ParserContext::new(());
let word: Vec<char> = input.chars().collect();
let (_, token) = parser(context.clone(), word.as_slice()).unwrap();
assert_eq!(except, token);
}