From 963e17a5ea727ab16858bc86d99f0308fa2e6870 Mon Sep 17 00:00:00 2001 From: damc Date: Mon, 25 Jul 2022 22:21:28 +0200 Subject: [PATCH] ppTests Allow `define __FILE__ and `define __LINE__ to parse. - Redefinitions are silently ignored. - ifdef/ifndef will always treat them as defined. - Enables compatibility with code from a silicon vendor I can think of. - NOTE: Whitespace bugs around endif/undef are observable in testcases. --- sv-parser-parser/src/keywords.rs | 2 - sv-parser-pp/src/preprocess.rs | 93 ++++++++++++++++++-------------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/sv-parser-parser/src/keywords.rs b/sv-parser-parser/src/keywords.rs index 36285c9..52442fe 100644 --- a/sv-parser-parser/src/keywords.rs +++ b/sv-parser-parser/src/keywords.rs @@ -1446,8 +1446,6 @@ pub(crate) const KEYWORDS_1800_2017: &[&str] = &[ ]; pub(crate) const KEYWORDS_DIRECTIVE: &[&str] = &[ - "__FILE__", - "__LINE__", "begin_keywords", "celldefine", "default_nettype", diff --git a/sv-parser-pp/src/preprocess.rs b/sv-parser-pp/src/preprocess.rs index 3b44cb2..5cc368c 100644 --- a/sv-parser-pp/src/preprocess.rs +++ b/sv-parser-pp/src/preprocess.rs @@ -399,7 +399,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let ifid = identifier(ifid.into(), &s).unwrap(); let mut hit = false; - if defines.contains_key(&ifid) { + if defines.contains_key(&ifid) || is_predefined_text_macro(&ifid) { hit = true; } else { skip_nodes.push(ifbody.into()); @@ -413,7 +413,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let elsifid = identifier(elsifid.into(), &s).unwrap(); if hit { skip_nodes.push(elsifbody.into()); - } else if defines.contains_key(&elsifid) { + } else if defines.contains_key(&elsifid) || is_predefined_text_macro(&ifid) { hit = true; } else { skip_nodes.push(elsifbody.into()); @@ -447,7 +447,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let ifid = identifier(ifid.into(), &s).unwrap(); let mut hit = false; - if !defines.contains_key(&ifid) { + if !defines.contains_key(&ifid) && !is_predefined_text_macro(&ifid) { hit = true; } else { skip_nodes.push(ifbody.into()); @@ -461,7 +461,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let elsifid = identifier(elsifid.into(), &s).unwrap(); if hit { skip_nodes.push(elsifbody.into()); - } else if defines.contains_key(&elsifid) { + } else if defines.contains_key(&elsifid) || is_predefined_text_macro(&ifid) { hit = true; } else { skip_nodes.push(elsifbody.into()); @@ -484,47 +484,49 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( let (ref name, ref args) = proto.nodes; let id = identifier(name.into(), &s).unwrap(); - let mut define_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, ref default) = arg.nodes; - let (ref arg, _) = arg.nodes; - let arg = String::from(arg.str(&s)); + if !is_predefined_text_macro(id.as_str()) { + let mut define_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, ref default) = arg.nodes; + let (ref arg, _) = arg.nodes; + let arg = String::from(arg.str(&s)); - let default = if let Some((_, x)) = default { - let x: Locate = x.try_into().unwrap(); - let x = String::from(x.str(&s)); - Some(x) - } else { - None - }; + let default = if let Some((_, x)) = default { + let x: Locate = x.try_into().unwrap(); + let x = String::from(x.str(&s)); + Some(x) + } else { + None + }; - define_args.push((arg, default)); + define_args.push((arg, default)); + } } + + let define_text = if let Some(text) = text { + let text: Locate = text.try_into().unwrap(); + let range = Range::new(text.offset, text.offset + text.len); + let text = String::from(text.str(&s)); + Some(DefineText { + text, + origin: Some((PathBuf::from(path.as_ref()), range)), + }) + } else { + None + }; + + let define = Define { + identifier: id.clone(), + arguments: define_args, + text: define_text, + }; + + defines.insert(id, Some(define)); } - let define_text = if let Some(text) = text { - let text: Locate = text.try_into().unwrap(); - let range = Range::new(text.offset, text.offset + text.len); - let text = String::from(text.str(&s)); - Some(DefineText { - text, - origin: Some((PathBuf::from(path.as_ref()), range)), - }) - } else { - None - }; - - let define = Define { - identifier: id.clone(), - arguments: define_args, - text: define_text, - }; - - defines.insert(id, Some(define)); - // Keep TextMacroDefinition after preprocess let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); @@ -708,6 +710,17 @@ fn get_str(node: RefNode, s: &str) -> String { ret } +fn is_predefined_text_macro(s: &str) -> bool { + match s { + "__LINE__" | "__FILE__" => { + true + } + _ => { + false + } + } +} + fn split_text(s: &str) -> Vec { let mut is_string = false; let mut is_ident = false;