478 lines
14 KiB
Rust
478 lines
14 KiB
Rust
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.clone()), |x: Span| into_locate(x))), |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.clone()), |x: Span| into_locate(x))), |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.clone()), 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.clone()), 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.clone()), into_locate)),
|
|
terminated(map(tag(t.clone()), 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.clone()), into_locate)),
|
|
terminated(map(tag(t.clone()), 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), |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 = str_concat::concat(a.fragment, b.fragment);
|
|
if let Ok(c) = c {
|
|
Some(Span {
|
|
offset: a.offset,
|
|
line: a.line,
|
|
fragment: c,
|
|
extra: a.extra,
|
|
})
|
|
} 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.offset,
|
|
line: s.line,
|
|
len: s.fragment.len(),
|
|
}
|
|
}
|