1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
#![recursion_limit = "256"] use nom::combinator::all_consuming; use std::collections::HashMap; use std::fmt; use std::path::Path; use sv_parser_error::{Error, ErrorKind}; use sv_parser_parser::{lib_parser, sv_parser, Span, SpanInfo}; use sv_parser_pp::preprocess::{preprocess, Define, Defines, PreprocessedText}; pub use sv_parser_syntaxtree::*; pub struct SyntaxTree { node: AnyNode, text: PreprocessedText, } impl SyntaxTree { pub fn get_str(&self, locate: &Locate) -> &str { unsafe { self.text .text() .get_unchecked(locate.offset..locate.offset + locate.len) } } } impl fmt::Display for SyntaxTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut ret = String::from(""); let mut skip = false; let mut depth = 0; for node in self.into_iter().event() { match node { NodeEvent::Enter(RefNode::Locate(locate)) if !skip => { ret.push_str(&format!("{}{}\n", " ".repeat(depth), self.get_str(locate))); depth += 1; } NodeEvent::Enter(RefNode::WhiteSpace(_)) => { skip = true; } NodeEvent::Leave(RefNode::WhiteSpace(_)) => { skip = false; } NodeEvent::Enter(_) => { depth += 1; } NodeEvent::Leave(_) => { depth -= 1; } } } write!(f, "{}", ret) } } impl<'a> IntoIterator for &'a SyntaxTree { type Item = RefNode<'a>; type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { let ref_node: RefNode = (&self.node).into(); ref_node.into_iter() } } pub fn parse_sv<T: AsRef<Path>, U: AsRef<Path>>( path: T, pre_defines: &HashMap<String, Option<Define>>, include_paths: &[U], ) -> Result<(SyntaxTree, Defines), Error> { let (text, defines) = preprocess(path, pre_defines, include_paths)?; let span = Span::new_extra(text.text(), SpanInfo::default()); let result = all_consuming(sv_parser)(span); match result { Ok((_, x)) => Ok(( SyntaxTree { node: x.into(), text, }, defines, )), Err(_) => Err(ErrorKind::Parse.into()), } } pub fn parse_lib<T: AsRef<Path>, U: AsRef<Path>>( path: T, pre_defines: &HashMap<String, Option<Define>>, include_paths: &[U], ) -> Result<(SyntaxTree, Defines), Error> { let (text, defines) = preprocess(path, pre_defines, include_paths)?; let span = Span::new_extra(text.text(), SpanInfo::default()); let result = all_consuming(lib_parser)(span); match result { Ok((_, x)) => Ok(( SyntaxTree { node: x.into(), text, }, defines, )), Err(_) => Err(ErrorKind::Parse.into()), } } #[macro_export] macro_rules! unwrap_node { ($n:expr, $( $ty:tt ),+) => {{ let unwrap = || { for x in $n { match x { $(RefNode::$ty(x) => return Some(RefNode::$ty(x)),)* _ => (), } } None }; unwrap() }}; }