Чтение байтов из файла и их разбор с помощью библиотеки парсера `pom`

Я пытаюсь написать синтаксический анализатор с pom, и это здорово - нет проблем с написанием синтаксических анализаторов. и подача строкового литерала в качестве тестовых данных. Однако, когда я пытаюсь запустить его байтами из файла, он задыхается;

108 |     fn parse_files() -> Result<(), Box<dyn Error>> {
109 |         let byte_vec: Vec<u8> = std::fs::read("assets/valid_so_far.idl")?;
110 |         let byte_slice: &[u8] = &byte_vec;
    |                                 ^^^^^^^^^ borrowed value does not live long enough
111 |         let idl_parser = idl();
112 |         let parse_result = idl_parser.parse(byte_slice)?;
    |                            ---------------------------- argument requires that `byte_vec` is borrowed for `'static`
113 |         
114 |         Ok(())
115 |     }
    |     - `byte_vec` dropped here while still borrowed

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

Функция parse в строке 109 имеет следующую подпись:

fn parse(&self, input: &'a [I]) -> Result<O>

pub type Result<O> = ::std::result::Result<O, Error>;

person Steve Cooper    schedule 18.12.2019    source источник
comment
Я подозреваю, что это как-то связано с Error, возвращаемым parse. Может быть, с точки зрения компилятора, он может содержать ссылку на ввод, поэтому он не должен пережить его, будучи возвращенным... Не могли бы вы поделиться подробнее о самом синтаксическом анализаторе?   -  person michalsrb    schedule 18.12.2019
comment
Компилируется ли он, если вы match результат idl_parser.parse(byte_slice) вручную и конвертируете Err во что-то, что точно не относится к byte_slice?   -  person phimuemue    schedule 18.12.2019
comment
Трудно ответить на ваш вопрос, потому что он не включает минимально воспроизводимый пример. Мы не можем сказать, какие крейты (и их версии), типы, трейты, поля и т. д. присутствуют в коде. Нам будет легче помочь вам, если вы попытаетесь воспроизвести ошибку на Rust Playground, если возможно, в противном случае в новом проекте Cargo отредактируйте свой вопрос, чтобы включить дополнительную информацию. Существуют советы по MRE для Rust, которые вы можете использовать, чтобы уменьшить исходный код для публикации здесь. Спасибо!   -  person Shepmaster    schedule 18.12.2019


Ответы (2)


нет проблем с написанием синтаксических анализаторов и подачей строкового литерала в качестве тестовых данных.

Это работает, потому что все строковые литералы имеют 'static время жизни. Когда вместо этого вы переключаетесь на чтение из файла, скрытый 'static исчезает. Поведение кода на самом деле меняется так, что вызывает ошибку.

Тогда возникает вопрос, почему ваша реализация синтаксического анализатора ожидает ввода 'static в первую очередь. Я подозреваю, что здесь виноват пример, приведенный в файле pom для чтения. Например, он имеет следующий код:

use pom::Parser;

fn space() -> Parser<u8, ()> {
    one_of(b" \t\r\n").repeat(0..).discard()
}

pom::Parser<u8, ()> на самом деле является псевдонимом pom::parser::Parser<'static, u8, ()>. Если бы это было написано так:

use pom::parser::Parser;

fn space<'a>() -> Parser<'a, u8, ()> {
    one_of(b" \t\r\n").repeat(0..).discard()
}

тогда он должен иметь возможность обрабатывать ввод как 'static, так и не 'static. Внесите аналогичные изменения в код вашего парсера, и он снова заработает.

person edwardw    schedule 18.12.2019
comment
Это работает, потому что константное r-значение, такое как литерал, подвергается статическому продвижению — здесь это не имеет значения. Строковые литералы всегда &'static str. Как время жизни работает с постоянными строками/строковыми литералами? - person Shepmaster; 18.12.2019
comment
это точно! У меня был блок use pom::* \n use pom::Parser вверху файла. Удаление второй строки исправило это - person Steve Cooper; 19.12.2019
comment
извините - это должно читаться use pom::parser::*; use pom::Parser - person Steve Cooper; 19.12.2019

pom::Parser<I, O> — это псевдоним для pom::parser::Parser<'static, I, O>. Таким образом, время жизни 'a в функции parse на самом деле равно 'static, если вы используете этот псевдоним. Используйте структуру pom::parser::Parser напрямую с пользовательским (возможно, опущенным - вам не нужно его писать) временем жизни.

person michalsrb    schedule 18.12.2019
comment
Спасибо за это! Вы правы - извините, я тоже не смог отметить ваш ответ как правильный. - person Steve Cooper; 19.12.2019