sv-parser/src/parser/utils.rs
2019-07-11 16:43:51 +09:00

273 lines
6.6 KiB
Rust

use crate::node::*;
use crate::parser::*;
use node_derive::Node;
use nom::branch::*;
use nom::bytes::complete::*;
use nom::character::complete::*;
use nom::combinator::*;
use nom::error::*;
use nom::multi::*;
use nom::{Err, IResult};
// -----------------------------------------------------------------------------
#[derive(Debug, Node)]
pub struct Symbol<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
}
#[derive(Debug, Node)]
pub enum WhiteSpace<'a> {
Space(Span<'a>),
Comment(Comment<'a>),
}
#[derive(Debug)]
pub struct Paren<'a, T: 'a> {
pub nodes: (Symbol<'a>, T, Symbol<'a>),
}
#[derive(Debug)]
pub struct Brace<'a, T: 'a> {
pub nodes: (Symbol<'a>, T, Symbol<'a>),
}
#[derive(Debug)]
pub struct Bracket<'a, T: 'a> {
pub nodes: (Symbol<'a>, T, Symbol<'a>),
}
#[derive(Debug)]
pub struct ApostropheBrace<'a, T: 'a> {
pub nodes: (Symbol<'a>, T, Symbol<'a>),
}
#[derive(Debug)]
pub struct List<U, T> {
pub nodes: (T, Vec<(U, T)>),
}
// -----------------------------------------------------------------------------
pub fn ws<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, (O, Vec<WhiteSpace<'a>>)>
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 fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol<'a>> {
move |s: Span<'a>| map(ws(tag(t.clone())), |x| Symbol { nodes: x })(s)
}
pub fn paren2<'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) }))
}
}
pub fn bracket2<'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) }))
}
}
pub fn brace2<'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) }))
}
}
pub fn apostrophe_brace2<'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) }))
}
}
pub 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.clone();
let mut ret = Vec::new();
loop {
if let Ok((t, b)) = f(s) {
let (u, c) = g(t)?;
s = u;
ret.push((b, c));
} else {
break;
}
}
Ok((s, List { nodes: (a, ret) }))
}
}
pub fn paren<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, _) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, _) = symbol(")")(s)?;
Ok((s, b))
}
}
pub fn bracket<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, _) = symbol("[")(s)?;
let (s, b) = f(s)?;
let (s, _) = symbol("]")(s)?;
Ok((s, b))
}
}
pub fn brace<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, _) = symbol("{")(s)?;
let (s, x) = f(s)?;
let (s, _) = symbol("}")(s)?;
Ok((s, x))
}
}
pub fn apostrophe_brace<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
let (s, _) = symbol("'{")(s)?;
let (s, x) = f(s)?;
let (s, _) = symbol("}")(s)?;
Ok((s, x))
}
}
pub fn rec<'a, O, F>(f: F, id: u32) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
if check_bit(s, id) {
return Err(Err::Error(make_error(s, ErrorKind::Fix)));
}
let s = set_bit(s, id, true);
let (s, x) = f(s)?;
let s = set_bit(s, id, false);
Ok((s, x))
}
}
pub 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 fn white_space(s: Span) -> IResult<Span, WhiteSpace> {
alt((
map(multispace1, |x| WhiteSpace::Space(x)),
map(comment, |x| WhiteSpace::Comment(x)),
))(s)
}
// -----------------------------------------------------------------------------
pub 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 fn check_bit(s: Span, id: u32) -> bool {
((s.extra >> id) & 1) == 1
}
pub fn set_bit(s: Span, id: u32, bit: bool) -> Span {
let val = if bit { 1u64 << id } else { 0u64 };
let mask = !(1u64 << id);
let val = (s.extra & mask) | val;
Span {
offset: s.offset,
line: s.line,
fragment: s.fragment,
extra: val,
}
}
// -----------------------------------------------------------------------------
#[cfg(test)]
macro_rules! parser_test {
( $x:expr, $y:expr, $z:pat ) => {
let ret = all_consuming($x)(Span::new_extra($y, 0));
if let $z = ret {
} else {
assert!(false, "{:?}", ret)
}
};
}