rust-nix/src/parser/token/brackets.rs

170 lines
3.5 KiB
Rust

use super::{
Token,
SpannedData,
SpanRef,
PResult,
TokenList,
IResultExt,
SpanExt,
};
fn parse_bracketed<'a, O, C, F, T>(
open_tag: &'static str,
close_tag: &'static str,
open: O,
close: C,
constructor: F,
span: SpanRef<'a>,
) -> PResult<'a, SpannedData<T>>
where
F: FnOnce(SpannedData<O>, TokenList, SpannedData<C>) -> T,
{
use nom::{Offset, Slice};
let (rem_span, open_span) = nom::bytes::complete::tag(open_tag)(span)?;
let (rem_span, inner) = TokenList::parse_expression(rem_span).unrecoverable()?;
let (rem_span, close_span) = nom::bytes::complete::tag(close_tag)(rem_span).unrecoverable()?;
let result = constructor(open_span.data(open), inner, close_span.data(close));
let index = span.offset(&rem_span);
let bracket_span = span.slice(..index);
Ok((rem_span, bracket_span.data(result)))
}
#[derive(Clone, Debug)]
pub struct CurlyOpen;
#[derive(Clone, Debug)]
pub struct CurlyClose;
#[derive(Clone)]
pub struct CurlyBrackets {
pub open: SpannedData<CurlyOpen>,
pub inner: TokenList,
pub close: SpannedData<CurlyClose>,
}
impl CurlyBrackets {
pub(super) fn parse(span: SpanRef) -> PResult<SpannedData<Token>> {
parse_bracketed(
"{", "}", CurlyOpen, CurlyClose,
|open, inner, close| {
Self { open, inner, close }.into()
},
span,
)
}
}
impl std::fmt::Debug for CurlyBrackets {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.inner.0.is_empty() {
f.write_str("{ }")
} else {
write!(f, "{{ {:?} }}", self.inner)
}
}
}
#[derive(Clone, Debug)]
pub struct SquareOpen;
#[derive(Clone, Debug)]
pub struct SquareClose;
#[derive(Clone)]
pub struct SquareBrackets {
pub open: SpannedData<SquareOpen>,
pub inner: TokenList,
pub close: SpannedData<SquareClose>,
}
impl SquareBrackets {
pub(super) fn parse(span: SpanRef) -> PResult<SpannedData<Token>> {
parse_bracketed(
"[", "]", SquareOpen, SquareClose,
|open, inner, close| {
Self { open, inner, close }.into()
},
span,
)
}
}
impl std::fmt::Debug for SquareBrackets {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.inner.0.is_empty() {
f.write_str("[ ]")
} else {
write!(f, "[ {:?} ]", self.inner)
}
}
}
#[derive(Clone, Debug)]
pub struct RoundOpen;
#[derive(Clone, Debug)]
pub struct RoundClose;
#[derive(Clone)]
pub struct RoundBrackets {
pub open: SpannedData<RoundOpen>,
pub inner: TokenList,
pub close: SpannedData<RoundClose>,
}
impl RoundBrackets {
pub(super) fn parse(span: SpanRef) -> PResult<SpannedData<Token>> {
parse_bracketed(
"(", ")", RoundOpen, RoundClose,
|open, inner, close| {
Self { open, inner, close }.into()
},
span,
)
}
}
impl std::fmt::Debug for RoundBrackets {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.inner.0.is_empty() {
f.write_str("( )")
} else {
write!(f, "( {:?} )", self.inner)
}
}
}
#[derive(Clone, Debug)]
pub struct InterpolateOpen;
/// Any `${...}` expresions, whether in strings or outside
#[derive(Clone)]
pub struct Interpolate {
pub open: SpannedData<InterpolateOpen>,
pub inner: TokenList,
pub close: SpannedData<CurlyClose>,
}
impl Interpolate {
pub(super) fn parse(span: SpanRef) -> PResult<SpannedData<Interpolate>> {
parse_bracketed(
"${", "}", InterpolateOpen, CurlyClose,
|open, inner, close| {
Self { open, inner, close }
},
span,
)
}
}
impl std::fmt::Debug for Interpolate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.inner.0.is_empty() {
f.write_str("${ }")
} else {
write!(f, "${{ {:?} }}", self.inner)
}
}
}