use super::BlankIdBuf;
use decoded_char::DecodedChar;
use iref::IriBuf;
use langtag::LangTagBuf;
use locspan::{ErrAt, Meta, Span};
use std::{fmt, iter::Peekable};
/// Fallible tokens iterator with lookahead.
pub trait Tokens {
type Error;
#[allow(clippy::type_complexity)]
fn peek(&mut self) -> Result, Span>, Meta>;
#[allow(clippy::type_complexity)]
fn next(&mut self) -> Result, Span>, Meta>;
/// Begin a new span.
///
/// Skips white spaces and return an empty span at the cursor position.
fn begin(&mut self) -> Result>;
/// Returns the span of the last parsed token.
fn last(&self) -> Span;
}
/// Lexing error.
#[derive(Debug)]
pub enum Error {
InvalidLangTag,
InvalidCodepoint(u32),
InvalidIriRef(String),
Unexpected(Option),
Stream(E),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::InvalidLangTag => write!(f, "invalid language tag"),
Self::InvalidCodepoint(c) => write!(f, "invalid character code point {c:x}"),
Self::InvalidIriRef(iri_ref) => {
write!(f, "invalid IRI reference <{iri_ref}>")
}
Self::Unexpected(None) => write!(f, "unexpected end of file"),
Self::Unexpected(Some(c)) => write!(f, "unexpected character `{c}`"),
Self::Stream(e) => e.fmt(f),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Stream(e) => Some(e),
_ => None,
}
}
}
/// Token.
#[derive(Debug)]
pub enum Token {
LangTag(LangTagBuf),
Iri(IriBuf),
StringLiteral(String),
BlankNodeLabel(BlankIdBuf),
Dot,
Carets,
}
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::LangTag(tag) => write!(f, "language tag `{tag}`"),
Self::Iri(iri) => write!(f, "IRI <{iri}>"),
Self::StringLiteral(string) => {
write!(f, "string literal \"{}\"", DisplayStringLiteral(string))
}
Self::BlankNodeLabel(label) => write!(f, "blank node label `{label}`"),
Self::Dot => write!(f, "dot `.`"),
Self::Carets => write!(f, "carets `^^`"),
}
}
}
/// Wrapper to display string literals.
pub struct DisplayStringLiteral<'a>(pub &'a str);
impl<'a> fmt::Display for DisplayStringLiteral<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.0.chars() {
match c {
'"' => write!(f, "\\u0022"),
'\\' => write!(f, "\\u005c"),
'\n' => write!(f, "\\n"),
'\r' => write!(f, "\\r"),
'\t' => write!(f, "\\t"),
'\u{08}' => write!(f, "\\b"),
'\u{0c}' => write!(f, "\\f"),
c => c.fmt(f),
}?
}
Ok(())
}
}
/// Characters iterator.
struct Chars(Peekable);
impl>> Chars {
fn peek(&mut self) -> Result