From 9c935af3974f772d90260ef55320fce269720689 Mon Sep 17 00:00:00 2001 From: dalance Date: Fri, 28 Aug 2020 19:51:04 +0900 Subject: [PATCH] Fix empty ifdef issue #10 --- CHANGELOG.md | 2 + sv-parser-pp/src/preprocess.rs | 89 +++++++++++++++++++++++++------- sv-parser-pp/testcases/test14.sv | 14 +++++ 3 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 sv-parser-pp/testcases/test14.sv diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c0cda9..607c57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased](https://github.com/dalance/sv-parser/compare/v0.8.1...Unreleased) - ReleaseDate +* [Fixed] empty ifdef issue [#10](https://github.com/dalance/sv-parser/issues/10) + ## [v0.8.1](https://github.com/dalance/sv-parser/compare/v0.8.0...v0.8.1) - 2020-08-28 * [Fixed] text macro with single line comment [#12](https://github.com/dalance/sv-parser/issues/12) diff --git a/sv-parser-pp/src/preprocess.rs b/sv-parser-pp/src/preprocess.rs index bccf019..a7a56c6 100644 --- a/sv-parser-pp/src/preprocess.rs +++ b/sv-parser-pp/src/preprocess.rs @@ -142,6 +142,34 @@ pub fn preprocess, U: AsRef, V: BuildHasher>( ) } +struct SkipNodes<'a> { + nodes: Vec>, +} + +impl<'a> SkipNodes<'a> { + fn new() -> Self { + Self { nodes: vec![] } + } + + fn push(&mut self, node: RefNode<'a>) { + // if a node doesn't have locate, the node should be ignored + // because the node can be identified in tree. + let mut have_locate = false; + for x in node.clone() { + if let RefNode::Locate(_) = x { + have_locate = true; + } + } + if have_locate { + self.nodes.push(node); + } + } + + fn contains(&self, node: &RefNode<'a>) -> bool { + self.nodes.contains(node) + } +} + pub fn preprocess_str, U: AsRef, V: BuildHasher>( s: &str, path: T, @@ -152,7 +180,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( resolve_depth: usize, ) -> Result<(PreprocessedText, Defines), Error> { let mut skip = false; - let mut skip_nodes = vec![]; + let mut skip_nodes = SkipNodes::new(); let mut defines = HashMap::new(); let mut last_item_line = None; @@ -196,6 +224,10 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( } } } + if skip { + continue; + } + match n.clone() { NodeEvent::Enter(RefNode::SourceDescriptionNotDirective(x)) => { let locate: Locate = x.try_into().unwrap(); @@ -224,12 +256,12 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( _ => (), } match n { - NodeEvent::Enter(RefNode::ResetallCompilerDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::ResetallCompilerDirective(x)) => { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::UndefineCompilerDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::UndefineCompilerDirective(x)) => { skip_nodes.push(x.into()); skip = true; @@ -237,42 +269,40 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let id = identifier((&name.nodes.0).into(), &s).unwrap(); defines.remove(&id); } - NodeEvent::Enter(RefNode::UndefineallCompilerDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::UndefineallCompilerDirective(x)) => { skip_nodes.push(x.into()); skip = true; defines.clear(); } - NodeEvent::Enter(RefNode::SourceDescriptionNotDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::SourceDescriptionNotDirective(x)) => { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::SourceDescription(SourceDescription::StringLiteral(x))) - if !skip => - { + NodeEvent::Enter(RefNode::SourceDescription(SourceDescription::StringLiteral(x))) => { let locate: Locate = (&**x).try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } NodeEvent::Enter(RefNode::SourceDescription(SourceDescription::EscapedIdentifier( x, - ))) if !skip => { + ))) => { let locate: Locate = (&**x).try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::KeywordsDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::KeywordsDirective(x)) => { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::EndkeywordsDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::EndkeywordsDirective(x)) => { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::IfdefDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::IfdefDirective(x)) => { let (_, ref keyword, ref ifid, ref ifbody, ref elsif, ref elsebody, _, _) = x.nodes; skip_nodes.push(keyword.into()); skip_nodes.push(ifid.into()); @@ -308,19 +338,19 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( } } } - NodeEvent::Enter(RefNode::WhiteSpace(x)) if !skip && !strip_comments => { + NodeEvent::Enter(RefNode::WhiteSpace(x)) if !strip_comments => { if let WhiteSpace::Space(_) = x { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset + locate.len, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } } - NodeEvent::Enter(RefNode::Comment(x)) if !skip && !strip_comments => { + NodeEvent::Enter(RefNode::Comment(x)) if !strip_comments => { let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); ret.push(locate.str(&s), Some((path.as_ref(), range))); } - NodeEvent::Enter(RefNode::IfndefDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::IfndefDirective(x)) => { let (_, ref keyword, ref ifid, ref ifbody, ref elsif, ref elsebody, _, _) = x.nodes; skip_nodes.push(keyword.into()); skip_nodes.push(ifid.into()); @@ -356,7 +386,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( } } } - NodeEvent::Enter(RefNode::TextMacroDefinition(x)) if !skip => { + NodeEvent::Enter(RefNode::TextMacroDefinition(x)) => { skip_nodes.push(x.into()); skip = true; @@ -405,7 +435,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( defines.insert(id, Some(define)); } - NodeEvent::Enter(RefNode::IncludeCompilerDirective(x)) if !skip && !ignore_include => { + NodeEvent::Enter(RefNode::IncludeCompilerDirective(x)) if !ignore_include => { skip_nodes.push(x.into()); skip = true; @@ -474,7 +504,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( defines = new_defines; ret.merge(include); } - NodeEvent::Enter(RefNode::TextMacroUsage(x)) if !skip => { + NodeEvent::Enter(RefNode::TextMacroUsage(x)) => { skip_nodes.push(x.into()); skip = true; @@ -491,7 +521,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( defines = new_defines; } } - NodeEvent::Enter(RefNode::PositionCompilerDirective(x)) if !skip => { + NodeEvent::Enter(RefNode::PositionCompilerDirective(x)) => { skip_nodes.push(x.into()); skip = true; @@ -1018,6 +1048,27 @@ endmodule r##" interface foo #(WIDTH = 42 ) (); endinterface +"## + ); + } + + #[test] + fn test14() { + let (ret, _) = preprocess( + get_testcase("test14.sv"), + &HashMap::new(), + &[] as &[String], + false, + false, + ) + .unwrap(); + assert_eq!( + ret.text(), + r##"module A; +wire a = 1'b0; + + +endmodule "## ); } diff --git a/sv-parser-pp/testcases/test14.sv b/sv-parser-pp/testcases/test14.sv new file mode 100644 index 0000000..bb2d360 --- /dev/null +++ b/sv-parser-pp/testcases/test14.sv @@ -0,0 +1,14 @@ +module A; +`ifdef OPT_1 + //wire a = 1'b1; +`else + wire a = 1'b0; +`endif +`ifdef DEBUG + `ifdef OPT_2 + //wire b = 1'b1; + `else + wire b = 1'b0; + `endif +`endif +endmodule