315 lines
6.7 KiB
Rust
315 lines
6.7 KiB
Rust
use std::sync::Arc;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Source {
|
|
pub filename: String,
|
|
pub content: String,
|
|
}
|
|
|
|
impl Source {
|
|
pub fn span<'a>(self: &'a Arc<Self>) -> SpanRef<'a> {
|
|
// Ensure offset/length can be stored in u32 for `Span`
|
|
assert!(self.content.len() <= u32::MAX as usize);
|
|
SpanRef {
|
|
source: self,
|
|
data: self.content.as_str(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Span {
|
|
source: Arc<Source>,
|
|
start: u32,
|
|
length: u32,
|
|
}
|
|
|
|
impl Span {
|
|
pub fn as_str(&self) -> &str {
|
|
&self.source.content[self.start as usize..][..self.length as usize]
|
|
}
|
|
|
|
pub fn as_ref(&self) -> SpanRef<'_> {
|
|
SpanRef {
|
|
source: &self.source,
|
|
data: self.as_str(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl nom::Slice<std::ops::Range<usize>> for Span {
|
|
fn slice(&self, range: std::ops::Range<usize>) -> Self {
|
|
assert!(range.start <= range.end);
|
|
assert!(range.end <= self.length as usize);
|
|
Self {
|
|
source: self.source.clone(),
|
|
start: self.start + range.start as u32,
|
|
length: (range.end - range.start) as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl nom::Slice<std::ops::RangeTo<usize>> for Span {
|
|
fn slice(&self, range: std::ops::RangeTo<usize>) -> Self {
|
|
assert!(range.end <= self.length as usize);
|
|
Self {
|
|
source: self.source.clone(),
|
|
start: self.start,
|
|
length: range.end as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl nom::Slice<std::ops::RangeFrom<usize>> for Span {
|
|
fn slice(&self, range: std::ops::RangeFrom<usize>) -> Self {
|
|
assert!(range.start <= self.length as usize);
|
|
Self {
|
|
source: self.source.clone(),
|
|
start: self.start + range.start as u32,
|
|
length: self.length - range.start as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl nom::Slice<std::ops::RangeFull> for Span {
|
|
fn slice(&self, _range: std::ops::RangeFull) -> Self {
|
|
self.clone()
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for Span {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}:{}: {:?}",
|
|
self.source.filename,
|
|
self.start,
|
|
self.as_str(),
|
|
)
|
|
}
|
|
}
|
|
|
|
impl From<SpanRef<'_>> for Span {
|
|
fn from(span_ref: SpanRef<'_>) -> Self {
|
|
use nom::Offset;
|
|
let start = span_ref.source.content.as_str().offset(span_ref.data) as u32;
|
|
Self {
|
|
source: span_ref.source.clone(),
|
|
start,
|
|
length: span_ref.data.len() as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct SpanRef<'a> {
|
|
source: &'a Arc<Source>,
|
|
data: &'a str,
|
|
}
|
|
|
|
impl std::fmt::Debug for SpanRef<'_> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
use nom::Offset;
|
|
write!(
|
|
f,
|
|
"{}:{}: {:?}",
|
|
self.source.filename,
|
|
self.source.content.as_str().offset(self.data),
|
|
self.data,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<'a> SpanRef<'a> {
|
|
pub fn as_str(&self) -> &'a str {
|
|
self.data
|
|
}
|
|
|
|
fn locate(&self, data: &str) -> &'a str {
|
|
use nom::Offset;
|
|
&self.data[self.data.offset(data)..][..data.len()]
|
|
}
|
|
|
|
fn lift_error<E>(&self, e: nom::error::Error<&str>) -> E
|
|
where
|
|
E: nom::error::ParseError<Self>
|
|
{
|
|
let input = Self { data: self.locate(e.input), ..*self };
|
|
E::from_error_kind(input, e.code)
|
|
}
|
|
|
|
fn lift_result<T, E>(&self, r: Result<T, nom::Err<nom::error::Error<&str>>>) -> Result<T, nom::Err<E>>
|
|
where
|
|
E: nom::error::ParseError<Self>
|
|
{
|
|
match r {
|
|
Ok(v) => Ok(v),
|
|
Err(e) => Err(e.map(|e| self.lift_error(e))),
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a> nom::AsBytes for SpanRef<'a> {
|
|
fn as_bytes(&self) -> &'a [u8] {
|
|
self.data.as_bytes()
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b> nom::Compare<&'b str> for SpanRef<'a> {
|
|
#[inline(always)]
|
|
fn compare(&self, t: &'b str) -> nom::CompareResult {
|
|
self.data.compare(t)
|
|
}
|
|
|
|
fn compare_no_case(&self, t: &'b str) -> nom::CompareResult {
|
|
self.data.compare_no_case(t)
|
|
}
|
|
}
|
|
|
|
impl nom::ExtendInto for SpanRef<'_> {
|
|
type Item = char;
|
|
type Extender = String;
|
|
|
|
fn new_builder(&self) -> Self::Extender {
|
|
String::new()
|
|
}
|
|
|
|
fn extend_into(&self, acc: &mut Self::Extender) {
|
|
acc.push_str(self.data);
|
|
}
|
|
}
|
|
|
|
impl nom::FindSubstring<&str> for SpanRef<'_> {
|
|
fn find_substring(&self, substr: &str) -> Option<usize> {
|
|
self.data.find_substring(substr)
|
|
}
|
|
}
|
|
|
|
impl<T> nom::FindToken<T> for SpanRef<'_>
|
|
where
|
|
for<'a> &'a str: nom::FindToken<T>,
|
|
{
|
|
fn find_token(&self, token: T) -> bool {
|
|
self.data.find_token(token)
|
|
}
|
|
}
|
|
|
|
impl<'a> nom::InputIter for SpanRef<'a> {
|
|
type Item = char;
|
|
type Iter = std::str::CharIndices<'a>;
|
|
type IterElem = std::str::Chars<'a>;
|
|
|
|
fn iter_indices(&self) -> Self::Iter {
|
|
self.data.iter_indices()
|
|
}
|
|
|
|
fn iter_elements(&self) -> Self::IterElem {
|
|
self.data.iter_elements()
|
|
}
|
|
|
|
fn position<P>(&self, predicate: P) -> Option<usize>
|
|
where
|
|
P: Fn(Self::Item) -> bool
|
|
{
|
|
self.data.position(predicate)
|
|
}
|
|
|
|
fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> {
|
|
self.as_str().slice_index(count)
|
|
}
|
|
}
|
|
|
|
impl nom::InputLength for SpanRef<'_> {
|
|
fn input_len(&self) -> usize {
|
|
self.data.len() as usize
|
|
}
|
|
}
|
|
|
|
impl<'a> nom::InputTake for SpanRef<'a> {
|
|
fn take(&self, count: usize) -> Self {
|
|
let data = self.data.take(count);
|
|
Self { data, ..*self }
|
|
}
|
|
|
|
fn take_split(&self, count: usize) -> (Self, Self) {
|
|
let (prefix, suffix) = self.data.take_split(count);
|
|
(Self { data: prefix, ..*self }, Self { data: suffix, ..*self })
|
|
}
|
|
}
|
|
|
|
impl nom::InputTakeAtPosition for SpanRef<'_> {
|
|
type Item = char;
|
|
|
|
fn split_at_position<P, E: nom::error::ParseError<Self>>(
|
|
&self,
|
|
predicate: P
|
|
) -> nom::IResult<Self, Self, E>
|
|
where
|
|
P: Fn(Self::Item) -> bool
|
|
{
|
|
let (rem, data) = self.lift_result(self.data.split_at_position(predicate))?;
|
|
Ok((Self { data: rem, ..*self }, Self { data, ..*self } ))
|
|
}
|
|
|
|
fn split_at_position1<P, E: nom::error::ParseError<Self>>(
|
|
&self,
|
|
predicate: P,
|
|
e: nom::error::ErrorKind
|
|
) -> nom::IResult<Self, Self, E>
|
|
where
|
|
P: Fn(Self::Item) -> bool
|
|
{
|
|
let (rem, data) = self.lift_result(self.data.split_at_position1(predicate, e))?;
|
|
Ok((Self { data: rem, ..*self }, Self { data, ..*self } ))
|
|
}
|
|
|
|
fn split_at_position_complete<P, E: nom::error::ParseError<Self>>(
|
|
&self,
|
|
predicate: P
|
|
) -> nom::IResult<Self, Self, E>
|
|
where
|
|
P: Fn(Self::Item) -> bool
|
|
{
|
|
let (rem, data) = self.lift_result(self.data.split_at_position_complete(predicate))?;
|
|
Ok((Self { data: rem, ..*self }, Self { data, ..*self } ))
|
|
}
|
|
|
|
fn split_at_position1_complete<P, E: nom::error::ParseError<Self>>(
|
|
&self,
|
|
predicate: P,
|
|
e: nom::error::ErrorKind
|
|
) -> nom::IResult<Self, Self, E>
|
|
where
|
|
P: Fn(Self::Item) -> bool
|
|
{
|
|
let (rem, data) = self.lift_result(self.data.split_at_position1_complete(predicate, e))?;
|
|
Ok((Self { data: rem, ..*self }, Self { data, ..*self } ))
|
|
}
|
|
}
|
|
|
|
impl<R> nom::ParseTo<R> for SpanRef<'_>
|
|
where
|
|
for<'a> &'a str: nom::ParseTo<R>,
|
|
{
|
|
fn parse_to(&self) -> Option<R> {
|
|
self.data.parse_to()
|
|
}
|
|
}
|
|
|
|
impl nom::Offset for SpanRef<'_> {
|
|
fn offset(&self, second: &Self) -> usize {
|
|
self.as_str().offset(second.as_str())
|
|
}
|
|
}
|
|
|
|
impl<R> nom::Slice<R> for SpanRef<'_>
|
|
where
|
|
for<'a> &'a str: nom::Slice<R>
|
|
{
|
|
fn slice(&self, range: R) -> Self {
|
|
let data = self.data.slice(range);
|
|
Self { data, ..*self }
|
|
}
|
|
}
|