Как реализовать nom :: InputIter для Ve c токенов? - PullRequest
2 голосов
/ 13 апреля 2020

Я создаю синтаксический анализатор, используя nom , и я хотел бы использовать комбинаторы nom для обработки входных токенов.

Поток токенов представлен Vec<Token<S>>, с Token:

#[derive(Debug, Clone, PartialEq)]
pub enum Token<S> {
    Identifier(S),
    String(S),
}

Я попытался реализовать InputIter для вектора произвольных значений:

impl<'a, T> InputIter for Vec<T> {
    type Item = T;
    type Iter = Enumerate<Self::IterElem>;
    type IterElem = Iter<'a, Self::Item>;

    fn iter_indices(&self) -> Self::Iter {
        self.iter().enumerate()
    }

    fn iter_elements(&self) -> Self::IterElem {
        self.iter()
    }
}

Когда я столкнулся со следующей ошибкой:

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
  --> src/lex/tokens.rs:37:6
   |
37 | impl<'a, T> InputIter for Vec<T> {
   |      ^^ unconstrained lifetime parameter

Затем я попытался ограничить параметр времени жизни с помощью параметра типа Token<S>:

impl<'a> InputIter for Vec<Token<&'a str>> {
    type Item = Token<&'a str>;
    type Iter = Enumerate<Self::IterElem>;
    type IterElem = Iter<'a, Self::Item>;

    fn iter_indices(&self) -> Self::Iter {
        self.iter().enumerate()
    }

    fn iter_elements(&self) -> Self::IterElem {
        self.iter()
    }
}

, что привело к следующему:

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
  --> src/lex/tokens.rs:51:1
   |
51 | impl<'a> InputIter for Vec<Token<&'a str>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^-------------------
   | |                      |
   | |                      `std::vec::Vec` is not defined in the current crate
   | impl doesn't use only types from inside the current crate
   |
   = note: define and implement a trait or new type instead

Ошибка, по-видимому, означает, что я могу не реализую внешнюю черту для внешнего типа, поэтому я пытаюсь заключить Vec<Token<S>> в пользовательскую структуру:

struct Tokens<S> {
    vec: Vec<Token<S>>,
}

impl<'a> InputIter for Tokens<&'a str> {
    type Item = Token<&'a str>;
    type Iter = Enumerate<Self::IterElem>;
    type IterElem = Iter<'a, Self::Item>;

    fn iter_indices(&self) -> Self::Iter {
        self.vec.iter().enumerate()
    }

    fn iter_elements(&self) -> Self::IterElem {
        self.vec.iter()
    }
}

, что приводит к следующей ошибке:

error[E0271]: type mismatch resolving `<std::iter::Enumerate<std::slice::Iter<'_, lex::tokens::Token<&str>>> as std::iter::Iterator>::Item == (usize, lex::tokens::Token<&str>)`
  --> src/lex/tokens.rs:56:3
   |
55 | impl<'a> InputIter for Tokens<&'a str> {
   | -------------------------------------- in this `impl` item
56 |   type Item = Token<&'a str>;
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found enum `lex::tokens::Token`
   |
   = note: expected tuple `(_, &lex::tokens::Token<&str>)`
              found tuple `(_, lex::tokens::Token<&str>)`

Означает ли это, что я ограничен использованием вектора ссылок в отличие от вектора, содержащего токены напрямую? Что дает? Кажется, в объявлении InputIter нет ничего, что подразумевало бы это ограничение.

Есть ли другой способ выполнить sh то, что я пытаюсь сделать, и представить токен поток, совместимый с именованными комбинаторами?

Воспроизводимый пример детская площадка :

use std::iter::Enumerate;
use std::slice::Iter;

#[derive(Debug, Clone, PartialEq)]
pub enum Token<S> {
    Identifier(S),
    String(S),
}

struct Tokens<S> {
    vec: Vec<Token<S>>,
}

pub trait InputIter {
    type Item;
    type Iter: Iterator<Item = (usize, Self::Item)>;
    type IterElem: Iterator<Item = Self::Item>;

    fn iter_indices(&self) -> Self::Iter;
    fn iter_elements(&self) -> Self::IterElem;
}

impl<'a> InputIter for Tokens<&'a str> {
    type Item = Token<&'a str>;
    type Iter = Enumerate<Self::IterElem>;
    type IterElem = Iter<'a, Token<&'a str>>;

    fn iter_indices(&self) -> Self::Iter {
        self.vec.iter().enumerate()
    }

    fn iter_elements(&self) -> Self::IterElem {
        self.vec.iter()
    }
}

fn main() {}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, Token<&str>> as std::iter::Iterator>::Item == Token<&str>`
  --> src/main.rs:24:5
   |
23 | impl<'a> InputIter for Tokens<&'a str> {
   | -------------------------------------- in this `impl` item
24 |     type Item = Token<&'a str>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found enum `Token`
   |
   = note: expected reference `&Token<&str>`
                   found enum `Token<&str>`

error[E0271]: type mismatch resolving `<std::iter::Enumerate<std::slice::Iter<'_, Token<&str>>> as std::iter::Iterator>::Item == (usize, Token<&str>)`
  --> src/main.rs:24:5
   |
23 | impl<'a> InputIter for Tokens<&'a str> {
   | -------------------------------------- in this `impl` item
24 |     type Item = Token<&'a str>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found enum `Token`
   |
   = note: expected tuple `(_, &Token<&str>)`
              found tuple `(_, Token<&str>)`
...