Skip to main content

Input

Struct Input 

Source
pub struct Input<'a> { /* private fields */ }
Expand description

The pending text of one REPL entry, as the pipeline sees it.

Each time a line is fed to a Session, the session calls the pipeline with an Input holding every line of the entry so far — the first line, then the first two, and so on until the pipeline answers Status::Complete. Lines are joined with '\n' and the text always ends with one.

The input also carries its position in the session’s SourceMap: base is the global offset its first byte will occupy once the entry is committed. Lex with cursor, or offset spans by base yourself, and every span the pipeline produces — in tokens, in syntax trees, in diagnostics — is already valid against Session::sources. There is no second pass to rebase spans after the entry is accepted.

Input is a borrowed, Copy view; it lives only for the duration of the pipeline call.

§Examples

use repl_lang::{Feed, Session, Status};

let mut session = Session::new();
let feed = session.feed("1 + 2", |input| {
    assert_eq!(input.text(), "1 + 2\n");
    assert_eq!(input.number(), 1);
    Status::Complete(input.text().len())
})?;
assert!(matches!(feed, Feed::Complete { value: 6, .. }));

Implementations§

Source§

impl<'a> Input<'a>

Source

pub const fn text(&self) -> &'a str

Every line of the entry so far, joined with '\n' and ending with one.

§Examples
use repl_lang::{Feed, Session, Status};

let mut session = Session::new();
let mut seen = Vec::new();
for line in ["(1 +", " 2)"] {
    session.feed(line, |input| {
        seen.push(input.text().to_owned());
        if input.text().matches('(').count() > input.text().matches(')').count() {
            Status::Incomplete
        } else {
            Status::Complete(())
        }
    })?;
}
assert_eq!(seen, ["(1 +\n", "(1 +\n 2)\n"]);
Source

pub const fn base(&self) -> BytePos

The global position the first byte of this entry occupies in the session’s source map.

Entries are laid out end to end, so the base of entry n is the total length of entries 1 through n − 1.

§Examples
use repl_lang::{Session, Status};

let mut session = Session::new();
session.feed("abc", |_| Status::Complete(()))?; // occupies 0..4 ("abc\n")
session.feed("x", |input| {
    assert_eq!(input.base().to_u32(), 4);
    Status::Complete(())
})?;
Source

pub const fn span(&self) -> Span

The global span the whole entry will occupy: from base to the end of text.

§Examples
use repl_lang::{Session, Span, Status};

let mut session = Session::new();
session.feed("let x = 1", |input| {
    assert_eq!(input.span(), Span::new(0, 10));
    Status::Complete(())
})?;
Source

pub const fn number(&self) -> u32

The entry number this input will be committed as, counting from 1.

Useful for prompts (In [3]:) and for names the evaluator binds per entry (_3). The number does not advance while an entry is incomplete, and blank lines never consume one.

§Examples
use repl_lang::{Session, Status};

let mut session = Session::new();
session.feed("a", |input| { assert_eq!(input.number(), 1); Status::Complete(()) })?;
session.feed("b", |input| { assert_eq!(input.number(), 2); Status::Complete(()) })?;
Source

pub fn cursor(&self) -> Cursor<'a>

A lexer_lang::Cursor over text, positioned at base.

Every token span the cursor produces is a global span in the session’s source map, so tokens, the syntax built from them, and any diagnostic pointing at them render correctly against Session::sources once the entry is committed.

§Examples
use repl_lang::{Session, Status};

let mut session = Session::new();
session.feed("first", |_| Status::Complete(()))?; // 0..6
session.feed("ab", |input| {
    let mut cursor = input.cursor();
    cursor.eat_while(|c| c.is_alphabetic());
    assert_eq!(cursor.lexeme(), "ab");
    assert_eq!(cursor.token_span().start().to_u32(), 6); // global, not 0
    Status::Complete(())
})?;
Source

pub fn is_incomplete(&self, errors: &[Diagnostic]) -> bool

Returns true if errors say the input ended too soon rather than that it is wrong — the signal to ask for another line.

That is the case when there is at least one error-severity diagnostic, and every one of them points at the end of the input: its primary span starts at or after the last non-whitespace byte. A parser that reaches the end of 1 + (2 * reports “expected expression” at the end, so the user simply has not finished typing; a parser that trips over 1 + ) reports the error at the ), and more lines will never fix that. Warnings, notes, and help messages are ignored.

The spans are global positions in the session’s source map, as a parser fed by cursor produces them. For a parser that runs on text alone and reports positions from 0 (a lang-forge language, for one), use is_incomplete_relative instead.

The rule matches how parser_lang reports a missing token at the end of input — an empty span just past the last token — and works with any parser that does the same. Errors a lexer reports where a construct starts, such as an unterminated string pointing at its opening quote, are not recognised; return Status::Incomplete for those directly.

§Examples
use diag_lang::{Diagnostic, Label, Severity};
use repl_lang::{Session, Span, Status};

let error_at = |at: u32| {
    Diagnostic::new(Severity::Error, "expected expression", Label::new(Span::empty(at), "here"))
};

let mut session = Session::new();
session.feed("1 + (2 *", |input| {
    // An error at the end (byte 8, before the trailing newline): incomplete.
    assert!(input.is_incomplete(&[error_at(8)]));
    // An error in the middle: the input is wrong, not unfinished.
    assert!(!input.is_incomplete(&[error_at(2), error_at(8)]));
    // No errors at all: complete.
    assert!(!input.is_incomplete(&[]));
    Status::Complete(())
})?;
Source

pub fn is_incomplete_relative(&self, errors: &[Diagnostic]) -> bool

is_incomplete for a parser whose spans are relative to text: byte 0 is the entry’s first byte, whatever its base.

Use it when the pipeline parses input.text() on its own, without cursor — a language forged with lang-forge, for example, whose Language::parse(input.text()) reports positions from 0. The rule is the same as is_incomplete’s: at least one error-severity diagnostic, and every one starting at or after the last non-whitespace byte of the text. Passing relative spans to is_incomplete instead would judge every entry after the first complete, because their end-of-input errors fall before the entry’s global end.

Which method suits which parser:

The parser…SpansMethod
lexes with Input::cursor (or adds Input::base itself)globalis_incomplete
parses Input::text as a standalone stringrelativeis_incomplete_relative

In the first entry the two agree, since base is 0; from the second on, only the matching one is right.

§Examples
use diag_lang::{Diagnostic, Label, Severity};
use repl_lang::{Session, Span, Status};

let error_at = |at: u32| {
    Diagnostic::new(Severity::Error, "expected expression", Label::new(Span::empty(at), "here"))
};

let mut session = Session::new();
session.feed("let a = 1;", |_| Status::Complete(()))?; // occupies 0..11
session.feed("(2 *", |input| {
    assert_eq!(input.base().to_u32(), 11);
    // A parser of `input.text()` alone reports the end of `(2 *` at 4.
    assert!(input.is_incomplete_relative(&[error_at(4)]));
    assert!(!input.is_incomplete_relative(&[error_at(1)])); // mid-text
    // The same spans read as global would point into entry 1.
    assert!(!input.is_incomplete(&[error_at(4)]));
    Status::Complete(())
})?;

Trait Implementations§

Source§

impl<'a> Clone for Input<'a>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Copy for Input<'a>

Source§

impl<'a> Debug for Input<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Eq for Input<'a>

Source§

impl<'a> PartialEq for Input<'a>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<'a> StructuralPartialEq for Input<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for Input<'a>

§

impl<'a> RefUnwindSafe for Input<'a>

§

impl<'a> Send for Input<'a>

§

impl<'a> Sync for Input<'a>

§

impl<'a> Unpin for Input<'a>

§

impl<'a> UnsafeUnpin for Input<'a>

§

impl<'a> UnwindSafe for Input<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.