Skip to content

Commit

Permalink
Remove 'static requirements from patterns and improve their printi… (#7)
Browse files Browse the repository at this point in the history
Remove 'static requirements from patterns and improve their printing.
  • Loading branch information
eddyb authored Jul 23, 2019
2 parents e86adcc + 47e7ed3 commit b024672
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 37 deletions.
27 changes: 18 additions & 9 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,29 @@ impl<'a> Input for &'a str {
}
}

pub trait InputMatch<Pat> {
fn match_left(&self, pat: &'static Pat) -> Option<usize>;
fn match_right(&self, pat: &'static Pat) -> Option<usize>;
pub trait InputMatch<Pat: ?Sized> {
fn match_left(&self, pat: &Pat) -> Option<usize>;
fn match_right(&self, pat: &Pat) -> Option<usize>;
}

impl<T: PartialEq> InputMatch<&'static [T]> for [T] {
fn match_left(&self, pat: &&[T]) -> Option<usize> {
impl<I: ?Sized + InputMatch<Pat>, Pat: ?Sized> InputMatch<&'_ Pat> for I {
fn match_left(&self, &pat: &&Pat) -> Option<usize> {
self.match_left(pat)
}
fn match_right(&self, &pat: &&Pat) -> Option<usize> {
self.match_right(pat)
}
}

impl<T: PartialEq> InputMatch<[T]> for [T] {
fn match_left(&self, pat: &[T]) -> Option<usize> {
if self.starts_with(pat) {
Some(pat.len())
} else {
None
}
}
fn match_right(&self, pat: &&[T]) -> Option<usize> {
fn match_right(&self, pat: &[T]) -> Option<usize> {
if self.ends_with(pat) {
Some(pat.len())
} else {
Expand Down Expand Up @@ -201,15 +210,15 @@ impl<T: PartialOrd> InputMatch<RangeInclusive<T>> for [T] {
}
}

impl InputMatch<&'static str> for str {
fn match_left(&self, pat: &&str) -> Option<usize> {
impl InputMatch<str> for str {
fn match_left(&self, pat: &str) -> Option<usize> {
if self.starts_with(pat) {
Some(pat.len())
} else {
None
}
}
fn match_right(&self, pat: &&str) -> Option<usize> {
fn match_right(&self, pat: &str) -> Option<usize> {
if self.ends_with(pat) {
Some(pat.len())
} else {
Expand Down
44 changes: 22 additions & 22 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;

pub struct Parser<'a, 'i, G: GrammarReflector, I: Input> {
state: &'a mut ParserState<'i, G, I>,
pub struct Parser<'a, 'i, G: GrammarReflector, I: Input, Pat> {
state: &'a mut ParserState<'i, G, I, Pat>,
result: Range<'i>,
remaining: Range<'i>,
}

struct ParserState<'i, G: GrammarReflector, I: Input> {
struct ParserState<'i, G: GrammarReflector, I: Input, Pat> {
forest: ParseForest<'i, G, I>,
last_input_pos: Index<'i, Unknown>,
expected_pats: Vec<&'static dyn fmt::Debug>,
expected_pats: Vec<Pat>,
}

#[derive(Debug)]
pub struct ParseError<A> {
pub struct ParseError<A, Pat> {
pub at: A,
pub expected: Vec<&'static dyn fmt::Debug>,
pub expected: Vec<Pat>,
}

pub type ParseResult<A, T> = Result<T, ParseError<A>>;
pub type ParseResult<A, Pat, T> = Result<T, ParseError<A, Pat>>;

impl<'i, P, G, I: Input> Parser<'_, 'i, G, I>
impl<'i, P, G, I: Input, Pat> Parser<'_, 'i, G, I, Pat>
where
// FIXME(eddyb) these shouldn't be needed, as they are bounds on
// `GrammarReflector::ParseNodeKind`, but that's ignored currently.
Expand All @@ -36,8 +36,8 @@ where
pub fn parse_with(
grammar: G,
input: I,
f: impl for<'i2> FnOnce(Parser<'_, 'i2, G, I>) -> Option<ParseNode<'i2, P>>,
) -> ParseResult<I::SourceInfoPoint, OwnedParseForestAndNode<G, P, I>> {
f: impl for<'i2> FnOnce(Parser<'_, 'i2, G, I, Pat>) -> Option<ParseNode<'i2, P>>,
) -> ParseResult<I::SourceInfoPoint, Pat, OwnedParseForestAndNode<G, P, I>> {
ErasableL::indexing_scope(input.to_container(), |lifetime, input| {
let range = Range(input.range());
let mut state = ParserState {
Expand Down Expand Up @@ -99,7 +99,7 @@ where
&'a mut self,
result: Range<'i>,
remaining: Range<'i>,
) -> Parser<'a, 'i, G, I> {
) -> Parser<'a, 'i, G, I, Pat> {
// HACK(eddyb) enforce that `result` and `remaining` are inside `self`.
assert_eq!(self.result, Range(self.remaining.frontiers().0));
let full_new_range = result.join(remaining.0).unwrap();
Expand All @@ -113,19 +113,19 @@ where
}
}

pub fn input_consume_left<'a, Pat: fmt::Debug>(
pub fn input_consume_left<'a, SpecificPat: Into<Pat>>(
&'a mut self,
pat: &'static Pat,
) -> Option<Parser<'a, 'i, G, I>>
pat: SpecificPat,
) -> Option<Parser<'a, 'i, G, I, Pat>>
where
I::Slice: InputMatch<Pat>,
I::Slice: InputMatch<SpecificPat>,
{
let start = self.remaining.first();
if start > self.state.last_input_pos {
self.state.last_input_pos = start;
self.state.expected_pats.clear();
}
match self.state.forest.input(self.remaining).match_left(pat) {
match self.state.forest.input(self.remaining).match_left(&pat) {
Some(n) => {
let (matching, after, _) = self.remaining.split_at(n);
if n > 0 {
Expand All @@ -140,22 +140,22 @@ where
}
None => {
if start == self.state.last_input_pos {
self.state.expected_pats.push(pat);
self.state.expected_pats.push(pat.into());
}
None
}
}
}

pub fn input_consume_right<'a, Pat>(
pub fn input_consume_right<'a, SpecificPat>(
&'a mut self,
pat: &'static Pat,
) -> Option<Parser<'a, 'i, G, I>>
pat: SpecificPat,
) -> Option<Parser<'a, 'i, G, I, Pat>>
where
I::Slice: InputMatch<Pat>,
I::Slice: InputMatch<SpecificPat>,
{
// FIXME(eddyb) implement error reporting support like in `input_consume_left`
match self.state.forest.input(self.remaining).match_right(pat) {
match self.state.forest.input(self.remaining).match_right(&pat) {
Some(n) => {
let (before, matching, _) = self.remaining.split_at(self.remaining.len() - n);
Some(Parser {
Expand Down
57 changes: 55 additions & 2 deletions src/proc_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::scannerless::Pat as SPat;
pub use proc_macro2::{
Delimiter, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
use std::fmt;
use std::ops::Deref;
use std::str::FromStr;

pub type Context = crate::context::Context<Pat>;
Expand Down Expand Up @@ -46,7 +48,7 @@ pub fn builtin(cx: &mut Context) -> crate::Grammar {
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Pat(pub Vec<FlatTokenPat<String>>);
pub struct Pat<Pats = Vec<FlatTokenPat<String>>>(pub Pats);

impl FromStr for Pat {
type Err = LexError;
Expand All @@ -72,6 +74,12 @@ impl From<&str> for Pat {
}
}

impl<Pats> From<Pats> for Pat<Pats> {
fn from(pats: Pats) -> Self {
Pat(pats)
}
}

impl From<FlatTokenPat<String>> for Pat {
fn from(pat: FlatTokenPat<String>) -> Self {
Pat(vec![pat])
Expand Down Expand Up @@ -100,7 +108,7 @@ pub enum FlatToken {
Literal(Literal),
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum FlatTokenPat<S: AsRef<str>> {
Delim(char),
Ident(Option<S>),
Expand All @@ -111,6 +119,51 @@ pub enum FlatTokenPat<S: AsRef<str>> {
Literal,
}

impl<S: AsRef<str>> fmt::Debug for FlatTokenPat<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FlatTokenPat::Delim(c) | FlatTokenPat::Punct { ch: Some(c), .. } => {
write!(f, "\"{}\"", c)
}
FlatTokenPat::Ident(None) => f.write_str("IDENT"),
FlatTokenPat::Ident(Some(ident)) => write!(f, "\"{}\"", ident.as_ref()),
FlatTokenPat::Punct { ch: None, .. } => f.write_str("PUNCT"),
FlatTokenPat::Literal => f.write_str("LITERAL"),
}
}
}

// FIXME(eddyb) can't use `Pats: AsRef<[FlatTokenPat<S>]` as it doesn't constrain `S`.
impl<S: AsRef<str>, Pats: Deref<Target = [FlatTokenPat<S>]>> fmt::Debug for Pat<Pats> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0[..] {
[] => f.write_str("\"\""),
[pat] => pat.fmt(f),
pats => {
let mut was_joint = true;
f.write_str("\"")?;
for pat in pats {
if !was_joint {
f.write_str(" ")?;
}
match pat {
FlatTokenPat::Punct { ch: Some(c), joint } => {
write!(f, "{}", c)?;
was_joint = *joint == Some(true);
}
FlatTokenPat::Ident(Some(ident)) => {
write!(f, "\"{}\"", ident.as_ref())?;
was_joint = false;
}
_ => unreachable!(),
}
}
f.write_str("\"")
}
}
}
}

impl FlatToken {
pub fn span(&self) -> Span {
match self {
Expand Down
6 changes: 3 additions & 3 deletions src/proc_macro_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl Input for TokenStream {
}
}

impl InputMatch<&'static [FlatTokenPat<&'static str>]> for [FlatToken] {
fn match_left(&self, &pat: &&[FlatTokenPat<&str>]) -> Option<usize> {
impl InputMatch<[FlatTokenPat<&'_ str>]> for [FlatToken] {
fn match_left(&self, pat: &[FlatTokenPat<&str>]) -> Option<usize> {
if self
.iter()
.zip(pat)
Expand All @@ -66,7 +66,7 @@ impl InputMatch<&'static [FlatTokenPat<&'static str>]> for [FlatToken] {
None
}
}
fn match_right(&self, &pat: &&[FlatTokenPat<&str>]) -> Option<usize> {
fn match_right(&self, pat: &[FlatTokenPat<&str>]) -> Option<usize> {
if self
.iter()
.zip(pat)
Expand Down
22 changes: 21 additions & 1 deletion src/scannerless.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
use crate::rule::{MatchesEmpty, MaybeKnown};
use std::char;
use std::fmt;
use std::ops::{self, Bound, RangeBounds};

pub type Context<S = String> = crate::context::Context<Pat<S>>;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Pat<S = String, C = char> {
String(S),
Range(C, C),
}

impl<S: fmt::Debug> fmt::Debug for Pat<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Pat::String(s) => s.fmt(f),
&Pat::Range(start, end) => {
if start != '\0' {
start.fmt(f)?;
}
f.write_str("..")?;
if end != char::MAX {
f.write_str("=")?;
end.fmt(f)?;
}
Ok(())
}
}
}
}

impl<'a, C> From<&'a str> for Pat<&'a str, C> {
fn from(s: &'a str) -> Self {
Pat::String(s)
Expand Down

0 comments on commit b024672

Please sign in to comment.