From 1e390e0f4429b5004e63327b64d5095775ef27b5 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Fri, 4 Oct 2024 21:02:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20undef=E9=A2=84=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sv-parser-error/src/lib.rs | 7 +- sv-parser-pp/src/preprocess.rs | 190 +++++++++++------------------- sv-parser/examples/module_list.rs | 6 +- sv-parser/examples/parse_sv.rs | 12 +- 4 files changed, 80 insertions(+), 135 deletions(-) diff --git a/sv-parser-error/src/lib.rs b/sv-parser-error/src/lib.rs index 56fd305..b5c3ae4 100644 --- a/sv-parser-error/src/lib.rs +++ b/sv-parser-error/src/lib.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use thiserror::Error; + // ----------------------------------------------------------------------------- #[derive(Error, Debug)] @@ -30,14 +31,14 @@ pub enum Error { #[error("Preprocess error: {0:?}")] Preprocess(Option<(PathBuf, usize)>), - #[error("Define argument not found: {0}")] - DefineArgNotFound(String), + #[error("Define argument not found: {0:?}")] + DefineArgNotFound(Option<(String, usize, usize)>), #[error("Define not found: {0}")] DefineNotFound(String), #[error("Define must have argument")] - DefineNoArgs(String), // String is the macro identifier. + DefineNoArgs(Option<(String, usize, usize)>), // String is the macro identifier. #[error("Exceed recursive limit")] ExceedRecursiveLimit, diff --git a/sv-parser-pp/src/preprocess.rs b/sv-parser-pp/src/preprocess.rs index 55f3b49..816d306 100644 --- a/sv-parser-pp/src/preprocess.rs +++ b/sv-parser-pp/src/preprocess.rs @@ -1,5 +1,6 @@ use crate::range::Range; use nom::combinator::all_consuming; +use nom::Parser; use nom_greedyerror::error_position; use std::collections::{BTreeMap, HashMap}; use std::convert::TryInto; @@ -256,6 +257,9 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( defines.insert(k.clone(), (*v).clone()); } + // let contain_a = defines.contains_key("a"); + // println!("defines contain a: {contain_a}"); + let span = Span::new_extra(&s, SpanInfo::default()); let (_, pp_text) = all_consuming(pp_parser)(span).map_err(|x| match x { nom::Err::Incomplete(_) => Error::Preprocess(None), @@ -445,7 +449,20 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( NodeEvent::Enter(RefNode::UndefineCompilerDirective(x)) => { let (_, _, ref name) = x.nodes; let id = identifier((&name.nodes.0).into(), &s).unwrap(); - defines.remove(&id); + // 确保填充 define 的唯一性 + let mut is_cover = false; + if let Some(define_text) = defines.get(&id) { + if let Some(define_text) = define_text { + if define_text.text.is_some() && define_text.text.clone().unwrap().text == "dide-undefined" { + is_cover = true; + } + } + } + + if !is_cover { + defines.remove(&id); + } + // println!("remove id {id}"); let locate: Locate = x.try_into().unwrap(); let range = Range::new(locate.offset, locate.offset + locate.len); @@ -598,7 +615,20 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( text: define_text, }; - defines.insert(id, Some(define)); + // 确保填充 define 的唯一性 + let mut is_cover = false; + if let Some(define_text) = defines.get(&id) { + if let Some(define_text) = define_text { + if define_text.text.is_some() && define_text.text.clone().unwrap().text == "dide-undefined" { + // println!("enter dide"); + is_cover = true; + } + } + } + + if !is_cover { + defines.insert(id, Some(define)); + } } // Keep TextMacroDefinition after preprocess_inner(). @@ -697,6 +727,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( }, )?; defines = new_defines; + // println!("[IncludeCompilerDirective] change defines, contain a : {}", defines.contains_key("a")); ret.merge(include); } NodeEvent::Enter(RefNode::TextMacroUsage(x)) => { @@ -714,6 +745,7 @@ pub fn preprocess_str, U: AsRef, V: BuildHasher>( )? { ret.push(&text, origin); defines = new_defines; + // println!("[TextMacroUsage] change defines, contain a : {}", defines.contains_key("a")); } // Push the trailing whitespace attached to either @@ -795,6 +827,23 @@ fn identifier(node: RefNode, s: &str) -> Option { None } +fn get_locate(node: RefNode) -> Option { + for x in node { + match x { + RefNode::SimpleIdentifier(x) => { + let x: Locate = x.nodes.0.try_into().unwrap(); + return Some(x); + } + RefNode::EscapedIdentifier(x) => { + let x: Locate = x.nodes.0.try_into().unwrap(); + return Some(x); + } + _ => (), + } + } + None +} + fn get_str(node: RefNode, s: &str) -> String { let mut ret = String::from(""); for x in node { @@ -945,128 +994,15 @@ fn resolve_text_macro_usage, U: AsRef>( let mut arg_map = HashMap::new(); if !define.arguments.is_empty() && no_args { - return Err(Error::DefineNoArgs(define.identifier.clone())); - } - - for (i, (arg, default)) in define.arguments.iter().enumerate() { - let value = match actual_args.get(i) { - Some(Some(actual_arg)) => *actual_arg, - Some(None) => { - if let Some(default) = default { - default - } else { - "" - } - } - None => { - if let Some(default) = default { - default - } else { - return Err(Error::DefineArgNotFound(String::from(arg))); - } - } - }; - arg_map.insert(String::from(arg), value); - } - - // restore () for textmacro without arguments - let paren = if define.arguments.is_empty() { - Some(args_str) - } else { - None - }; - - if let Some(ref text) = define.text { - let mut replaced = String::from(""); - for text in split_text(&text.text) { - if let Some(value) = arg_map.get(&text) { - replaced.push_str(*value); - } else { - replaced.push_str( - &text - .replace("``", "") // Argument substitution. - .replace("`\\`\"", "\\\"") // Escaped backslash. - .replace("`\"", "\"") // Escaped quote. - .replace("\\\n", "\n") // Line continuation (Unix). - .replace("\\\r\n", "\r\n") // Line continuation (Windows). - .replace("\\\r", "\r"), // Line continuation (old Mac). - ); - } - } - - if let Some(paren) = paren { - replaced.push_str(&paren); - } - - let (replaced, new_defines) = preprocess_str( - &replaced, - path.as_ref(), - &defines, - include_paths, - false, - strip_comments, - resolve_depth, - 0, // include_depth - )?; - Ok(Some(( - String::from(replaced.text()), - text.origin.clone(), - new_defines, - ))) - } else { - Ok(None) - } - } else if define.is_some() { - Ok(None) - } else { - Err(Error::DefineNotFound(id)) - } -} - -fn resolve_text_macro_usage_retain_error, U: AsRef>( - x: &TextMacroUsage, - s: &str, - path: T, - defines: &Defines, - include_paths: &[U], - strip_comments: bool, - resolve_depth: usize, -) -> Result, Defines)>, Error> { - let (_, ref name, ref args) = x.nodes; - let id = identifier((&name.nodes.0).into(), &s).unwrap(); - - if resolve_depth > RECURSIVE_LIMIT { - return Err(Error::ExceedRecursiveLimit); - } - - let mut args_str = String::from(""); - let mut actual_args = Vec::new(); - let no_args = args.is_none(); - if let Some(args) = args { - args_str.push_str(&get_str((&args.nodes.0).into(), s)); - args_str.push_str(&get_str((&args.nodes.1).into(), s)); - args_str.push_str(&get_str((&args.nodes.2).into(), s)); - - let (_, ref args, _) = args.nodes; - let (ref args,) = args.nodes; - for arg in args.contents() { - if let Some(arg) = arg { - let (ref arg,) = arg.nodes; - let arg = arg.str(&s).trim_end(); - actual_args.push(Some(arg)); + let locate = get_locate(sv_parser_syntaxtree::RefNode::TextMacroIdentifier(name)); + if let Some(locate) = locate { + let start_byte_idx = locate.offset; + let end_byte_idx = start_byte_idx + locate.len; + return Err(Error::DefineNoArgs(Some((define.identifier.clone(), start_byte_idx, end_byte_idx)))) } else { - actual_args.push(None); + return Err(Error::DefineNoArgs(None)); } } - } - - let define = defines.get(&id); - if let Some(Some(define)) = define { - let mut arg_map = HashMap::new(); - - if !define.arguments.is_empty() && no_args { - return Err(Error::DefineNoArgs(define.identifier.clone())); - } for (i, (arg, default)) in define.arguments.iter().enumerate() { let value = match actual_args.get(i) { @@ -1082,7 +1018,16 @@ fn resolve_text_macro_usage_retain_error, U: AsRef>( if let Some(default) = default { default } else { - return Err(Error::DefineArgNotFound(String::from(arg))); + // 找到对应出错的宏调用,再返回 + let locate: Option = get_locate(sv_parser_syntaxtree::RefNode::TextMacroIdentifier(name)); + if let Some(locate) = locate { + let arg_name = arg.to_string(); + let start_byte_idx = locate.offset; + let end_byte_idx = start_byte_idx + locate.len; + return Err(Error::DefineArgNotFound(Some((arg_name, start_byte_idx, end_byte_idx)))); + } else { + return Err(Error::DefineArgNotFound(None)); + } } } }; @@ -1143,7 +1088,6 @@ fn resolve_text_macro_usage_retain_error, U: AsRef>( } } - #[cfg(test)] mod tests { use super::*; diff --git a/sv-parser/examples/module_list.rs b/sv-parser/examples/module_list.rs index 57bf1aa..c86cea9 100644 --- a/sv-parser/examples/module_list.rs +++ b/sv-parser/examples/module_list.rs @@ -29,19 +29,19 @@ fn main() { // Original string can be got by SyntexTree::get_str(self, node: &RefNode) let id = syntax_tree.get_str(&id).unwrap(); - println!("module: {}", id); + // println!("module: {}", id); } RefNode::ModuleDeclarationAnsi(x) => { let id = unwrap_node!(x, ModuleIdentifier).unwrap(); let id = get_identifier(id).unwrap(); let id = syntax_tree.get_str(&id).unwrap(); - println!("module: {}", id); + // println!("module: {}", id); } _ => (), } } } else { - println!("Parse failed"); + // println!("Parse failed"); } } diff --git a/sv-parser/examples/parse_sv.rs b/sv-parser/examples/parse_sv.rs index 7453e98..45e5249 100644 --- a/sv-parser/examples/parse_sv.rs +++ b/sv-parser/examples/parse_sv.rs @@ -70,7 +70,7 @@ fn main() { false, // ignore_include ) { Ok((preprocessed_text, new_defines)) => { - println!("{}", preprocessed_text.text()); + // println!("{}", preprocessed_text.text()); defines = new_defines; } _ => (), @@ -79,24 +79,24 @@ fn main() { match parse_sv(&path, &defines, &opt.includes, false, opt.incomplete) { Ok((syntax_tree, new_defines)) => { if opt.tree { - println!("{}", syntax_tree); + // println!("{}", syntax_tree); } defines = new_defines; if !opt.quiet { - println!("parse succeeded: {:?}", path); + // println!("parse succeeded: {:?}", path); } } Err(x) => { match x { Error::Parse(Some((origin_path, origin_pos))) => { - println!("parse failed: {:?}", path); + // println!("parse failed: {:?}", path); print_parse_error(&origin_path, &origin_pos); } x => { - println!("parse failed: {:?} ({:?})", path, x); + // println!("parse failed: {:?} ({:?})", path, x); let mut err = x.source(); while let Some(x) = err { - println!(" Caused by {}", x); + // println!(" Caused by {}", x); err = x.source(); } }