2019-08-06 00:37:12 +09:00

552 lines
12 KiB
Rust

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<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)))
}
}
#[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 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()), |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<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()), |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<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 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.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<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)))
}
}
// -----------------------------------------------------------------------------
#[tracable_parser]
#[packrat_parser]
pub(crate) fn white_space(s: Span) -> IResult<Span, WhiteSpace> {
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<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 {
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(),
}
}