zirium 0.5.1

Lossless textual MLIR syntax parsing and semantic processing
Documentation
use zirium::{
    CompactError, EventBuilder, SyntaxElement, SyntaxKind,
    lexer::{TokenKind, lex},
    source::Source,
};

#[test]
fn markers_complete_abandon_and_nested_precede() {
    let source = Source::new(&b"abc"[..]).unwrap();
    let tokens = lex(&source).tokens().to_vec();
    let mut b = EventBuilder::new();
    let abandoned = b.start();
    b.abandon(abandoned).unwrap();
    let leaf = b.start();
    b.token(0).unwrap();
    let leaf = b.complete(leaf, SyntaxKind::Operation).unwrap();
    let parent = b.precede(leaf).unwrap();
    let parent = b.complete(parent, SyntaxKind::Region).unwrap();
    let root = b.precede(parent).unwrap();
    b.token(1).unwrap();
    b.complete(root, SyntaxKind::File).unwrap();
    let tree = b.finish(tokens).unwrap();
    let nodes: Vec<_> = tree.subtree(tree.root()).unwrap().collect();
    assert_eq!(nodes.len(), 3);
    assert_eq!(tree.kind(nodes[0]), Some(SyntaxKind::File));
    assert_eq!(tree.kind(nodes[1]), Some(SyntaxKind::Region));
    assert_eq!(tree.kind(nodes[2]), Some(SyntaxKind::Operation));
}

#[test]
fn rejects_invalid_markers() {
    let mut b = EventBuilder::new();
    let marker = b.start();
    b.token(0).unwrap();
    assert_eq!(b.abandon(marker), Err(CompactError::InvalidMarker));
    let done = b.complete(marker, SyntaxKind::File).unwrap();
    let _ = b.precede(done).unwrap();
    assert_eq!(b.precede(done), Err(CompactError::InvalidMarker));
}

#[test]
fn mixed_traversal_is_lossless_without_token_nodes() {
    let source = Source::new(&b"a { b } c"[..]).unwrap();
    let tree = zirium::parser::parse_brace_fixture(&lex(&source)).unwrap();
    fn append(tree: &zirium::SyntaxTree, source: &Source, node: zirium::NodeId, out: &mut Vec<u8>) {
        for element in tree.elements(node).unwrap() {
            match element {
                SyntaxElement::Node(child) => append(tree, source, child, out),
                SyntaxElement::Token { token, .. } if token.kind() != TokenKind::Eof => {
                    out.extend_from_slice(source.slice(token.range()).unwrap())
                }
                _ => {}
            }
        }
    }
    let mut bytes = vec![];
    append(&tree, &source, tree.root(), &mut bytes);
    assert_eq!(bytes, source.bytes());
    assert!(tree.node_count() < tree.token_count());
    assert_eq!(
        tree.subtree(tree.root()).unwrap().count(),
        tree.node_count()
    );
}

#[test]
fn parent_lookup_is_lazy() {
    let source = Source::new(&b"{{}}"[..]).unwrap();
    let tree = zirium::parser::parse_brace_fixture(&lex(&source)).unwrap();
    let nodes: Vec<_> = tree.subtree(tree.root()).unwrap().collect();
    let _ = tree.elements(tree.root()).unwrap();
    assert!(!tree.parent_index_is_built());
    assert_eq!(tree.parent(nodes[2]), Some(nodes[1]));
    assert!(tree.parent_index_is_built());
}