use crate::*;
pub(crate) fn ws<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, (O, Vec<WhiteSpace>)>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, x) = f(s)?;
let (s, y) = many0(white_space)(s)?;
Ok((s, (x, y)))
}
}
pub(crate) fn no_ws<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, (O, Vec<WhiteSpace>)>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, x) = f(s)?;
Ok((s, (x, vec![])))
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol> {
move |s: Span<'a>| {
let (s, x) = map(ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
Ok((s, x))
}
}
#[cfg(feature = "trace")]
pub(crate) fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol> {
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, &format!("symbol(\"{}\")", t));
let body = || {
let (s, x) = map(ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
Ok((s, x))
};
let ret = body();
nom_tracable::backward_trace(ret, &format!("symbol(\"{}\")", t), depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol> {
move |s: Span<'a>| {
let (s, x) = map(no_ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
Ok((s, x))
}
}
#[cfg(feature = "trace")]
pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol> {
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, &format!("symbol(\"{}\")", t));
let body = || {
let (s, x) = map(no_ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
Ok((s, x))
};
let ret = body();
nom_tracable::backward_trace(ret, &format!("symbol(\"{}\")", t), depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Keyword> {
move |s: Span<'a>| {
let (s, x) = map(
ws(alt((
all_consuming(map(tag(t), into_locate)),
terminated(map(tag(t), into_locate), peek(none_of(AZ09_))),
))),
|x| Keyword { nodes: x },
)(s)?;
Ok((s, x))
}
}
#[cfg(feature = "trace")]
pub(crate) fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Keyword> {
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, &format!("keyword(\"{}\")", t));
let body = || {
let (s, x) = map(
ws(alt((
all_consuming(map(tag(t), into_locate)),
terminated(map(tag(t), into_locate), peek(none_of(AZ09_))),
))),
|x| Keyword { nodes: x },
)(s)?;
Ok((s, x))
};
let ret = body();
nom_tracable::backward_trace(ret, &format!("keyword(\"{}\")", t), depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn paren<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Paren<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, a) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol(")")(s)?;
Ok((s, Paren { nodes: (a, b, c) }))
}
}
#[cfg(feature = "trace")]
pub(crate) fn paren<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Paren<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, "paren");
let body = || {
let (s, a) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol(")")(s)?;
Ok((s, Paren { nodes: (a, b, c) }))
};
let ret = body();
nom_tracable::backward_trace(ret, "paren", depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn paren_exact<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Paren<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, a) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol_exact(")")(s)?;
Ok((s, Paren { nodes: (a, b, c) }))
}
}
#[cfg(feature = "trace")]
pub(crate) fn paren_exact<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Paren<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, "paren");
let body = || {
let (s, a) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol_exact(")")(s)?;
Ok((s, Paren { nodes: (a, b, c) }))
};
let ret = body();
nom_tracable::backward_trace(ret, "paren", depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn bracket<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Bracket<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, a) = symbol("[")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("]")(s)?;
Ok((s, Bracket { nodes: (a, b, c) }))
}
}
#[cfg(feature = "trace")]
pub(crate) fn bracket<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Bracket<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, "bracket");
let body = || {
let (s, a) = symbol("[")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("]")(s)?;
Ok((s, Bracket { nodes: (a, b, c) }))
};
let ret = body();
nom_tracable::backward_trace(ret, "bracket", depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn brace<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Brace<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, a) = symbol("{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
Ok((s, Brace { nodes: (a, b, c) }))
}
}
#[cfg(feature = "trace")]
pub(crate) fn brace<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Brace<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, "brace");
let body = || {
let (s, a) = symbol("{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
Ok((s, Brace { nodes: (a, b, c) }))
};
let ret = body();
nom_tracable::backward_trace(ret, "brace", depth)
}
}
#[cfg(not(feature = "trace"))]
pub(crate) fn apostrophe_brace<'a, O, F>(
f: F,
) -> impl Fn(Span<'a>) -> IResult<Span<'a>, ApostropheBrace<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, a) = symbol("'{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
Ok((s, ApostropheBrace { nodes: (a, b, c) }))
}
}
#[cfg(feature = "trace")]
pub(crate) fn apostrophe_brace<'a, O, F>(
f: F,
) -> impl Fn(Span<'a>) -> IResult<Span<'a>, ApostropheBrace<O>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (depth, s) = nom_tracable::forward_trace(s, "apostrophe_brace");
let body = || {
let (s, a) = symbol("'{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
Ok((s, ApostropheBrace { nodes: (a, b, c) }))
};
let ret = body();
nom_tracable::backward_trace(ret, "apostrophe_brace", depth)
}
}
pub(crate) fn list<'a, O1, O2, F, G>(
f: F,
g: G,
) -> impl Fn(Span<'a>) -> IResult<Span<'a>, List<O1, O2>>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O1>,
G: Fn(Span<'a>) -> IResult<Span<'a>, O2>,
{
move |s: Span<'a>| {
let (s, a) = g(s)?;
let mut s = s;
let mut ret = Vec::new();
while let Ok((t, b)) = f(s) {
if let Ok((u, c)) = g(t) {
s = u;
ret.push((b, c));
} else {
break;
}
}
Ok((s, List { nodes: (a, ret) }))
}
}
pub(crate) fn triple<'a, O1, O2, O3, F, G, H>(
f: F,
g: G,
h: H,
) -> impl Fn(Span<'a>) -> IResult<Span<'a>, (O1, O2, O3)>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O1>,
G: Fn(Span<'a>) -> IResult<Span<'a>, O2>,
H: Fn(Span<'a>) -> IResult<Span<'a>, O3>,
{
move |s: Span<'a>| {
let (s, x) = f(s)?;
let (s, y) = g(s)?;
let (s, z) = h(s)?;
Ok((s, (x, y, z)))
}
}
pub(crate) fn eof(s: Span) -> IResult<Span, Span> {
use nom::InputLength;
if s.input_len() == 0 {
Ok((s, s))
} else {
Err(Err::Error(make_error(s, ErrorKind::Eof)))
}
}
#[tracable_parser]
#[packrat_parser]
pub(crate) fn white_space(s: Span) -> IResult<Span, WhiteSpace> {
if in_directive() {
alt((
map(multispace1, |x: Span| {
WhiteSpace::Space(Box::new(into_locate(x)))
}),
map(preceded(peek(char('/')), comment), |x| {
WhiteSpace::Comment(Box::new(x))
}),
))(s)
} else {
alt((
map(multispace1, |x: Span| {
WhiteSpace::Space(Box::new(into_locate(x)))
}),
map(preceded(peek(char('/')), comment), |x| {
WhiteSpace::Comment(Box::new(x))
}),
map(
preceded(peek(char('`')), compiler_directive_without_resetall),
|x| WhiteSpace::CompilerDirective(Box::new(x)),
),
))(s)
}
}
thread_local!(
static IN_DIRECTIVE: core::cell::RefCell<Vec<()>> = {
core::cell::RefCell::new(Vec::new())
}
);
pub(crate) fn in_directive() -> bool {
IN_DIRECTIVE.with(|x| x.borrow().last().is_some())
}
pub(crate) fn begin_directive() {
IN_DIRECTIVE.with(|x| x.borrow_mut().push(()));
}
pub(crate) fn end_directive() {
IN_DIRECTIVE.with(|x| x.borrow_mut().pop());
}
#[derive(Clone, Copy)]
pub(crate) enum VersionSpecifier {
Ieee1364_1995,
Ieee1364_2001,
Ieee1364_2001Noconfig,
Ieee1364_2005,
Ieee1800_2005,
Ieee1800_2009,
Ieee1800_2012,
Ieee1800_2017,
Directive,
}
thread_local!(
static CURRENT_VERSION: core::cell::RefCell<Vec<VersionSpecifier>> = {
core::cell::RefCell::new(Vec::new())
}
);
pub(crate) fn begin_keywords(version: &str) {
CURRENT_VERSION.with(|current_version| match version {
"1364-1995" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1364_1995),
"1364-2001" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1364_2001),
"1364-2001-noconfig" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1364_2001Noconfig),
"1364-2005" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1364_2005),
"1800-2005" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1800_2005),
"1800-2009" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1800_2009),
"1800-2012" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1800_2012),
"1800-2017" => current_version
.borrow_mut()
.push(VersionSpecifier::Ieee1800_2017),
"directive" => current_version
.borrow_mut()
.push(VersionSpecifier::Directive),
_ => (),
});
}
pub(crate) fn end_keywords() {
CURRENT_VERSION.with(|current_version| {
current_version.borrow_mut().pop();
});
}
pub(crate) fn current_version() -> Option<VersionSpecifier> {
CURRENT_VERSION.with(|current_version| match current_version.borrow().last() {
Some(x) => Some(*x),
None => None,
})
}
pub(crate) fn concat<'a>(a: Span<'a>, b: Span<'a>) -> Option<Span<'a>> {
let c = unsafe { str_concat::concat(a.fragment(), b.fragment()) };
if let Ok(c) = c {
let ret = unsafe {
Span::new_from_raw_offset(a.location_offset(), a.location_line(), c, a.extra)
};
Some(ret)
} else {
None
}
}
pub(crate) fn is_keyword(s: &Span) -> bool {
let keywords = match current_version() {
Some(VersionSpecifier::Ieee1364_1995) => KEYWORDS_1364_1995,
Some(VersionSpecifier::Ieee1364_2001) => KEYWORDS_1364_2001,
Some(VersionSpecifier::Ieee1364_2001Noconfig) => KEYWORDS_1364_2001_NOCONFIG,
Some(VersionSpecifier::Ieee1364_2005) => KEYWORDS_1364_2005,
Some(VersionSpecifier::Ieee1800_2005) => KEYWORDS_1800_2005,
Some(VersionSpecifier::Ieee1800_2009) => KEYWORDS_1800_2009,
Some(VersionSpecifier::Ieee1800_2012) => KEYWORDS_1800_2012,
Some(VersionSpecifier::Ieee1800_2017) => KEYWORDS_1800_2017,
Some(VersionSpecifier::Directive) => KEYWORDS_DIRECTIVE,
None => KEYWORDS_1800_2017,
};
for k in keywords {
if s.fragment() == k {
return true;
}
}
false
}
pub(crate) fn into_locate(s: Span) -> Locate {
Locate {
offset: s.location_offset(),
line: s.location_line(),
len: s.fragment().len(),
}
}