From 5b6f8bc808290f524bbab6ae47cca250d86a56a3 Mon Sep 17 00:00:00 2001 From: light-ly <1505507717@qq.com> Date: Fri, 18 Oct 2024 11:51:21 +0800 Subject: [PATCH] fix fast parameter parse --- src/core/hdlparam.rs | 1 + src/core/sv_parser.rs | 241 ++++++++++++++++++++++++------------------ 2 files changed, 141 insertions(+), 101 deletions(-) diff --git a/src/core/hdlparam.rs b/src/core/hdlparam.rs index 75d254b..eb3b99c 100644 --- a/src/core/hdlparam.rs +++ b/src/core/hdlparam.rs @@ -267,6 +267,7 @@ impl FastHdlparam { } }; last_module.params.push(parameter); + last_module.params.dedup(); } } diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index f41ca47..8269365 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -7,13 +7,71 @@ use log::info; use regex::Regex; use ropey::Rope; use tower_lsp::lsp_types::Url; -use sv_parser::{unwrap_node, Locate, RefNode, SyntaxTree}; +use sv_parser::{unwrap_locate, unwrap_node, EventIter, ListOfParamAssignments, ListOfTypeAssignments, Locate, NodeEvent, ParamAssignment, ParameterDeclaration, RefNode, SyntaxTree, TypeAssignment}; use crate::sources::recovery_sv_parse_with_retry; use crate::utils::to_escape_path; use super::hdlparam::{FastHdlparam, Macro}; +macro_rules! advance_until_leave { + ($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{ + let mut result: Option = None; + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Leave(x) => match x { + $node(node) => { + result = Some($node(node)); + break; + } + RefNode::Locate(node) => { + $tokens.push(' '); + $tokens.push_str($tree.get_str(node).unwrap()); + } + _ => (), + }, + NodeEvent::Enter(_) => (), + } + } + result + }}; +} + +macro_rules! skip_until_enter { + ($tree:ident, $event_iter:ident, $node:path, $type:ty) => {{ + let mut result: Option<$type> = None; + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(x) => match x { + $node(node) => { + result = Some(node); + break; + } + _ => (), + }, + NodeEvent::Leave(_) => (), + } + } + result + }}; +} + +macro_rules! skip_until_leave { + ($tree:ident, $event_iter:ident, $node:path) => { + while let Some(event) = $event_iter.next() { + match event { + NodeEvent::Enter(_) => (), + NodeEvent::Leave(x) => match x { + $node(_) => { + break; + } + _ => (), + }, + } + } + }; +} + #[allow(unused)] pub fn sv_parser(path: &str) -> Option { // The path of SystemVerilog source file @@ -115,110 +173,39 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re let name = syntax_tree.get_str(&id).unwrap(); hdlparam.new_module(name, line, character, end_character); } - RefNode::ParameterPortDeclaration(x) => { - if let Some(id) = unwrap_node!(x, ParameterIdentifier) { - let id = get_identifier(id).unwrap(); - let name = syntax_tree.get_str(&id).unwrap(); - if !added_param_names.contains(name) { - added_param_names.insert(name.to_string()); - match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { - Some(RefNode::ParameterDeclarationParam(param_node)) => { - // println!("{:?}", param_node); - let keyword_locate = param_node.nodes.0.nodes.0; - // println!("keyword {:#?}", keyword_locate); - let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); - let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); - let net_type = match unwrap_node!(param_node, DataType) { - Some(RefNode::DataType(data_type)) => { - let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); - if id == None { - "wire" - } else { - let id = get_identifier(id.unwrap()).unwrap(); - syntax_tree.get_str(&id).unwrap() - } - } - _ => "wire" - }; - let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { - match init { - RefNode::ConstantMintypmaxExpression(expression) => { - // println!("expression {:?}", x); - let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); - let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); - (end_line, end_character) = if last_locate != None { - // println!("param {:?} lastlocate {:?}", name, last_locate); - (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) - } else { - (end_line, end_character) - }; - // println!("end pos {} {}", end_line, end_character); - exp - } - _ => "unknown".to_string() - } + RefNode::ParameterDeclaration(param_dec) => { + let mut event_iter = param_dec.into_iter().event(); + match param_dec { + ParameterDeclaration::Param(x) => { + let keyword_locate = &x.nodes.0.nodes.0; + // println!("keyword {:#?}", keyword_locate); + let (start_line, start_character) = (keyword_locate.line, get_column_by_offset(&content, keyword_locate.offset) as u32); + let net_type = match unwrap_node!(RefNode::ParameterDeclarationParam(x), DataType) { + Some(RefNode::DataType(data_type)) => { + let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); + if id == None { + "wire" } else { - "unknown".to_string() - }; - hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); + let id = get_identifier(id.unwrap()).unwrap(); + syntax_tree.get_str(&id).unwrap() + } } - _ => () - } - } - } - } - RefNode::ParameterDeclaration(x) => { - if let Some(id) = unwrap_node!(x, ParameterIdentifier) { - let id = get_identifier(id).unwrap(); - let name = syntax_tree.get_str(&id).unwrap(); - if !added_param_names.contains(name) { - added_param_names.insert(name.to_string()); - match unwrap_node!(x, ParameterDeclarationParam, ParameterPortDeclarationParamList) { - Some(RefNode::ParameterDeclarationParam(param_node)) => { - // println!("{:?}", param_node); - let keyword_locate = param_node.nodes.0.nodes.0; - // println!("keyword {:#?}", keyword_locate); - let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32); - let (mut end_line, mut end_character) = (id.line, start_character + id.len as u32); - let net_type = match unwrap_node!(param_node, DataType) { - Some(RefNode::DataType(data_type)) => { - let id = unwrap_node!(data_type, SimpleIdentifier, Keyword); - if id == None { - "wire" - } else { - let id = get_identifier(id.unwrap()).unwrap(); - syntax_tree.get_str(&id).unwrap() - } - } - _ => "wire" - }; - let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) { - match init { - RefNode::ConstantMintypmaxExpression(expression) => { - // println!("expression {:?}", x); - let param_init = sv_parser::NeedParseExpression::Parameter(expression.clone()); - let (exp, last_locate) = parse_expression(&syntax_tree, ¶m_init); - (end_line, end_character) = if last_locate != None { - // println!("param {:?} lastlocate {:?}", name, last_locate); - (last_locate.unwrap().line, (get_column_by_offset(&content, last_locate.unwrap().offset) + last_locate.unwrap().len) as u32) - } else { - (end_line, end_character) - }; - // println!("end pos {} {}", end_line, end_character); - exp - } - _ => "unknown".to_string() - } - } else { - "unknown".to_string() - }; - hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character); - } - _ => () - } - } + _ => "wire" + }; + for (index, (name, loc, init)) in list_param_assignment(syntax_tree, &x.nodes.2, &mut event_iter).iter().enumerate() { + let (start_line, start_character) = if index != 0 { + (loc.line as u32, get_column_by_offset(&content, loc.offset) as u32) + } else { + (start_line, start_character) + }; + let (end_line, end_character) = (loc.line as u32, (get_column_by_offset(&content, loc.offset) + loc.len) as u32); + hdlparam.add_parameter(name, net_type, init, start_line, start_character, end_line, end_character); + } + } + _ => () } + } RefNode::PortDeclaration(x) => { if let Some(id) = unwrap_node!(x, InputDeclaration, OutputDeclaration, InoutDeclaration) { @@ -692,6 +679,58 @@ fn get_column_by_offset(content: &[String], offset: usize) -> usize { 1 // if offset over the file lentgh,return 1 } +fn param_assignment( + tree: &SyntaxTree, + _: &ParamAssignment, + event_iter: &mut EventIter, +) -> Option<(String, Locate, String)> { + if let Some(param_assign) = + skip_until_enter!(tree, event_iter, RefNode::ParamAssignment, &ParamAssignment) { + let ident = get_ident(tree, RefNode::ParameterIdentifier(¶m_assign.nodes.0)); + let mut type_str = String::new(); + advance_until_leave!(type_str, tree, event_iter, RefNode::ParamAssignment); + let parts: Vec<&str> = type_str.split_whitespace().collect(); + type_str = if let Some(last_part) = parts.last() { + last_part.to_string() + } else { + "unknown".to_string() + }; + Some((ident.0, ident.1, type_str)) + } else { + None + } +} + +fn list_param_assignment( + tree: &SyntaxTree, + _: &ListOfParamAssignments, + event_iter: &mut EventIter, +) -> Vec<(String, Locate, String)>{ + let mut params = Vec::new(); + // let mut defs: Vec = Vec::new(); + if let Some(p_a_list) = skip_until_enter!( + tree, + event_iter, + RefNode::ListOfParamAssignments, + &ListOfParamAssignments + ) { + for param_assign in p_a_list.nodes.0.contents() { + if let Some(assignment) = param_assignment(tree, param_assign, event_iter) { + params.push(assignment); + } + } + }; + params +} + +/// 找到 node 的 名字,开始的位置和结束的位置 +pub fn get_ident(tree: &SyntaxTree, node: RefNode) -> (String, Locate) { + let loc = unwrap_locate!(node).unwrap(); + let ident_str = tree.get_str(loc).unwrap().to_string(); + + (ident_str, *loc) +} + #[cfg(test)] mod tests { use std::{fs, path::Path};