use crate::*; // ----------------------------------------------------------------------------- const KEYWORDS: &[&str] = &[ "accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before", "begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle", "checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint", "cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker", "endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage", "endprimitive", "endprogram", "endproperty", "endspecify", "endsequence", "endtable", "endtask", "enum", "event", "eventually", "expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function", "generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies", "import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface", "intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint", "macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor", "noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive", "priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent", "pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat", "restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until", "s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify", "specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on", "sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1", "tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with", "untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while", "wildcard", "wire", "with", "within", "wor", "xnor", "xor", ]; // ----------------------------------------------------------------------------- pub(crate) fn ws<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult, (O, Vec)> where F: Fn(Span<'a>) -> IResult, O>, { move |s: Span<'a>| { let (s, x) = f(s)?; let (s, y) = many0(white_space)(s)?; Ok((s, (x, y))) } } #[cfg(not(feature = "trace"))] pub(crate) fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, 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, 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 keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, Keyword> { move |s: Span<'a>| { let (s, x) = map( ws(alt(( all_consuming(map(tag(t.clone()), |x: Span| into_locate(x))), terminated( map(tag(t.clone()), |x: Span| into_locate(x)), 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, 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()), |x: Span| into_locate(x))), terminated( map(tag(t.clone()), |x: Span| into_locate(x)), 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, Paren> where F: Fn(Span<'a>) -> IResult, 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, Paren> where F: Fn(Span<'a>) -> IResult, 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 bracket<'a, O, F>(f: F) -> impl Fn(Span<'a>) -> IResult, Bracket> where F: Fn(Span<'a>) -> IResult, 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, Bracket> where F: Fn(Span<'a>) -> IResult, 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, Brace> where F: Fn(Span<'a>) -> IResult, 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, Brace> where F: Fn(Span<'a>) -> IResult, 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, ApostropheBrace> where F: Fn(Span<'a>) -> IResult, 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, ApostropheBrace> where F: Fn(Span<'a>) -> IResult, 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, List> where F: Fn(Span<'a>) -> IResult, O1>, G: Fn(Span<'a>) -> IResult, 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) { if let Ok((u, c)) = g(t) { s = u; ret.push((b, c)); } else { break; } } 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, (O1, O2, O3)> where F: Fn(Span<'a>) -> IResult, O1>, G: Fn(Span<'a>) -> IResult, O2>, H: Fn(Span<'a>) -> IResult, 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))) } } // ----------------------------------------------------------------------------- #[tracable_parser] #[packrat_parser] pub(crate) fn white_space(s: Span) -> IResult { alt(( map(multispace1, |x: Span| { WhiteSpace::Space(Box::new(into_locate(x))) }), map(comment, |x| WhiteSpace::Comment(Box::new(x))), ))(s) } // ----------------------------------------------------------------------------- pub(crate) fn concat<'a>(a: Span<'a>, b: Span<'a>) -> Option> { 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 { 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(), } }