rust-nix/src/parser/source.rs

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 }
}
}