Skip to content

Upgrade to combine 4.x.y #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ authors = ["Paul Colomiets <paul@colomiets.name>"]
edition = "2018"

[dependencies]
combine = "3.2.0"
combine = "4.6.0"
thiserror = "1.0.11"

[dev-dependencies]
Expand Down
70 changes: 29 additions & 41 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::{fmt, collections::BTreeMap};

use combine::{parser, ParseResult, Parser};
use combine::{parser, StdParseResult, Parser, many, many1, optional, position, choice};
use combine::easy::Error;
use combine::error::StreamError;
use combine::combinator::{many, many1, optional, position, choice};

use crate::tokenizer::{Kind as T, Token, TokenStream};
use crate::helpers::{punct, ident, kind, name};
Expand All @@ -12,7 +11,7 @@ use crate::position::Pos;
/// Text abstracts over types that hold a string value.
/// It is used to make the AST generic over the string type.
pub trait Text<'a>: 'a {
type Value: 'a + From<&'a str> + AsRef<str> + std::borrow::Borrow<str> + PartialEq + Eq + PartialOrd + Ord + fmt::Debug + Clone;
type Value: 'a + From<&'a str> + AsRef<str> + std::borrow::Borrow<str> + PartialEq + Eq + PartialOrd + Ord + fmt::Debug + Clone;
}

impl<'a> Text<'a> for &'a str {
Expand Down Expand Up @@ -98,9 +97,8 @@ impl From<i32> for Number {
}
}

pub fn directives<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Vec<Directive<'a, T>>, TokenStream<'a>>
where T: Text<'a>,
pub fn directives<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Vec<Directive<'a, T>>, TokenStream<'a>>
where T: Text<'a>,
{
many(position()
.skip(punct("@"))
Expand All @@ -109,11 +107,10 @@ pub fn directives<'a, T>(input: &mut TokenStream<'a>)
.map(|((position, name), arguments)| {
Directive { position, name, arguments }
}))
.parse_stream(input)
.parse_stream(input).into()
}

pub fn arguments<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Vec<(T::Value, Value<'a, T>)>, TokenStream<'a>>
pub fn arguments<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Vec<(T::Value, Value<'a, T>)>, TokenStream<'a>>
where T: Text<'a>,
{
optional(
Expand All @@ -125,25 +122,23 @@ pub fn arguments<'a, T>(input: &mut TokenStream<'a>)
.map(|opt| {
opt.unwrap_or_else(Vec::new)
})
.parse_stream(input)
.parse_stream(input).into()
}

pub fn int_value<'a, S>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, S>, TokenStream<'a>>
pub fn int_value<'a, S>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, S>, TokenStream<'a>>
where S: Text<'a>
{
kind(T::IntValue).and_then(|tok| tok.value.parse())
.map(Number).map(Value::Int)
.parse_stream(input)
.parse_stream(input).into()
}

pub fn float_value<'a, S>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, S>, TokenStream<'a>>
pub fn float_value<'a, S>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, S>, TokenStream<'a>>
where S: Text<'a>
{
kind(T::FloatValue).and_then(|tok| tok.value.parse())
.map(Value::Float)
.parse_stream(input)
.parse_stream(input).into()
}

fn unquote_block_string<'a>(src: &'a str) -> Result<String, Error<Token<'a>, Token<'a>>> {
Expand Down Expand Up @@ -182,7 +177,7 @@ fn unquote_block_string<'a>(src: &'a str) -> Result<String, Error<Token<'a>, Tok
Ok(result)
}

fn unquote_string<'a>(s: &'a str) -> Result<String, Error<Token, Token>>
fn unquote_string<'a>(s: &'a str) -> Result<String, Error<Token, Token>>
{
let mut res = String::with_capacity(s.len());
debug_assert!(s.starts_with('"') && s.ends_with('"'));
Expand All @@ -203,7 +198,7 @@ fn unquote_string<'a>(s: &'a str) -> Result<String, Error<Token, Token>>
for _ in 0..4 {
match chars.next() {
Some(inner_c) => temp_code_point.push(inner_c),
None => return Err(Error::unexpected_message(
None => return Err(Error::unexpected_format(
format_args!("\\u must have 4 characters after it, only found '{}'", temp_code_point)
)),
}
Expand All @@ -213,13 +208,13 @@ fn unquote_string<'a>(s: &'a str) -> Result<String, Error<Token, Token>>
match u32::from_str_radix(&temp_code_point, 16).map(std::char::from_u32) {
Ok(Some(unicode_char)) => res.push(unicode_char),
_ => {
return Err(Error::unexpected_message(
return Err(Error::unexpected_format(
format_args!("{} is not a valid unicode code point", temp_code_point)))
}
}
},
c => {
return Err(Error::unexpected_message(
return Err(Error::unexpected_format(
format_args!("bad escaped char {:?}", c)));
}
}
Expand All @@ -231,35 +226,31 @@ fn unquote_string<'a>(s: &'a str) -> Result<String, Error<Token, Token>>
Ok(res)
}

pub fn string<'a>(input: &mut TokenStream<'a>)
-> ParseResult<String, TokenStream<'a>>
pub fn string<'a>(input: &mut TokenStream<'a>) -> StdParseResult<String, TokenStream<'a>>
{
choice((
kind(T::StringValue).and_then(|tok| unquote_string(tok.value)),
kind(T::BlockString).and_then(|tok| unquote_block_string(tok.value)),
)).parse_stream(input)
)).parse_stream(input).into()
}

pub fn string_value<'a, S>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, S>, TokenStream<'a>>
pub fn string_value<'a, S>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, S>, TokenStream<'a>>
where S: Text<'a>,
{
kind(T::StringValue).and_then(|tok| unquote_string(tok.value))
.map(Value::String)
.parse_stream(input)
.parse_stream(input).into()
}

pub fn block_string_value<'a, S>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, S>, TokenStream<'a>>
pub fn block_string_value<'a, S>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, S>, TokenStream<'a>>
where S: Text<'a>,
{
kind(T::BlockString).and_then(|tok| unquote_block_string(tok.value))
.map(Value::String)
.parse_stream(input)
.parse_stream(input).into()
}

pub fn plain_value<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, T>, TokenStream<'a>>
pub fn plain_value<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, T>, TokenStream<'a>>
where T: Text<'a>,
{
ident("true").map(|_| Value::Boolean(true))
Expand All @@ -270,11 +261,10 @@ pub fn plain_value<'a, T>(input: &mut TokenStream<'a>)
.or(parser(float_value))
.or(parser(string_value))
.or(parser(block_string_value))
.parse_stream(input)
.parse_stream(input).into()
}

pub fn value<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, T>, TokenStream<'a>>
pub fn value<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, T>, TokenStream<'a>>
where T: Text<'a>,
{
parser(plain_value)
Expand All @@ -285,11 +275,10 @@ pub fn value<'a, T>(input: &mut TokenStream<'a>)
.with(many(name::<'a, T>().skip(punct(":")).and(parser(value))))
.skip(punct("}"))
.map(Value::Object))
.parse_stream(input)
.parse_stream(input).into()
}

pub fn default_value<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Value<'a, T>, TokenStream<'a>>
pub fn default_value<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Value<'a, T>, TokenStream<'a>>
where T: Text<'a>,
{
parser(plain_value)
Expand All @@ -299,11 +288,10 @@ pub fn default_value<'a, T>(input: &mut TokenStream<'a>)
.with(many(name::<'a, T>().skip(punct(":")).and(parser(default_value))))
.skip(punct("}"))
.map(Value::Object))
.parse_stream(input)
.parse_stream(input).into()
}

pub fn parse_type<'a, T>(input: &mut TokenStream<'a>)
-> ParseResult<Type<'a, T>, TokenStream<'a>>
pub fn parse_type<'a, T>(input: &mut TokenStream<'a>) -> StdParseResult<Type<'a, T>, TokenStream<'a>>
where T: Text<'a>,
{
name::<'a, T>().map(Type::NamedType)
Expand All @@ -320,7 +308,7 @@ pub fn parse_type<'a, T>(input: &mut TokenStream<'a>)
typ
}
)
.parse_stream(input)
.parse_stream(input).into()
}

#[cfg(test)]
Expand Down
37 changes: 13 additions & 24 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::marker::PhantomData;

use combine::{Parser, ConsumedResult, satisfy, StreamOnce};
use combine::{Parser, ParseResult, satisfy, StreamOnce};
use combine::error::{Tracked};
use combine::stream::easy::{Error, Errors, Info};

Expand All @@ -17,7 +17,7 @@ pub struct TokenMatch<'a> {
}

#[derive(Debug, Clone)]
pub struct NameMatch<'a, T>
pub struct NameMatch<'a, T>
where T: Text<'a>
{
phantom: PhantomData<&'a T>,
Expand All @@ -38,29 +38,24 @@ pub fn kind<'x>(kind: Kind) -> TokenMatch<'x> {
}
}

pub fn name<'a, T>() -> NameMatch<'a, T>
pub fn name<'a, T>() -> NameMatch<'a, T>
where T: Text<'a>
{
NameMatch {
phantom: PhantomData,
}
}

impl<'a> Parser for TokenMatch<'a> {
type Input = TokenStream<'a>;
impl<'a> Parser<TokenStream<'a>> for TokenMatch<'a> {
type Output = Token<'a>;
type PartialState = ();

#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input)
-> ConsumedResult<Self::Output, Self::Input>
{
fn parse_lazy(&mut self, input: &mut TokenStream<'a>) -> ParseResult<Self::Output, <TokenStream<'a> as StreamOnce>::Error> {
satisfy(|c: Token<'a>| c.kind == self.kind).parse_lazy(input)
}

fn add_error(&mut self,
error: &mut Tracked<Errors<Token<'a>, Token<'a>, Pos>>)
{
fn add_error(&mut self, error: &mut Tracked<Errors<Token<'a>, Token<'a>, Pos>>) {
error.error.add_error(Error::Expected(Info::Owned(
format!("{:?}", self.kind))));
}
Expand All @@ -82,38 +77,32 @@ pub fn ident<'s>(value: &'static str) -> Value<'s> {
}
}

impl<'a> Parser for Value<'a> {
type Input = TokenStream<'a>;
impl<'a> Parser<TokenStream<'a>> for Value<'a> {
type Output = Token<'a>;
type PartialState = ();

#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input)
-> ConsumedResult<Self::Output, Self::Input>
{
fn parse_lazy(&mut self, input: &mut TokenStream<'a>) -> ParseResult<Self::Output, <TokenStream<'a> as StreamOnce>::Error> {
satisfy(|c: Token<'a>| {
c.kind == self.kind && c.value == self.value
}).parse_lazy(input)
}

fn add_error(&mut self,
error: &mut Tracked<<Self::Input as StreamOnce>::Error>)
error: &mut Tracked<<TokenStream<'a> as StreamOnce>::Error>)
{
error.error.add_error(Error::Expected(Info::Borrowed(self.value)));
error.error.add_error(Error::Expected(Info::Static(self.value)));
}
}

impl<'a, S> Parser for NameMatch<'a, S>
impl<'a, S> Parser<TokenStream<'a>> for NameMatch<'a, S>
where S: Text<'a>,
{
type Input = TokenStream<'a>;
type Output = S::Value;
type PartialState = ();

#[inline]
fn parse_lazy(&mut self, input: &mut Self::Input)
-> ConsumedResult<Self::Output, Self::Input>
{
fn parse_lazy(&mut self, input: &mut TokenStream<'a>) -> ParseResult<Self::Output, <TokenStream<'a> as StreamOnce>::Error> {
satisfy(|c: Token<'a>| c.kind == Kind::Name)
.map(|t: Token<'a>| -> S::Value { S::Value::from(t.value) } )
.parse_lazy(input)
Expand All @@ -122,6 +111,6 @@ impl<'a, S> Parser for NameMatch<'a, S>
fn add_error(&mut self,
error: &mut Tracked<Errors<Token<'a>, Token<'a>, Pos>>)
{
error.error.add_error(Error::Expected(Info::Borrowed("Name")));
error.error.add_error(Error::Expected(Info::Static("Name")));
}
}
Loading