diff --git a/src/core/fast_hdlparam.rs b/src/core/fast_hdlparam.rs index 36f0cd7..df6d3f7 100644 --- a/src/core/fast_hdlparam.rs +++ b/src/core/fast_hdlparam.rs @@ -61,12 +61,65 @@ pub struct Module { pub range: Range } +#[derive(Debug, Serialize)] +pub struct DefineParam { + pub name: String, + pub value: String +} + +#[derive(Debug, Serialize)] +pub struct Define { + name: String, + replacement: String, + range: Range, + params: Vec +} + +#[derive(Debug, Serialize)] +pub struct Include { + pub path: String, + pub range: Range +} + +#[derive(Debug, Serialize)] +pub struct Error { + severity: String, + message: String, + source: String, + range: Position, + running_mode: Option, + running_phase: Option, +} + +#[derive(Debug, Serialize)] +pub struct Macro { + pub defines: Vec, + pub includes: Vec, + pub errors: Vec, + pub invalid: Vec +} + #[derive(Debug, Serialize)] pub struct FastHdlparam { - pub fast: Vec + pub fast_macro: Macro, + pub content: Vec } impl FastHdlparam { + pub fn add_define(&mut self, name: &str, replacement: &str, start_line: u32, start_character: u32, + end_line: u32, end_character: u32, params: Vec) { + let define = Define { + name: name.to_string(), + replacement: replacement.to_string(), + range: Range { + start: Position { line: start_line, character: start_character }, + end: Position { line: end_line, character: end_character } + }, + params + }; + self.fast_macro.defines.push(define); + } + pub fn new_module(&mut self, name: &str, line: u32, character: u32, end_character: u32) { let module = Module { name: name.to_string(), @@ -82,12 +135,12 @@ impl FastHdlparam { } } }; - self.fast.push(module); + self.content.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 last_module = self.content.last_mut().unwrap(); let parameter = Parameter { name: name.to_string(), net_type: net_type.to_string(), @@ -106,7 +159,7 @@ impl FastHdlparam { 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 last_module = self.content.last_mut().unwrap(); let port = Port { name: name.to_string(), dir_type: dir_type.to_string(), @@ -129,7 +182,7 @@ impl FastHdlparam { 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 last_module = self.content.last_mut().unwrap(); let instance = Instance { name: name.to_string(), inst_type: inst_type.to_string(), @@ -174,10 +227,10 @@ impl FastHdlparam { } pub fn print_fast(&self) { - if self.fast.is_empty() { + if self.content.is_empty() { println!("none module"); } else { - for module in &self.fast { + for module in &self.content { println!("module {}", module.name); if !module.params.is_empty() { println!(" params:"); diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index e7feba9..cee6043 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -1,7 +1,9 @@ -use std::collections::HashMap; +use std::fs::File; +use std::io::BufRead; +use std::{collections::HashMap, io::BufReader}; use std::path::PathBuf; use sv_parser::{parse_sv, unwrap_node, ConstantMintypmaxExpression, GateInstantiation, ListOfParameterAssignments, ListOfPortConnections, Locate, PackedDimensionRange, RefNode, SyntaxTree}; -use super::fast_hdlparam::FastHdlparam; +use super::fast_hdlparam::{FastHdlparam, Macro}; pub fn sv_parser(path: &str) -> Option { // The path of SystemVerilog source file @@ -13,16 +15,22 @@ pub fn sv_parser(path: &str) -> Option { let result = parse_sv(&path, &defines, &includes, false, true); if let Ok((syntax_tree, _)) = result { - let hdlparam = make_fast_from_syntaxtree(syntax_tree); + let hdlparam = make_fast_from_syntaxtree(syntax_tree, path); return Some(hdlparam); } None } -pub fn make_fast_from_syntaxtree(syntax_tree: SyntaxTree) -> FastHdlparam { +pub fn make_fast_from_syntaxtree(syntax_tree: SyntaxTree, path: PathBuf) -> FastHdlparam { let mut hdlparam = FastHdlparam { - fast: Vec::new() + fast_macro: Macro { + defines: Vec::new(), + errors: Vec::new(), + includes: get_includes(path), + invalid: Vec::new() + }, + content: Vec::new() }; let mut ansi_port_last_dir = ""; @@ -32,6 +40,40 @@ pub fn make_fast_from_syntaxtree(syntax_tree: SyntaxTree) -> FastHdlparam { // &SyntaxTree is iterable for node in &syntax_tree { match node { + RefNode::TextMacroDefinition(x) => { + let start = unwrap_node!(x, TextMacroDefinition).unwrap(); + let start = get_identifier(start).unwrap(); + let (start_line, start_character) = (start.line, get_column_by_offset(&content, start.offset)); + + let name = unwrap_node!(x, TextMacroName).unwrap(); + let name = get_identifier(name).unwrap(); + let name = syntax_tree.get_str(&name).unwrap(); + + let mut params_vec = Vec::new(); + if let Some(RefNode::ListOfFormalArguments(x)) = unwrap_node!(x, ListOfFormalArguments) { + for node in x { + if let RefNode::FormalArgument(x) = node { + let param_name = unwrap_node!(x, SimpleIdentifier).unwrap(); + let param_name = get_identifier(param_name).unwrap(); + let param_name = syntax_tree.get_str(¶m_name).unwrap(); + let param_val = match unwrap_node!(x, DefaultText) { + Some(RefNode::DefaultText(x)) => syntax_tree.get_str(&x.nodes.0).unwrap(), + _ => "Unknown" + }; + params_vec.push(crate::core::fast_hdlparam::DefineParam { name: param_name.to_string(), value: param_val.to_string() }); + } + } + } + + let replacement = match unwrap_node!(x, MacroText) { + Some(RefNode::MacroText(x)) => Some(x.nodes.0), + _ => None + }.unwrap(); + let (end_line, end_character) = (replacement.line, get_column_by_offset(&content, replacement.offset) + replacement.len); + let replacement = syntax_tree.get_str(&replacement).unwrap(); + + hdlparam.add_define(name, replacement, start_line, start_character as u32, end_line, end_character as u32, params_vec); + } RefNode::ModuleDeclaration(x) => { let id = unwrap_node!(x, ModuleIdentifier).unwrap(); let id = get_identifier(id).unwrap(); @@ -490,6 +532,41 @@ fn get_identifier(node: RefNode) -> Option { } } +fn get_includes(path: PathBuf) -> Vec { + let mut includes = Vec::new(); + + let file = File::open(path).unwrap(); + let reader = BufReader::new(file); + + for (line_number, line_content) in reader.lines().enumerate() { + let line_content = line_content.unwrap(); + + if line_content.trim().starts_with("`include") { + + let parts: Vec<&str> = line_content.split_whitespace().collect(); + + if parts.len() >= 2 { + let path = parts[1]; + let last_character = line_content.find(path).unwrap() + path.len(); + + includes.push(crate::core::fast_hdlparam::Include { + path: path.to_string(), + range: crate::core::fast_hdlparam::Range { + start: crate::core::fast_hdlparam::Position { + line: (line_number + 1) as u32, character: 1 + }, + end: crate::core::fast_hdlparam::Position { + line: (line_number + 1) as u32, character: last_character as u32 + } + } + }); + } + } + } + + includes +} + fn get_column_by_offset(content: &[String], offset: usize) -> usize { let mut current_offset = 0; diff --git a/src/core/vhdl_parser.rs b/src/core/vhdl_parser.rs index 9ead6f6..0b6bdad 100644 --- a/src/core/vhdl_parser.rs +++ b/src/core/vhdl_parser.rs @@ -8,7 +8,13 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam { let path = PathBuf::from(path); let mut hdlparam = FastHdlparam { - fast: Vec::new() + fast_macro: Macro { + defines: Vec::new(), + errors: Vec::new(), + includes: Vec::new(), + invalid: Vec::new() + }, + content: Vec::new() }; let parser = VHDLParser::new(VHDLStandard::VHDL2008); @@ -20,7 +26,7 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam { all_tockens.extend(tokens); } - hdlparam.fast.extend(parse_tokens(all_tockens)); + hdlparam.content.extend(parse_tokens(all_tockens)); hdlparam } diff --git a/src/custom_request.rs b/src/custom_request.rs index 55b1846..04af477 100644 --- a/src/custom_request.rs +++ b/src/custom_request.rs @@ -113,7 +113,7 @@ pub fn do_fast(path: String) -> Result { ); if let Some(syntax_tree) = parse_result { - let hdlparam = make_fast_from_syntaxtree(syntax_tree); + let hdlparam = make_fast_from_syntaxtree(syntax_tree, path_buf); return Ok(hdlparam); }