Implement TextMacroUsage
This commit is contained in:
parent
e15982c774
commit
5bc22d62a8
@ -71,7 +71,7 @@ impl PreprocessedText {
|
|||||||
|
|
||||||
pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
|
pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
|
||||||
path: T,
|
path: T,
|
||||||
pre_defines: &HashMap<String, Option<TextMacroDefinition>>,
|
pre_defines: &HashMap<String, Option<(TextMacroDefinition, PathBuf)>>,
|
||||||
include_paths: &[U],
|
include_paths: &[U],
|
||||||
) -> Result<PreprocessedText, Error> {
|
) -> Result<PreprocessedText, Error> {
|
||||||
let f = File::open(path.as_ref())?;
|
let f = File::open(path.as_ref())?;
|
||||||
@ -171,7 +171,7 @@ pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
|
|||||||
NodeEvent::Enter(RefNode::TextMacroDefinition(x)) if !skip => {
|
NodeEvent::Enter(RefNode::TextMacroDefinition(x)) if !skip => {
|
||||||
let (_, _, ref name, _) = x.nodes;
|
let (_, _, ref name, _) = x.nodes;
|
||||||
let id = identifier((&name.nodes.0).into(), &s).unwrap();
|
let id = identifier((&name.nodes.0).into(), &s).unwrap();
|
||||||
defines.insert(id, Some(x.clone()));
|
defines.insert(id, Some((x.clone(), PathBuf::from(path.as_ref()))));
|
||||||
}
|
}
|
||||||
NodeEvent::Enter(RefNode::IncludeCompilerDirective(x)) if !skip => {
|
NodeEvent::Enter(RefNode::IncludeCompilerDirective(x)) if !skip => {
|
||||||
let path = match x {
|
let path = match x {
|
||||||
@ -201,6 +201,86 @@ pub fn preprocess<T: AsRef<Path>, U: AsRef<Path>>(
|
|||||||
let include = preprocess(path, &defines, include_paths)?;
|
let include = preprocess(path, &defines, include_paths)?;
|
||||||
ret.merge(include);
|
ret.merge(include);
|
||||||
}
|
}
|
||||||
|
NodeEvent::Enter(RefNode::TextMacroUsage(x)) if !skip => {
|
||||||
|
let (_, ref name, ref args) = x.nodes;
|
||||||
|
let id = identifier((&name.nodes.0).into(), &s).unwrap();
|
||||||
|
|
||||||
|
let mut actual_args = Vec::new();
|
||||||
|
if let Some(args) = args {
|
||||||
|
let (_, ref args, _) = args.nodes;
|
||||||
|
let (ref args,) = args.nodes;
|
||||||
|
for arg in args.contents() {
|
||||||
|
let (ref arg,) = arg.nodes;
|
||||||
|
let arg: Locate = arg.try_into().unwrap();
|
||||||
|
let arg = arg.str(&s);
|
||||||
|
actual_args.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let define = defines.get(&id);
|
||||||
|
if let Some(Some((define, define_path))) = define {
|
||||||
|
let (_, _, ref proto, ref text) = define.nodes;
|
||||||
|
|
||||||
|
let mut arg_names = Vec::new();
|
||||||
|
let mut defaults = Vec::new();
|
||||||
|
let (_, ref args) = proto.nodes;
|
||||||
|
if let Some(args) = args {
|
||||||
|
let (_, ref args, _) = args.nodes;
|
||||||
|
let (ref args,) = args.nodes;
|
||||||
|
for arg in args.contents() {
|
||||||
|
let (ref arg, ref default) = arg.nodes;
|
||||||
|
let (ref arg, _) = arg.nodes;
|
||||||
|
let arg = arg.str(&s);
|
||||||
|
|
||||||
|
let default = if let Some((_, x)) = default {
|
||||||
|
let x: Locate = x.try_into().unwrap();
|
||||||
|
let x = x.str(&s);
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
arg_names.push(arg);
|
||||||
|
defaults.push(default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut arg_map = HashMap::new();
|
||||||
|
for (i, arg) in arg_names.iter().enumerate() {
|
||||||
|
let value = if let Some(actual_arg) = actual_args.get(i) {
|
||||||
|
actual_arg
|
||||||
|
} else {
|
||||||
|
if let Some(default) = defaults.get(i).unwrap() {
|
||||||
|
default
|
||||||
|
} else {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
arg_map.insert(String::from(*arg), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(text) = text {
|
||||||
|
let text: Locate = text.try_into().unwrap();
|
||||||
|
let range = Range::new(text.offset, text.offset + text.len);
|
||||||
|
let text = text.str(&s);
|
||||||
|
let mut replaced = String::from("");
|
||||||
|
for text in split_text(text) {
|
||||||
|
if let Some(value) = arg_map.get(&text) {
|
||||||
|
replaced.push_str(**value);
|
||||||
|
} else {
|
||||||
|
replaced.push_str(&text.replace("``", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.push(&replaced, define_path, range);
|
||||||
|
} else {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
} else if let Some(_) = define {
|
||||||
|
unimplemented!();
|
||||||
|
} else {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
NodeEvent::Enter(x) => {
|
NodeEvent::Enter(x) => {
|
||||||
if skip_nodes.contains(&x) {
|
if skip_nodes.contains(&x) {
|
||||||
skip = true;
|
skip = true;
|
||||||
@ -234,6 +314,25 @@ fn identifier(node: RefNode, s: &str) -> Option<String> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_text(s: &str) -> Vec<String> {
|
||||||
|
let mut is_ident = false;
|
||||||
|
let mut is_ident_prev;
|
||||||
|
let mut x = String::from("");
|
||||||
|
let mut ret = vec![];
|
||||||
|
for c in s.chars() {
|
||||||
|
is_ident_prev = is_ident;
|
||||||
|
is_ident = c.is_ascii_alphanumeric() | (c == '_');
|
||||||
|
|
||||||
|
if is_ident != is_ident_prev {
|
||||||
|
ret.push(x);
|
||||||
|
x = String::from("");
|
||||||
|
}
|
||||||
|
|
||||||
|
x.push(c);
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -290,7 +389,6 @@ endmodule
|
|||||||
fn test2() {
|
fn test2() {
|
||||||
let include_paths = [get_testcase("")];
|
let include_paths = [get_testcase("")];
|
||||||
let ret = preprocess(get_testcase("test2.sv"), &HashMap::new(), &include_paths).unwrap();
|
let ret = preprocess(get_testcase("test2.sv"), &HashMap::new(), &include_paths).unwrap();
|
||||||
let ret = dbg!(ret);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ret.text(),
|
ret.text(),
|
||||||
r##"module and_op (a, b, c);
|
r##"module and_op (a, b, c);
|
||||||
@ -308,13 +406,34 @@ endmodule
|
|||||||
assert_eq!(ret.origin(10).unwrap().1, 10);
|
assert_eq!(ret.origin(10).unwrap().1, 10);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ret.origin(50).unwrap().0,
|
ret.origin(50).unwrap().0,
|
||||||
&PathBuf::from(get_testcase("test3.sv"))
|
&PathBuf::from(get_testcase("test2.svh"))
|
||||||
);
|
);
|
||||||
assert_eq!(ret.origin(50).unwrap().1, 73);
|
assert_eq!(ret.origin(50).unwrap().1, 73);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ret.origin(70).unwrap().0,
|
ret.origin(70).unwrap().0,
|
||||||
&PathBuf::from(get_testcase("test2.sv"))
|
&PathBuf::from(get_testcase("test2.sv"))
|
||||||
);
|
);
|
||||||
assert_eq!(ret.origin(70).unwrap().1, 51);
|
assert_eq!(ret.origin(70).unwrap().1, 52);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
let ret = preprocess(get_testcase("test3.sv"), &HashMap::new(), &[] as &[String]).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
ret.text(),
|
||||||
|
r##"
|
||||||
|
|
||||||
|
module a ();
|
||||||
|
|
||||||
|
\
|
||||||
|
assign a_0__x = a[0].x; \
|
||||||
|
assign a_0__y = a[0].y;
|
||||||
|
\
|
||||||
|
assign a_1__x = a[1].x; \
|
||||||
|
assign a_1__y = a[1].y;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
"##
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
module and_op (a, b, c);
|
module and_op (a, b, c);
|
||||||
`include "test3.sv"
|
`include "test2.svh"
|
||||||
endmodule
|
endmodule
|
||||||
|
8
sv-parser-pp/testcases/test2.svh
Normal file
8
sv-parser-pp/testcases/test2.svh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
output a;
|
||||||
|
input b, c;
|
||||||
|
|
||||||
|
`ifdef behavioral
|
||||||
|
wire a = b & c;
|
||||||
|
`else
|
||||||
|
and a1 (a,b,c);
|
||||||
|
`endif
|
@ -1,8 +1,10 @@
|
|||||||
output a;
|
`define connect(NAME, INDEX = 0) \
|
||||||
input b, c;
|
assign NAME``_``INDEX``__x = NAME[INDEX].x; \
|
||||||
|
assign NAME``_``INDEX``__y = NAME[INDEX].y;
|
||||||
|
|
||||||
`ifdef behavioral
|
module a ();
|
||||||
wire a = b & c;
|
|
||||||
`else
|
`connect(a);
|
||||||
and a1 (a,b,c);
|
`connect(a, 1);
|
||||||
`endif
|
|
||||||
|
endmodule
|
||||||
|
@ -43,3 +43,15 @@ pub struct ApostropheBrace<T> {
|
|||||||
pub struct List<T, U> {
|
pub struct List<T, U> {
|
||||||
pub nodes: (U, Vec<(T, U)>),
|
pub nodes: (U, Vec<(T, U)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, U> List<T, U> {
|
||||||
|
pub fn contents(&self) -> Vec<&U> {
|
||||||
|
let mut ret = vec![];
|
||||||
|
let (ref x, ref y) = self.nodes;
|
||||||
|
ret.push(x);
|
||||||
|
for (_, y) in y {
|
||||||
|
ret.push(y)
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user