fix fast parameter parse
This commit is contained in:
parent
e2420638bf
commit
5b6f8bc808
@ -267,6 +267,7 @@ impl FastHdlparam {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
last_module.params.push(parameter);
|
last_module.params.push(parameter);
|
||||||
|
last_module.params.dedup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,71 @@ use log::info;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use tower_lsp::lsp_types::Url;
|
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::sources::recovery_sv_parse_with_retry;
|
||||||
use crate::utils::to_escape_path;
|
use crate::utils::to_escape_path;
|
||||||
|
|
||||||
use super::hdlparam::{FastHdlparam, Macro};
|
use super::hdlparam::{FastHdlparam, Macro};
|
||||||
|
|
||||||
|
macro_rules! advance_until_leave {
|
||||||
|
($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{
|
||||||
|
let mut result: Option<RefNode> = 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)]
|
#[allow(unused)]
|
||||||
pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
|
pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
|
||||||
// The path of SystemVerilog source file
|
// The path of SystemVerilog source file
|
||||||
@ -115,20 +173,14 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
|||||||
let name = syntax_tree.get_str(&id).unwrap();
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
hdlparam.new_module(name, line, character, end_character);
|
hdlparam.new_module(name, line, character, end_character);
|
||||||
}
|
}
|
||||||
RefNode::ParameterPortDeclaration(x) => {
|
RefNode::ParameterDeclaration(param_dec) => {
|
||||||
if let Some(id) = unwrap_node!(x, ParameterIdentifier) {
|
let mut event_iter = param_dec.into_iter().event();
|
||||||
let id = get_identifier(id).unwrap();
|
match param_dec {
|
||||||
let name = syntax_tree.get_str(&id).unwrap();
|
ParameterDeclaration::Param(x) => {
|
||||||
if !added_param_names.contains(name) {
|
let keyword_locate = &x.nodes.0.nodes.0;
|
||||||
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);
|
// println!("keyword {:#?}", keyword_locate);
|
||||||
let (start_line, start_character) = (id.line, get_column_by_offset(&content, keyword_locate.offset) as u32);
|
let (start_line, start_character) = (keyword_locate.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!(RefNode::ParameterDeclarationParam(x), DataType) {
|
||||||
let net_type = match unwrap_node!(param_node, DataType) {
|
|
||||||
Some(RefNode::DataType(data_type)) => {
|
Some(RefNode::DataType(data_type)) => {
|
||||||
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
let id = unwrap_node!(data_type, SimpleIdentifier, Keyword);
|
||||||
if id == None {
|
if id == None {
|
||||||
@ -140,86 +192,21 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re
|
|||||||
}
|
}
|
||||||
_ => "wire"
|
_ => "wire"
|
||||||
};
|
};
|
||||||
let init = if let Some(init) = unwrap_node!(param_node, ConstantMintypmaxExpression) {
|
|
||||||
match init {
|
for (index, (name, loc, init)) in list_param_assignment(syntax_tree, &x.nodes.2, &mut event_iter).iter().enumerate() {
|
||||||
RefNode::ConstantMintypmaxExpression(expression) => {
|
let (start_line, start_character) = if index != 0 {
|
||||||
// println!("expression {:?}", x);
|
(loc.line as u32, get_column_by_offset(&content, loc.offset) as u32)
|
||||||
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 {
|
} else {
|
||||||
(end_line, end_character)
|
(start_line, start_character)
|
||||||
};
|
};
|
||||||
// println!("end pos {} {}", end_line, end_character);
|
let (end_line, end_character) = (loc.line as u32, (get_column_by_offset(&content, loc.offset) + loc.len) as u32);
|
||||||
exp
|
hdlparam.add_parameter(name, net_type, init, start_line, start_character, end_line, end_character);
|
||||||
}
|
}
|
||||||
_ => "unknown".to_string()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"unknown".to_string()
|
|
||||||
};
|
|
||||||
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
RefNode::PortDeclaration(x) => {
|
RefNode::PortDeclaration(x) => {
|
||||||
if let Some(id) = unwrap_node!(x, InputDeclaration, OutputDeclaration, InoutDeclaration) {
|
if let Some(id) = unwrap_node!(x, InputDeclaration, OutputDeclaration, InoutDeclaration) {
|
||||||
let id = get_identifier(id).unwrap();
|
let id = get_identifier(id).unwrap();
|
||||||
@ -692,6 +679,58 @@ fn get_column_by_offset(content: &[String], offset: usize) -> usize {
|
|||||||
1 // if offset over the file lentgh,return 1
|
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<GenericDec> = 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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{fs, path::Path};
|
use std::{fs, path::Path};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user