commit
This commit is contained in:
parent
51d106b518
commit
c84a77dd36
1
src/core.rs
Normal file
1
src/core.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod fast_hdlparam;
|
232
src/core/fast_hdlparam.rs
Normal file
232
src/core/fast_hdlparam.rs
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct Position {
|
||||||
|
pub line: u32,
|
||||||
|
pub character: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct Range {
|
||||||
|
pub start: Position,
|
||||||
|
pub end: Position
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Port {
|
||||||
|
pub name: String,
|
||||||
|
pub dir_type: String,
|
||||||
|
pub net_type: String,
|
||||||
|
pub width: String,
|
||||||
|
pub signed: String,
|
||||||
|
pub range: Range
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Parameter {
|
||||||
|
pub name: String,
|
||||||
|
pub net_type: String,
|
||||||
|
pub init: String,
|
||||||
|
pub range: Range
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Debug, Serialize)]
|
||||||
|
// pub struct InstPort {
|
||||||
|
// pub name: String,
|
||||||
|
// pub range: Range
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Debug, Serialize)]
|
||||||
|
// pub struct InstParameter {
|
||||||
|
// pub name: String,
|
||||||
|
// pub value: String,
|
||||||
|
// pub range: Range
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Instance {
|
||||||
|
pub name: String,
|
||||||
|
pub inst_type: String,
|
||||||
|
pub instparams: Option<Range>,
|
||||||
|
pub instports: Option<Range>,
|
||||||
|
pub range: Range
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Module {
|
||||||
|
pub name: String,
|
||||||
|
pub params: Vec<Parameter>,
|
||||||
|
pub ports: Vec<Port>,
|
||||||
|
pub instances: Vec<Instance>,
|
||||||
|
pub range: Range
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct FastHdlparam {
|
||||||
|
pub fast: Vec<Module>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FastHdlparam {
|
||||||
|
pub fn new_module(&mut self, name: &str, line: u32, character: u32, end_character: u32) {
|
||||||
|
let module = Module {
|
||||||
|
name: name.to_string(),
|
||||||
|
params: Vec::new(),
|
||||||
|
ports: Vec::new(),
|
||||||
|
instances: Vec::new(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line, character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line, character: end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.fast.push(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_parameter(&mut self, name: &str, net_type: &str, init: &str,
|
||||||
|
start_line: u32, start_character: u32, end_line: u32, end_character: u32) {
|
||||||
|
let last_module = self.fast.last_mut().unwrap();
|
||||||
|
let parameter = Parameter {
|
||||||
|
name: name.to_string(),
|
||||||
|
net_type: net_type.to_string(),
|
||||||
|
init: init.to_string(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_line, character: start_character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line:end_line, character: end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
last_module.params.push(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_port(&mut self, name: &str, dir_type: &str, net_type: &str, width: &str,
|
||||||
|
start_line: u32, start_character: u32, end_line: u32, end_character: u32) {
|
||||||
|
let last_module = self.fast.last_mut().unwrap();
|
||||||
|
let port = Port {
|
||||||
|
name: name.to_string(),
|
||||||
|
dir_type: dir_type.to_string(),
|
||||||
|
net_type: net_type.to_string(),
|
||||||
|
width: width.to_string(),
|
||||||
|
signed: "unsigned".to_string(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_line, character: start_character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line:end_line, character: end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
last_module.ports.push(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_instance(&mut self, name: &str, inst_type: &str, line: u32, character: u32, end_character: u32,
|
||||||
|
param_start_line: u32, param_start_character: u32, param_end_line: u32, param_end_character: u32,
|
||||||
|
port_start_line: u32, port_start_character: u32, port_end_line: u32, port_end_character: u32 ) {
|
||||||
|
let last_module = self.fast.last_mut().unwrap();
|
||||||
|
let instance = Instance {
|
||||||
|
name: name.to_string(),
|
||||||
|
inst_type: inst_type.to_string(),
|
||||||
|
instparams: if param_start_line == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
Range {
|
||||||
|
start: Position {
|
||||||
|
line: param_start_line, character: param_start_character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: param_end_line, character: param_end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
instports: if port_start_line == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
Range {
|
||||||
|
start: Position {
|
||||||
|
line: port_start_line, character: port_start_character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: port_end_line, character: port_end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line, character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line, character: end_character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
last_module.instances.push(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_fast(&self) {
|
||||||
|
if self.fast.is_empty() {
|
||||||
|
println!("none module");
|
||||||
|
} else {
|
||||||
|
for module in &self.fast {
|
||||||
|
println!("module {}", module.name);
|
||||||
|
if !module.params.is_empty() {
|
||||||
|
println!(" params:");
|
||||||
|
for param in &module.params {
|
||||||
|
println!(" parameter {} {} {}", param.net_type, param.name, param.init);
|
||||||
|
println!(" range start {} {}", param.range.start.line, param.range.start.character);
|
||||||
|
println!(" range end {} {}", param.range.end.line, param.range.end.character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !module.ports.is_empty() {
|
||||||
|
println!(" ports:");
|
||||||
|
for port in &module.ports {
|
||||||
|
if port.width == "1" {
|
||||||
|
println!(" {} {} {}", port.dir_type, port.net_type, port.name);
|
||||||
|
} else {
|
||||||
|
println!(" {} {} {} {}", port.dir_type, port.net_type, port.width, port.name);
|
||||||
|
}
|
||||||
|
println!(" range start {} {}", port.range.start.line, port.range.start.character);
|
||||||
|
println!(" range end {} {}", port.range.end.line, port.range.end.character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !module.instances.is_empty() {
|
||||||
|
println!(" instances:");
|
||||||
|
for instance in &module.instances {
|
||||||
|
println!(" {} {}", instance.inst_type, instance.name);
|
||||||
|
if instance.instparams.is_none() {
|
||||||
|
println!(" params: {:?}", instance.instparams);
|
||||||
|
} else {
|
||||||
|
println!(" params:");
|
||||||
|
println!(" range start {} {}", instance.instparams.clone().unwrap().start.line,
|
||||||
|
instance.instparams.clone().unwrap().start.character);
|
||||||
|
println!(" range end {} {}", instance.instparams.clone().unwrap().end.line,
|
||||||
|
instance.instparams.clone().unwrap().end.character);
|
||||||
|
}
|
||||||
|
if instance.instports.is_none() {
|
||||||
|
println!(" ports: {:?}", instance.instports);
|
||||||
|
} else {
|
||||||
|
println!(" ports:");
|
||||||
|
println!(" range start {} {}", instance.instports.clone().unwrap().start.line,
|
||||||
|
instance.instports.clone().unwrap().start.character);
|
||||||
|
println!(" range end {} {}", instance.instports.clone().unwrap().end.line,
|
||||||
|
instance.instports.clone().unwrap().end.character);
|
||||||
|
}
|
||||||
|
println!(" range start {} {}", instance.range.start.line, instance.range.start.character);
|
||||||
|
println!(" range end {} {}", instance.range.end.line, instance.range.end.character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!(" range start {} {}", module.range.start.line, module.range.start.character);
|
||||||
|
println!(" range end {} {}", module.range.end.line, module.range.end.character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,155 +0,0 @@
|
|||||||
// use std::collections::HashMap;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct RangeInfo {
|
|
||||||
line: u32,
|
|
||||||
character: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Range {
|
|
||||||
start: RangeInfo,
|
|
||||||
end: RangeInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Parameter {
|
|
||||||
name: String,
|
|
||||||
parameter_type: String,
|
|
||||||
init: String,
|
|
||||||
range: Range,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Port {
|
|
||||||
name: String,
|
|
||||||
port_type: String,
|
|
||||||
net_type: String,
|
|
||||||
width: String,
|
|
||||||
range: Range,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct Instance {
|
|
||||||
name: String,
|
|
||||||
instance_type: String,
|
|
||||||
instparams: Range,
|
|
||||||
instports: Range,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct SvlogModule {
|
|
||||||
name: String,
|
|
||||||
params: Vec<Parameter>,
|
|
||||||
ports: Vec<Port>,
|
|
||||||
instances: Vec<Instance>,
|
|
||||||
range: Range
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct SvlogInfo {
|
|
||||||
pub fast: Vec<SvlogModule>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SvlogInfo {
|
|
||||||
pub fn new_module(&mut self, symbol_name: &str, symbol_line: u32, start_col: usize, end_col: usize) {
|
|
||||||
let new_mod = SvlogModule {
|
|
||||||
name: symbol_name.to_string(),
|
|
||||||
range: Range {
|
|
||||||
start: RangeInfo {
|
|
||||||
line: symbol_line,
|
|
||||||
character: start_col
|
|
||||||
},
|
|
||||||
end: RangeInfo {
|
|
||||||
line: symbol_line,
|
|
||||||
character: end_col
|
|
||||||
}
|
|
||||||
},
|
|
||||||
params: Vec::new(),
|
|
||||||
ports: Vec::new(),
|
|
||||||
instances: Vec::new()
|
|
||||||
};
|
|
||||||
self.fast.push(new_mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_parameter(&mut self, param_name: &str, param_type: &str, start_line: u32, start_col: usize, end_line: u32, end_col: usize) {
|
|
||||||
if let Some(last_mod) = self.fast.last_mut() {
|
|
||||||
let parameter = Parameter {
|
|
||||||
name: param_name.to_string(),
|
|
||||||
parameter_type: param_type.to_string(),
|
|
||||||
init: "unknown".to_string(),
|
|
||||||
range: Range {
|
|
||||||
start: RangeInfo {
|
|
||||||
line: start_line,
|
|
||||||
character: start_col
|
|
||||||
},
|
|
||||||
end: RangeInfo {
|
|
||||||
line: end_line,
|
|
||||||
character: end_col
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(*last_mod).params.push(parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_port(&mut self, port_name: &str, port_net_type: &str, port_dir: &str, start_line: u32, start_col: usize, end_line: u32, end_col: usize) {
|
|
||||||
if let Some(last_mod) = self.fast.last_mut() {
|
|
||||||
let port = Port {
|
|
||||||
name: port_name.to_string(),
|
|
||||||
port_type: port_dir.to_string(),
|
|
||||||
net_type: port_net_type.to_string(),
|
|
||||||
width: "unknown".to_string(),
|
|
||||||
range: Range {
|
|
||||||
start: RangeInfo {
|
|
||||||
line: start_line,
|
|
||||||
character: start_col
|
|
||||||
},
|
|
||||||
end: RangeInfo {
|
|
||||||
line: end_line,
|
|
||||||
character: end_col
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(*last_mod).ports.push(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_instance(&mut self, symbol_name: &str) {
|
|
||||||
if let Some(last_mod) = self.fast.last_mut() {
|
|
||||||
let instance = Instance {
|
|
||||||
name: symbol_name.to_string(),
|
|
||||||
instance_type: (*last_mod.name).to_string(),
|
|
||||||
instparams: Range {
|
|
||||||
start: RangeInfo {
|
|
||||||
line: 0,
|
|
||||||
character: 0
|
|
||||||
},
|
|
||||||
end: RangeInfo {
|
|
||||||
line: 0,
|
|
||||||
character: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
instports: Range {
|
|
||||||
start: RangeInfo {
|
|
||||||
line: 0,
|
|
||||||
character: 0
|
|
||||||
},
|
|
||||||
end: RangeInfo {
|
|
||||||
line: 0,
|
|
||||||
character: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(*last_mod).instances.push(instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// const RS2JSON_RENAME_LIST: [(&str, &str); 4] = [
|
|
||||||
// ("parameter_type", "type"),
|
|
||||||
// ("port_type", "type"),
|
|
||||||
// ("net_type", "netType"),
|
|
||||||
// ("instance_type", "type"),
|
|
||||||
// ];
|
|
517
src/core/sv_parser.rs
Normal file
517
src/core/sv_parser.rs
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use sv_parser::{parse_sv, unwrap_node, ConstantMintypmaxExpression, GateInstantiation, ListOfParameterAssignments, ListOfPortConnections, Locate, PackedDimensionRange, RefNode, SyntaxTree};
|
||||||
|
use crate::core::fast_hdlparam::FastHdlparam;
|
||||||
|
|
||||||
|
pub fn sv_parser(path: &str) -> FastHdlparam {
|
||||||
|
// The path of SystemVerilog source file
|
||||||
|
let path = PathBuf::from(path);
|
||||||
|
// The list of defined macros
|
||||||
|
let defines = HashMap::new();
|
||||||
|
// The list of include paths
|
||||||
|
let includes: Vec<PathBuf> = Vec::new();
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
let result: Result<(SyntaxTree, HashMap<String, Option<sv_parser::Define>>), sv_parser::Error> = parse_sv(&path, &defines, &includes, false, true);
|
||||||
|
|
||||||
|
let hdlparam = make_fast_from_syntaxtree(result);
|
||||||
|
|
||||||
|
hdlparam
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_fast_from_syntaxtree(result: Result<(SyntaxTree, HashMap<String, Option<sv_parser::Define>>), sv_parser::Error>) -> FastHdlparam {
|
||||||
|
let mut hdlparam = FastHdlparam {
|
||||||
|
fast: Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut nonansi_port_locate = HashMap::new();
|
||||||
|
let mut ansi_port_last_dir = "";
|
||||||
|
|
||||||
|
if let Ok((syntax_tree, _)) = result {
|
||||||
|
let content = syntax_tree.text.text().split('\n')
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
// &SyntaxTree is iterable
|
||||||
|
for node in &syntax_tree {
|
||||||
|
match node {
|
||||||
|
RefNode::ModuleDeclaration(x) => {
|
||||||
|
let id = unwrap_node!(x, ModuleIdentifier).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let (line, character) = (id.line, get_column_by_offset(&content, id.offset) as u32);
|
||||||
|
let end_character = character + id.len as u32;
|
||||||
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
|
hdlparam.new_module(name, line, character, end_character);
|
||||||
|
}
|
||||||
|
RefNode::ParameterPortDeclaration(x) => {
|
||||||
|
let id = unwrap_node!(x, ParameterIdentifier).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
|
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 = get_identifier(unwrap_node!(data_type, SimpleIdentifier, Keyword).unwrap()).unwrap();
|
||||||
|
syntax_tree.get_str(&id).unwrap()
|
||||||
|
}
|
||||||
|
_ => "wire"
|
||||||
|
};
|
||||||
|
let init = match unwrap_node!(param_node, ConstantMintypmaxExpression).unwrap() {
|
||||||
|
RefNode::ConstantMintypmaxExpression(expression) => {
|
||||||
|
// println!("expression {:?}", expression);
|
||||||
|
let (exp, last_locate) = parse_parameter_expression(&syntax_tree, expression);
|
||||||
|
(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()
|
||||||
|
};
|
||||||
|
hdlparam.add_parameter(name, net_type, init.as_str(), start_line, start_character, end_line, end_character);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RefNode::Port(x) => {
|
||||||
|
let id = unwrap_node!(x, SimpleIdentifier).unwrap();
|
||||||
|
let locate = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&locate.clone()).unwrap();
|
||||||
|
// println!("get port {} {:?}", name, locate);
|
||||||
|
nonansi_port_locate.insert(name, locate);
|
||||||
|
}
|
||||||
|
RefNode::PortDeclaration(x) => {
|
||||||
|
let id = unwrap_node!(x, InputDeclaration, OutputDeclaration, InoutDeclaration).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let dir_type = syntax_tree.get_str(&id).unwrap();
|
||||||
|
let (dir_line, dir_character) = (id.line, get_column_by_offset(&content, id.offset) as u32);
|
||||||
|
|
||||||
|
let net_type = match unwrap_node!(x, DataType, ImplicitDataType) {
|
||||||
|
Some(RefNode::DataType(x)) => {
|
||||||
|
let id = unwrap_node!(x, Keyword).unwrap();
|
||||||
|
syntax_tree.get_str(&get_identifier(id).unwrap()).unwrap()
|
||||||
|
},
|
||||||
|
Some(RefNode::ImplicitDataType(_)) => "wire",
|
||||||
|
_ => "unknown"
|
||||||
|
};
|
||||||
|
|
||||||
|
let width = match unwrap_node!(x, PackedDimensionRange) {
|
||||||
|
Some(RefNode::PackedDimensionRange(x)) => {
|
||||||
|
parse_port_expression(&syntax_tree, x)
|
||||||
|
}
|
||||||
|
_ => "1".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = unwrap_node!(x, PortIdentifier).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
|
let (start_line, start_character, end_line, end_character) = if nonansi_port_locate.contains_key(name) {
|
||||||
|
let start_character = get_column_by_offset(&content, nonansi_port_locate[name].offset);
|
||||||
|
(nonansi_port_locate[name].line, start_character as u32,
|
||||||
|
nonansi_port_locate[name].line, (start_character + nonansi_port_locate[name].len) as u32)
|
||||||
|
} else {
|
||||||
|
(dir_line, dir_character, id.line, (get_column_by_offset(&content, id.offset) + id.len) as u32)
|
||||||
|
};
|
||||||
|
|
||||||
|
hdlparam.add_port(name, dir_type, net_type, width.as_str(), start_line, start_character, end_line, end_character);
|
||||||
|
}
|
||||||
|
RefNode::AnsiPortDeclaration(x) => {
|
||||||
|
let id = unwrap_node!(x, PortIdentifier).unwrap();
|
||||||
|
let name_locate = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&name_locate).unwrap();
|
||||||
|
let character = get_column_by_offset(&content, name_locate.offset);
|
||||||
|
let (end_line, end_character) = (name_locate.line, (character + name_locate.len) as u32);
|
||||||
|
|
||||||
|
let id = unwrap_node!(x, PortDirection);
|
||||||
|
let (start_line, start_character) = if id != None {
|
||||||
|
let id = id.unwrap();
|
||||||
|
let dir_locate = get_identifier(id).unwrap();
|
||||||
|
ansi_port_last_dir = syntax_tree.get_str(&dir_locate).unwrap();
|
||||||
|
(dir_locate.line, get_column_by_offset(&content, dir_locate.offset) as u32)
|
||||||
|
} else {
|
||||||
|
(name_locate.line, character as u32)
|
||||||
|
};
|
||||||
|
|
||||||
|
let net_type = if unwrap_node!(x, AnsiPortDeclarationVariable) != None {
|
||||||
|
"wire"
|
||||||
|
} else {
|
||||||
|
match unwrap_node!(x, DataType, ImplicitDataType) {
|
||||||
|
Some(RefNode::DataType(x)) => {
|
||||||
|
let id = unwrap_node!(x, Keyword).unwrap();
|
||||||
|
syntax_tree.get_str(&get_identifier(id).unwrap()).unwrap()
|
||||||
|
},
|
||||||
|
Some(RefNode::ImplicitDataType(_)) => "wire",
|
||||||
|
_ => "unknown"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let width = match unwrap_node!(x, PackedDimensionRange) {
|
||||||
|
Some(RefNode::PackedDimensionRange(x)) => {
|
||||||
|
parse_port_expression(&syntax_tree, x)
|
||||||
|
}
|
||||||
|
_ => "1".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
hdlparam.add_port(name, ansi_port_last_dir, net_type, width.as_str(), start_line, start_character, end_line, end_character);
|
||||||
|
}
|
||||||
|
RefNode::ModuleInstantiation(x) => {
|
||||||
|
let id = unwrap_node!(x, ModuleIdentifier).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let inst_type = syntax_tree.get_str(&id).unwrap();
|
||||||
|
|
||||||
|
let id = unwrap_node!(x, HierarchicalInstance).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
|
let (line, character) = (id.line, get_column_by_offset(&content, id.offset) as u32);
|
||||||
|
let end_character = character + id.len as u32;
|
||||||
|
|
||||||
|
let (param_start_line, param_start_character,
|
||||||
|
param_end_line, param_end_character) = match unwrap_node!(x, ListOfParameterAssignments) {
|
||||||
|
Some(RefNode::ListOfParameterAssignments(x)) => {
|
||||||
|
let locate = get_inst_param_last_locate(x);
|
||||||
|
if locate.is_none() {
|
||||||
|
(0, 0, 0, 0)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
locate.unwrap().0.line, get_column_by_offset(&content, locate.unwrap().0.offset) as u32,
|
||||||
|
locate.unwrap().1.line, (get_column_by_offset(&content, locate.unwrap().1.offset) + locate.unwrap().1.len) as u32
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (0, 0, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (port_start_line, port_start_character,
|
||||||
|
port_end_line, port_end_character) = match unwrap_node!(x, ListOfPortConnections) {
|
||||||
|
Some(RefNode::ListOfPortConnections(x)) => {
|
||||||
|
let locate = get_inst_port_last_locate(x);
|
||||||
|
if locate.is_none() {
|
||||||
|
(0, 0, 0, 0)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
locate.unwrap().0.line, get_column_by_offset(&content, locate.unwrap().0.offset) as u32,
|
||||||
|
locate.unwrap().1.line, (get_column_by_offset(&content, locate.unwrap().1.offset) + locate.unwrap().1.len) as u32
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (0, 0, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
hdlparam.add_instance(name, inst_type, line, character, end_character,
|
||||||
|
param_start_line, param_start_character, param_end_line, param_end_character,
|
||||||
|
port_start_line, port_start_character, port_end_line, port_end_character
|
||||||
|
);
|
||||||
|
}
|
||||||
|
RefNode::GateInstantiation(x) => {
|
||||||
|
let id = unwrap_node!(x, GateInstantiation).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let inst_type = syntax_tree.get_str(&id).unwrap();
|
||||||
|
|
||||||
|
let id = unwrap_node!(x, NInputGateInstance, NOutputGateInstance).unwrap();
|
||||||
|
let id = get_identifier(id).unwrap();
|
||||||
|
let name = syntax_tree.get_str(&id).unwrap();
|
||||||
|
let (line, character) = (id.line, get_column_by_offset(&content, id.offset) as u32);
|
||||||
|
let end_character = character + id.len as u32;
|
||||||
|
|
||||||
|
let locate = get_gateinst_port_locate(x);
|
||||||
|
let (param_start_line, param_start_character, param_end_line, param_end_character) = (0, 0, 0, 0);
|
||||||
|
let (port_start_line, port_start_character, port_end_line, port_end_character) = if locate.is_none() {
|
||||||
|
(0,0,0,0)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
locate.unwrap().0.line, get_column_by_offset(&content, locate.unwrap().0.offset) as u32,
|
||||||
|
locate.unwrap().1.line, (get_column_by_offset(&content, locate.unwrap().1.offset) + locate.unwrap().1.len) as u32
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
hdlparam.add_instance(name, inst_type, line, character, end_character,
|
||||||
|
param_start_line, param_start_character, param_end_line, param_end_character,
|
||||||
|
port_start_line, port_start_character, port_end_line, port_end_character
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("Parse failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
hdlparam
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_inst_param_last_locate(x: &ListOfParameterAssignments) -> Option<(Locate, Locate)> {
|
||||||
|
let mut first_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
let mut last_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
|
||||||
|
for node in x {
|
||||||
|
match unwrap_node!(node, SimpleIdentifier, Symbol) {
|
||||||
|
Some(RefNode::SimpleIdentifier(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate { last_locate = locate; }
|
||||||
|
if first_locate.offset == 0 { first_locate = locate; };
|
||||||
|
}
|
||||||
|
Some(RefNode::Symbol(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate { last_locate = locate; }
|
||||||
|
if first_locate.offset == 0 { first_locate = locate; };
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if last_locate.offset == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((first_locate, last_locate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_inst_port_last_locate(x: &ListOfPortConnections) -> Option<(Locate, Locate)> {
|
||||||
|
let mut first_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
let mut last_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
|
||||||
|
for node in x {
|
||||||
|
match unwrap_node!(node, SimpleIdentifier, Symbol) {
|
||||||
|
Some(RefNode::SimpleIdentifier(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate { last_locate = locate; }
|
||||||
|
if first_locate.offset == 0 { first_locate = locate; };
|
||||||
|
}
|
||||||
|
Some(RefNode::Symbol(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate { last_locate = locate; }
|
||||||
|
if first_locate.offset == 0 { first_locate = locate; };
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if last_locate.offset == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((first_locate, last_locate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_gateinst_port_locate(x: &GateInstantiation) -> Option<(Locate, Locate)> {
|
||||||
|
let mut first_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
let mut last_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
|
||||||
|
for node in x {
|
||||||
|
match unwrap_node!(node, InputTerminal, OutputTerminal) {
|
||||||
|
Some(RefNode::InputTerminal(x)) => {
|
||||||
|
let id = unwrap_node!(x, Identifier).unwrap();
|
||||||
|
let locate = get_identifier(id).unwrap();
|
||||||
|
if locate != last_locate { last_locate = locate; }
|
||||||
|
if first_locate.offset == 0 { first_locate = locate; };
|
||||||
|
}
|
||||||
|
Some(RefNode::OutputTerminal(x)) => {
|
||||||
|
let id = unwrap_node!(x, Identifier).unwrap();
|
||||||
|
let locate = get_identifier(id).unwrap();
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if last_locate.offset == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((first_locate, last_locate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_port_expression(syntax_tree: &SyntaxTree, x: &PackedDimensionRange) -> String {
|
||||||
|
let mut last_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
let mut expression = String::new();
|
||||||
|
for node in x {
|
||||||
|
// println!("parse expression::node {:#?}", node);
|
||||||
|
match unwrap_node!(node, SimpleIdentifier, Symbol, UnsignedNumber, HexNumber, OctalNumber, BinaryNumber) {
|
||||||
|
Some(RefNode::SimpleIdentifier(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&locate).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::Symbol(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&x.nodes.0).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::UnsignedNumber(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&x.nodes.0).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::HexNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::OctalNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::BinaryNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expression == "" {
|
||||||
|
"unknown".to_string()
|
||||||
|
} else {
|
||||||
|
// println!("get {}", expression);
|
||||||
|
expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_parameter_expression(syntax_tree: &SyntaxTree, x: &ConstantMintypmaxExpression) -> (String, Option<Locate>) {
|
||||||
|
let mut last_locate = Locate { offset: 0, line: 0, len: 0 };
|
||||||
|
let mut expression = String::new();
|
||||||
|
for node in x {
|
||||||
|
// println!("parse expression::node {:#?}", node);
|
||||||
|
match unwrap_node!(node, SimpleIdentifier, Symbol, UnsignedNumber, HexNumber, OctalNumber, BinaryNumber) {
|
||||||
|
Some(RefNode::SimpleIdentifier(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&locate).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::Symbol(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&x.nodes.0).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::UnsignedNumber(x)) => {
|
||||||
|
let locate = x.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let s = syntax_tree.get_str(&x.nodes.0).unwrap();
|
||||||
|
expression = expression + s;
|
||||||
|
// println!("parse expression {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::HexNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::OctalNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(RefNode::BinaryNumber(x)) => {
|
||||||
|
let locate = x.nodes.1.nodes.0;
|
||||||
|
if locate != last_locate {
|
||||||
|
last_locate = locate;
|
||||||
|
let size = if x.nodes.0 != None { syntax_tree.get_str(&x.nodes.0).unwrap() } else { "" };
|
||||||
|
let base = syntax_tree.get_str(&x.nodes.1.nodes.0).unwrap();
|
||||||
|
let number = syntax_tree.get_str(&x.nodes.2.nodes.0).unwrap();
|
||||||
|
expression = expression + size + base + number;
|
||||||
|
// println!("parse expression {}", expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expression == "" {
|
||||||
|
("unknown".to_string(), None)
|
||||||
|
} else {
|
||||||
|
// println!("parse function lastlocate {:?}", last_locate);
|
||||||
|
(expression, Some(last_locate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_identifier(node: RefNode) -> Option<Locate> {
|
||||||
|
// unwrap_node! can take multiple types
|
||||||
|
match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier, Keyword) {
|
||||||
|
Some(RefNode::SimpleIdentifier(x)) => {
|
||||||
|
return Some(x.nodes.0);
|
||||||
|
}
|
||||||
|
Some(RefNode::EscapedIdentifier(x)) => {
|
||||||
|
return Some(x.nodes.0);
|
||||||
|
}
|
||||||
|
Some(RefNode::Keyword(x)) => {
|
||||||
|
return Some(x.nodes.0);
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_column_by_offset(content: &[String], offset: usize) -> usize {
|
||||||
|
let mut current_offset = 0;
|
||||||
|
|
||||||
|
for line_content in content {
|
||||||
|
let line_length = line_content.len() + 1; // +1 for newline character
|
||||||
|
// println!("now line {} len {}", line_content, line_length);
|
||||||
|
// println!("now offset {} offset {}", current_offset + line_length, offset);
|
||||||
|
if current_offset + line_length > offset {
|
||||||
|
return offset - current_offset + 1;
|
||||||
|
}
|
||||||
|
current_offset += line_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
1 // if offset over the file lentgh,return 1
|
||||||
|
}
|
343
src/core/vhdl_parser.rs
Normal file
343
src/core/vhdl_parser.rs
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use vhdl_lang::{kind_str, Token, VHDLParser, VHDLStandard};
|
||||||
|
use crate::fast_hdlparam::*;
|
||||||
|
|
||||||
|
pub fn vhdl_parser(path: &str) -> FastHdlparam {
|
||||||
|
// The path of SystemVerilog source file
|
||||||
|
let path = PathBuf::from(path);
|
||||||
|
|
||||||
|
let mut hdlparam = FastHdlparam {
|
||||||
|
fast: Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
let parser = VHDLParser::new(VHDLStandard::VHDL2008);
|
||||||
|
let mut diagnostics = Vec::new();
|
||||||
|
let (_, design_file) = parser.parse_design_file(&path, &mut diagnostics).unwrap();
|
||||||
|
|
||||||
|
let mut all_tockens = Vec::new();
|
||||||
|
for (tokens, _) in design_file.design_units {
|
||||||
|
all_tockens.extend(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdlparam.fast.extend(parse_tokens(all_tockens));
|
||||||
|
hdlparam
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_tokens(tokens: Vec<Token>) -> Vec<Module> {
|
||||||
|
let mut modules = Vec::new();
|
||||||
|
let mut instance_type = HashSet::new();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
while i < tokens.len() {
|
||||||
|
let token = &tokens[i];
|
||||||
|
match kind_str(token.kind) {
|
||||||
|
"entity" => {
|
||||||
|
i += 1;
|
||||||
|
let module = Module {
|
||||||
|
name: get_value(&tokens[i]),
|
||||||
|
params: Vec::new(),
|
||||||
|
ports: Vec::new(),
|
||||||
|
instances: Vec::new(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: tokens[i].pos.range.start.line + 1,
|
||||||
|
character: tokens[i].pos.range.start.character + 1
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: tokens[i].pos.range.end.line + 1,
|
||||||
|
character: tokens[i].pos.range.end.character + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
modules.push(module);
|
||||||
|
}
|
||||||
|
"component" => {
|
||||||
|
i += 1;
|
||||||
|
instance_type.insert(get_value(&tokens[i]));
|
||||||
|
while !(kind_str(tokens[i].kind) == "end" && kind_str(tokens[i+1].kind) == "component") {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
":" => {
|
||||||
|
if instance_type.contains(&get_value(&tokens[i+1])) {
|
||||||
|
let instance = Instance {
|
||||||
|
name: get_value(&tokens[i-1]),
|
||||||
|
inst_type: get_value(&tokens[i+1]),
|
||||||
|
instports: None,
|
||||||
|
instparams: None,
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: tokens[i-1].pos.range.start.line,
|
||||||
|
character: tokens[i-1].pos.range.start.character
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: tokens[i+1].pos.range.start.line,
|
||||||
|
character: tokens[i+1].pos.range.start.character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
modules.last_mut().unwrap().instances.push(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"generic" => {
|
||||||
|
let is_map = kind_str(tokens[i+1].kind) == "map";
|
||||||
|
let (params, next_index) = parse_parameters(&tokens, i + 1, is_map);
|
||||||
|
if is_map {
|
||||||
|
let start = params.first().unwrap().range.start.clone();
|
||||||
|
let end = params.last().unwrap().range.start.clone();
|
||||||
|
modules.last_mut().unwrap().instances.last_mut().unwrap().instparams = Some(Range { start, end });
|
||||||
|
} else {
|
||||||
|
modules.last_mut().unwrap().params.extend(params);
|
||||||
|
}
|
||||||
|
i = next_index;
|
||||||
|
}
|
||||||
|
"port" => {
|
||||||
|
let is_map = kind_str(tokens[i+1].kind) == "map";
|
||||||
|
let (ports, next_index) = parse_port(&tokens, i + 1, is_map);
|
||||||
|
if is_map {
|
||||||
|
let start = ports.first().unwrap().range.start.clone();
|
||||||
|
let end = ports.last().unwrap().range.start.clone();
|
||||||
|
modules.last_mut().unwrap().instances.last_mut().unwrap().instports = Some(Range { start, end });
|
||||||
|
} else {
|
||||||
|
modules.last_mut().unwrap().ports.extend(ports);
|
||||||
|
}
|
||||||
|
i = next_index;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// println!("{:?}", modules);
|
||||||
|
modules
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_port(tokens: &[Token], start: usize, is_map: bool) -> (Vec<Port>, usize) {
|
||||||
|
let mut ports = Vec::new();
|
||||||
|
let mut i = start;
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
|
||||||
|
while i < tokens.len() {
|
||||||
|
let token = &tokens[i];
|
||||||
|
match kind_str(token.kind) {
|
||||||
|
"(" => {
|
||||||
|
stack.push(token);
|
||||||
|
}
|
||||||
|
")" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
";" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"{identifier}" => {
|
||||||
|
if is_map {
|
||||||
|
let start_pos = tokens[i].pos.range.start;
|
||||||
|
let end_pos = tokens[i+3].pos.range.end;
|
||||||
|
let port = Port {
|
||||||
|
name: get_value(&tokens[i]),
|
||||||
|
dir_type: "none".to_string(),
|
||||||
|
net_type: get_value(&tokens[i+2]),
|
||||||
|
width: "none".to_string(),
|
||||||
|
signed: "unsigned".to_string(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_pos.line + 1,
|
||||||
|
character: start_pos.character + 1
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: end_pos.line + 1,
|
||||||
|
character: end_pos.character + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
i += 2;
|
||||||
|
ports.push(port);
|
||||||
|
} else {
|
||||||
|
let start_pos = tokens[i].pos.range.start;
|
||||||
|
let width ;
|
||||||
|
let end_idx;
|
||||||
|
if get_value(&tokens[i+3]).contains("VECTOR") || get_value(&tokens[i+3]).contains("vector") {
|
||||||
|
let (width_str, index) = parse_width(&tokens, i+4);
|
||||||
|
width = "[".to_string() + &width_str + "]";
|
||||||
|
end_idx = index;
|
||||||
|
} else {
|
||||||
|
width = "1".to_string();
|
||||||
|
end_idx = i+3;
|
||||||
|
}
|
||||||
|
let end_pos = tokens[end_idx].pos.range.end;
|
||||||
|
let direction = if kind_str(tokens[i+2].kind) == "buffer" { "out" } else { kind_str(tokens[i+2].kind) };
|
||||||
|
let port = Port {
|
||||||
|
name: get_value(&tokens[i]),
|
||||||
|
dir_type: direction.to_string(),
|
||||||
|
net_type: get_value(&tokens[i+3]),
|
||||||
|
width,
|
||||||
|
signed: "unsigned".to_string(),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_pos.line + 1,
|
||||||
|
character: start_pos.character + 1
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: end_pos.line + 1,
|
||||||
|
character: end_pos.character + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
i = end_idx;
|
||||||
|
ports.push(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(ports, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_width(tokens: &[Token], start: usize) -> (String, usize) {
|
||||||
|
let mut width = String::new();
|
||||||
|
let mut i = start;
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
|
||||||
|
while i < tokens.len() {
|
||||||
|
match kind_str(tokens[i].kind) {
|
||||||
|
"(" => {
|
||||||
|
stack.push(&tokens[i]);
|
||||||
|
}
|
||||||
|
")" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
";" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if stack.len() >= 1 {
|
||||||
|
if get_value(&tokens[i]) == "None" {
|
||||||
|
if kind_str(tokens[i].kind) == "downto" || kind_str(tokens[i].kind) == "to" {
|
||||||
|
width = width + ":";
|
||||||
|
} else {
|
||||||
|
width = width + kind_str(tokens[i].kind);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = width + &get_value(&tokens[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
(width, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_parameters(tokens: &[Token], start: usize, is_map: bool) -> (Vec<Parameter>, usize) {
|
||||||
|
let mut params = Vec::new();
|
||||||
|
let mut i = start;
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
|
||||||
|
while i < tokens.len() {
|
||||||
|
let token = &tokens[i];
|
||||||
|
match kind_str(token.kind) {
|
||||||
|
"(" => {
|
||||||
|
stack.push(token);
|
||||||
|
}
|
||||||
|
")" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
";" => {
|
||||||
|
if stack.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"{identifier}" => {
|
||||||
|
if is_map {
|
||||||
|
let start_pos = tokens[i].pos.range.start;
|
||||||
|
let end_pos = tokens[i+2].pos.range.end;
|
||||||
|
let param = Parameter {
|
||||||
|
name: get_value(&tokens[i]),
|
||||||
|
net_type: get_value(&tokens[i+2]),
|
||||||
|
init: get_value(&tokens[i+2]),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_pos.line + 1,
|
||||||
|
character: start_pos.character + 1
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: end_pos.line + 1,
|
||||||
|
character: end_pos.character + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
i += 2;
|
||||||
|
params.push(param);
|
||||||
|
} else {
|
||||||
|
let start_pos = tokens[i].pos.range.start;
|
||||||
|
let end_pos = tokens[i+4].pos.range.end;
|
||||||
|
let param = Parameter {
|
||||||
|
name: get_value(&tokens[i]),
|
||||||
|
net_type: get_value(&tokens[i+2]),
|
||||||
|
init: get_value(&tokens[i+4]),
|
||||||
|
range: Range {
|
||||||
|
start: Position {
|
||||||
|
line: start_pos.line + 1,
|
||||||
|
character: start_pos.character + 1
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: end_pos.line + 1,
|
||||||
|
character: end_pos.character + 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
i += 4;
|
||||||
|
params.push(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(params, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value(token: &Token) -> String {
|
||||||
|
match &token.value {
|
||||||
|
vhdl_lang::Value::Identifier(symbol) => {
|
||||||
|
return symbol.name_utf8();
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::String(latin1_string) => {
|
||||||
|
return latin1_string.to_string();
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::BitString(latin1_string, _) => {
|
||||||
|
return latin1_string.to_string().replace("\\", "");
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::AbstractLiteral(latin1_string, _) => {
|
||||||
|
return latin1_string.to_string();
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::Character(character) => {
|
||||||
|
return character.to_string();
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::Text(latin1_string) => {
|
||||||
|
return latin1_string.to_string();
|
||||||
|
}
|
||||||
|
vhdl_lang::Value::None => {
|
||||||
|
return "None".to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ use serde_json::{json, Value};
|
|||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
|
||||||
|
use crate::core::fast_hdlparam::FastHdlparam;
|
||||||
use crate::server::Backend;
|
use crate::server::Backend;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -39,4 +40,19 @@ pub fn custom_request() -> Result<i32> {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
Ok(123)
|
Ok(123)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DoFastApi;
|
||||||
|
|
||||||
|
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (), Result<FastHdlparam>> for CustomRequest {
|
||||||
|
type Future = future::Ready<Result<FastHdlparam>>;
|
||||||
|
|
||||||
|
fn invoke(&self, _server: &'a Arc<Backend>, _params: ()) -> Self::Future {
|
||||||
|
future::ready(do_fast())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_fast() -> Result<FastHdlparam> {
|
||||||
|
|
||||||
}
|
}
|
@ -12,6 +12,7 @@ pub use def_types::*;
|
|||||||
mod extract_defs;
|
mod extract_defs;
|
||||||
use extract_defs::*;
|
use extract_defs::*;
|
||||||
|
|
||||||
|
|
||||||
impl LSPServer {
|
impl LSPServer {
|
||||||
pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
pub fn goto_definition(&self, params: GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
|
||||||
let doc = params.text_document_position_params.text_document.uri;
|
let doc = params.text_document_position_params.text_document.uri;
|
||||||
@ -20,9 +21,7 @@ impl LSPServer {
|
|||||||
self.srcs.wait_parse_ready(file_id, false);
|
self.srcs.wait_parse_ready(file_id, false);
|
||||||
let file = self.srcs.get_file(file_id)?;
|
let file = self.srcs.get_file(file_id)?;
|
||||||
let file = file.read().ok()?;
|
let file = file.read().ok()?;
|
||||||
let token = get_definition_token(file.text.line(pos.line as usize), pos);
|
let token: String = get_definition_token(file.text.line(pos.line as usize), pos);
|
||||||
|
|
||||||
// info!("definition token: {}", token);
|
|
||||||
|
|
||||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ impl LSPServer {
|
|||||||
.as_ref()?
|
.as_ref()?
|
||||||
// 获取定义
|
// 获取定义
|
||||||
.get_definition(&token, file.text.pos_to_byte(&pos), &doc)?;
|
.get_definition(&token, file.text.pos_to_byte(&pos), &doc)?;
|
||||||
|
|
||||||
let def_pos = file.text.byte_to_pos(def.byte_idx());
|
let def_pos = file.text.byte_to_pos(def.byte_idx());
|
||||||
Some(GotoDefinitionResponse::Scalar(Location::new(
|
Some(GotoDefinitionResponse::Scalar(Location::new(
|
||||||
def.url(),
|
def.url(),
|
||||||
@ -39,22 +38,26 @@ impl LSPServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover(&self, params: HoverParams) -> Option<Hover> {
|
pub fn hover(&self, params: HoverParams) -> Option<Hover> {
|
||||||
let doc = params.text_document_position_params.text_document.uri;
|
let doc: Url = params.text_document_position_params.text_document.uri;
|
||||||
let pos = params.text_document_position_params.position;
|
let pos: Position = params.text_document_position_params.position;
|
||||||
let file_id = self.srcs.get_id(&doc).to_owned();
|
let file_id: usize = self.srcs.get_id(&doc).to_owned();
|
||||||
self.srcs.wait_parse_ready(file_id, false);
|
self.srcs.wait_parse_ready(file_id, false);
|
||||||
let file = self.srcs.get_file(file_id)?;
|
let file: std::sync::Arc<std::sync::RwLock<crate::sources::Source>> = self.srcs.get_file(file_id)?;
|
||||||
let file = file.read().ok()?;
|
let file: std::sync::RwLockReadGuard<'_, crate::sources::Source> = file.read().ok()?;
|
||||||
let token = get_definition_token(file.text.line(pos.line as usize), pos);
|
let token: String = get_definition_token(file.text.line(pos.line as usize), pos);
|
||||||
debug!("hover, token: {}", &token);
|
|
||||||
let scope_tree = self.srcs.scope_tree.read().ok()?;
|
let scope_tree: std::sync::RwLockReadGuard<'_, Option<GenericScope>> = self.srcs.scope_tree.read().ok()?;
|
||||||
let def = scope_tree
|
|
||||||
|
let def: GenericDec = scope_tree
|
||||||
.as_ref()?
|
.as_ref()?
|
||||||
.get_definition(&token, file.text.pos_to_byte(&pos), &doc)?;
|
.get_definition(&token, file.text.pos_to_byte(&pos), &doc)?;
|
||||||
|
|
||||||
let def_line = file.text.byte_to_line(def.byte_idx());
|
let def_line = file.text.byte_to_line(def.byte_idx());
|
||||||
|
let language_id = get_language_id_by_uri(&doc);
|
||||||
|
|
||||||
Some(Hover {
|
Some(Hover {
|
||||||
contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString {
|
contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString {
|
||||||
language: "systemverilog".to_owned(),
|
language: language_id,
|
||||||
value: get_hover(&file.text, def_line),
|
value: get_hover(&file.text, def_line),
|
||||||
})),
|
})),
|
||||||
range: None,
|
range: None,
|
||||||
@ -126,7 +129,7 @@ fn get_definition_token(line: RopeSlice, pos: Position) -> String {
|
|||||||
line_iter.next();
|
line_iter.next();
|
||||||
}
|
}
|
||||||
let mut c = line_iter.prev();
|
let mut c = line_iter.prev();
|
||||||
while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_' || c.unwrap() == '`') {
|
while c.is_some() && (c.unwrap().is_alphanumeric() || c.unwrap() == '_') {
|
||||||
token.push(c.unwrap());
|
token.push(c.unwrap());
|
||||||
c = line_iter.prev();
|
c = line_iter.prev();
|
||||||
}
|
}
|
||||||
@ -143,6 +146,22 @@ fn get_definition_token(line: RopeSlice, pos: Position) -> String {
|
|||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn get_language_id_by_uri(uri: &Url) -> String {
|
||||||
|
let path = uri.path();
|
||||||
|
let ext_name = std::path::Path::new(path)
|
||||||
|
.extension()
|
||||||
|
.and_then(std::ffi::OsStr::to_str)
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
match ext_name {
|
||||||
|
"vhd" | "vhdl" | "vho" | "vht" => "vhdl".to_string(),
|
||||||
|
"v" | "V" | "vh" | "vl" => "verilog".to_string(),
|
||||||
|
"sv" | "svh" => "systemverilog".to_string(),
|
||||||
|
_ => "plaintext".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ScopesAndDefs = Option<(Vec<Box<dyn Scope>>, Vec<Box<dyn Definition>>)>;
|
type ScopesAndDefs = Option<(Vec<Box<dyn Scope>>, Vec<Box<dyn Definition>>)>;
|
||||||
|
|
||||||
/// Take a given syntax node from a sv-parser syntax tree and extract out the definition/scope at
|
/// Take a given syntax node from a sv-parser syntax tree and extract out the definition/scope at
|
||||||
@ -154,7 +173,7 @@ pub fn match_definitions(
|
|||||||
url: &Url,
|
url: &Url,
|
||||||
) -> ScopesAndDefs {
|
) -> ScopesAndDefs {
|
||||||
let mut definitions: Vec<Box<dyn Definition>> = Vec::new();
|
let mut definitions: Vec<Box<dyn Definition>> = Vec::new();
|
||||||
let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
|
let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
|
||||||
match node {
|
match node {
|
||||||
RefNode::ModuleDeclaration(n) => {
|
RefNode::ModuleDeclaration(n) => {
|
||||||
let module = module_dec(syntax_tree, n, event_iter, url);
|
let module = module_dec(syntax_tree, n, event_iter, url);
|
||||||
@ -271,9 +290,7 @@ pub fn match_definitions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefNode::TextMacroDefinition(n) => {
|
RefNode::TextMacroDefinition(n) => {
|
||||||
let dec = text_macro_def(syntax_tree, n, event_iter, url);
|
let dec = text_macro_def(syntax_tree, n, event_iter, url);
|
||||||
|
|
||||||
|
|
||||||
if dec.is_some() {
|
if dec.is_some() {
|
||||||
definitions.push(Box::new(dec?));
|
definitions.push(Box::new(dec?));
|
||||||
}
|
}
|
||||||
@ -289,7 +306,7 @@ pub fn match_definitions(
|
|||||||
pub fn get_scopes(syntax_tree: &SyntaxTree, url: &Url) -> Option<GenericScope> {
|
pub fn get_scopes(syntax_tree: &SyntaxTree, url: &Url) -> Option<GenericScope> {
|
||||||
let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
|
let mut scopes: Vec<Box<dyn Scope>> = Vec::new();
|
||||||
let mut global_scope: GenericScope = GenericScope::new(url);
|
let mut global_scope: GenericScope = GenericScope::new(url);
|
||||||
global_scope.ident = "global".to_string();
|
global_scope.ident = String::from("global");
|
||||||
let mut event_iter = syntax_tree.into_iter().event();
|
let mut event_iter = syntax_tree.into_iter().event();
|
||||||
// iterate over each enter event and extract out any scopes or definitions
|
// iterate over each enter event and extract out any scopes or definitions
|
||||||
// match_definitions is recursively called so we get a tree in the end
|
// match_definitions is recursively called so we get a tree in the end
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::thread::scope;
|
|
||||||
|
|
||||||
use crate::sources::LSPSupport;
|
use crate::sources::LSPSupport;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
@ -127,7 +125,6 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
|||||||
// the users token
|
// the users token
|
||||||
let completion_idents: Vec<String> = completions.iter().map(|x| x.label.clone()).collect();
|
let completion_idents: Vec<String> = completions.iter().map(|x| x.label.clone()).collect();
|
||||||
for def in self.defs() {
|
for def in self.defs() {
|
||||||
// info!("current def: {:?}, trigger token: {}, contain: {}, start with: {}", def, token, completion_idents.contains(&def.ident()), def.starts_with(token));
|
|
||||||
|
|
||||||
if !completion_idents.contains(&def.ident()) && def.ident().to_lowercase().starts_with(&lower_case_token) {
|
if !completion_idents.contains(&def.ident()) && def.ident().to_lowercase().starts_with(&lower_case_token) {
|
||||||
completions.push(def.completion());
|
completions.push(def.completion());
|
||||||
@ -189,16 +186,25 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
|||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return a definition from the scope tree, this function should be called on the global
|
/// 获取当前的 scope,如果返回 None,则说明当前 scope 为 global
|
||||||
/// scope
|
// fn get_current_scope(&self, byte_idx: usize, url: &Url) -> Option<Box<dyn Scope>> {
|
||||||
|
|
||||||
|
// for scope in self.scopes() {
|
||||||
|
// if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
|
||||||
|
// return scope.get_current_scope(byte_idx, url);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// self
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// 根据输入的 token,计算出这个 token 在 scope 中的定义
|
||||||
|
/// 比如输入 clock,则返回 clock 这个变量在哪里被定义,没有则返回 None
|
||||||
|
/// - `token`: 需要查找定义的完整的单词
|
||||||
|
/// - `byte_idx`: 当前光标所在文档的偏移量
|
||||||
|
/// - `url`: 当前文档的 url
|
||||||
fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option<GenericDec> {
|
fn get_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option<GenericDec> {
|
||||||
let mut definition: Option<GenericDec> = None;
|
let mut definition: Option<GenericDec> = None;
|
||||||
|
|
||||||
if token.starts_with("`") {
|
|
||||||
// 计算宏的定义跳转
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for scope in self.scopes() {
|
for scope in self.scopes() {
|
||||||
if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
|
if &scope.url() == url && scope.start() <= byte_idx && byte_idx <= scope.end() {
|
||||||
definition = scope.get_definition(token, byte_idx, url);
|
definition = scope.get_definition(token, byte_idx, url);
|
||||||
@ -207,6 +213,7 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if definition.is_none() {
|
if definition.is_none() {
|
||||||
|
// 优先找 定义,再找 scope
|
||||||
for def in self.defs() {
|
for def in self.defs() {
|
||||||
if def.ident() == token {
|
if def.ident() == token {
|
||||||
return Some(GenericDec {
|
return Some(GenericDec {
|
||||||
@ -229,6 +236,20 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
|||||||
definition
|
definition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 计算并得到有关 macro 的定义,保证 token 是以 ` 开头的
|
||||||
|
fn get_macro_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option<GenericDec> {
|
||||||
|
let mut definition: Option<GenericDec> = None;
|
||||||
|
|
||||||
|
if !token.starts_with("`") {
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算 macro 的位置,需要 global scope 下的所有 defs 加上 current scope 上的位置
|
||||||
|
|
||||||
|
definition
|
||||||
|
}
|
||||||
|
|
||||||
/// returns all symbols in a document
|
/// returns all symbols in a document
|
||||||
fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec<DocumentSymbol> {
|
fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec<DocumentSymbol> {
|
||||||
let mut symbols: Vec<DocumentSymbol> = Vec::new();
|
let mut symbols: Vec<DocumentSymbol> = Vec::new();
|
||||||
|
@ -7,4 +7,5 @@ pub mod format;
|
|||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod sources;
|
pub mod sources;
|
||||||
pub mod support;
|
pub mod support;
|
||||||
pub mod custom_request;
|
pub mod custom_request;
|
||||||
|
pub mod core;
|
@ -362,6 +362,7 @@ impl LanguageServer for Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
|
async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
|
||||||
|
|
||||||
Ok(self.server.hover(params))
|
Ok(self.server.hover(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ use crate::definition::def_types::*;
|
|||||||
use crate::definition::get_scopes;
|
use crate::definition::get_scopes;
|
||||||
use crate::diagnostics::{get_diagnostics, is_hidden};
|
use crate::diagnostics::{get_diagnostics, is_hidden};
|
||||||
use crate::server::LSPServer;
|
use crate::server::LSPServer;
|
||||||
use log::info;
|
|
||||||
use log::{debug, error, trace};
|
use log::{debug, error, trace};
|
||||||
use pathdiff::diff_paths;
|
use pathdiff::diff_paths;
|
||||||
use ropey::{Rope, RopeSlice};
|
use ropey::{Rope, RopeSlice};
|
||||||
@ -14,7 +13,6 @@ use std::ops::Range as StdRange;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
use std::sync::{Arc, Condvar, Mutex, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Instant;
|
|
||||||
use sv_parser::*;
|
use sv_parser::*;
|
||||||
use thread::JoinHandle;
|
use thread::JoinHandle;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
@ -211,7 +209,6 @@ impl Sources {
|
|||||||
let parse_handle = thread::spawn(move || {
|
let parse_handle = thread::spawn(move || {
|
||||||
let (lock, cvar) = &*valid_parse2;
|
let (lock, cvar) = &*valid_parse2;
|
||||||
loop {
|
loop {
|
||||||
let now = Instant::now();
|
|
||||||
let file = source_handle.read().unwrap();
|
let file = source_handle.read().unwrap();
|
||||||
let text = file.text.clone();
|
let text = file.text.clone();
|
||||||
let uri = &file.uri.clone();
|
let uri = &file.uri.clone();
|
||||||
@ -270,7 +267,7 @@ impl Sources {
|
|||||||
valid_parse,
|
valid_parse,
|
||||||
parse_handle,
|
parse_handle,
|
||||||
})));
|
})));
|
||||||
debug!("added {}", &doc.uri);
|
|
||||||
self.names.write().unwrap().insert(doc.uri, fid);
|
self.names.write().unwrap().insert(doc.uri, fid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,10 +373,10 @@ pub fn parse(
|
|||||||
uri.to_file_path().unwrap(),
|
uri.to_file_path().unwrap(),
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&includes,
|
&includes,
|
||||||
false,
|
true,
|
||||||
true
|
true
|
||||||
) {
|
) {
|
||||||
Ok((syntax_tree, defines)) => {
|
Ok((syntax_tree, _)) => {
|
||||||
return Some(syntax_tree);
|
return Some(syntax_tree);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user