pub use bork::SourceError;
use std::ops::Bound;
use std::ops::Range;
use std::ops::RangeBounds;
#[derive(Clone, Debug, PartialEq)]
pub struct ParserContext<'a> {
pub input: &'a str,
pub bounds: Range<usize>,
}
impl<'a> From<&'a str> for ParserContext<'a> {
fn from(input: &'a str) -> Self {
ParserContext {
bounds: 0..0,
input,
}
}
}
impl<'a> From<&'a String> for ParserContext<'a> {
fn from(input: &'a String) -> Self {
ParserContext {
bounds: 0..0,
input,
}
}
}
impl<'a, RE> From<(ParserContext<'a>, RE)> for ParserContext<'a> {
fn from(parsed: (ParserContext<'a>, RE)) -> Self {
parsed.0
}
}
impl<'a> ParserContext<'a> {
#[inline]
pub fn parsed(&self) -> &str {
&self.input[..self.bounds.end]
}
#[inline]
pub fn unparsed(&self) -> &str {
&self.input[self.bounds.end..]
}
#[inline]
pub fn end_of_input(&'a self) -> bool {
self.bounds.end == self.input.len()
}
#[inline]
pub fn start_of_input(&'a self) -> bool {
self.bounds.end == 0
}
#[inline]
pub fn expand(self, other: Self) -> Self {
let end = other.bounds.end - self.bounds.end;
self.select(..end)
}
#[inline]
pub fn select<B>(self, bounds: B) -> Self
where
B: RangeBounds<usize>,
{
let start = match bounds.start_bound() {
Bound::Excluded(start) => *start,
Bound::Included(start) => *start,
Bound::Unbounded => 0,
};
let end = match bounds.end_bound() {
Bound::Excluded(end) => *end,
Bound::Included(end) => *end + 1,
Bound::Unbounded => 0,
};
let bounds = (self.bounds.end + start)..(self.bounds.end + end);
ParserContext { bounds, ..self }
}
#[inline]
pub fn select_character(self) -> Self {
let character = self.unparsed().chars().nth(0).unwrap();
let offset = character.len_utf8();
self.select(..offset)
}
#[inline]
pub fn select_empty(self) -> Self {
self.select(0..0)
}
}
pub type ParsedData<'a, RE> = (ParserContext<'a>, RE);
pub trait ConstructParsedData<'a> {
fn with_data<R>(self, result: R) -> ParsedData<'a, R>;
fn with_str(self) -> ParsedData<'a, &'a str>;
}
impl<'a> ConstructParsedData<'a> for ParserContext<'a> {
#[inline]
fn with_data<R>(self, result: R) -> ParsedData<'a, R> {
(self, result)
}
#[inline]
fn with_str(self) -> ParsedData<'a, &'a str> {
let value = &self.input[self.bounds.start..self.bounds.end];
(self, value)
}
}
impl<'a, RE> ConstructParsedData<'a> for ParsedData<'a, RE> {
#[inline]
fn with_data<R>(self, result: R) -> ParsedData<'a, R> {
self.0.with_data(result)
}
#[inline]
fn with_str(self) -> ParsedData<'a, &'a str> {
self.0.with_str()
}
}
pub type ParserResult<'a, R> = Result<(ParserContext<'a>, R), (ParserContext<'a>, SourceError)>;
pub trait MapParserResult<'a, R> {
fn map_error<F>(self, callback: F) -> ParserResult<'a, R>
where
F: FnMut(SourceError) -> SourceError;
fn map_result<F, RX>(self, callback: F) -> ParserResult<'a, RX>
where
F: FnMut(R) -> RX;
}
impl<'a, R> MapParserResult<'a, R> for ParserResult<'a, R> {
#[inline]
fn map_error<F>(self, mut callback: F) -> ParserResult<'a, R>
where
F: FnMut(SourceError) -> SourceError,
{
match self {
Ok(ok) => Ok(ok),
Err((ctx, error)) => Err((ctx, callback(error))),
}
}
#[inline]
fn map_result<F, RX>(self, mut callback: F) -> ParserResult<'a, RX>
where
F: FnMut(R) -> RX,
{
match self {
Ok((ctx, result)) => Ok((ctx, callback(result))),
Err(err) => Err(err),
}
}
}
pub trait Parser<'a, R> {
fn parse<C>(&mut self, ctx: C) -> ParserResult<'a, R>
where
C: Into<ParserContext<'a>>;
fn test<C>(&mut self, ctx: C) -> bool
where
C: Into<ParserContext<'a>>;
}
impl<'a, F, R> Parser<'a, R> for F
where
F: FnMut(ParserContext<'a>) -> ParserResult<'a, R>,
{
#[inline]
fn parse<C>(&mut self, ctx: C) -> ParserResult<'a, R>
where
C: Into<ParserContext<'a>>,
{
self(ctx.into())
}
#[inline]
fn test<C>(&mut self, ctx: C) -> bool
where
C: Into<ParserContext<'a>>,
{
self(ctx.into()).is_ok()
}
}
pub trait BranchParser<'a, R> {
fn find_any<C>(&mut self, ctx: C) -> ParserResult<'a, R>
where
C: Into<ParserContext<'a>>;
fn take_any<C>(&mut self, ctx: C) -> ParserResult<'a, &'a str>
where
C: Into<ParserContext<'a>>;
}
pub trait SequenceParser<'a, R> {
fn find_all<C>(&mut self, ctx: C) -> ParserResult<'a, R>
where
C: Into<ParserContext<'a>>;
fn take_all<C>(&mut self, ctx: C) -> ParserResult<'a, &'a str>
where
C: Into<ParserContext<'a>>;
}
pub trait MatchParser {
fn is<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str>;
fn isnt<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str>;
}
impl<F: Fn(char) -> bool> MatchParser for F {
#[inline]
fn is<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if self(character) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
#[inline]
fn isnt<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if !self(character) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
}
impl MatchParser for char {
#[inline]
fn is<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if self == &character {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
#[inline]
fn isnt<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if self != &character {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
}
impl<'a> MatchParser for std::str::Chars<'a> {
#[inline]
fn is<'b>(&self, ctx: ParserContext<'b>) -> ParserResult<'b, &'b str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if self.clone().any(|x| x == character) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
#[inline]
fn isnt<'b>(&self, ctx: ParserContext<'b>) -> ParserResult<'b, &'b str> {
let unparsed = ctx.unparsed();
match unparsed.chars().nth(0) {
Some(character) => {
if !self.clone().any(|x| x == character) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
None => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
}
impl MatchParser for &str {
#[inline]
fn is<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
if unparsed.len() >= self.len() && unparsed.starts_with(self) {
Ok(ctx.select(..self.len()).with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
#[inline]
fn isnt<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
if unparsed.len() >= 1 && !unparsed.starts_with(self) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
impl MatchParser for String {
#[inline]
fn is<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
if unparsed.len() >= self.len() && unparsed.starts_with(self) {
Ok(ctx.select(..self.len()).with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
#[inline]
fn isnt<'a>(&self, ctx: ParserContext<'a>) -> ParserResult<'a, &'a str> {
let unparsed = ctx.unparsed();
if unparsed.len() >= 1 && !unparsed.starts_with(self) {
Ok(ctx.select_character().with_str())
} else {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
}
}
macro_rules! auto_implement(
($($index:tt)+) => {
paste::item! {
impl<'a, Res, $([<Par $index>],)+> BranchParser<'a, Res> for ($([<Par $index>],)+)
where
$([<Par $index>]: Parser<'a, Res>,)+
{
#[inline]
fn find_any<Ctx>(&mut self, ctx: Ctx) -> ParserResult<'a, Res>
where
Ctx: Into<ParserContext<'a>>
{
let ctx = ctx.into();
let mut errors = Vec::new();
$(
match self.$index.parse(ctx.clone()) {
Ok(result) => return Ok(result),
Err((_, error)) => errors.push(error),
};
)+
Err((ctx, SourceError::Ranges(errors)))
}
#[inline]
fn take_any<Ctx>(&mut self, ctx: Ctx) -> ParserResult<'a, &'a str>
where
Ctx: Into<ParserContext<'a>>
{
let ctx = ctx.into();
let mut errors = Vec::new();
$(
match self.$index.parse(ctx.clone()) {
Ok(result) => return Ok(result.with_str()),
Err((_, error)) => errors.push(error),
};
)+
Err((ctx, SourceError::Ranges(errors)))
}
}
impl<'a, $([<Res $index>], [<Par $index>],)+>
SequenceParser<'a, ($([<Res $index>],)+)> for ($([<Par $index>],)+)
where
$([<Par $index>]: Parser<'a, [<Res $index>]>,)+
{
#[inline]
fn find_all<Ctx>(&mut self, ctx: Ctx) -> ParserResult<'a, ($([<Res $index>],)+)>
where
Ctx: Into<ParserContext<'a>>
{
let ctx = ctx.into();
let temp_ctx = ctx.clone();
$(
let (temp_ctx, [<out $index>]) = self.$index.parse(temp_ctx)?;
)+
Ok(ctx.expand(temp_ctx).with_data(($([<out $index>],)+)))
}
#[inline]
fn take_all<Ctx>(&mut self, ctx: Ctx) -> ParserResult<'a, &'a str>
where
Ctx: Into<ParserContext<'a>>
{
let ctx = ctx.into();
let temp_ctx = ctx.clone();
$(
let (temp_ctx, _) = self.$index.parse(temp_ctx)?;
)+
Ok(ctx.expand(temp_ctx).with_str())
}
}
}
};
);
auto_implement!(0);
auto_implement!(0 1);
auto_implement!(0 1 2);
auto_implement!(0 1 2 3);
auto_implement!(0 1 2 3 4);
auto_implement!(0 1 2 3 4 5);
auto_implement!(0 1 2 3 4 5 6);
auto_implement!(0 1 2 3 4 5 6 7);
auto_implement!(0 1 2 3 4 5 6 7 8);
auto_implement!(0 1 2 3 4 5 6 7 8 9);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28);
auto_implement!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29);