jsslint_core/tex/mod.rs
1//! Tolerant LaTeX parsing substrate — spec 018 Phase 1. Ports
2//! `pylatexenc.latexwalker`'s node model (`node.rs`, `parser.rs`),
3//! `core/parser.py`'s pre-tokenization neutralization
4//! (`neutralize.rs`), `pos_to_lineno_colno` (`position.rs`), and
5//! `_helpers.py`'s prose-context classifier (`prose.rs`).
6//!
7//! No rules live here yet (Phase 3) — this module's job is only to
8//! prove the substrate matches, validated by `tests/parser_parity.rs`
9//! against a Python oracle dump (`tools/dump_tex_nodes.py`).
10
11pub mod debug;
12pub mod extract;
13pub mod neutralize;
14pub mod node;
15pub mod parser;
16pub mod position;
17pub mod prose;
18mod specs;
19
20pub use node::*;
21pub use position::LineIndex;
22
23/// Full `.tex` parse pipeline, mirroring
24/// `core/parser.py::parse_tex_source`'s preprocessing + tokenize order
25/// (tolerant-parsing path only — see `parser::parse`'s doc comment).
26pub struct ParsedTex {
27 pub source: String,
28 pub chars: Vec<char>,
29 pub nodes: Vec<Node>,
30 /// Zero for a normal `.tex`/`.rnw` file. Non-zero for a `.Rmd`
31 /// raw-LaTeX prose fragment (see `crate::rmd`): `chars`/`node.pos`
32 /// stay 0-based within the fragment's own (unpadded) text — same
33 /// as Python's `node.pos`, which `_OffsetWalker` never touches —
34 /// while every rule module's `LineIndex::with_offset(&parsed.chars,
35 /// parsed.line_offset)` call adds this back in so reported lines
36 /// stay source-accurate on the original `.Rmd`.
37 pub line_offset: u32,
38}
39
40pub fn parse_tex_source(source: &str) -> ParsedTex {
41 let preprocessed = neutralize::preprocess(source);
42 let (nodes, chars) = parser::parse(&preprocessed);
43 ParsedTex {
44 source: preprocessed,
45 chars,
46 nodes,
47 line_offset: 0,
48 }
49}