usfm3 0.2.0

Error-tolerant USFM 3.x parser with USJ, USX, and USFM output
Documentation
# usfm3

`usfm3` is the core Rust crate for parsing USFM 3.x.

The public pipeline is:

`tokenize -> parse_cst -> parse_ast / lower_cst -> serialize`

## Installation

```toml
[dependencies]
usfm3 = "0.1"
```

## Lazy Parse Handle

```rust
let parsed = usfm3::parse(text, usfm3::ParseOptions::default());

let tokens = parsed.tokens();
let cst = parsed.cst();
let ast = parsed.ast();
let source_map = parsed.source_map();
let diagnostics = parsed.diagnostics();

let usj = parsed
    .to_usj(usfm3::usj::UsjOptions { include_spans: false })
    .unwrap();
let usx = parsed.to_usx().unwrap();
let usfm = parsed.to_usfm();
let vref = parsed.to_vref();
```

`parse()` is lazy and diagnostics-off by default, so token/CST/editor consumers do not pay for validation unless they opt in.

## Eager AST

```rust
let ast_document = usfm3::parse_ast(
    text,
    usfm3::ParseOptions {
        diagnostics: true,
    },
);

let ast = ast_document.ast;
let source_map = ast_document.source_map;
let diagnostics = ast_document.diagnostics;
```

## CST-First Lowering

```rust
let cst = usfm3::parse_cst(text);
let ast_document = usfm3::lower_cst(
    &cst,
    usfm3::ParseOptions {
        diagnostics: true,
    },
);
```

## Notes

- AST nodes are semantic-only and do not own spans.
- `source_map` mirrors the AST and holds source ranges plus CST anchors.
- Diagnostics are a single flat list when requested, otherwise `None`.
- USJ inline spans come from `source_map`, not from the AST.

## License

MIT