#parser #verilog #systemverilog

sv-parser-syntaxtree

Helper crate of sv-parser

34 releases (5 breaking)

✓ Uses Rust 2018 edition

new 0.6.3 Feb 13, 2020
0.6.0 Jan 24, 2020
0.4.19 Dec 12, 2019
0.4.5 Nov 28, 2019

#51 in Parser tooling

Download history 316/week @ 2019-11-01 223/week @ 2019-11-08 143/week @ 2019-11-15 250/week @ 2019-11-22 208/week @ 2019-11-29 327/week @ 2019-12-06 79/week @ 2019-12-13 14/week @ 2019-12-20 37/week @ 2019-12-27 46/week @ 2020-01-03 83/week @ 2020-01-10 240/week @ 2020-01-17 115/week @ 2020-01-24 54/week @ 2020-01-31 121/week @ 2020-02-07

538 downloads per month
Used in 5 crates (3 directly)

MIT/Apache

255KB
8K SLoC

sv-parser

SystemVerilog parser library fully complient with IEEE 1800-2017.

Actions Status Crates.io Docs.rs

Tools using sv-parser

  • svlint: SystemVerilog linter
  • svls: SystemVerilog language server

Usage

[dependencies]
sv-parser = "0.6.1"

sv-parser provides parse_sv function which returns SyntaxTree. SyntaxTree shows Concrete Syntax Tree. It has the preprocessed string and the parsed tree.

RefNode shows a reference to any node of SyntaxTree. You can get RefNode through an iterator of SyntaxTree. Variant names of RefNode follows "Annex A Formal syntax" of IEEE 1800-2017.

Locate shows a position of token. All leaf node of SyntaxTree is Locate. You can get string from Locate by get_str.

Example

The following example parses a SystemVerilog source file and shows module names.

use std::collections::HashMap;
use std::env;
use std::path::PathBuf;
use sv_parser::{parse_sv, unwrap_node, Locate, RefNode};

fn main() {
    let args: Vec<String> = env::args().collect();

    // The path of SystemVerilog source file
    let path = PathBuf::from(&args[1]);
    // The list of defined macros
    let defines = HashMap::new();
    // The list of include paths
    let includes: Vec<PathBuf> = Vec::new();

    // Parse
    let result = parse_sv(&path, &defines, &includes);

    if let Ok((syntax_tree, _)) = result {
        // &SyntaxTree is iterable
        for node in &syntax_tree {
            // The type of each node is RefNode
            match node {
                RefNode::ModuleDeclarationNonansi(x) => {
                    // unwrap_node! gets the nearest ModuleIdentifier from x
                    let id = unwrap_node!(x, ModuleIdentifier).unwrap();

                    let id = get_identifier(id).unwrap();

                    // Original string can be got by SyntaxTree::get_str(self, locate: &Locate)
                    let id = syntax_tree.get_str(&id);
                    println!("module: {}", id);
                }
                RefNode::ModuleDeclarationAnsi(x) => {
                    let id = unwrap_node!(x, ModuleIdentifier).unwrap();
                    let id = get_identifier(id).unwrap();
                    let id = syntax_tree.get_str(&id);
                    println!("module: {}", id);
                }
                _ => (),
            }
        }
    } else {
        println!("Parse failed");
    }
}

fn get_identifier(node: RefNode) -> Option<Locate> {
    // unwrap_node! can take multiple types
    match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier) {
        Some(RefNode::SimpleIdentifier(x)) => {
            return Some(x.nodes.0);
        }
        Some(RefNode::EscapedIdentifier(x)) => {
            return Some(x.nodes.0);
        }
        _ => None,
    }
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~0.5–1MB
~23K SLoC