Compare commits

...

2 Commits

4 changed files with 87 additions and 5 deletions

View File

@ -9,7 +9,9 @@ use crate::combinators::left_right_parsers::{LeftParser, RightParser};
use crate::combinators::many_parsers::{ use crate::combinators::many_parsers::{
Many1Parser, Many1TillParser, ManyParser, ManyTillParser, Skip1Parser, SkipParser, 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::combinators::tuple_parser::{ParserTuple, TupleParser};
use crate::parser::{any, Parser}; use crate::parser::{any, Parser};
use std::fmt::Debug; use std::fmt::Debug;
@ -190,7 +192,13 @@ where
PLeft: Parser<'a, TToken, TLeft, TContext>, PLeft: Parser<'a, TToken, TLeft, TContext>,
PRight: Parser<'a, TToken, TRight, 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>( pub fn separate_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(

View File

@ -270,6 +270,18 @@ mod test {
char_parser('a').many_till(char_parser('b')).parse(c, i) char_parser('a').many_till(char_parser('b')).parse(c, i)
}); });
parser_test_helper(
ParserContext::new_with_str("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(ParserContext::new_with_str("aaacb", ()), |c, i| { failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| {
char_parser('a').many_till(char_parser('b')).parse(c, i) char_parser('a').many_till(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::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; 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<TToken, 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 struct SeparateBy1Parser<P, PSeparator, TSeparator> {
pub(crate) parser: P, pub(crate) parser: P,
pub(crate) separator: PSeparator, pub(crate) separator: PSeparator,
@ -82,6 +133,7 @@ mod test {
use super::*; use super::*;
use crate::combinators::{ use crate::combinators::{
end_by, end_by1, quote, separate_by, separate_by1, separate_or_end_by, separate_or_end_by1, 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::parser::{failed_parser_test_helper, parser_test_helper, satisfy};
use crate::text::char_parser; use crate::text::char_parser;
@ -106,7 +158,17 @@ mod test {
parser, parser,
); );
parser_test_helper(ParserContext::new_with_str("''", ()), &vec![], parser); parser_test_helper(ParserContext::new_with_str("''", ()), &vec![], parser);
failed_parser_test_helper(ParserContext::new_with_str("asd", ()), parser) failed_parser_test_helper(ParserContext::new_with_str("asd", ()), parser);
parser_test_helper(
ParserContext::new_with_str("'a'b", ()),
&vec!['a'],
|c, i| {
quote(char_parser('\''), char_parser('a'), char_parser('\''))
.left(char_parser('b'))
.parse(c, i)
},
)
} }
#[test] #[test]

View File

@ -211,7 +211,7 @@ pub fn literal_string_parser(
let length = x.len(); let length = x.len();
NewLexicalToken { NewLexicalToken {
token_type: LexicalTokenType::LiteralString, token_type: LexicalTokenType::LiteralString,
literal_value: &x[1..length], literal_value: &x[1..length - 1],
} }
}) })
.parse(context, input) .parse(context, input)