| Crates.io | chasa-recover |
| lib.rs | chasa-recover |
| version | 0.1.0 |
| created_at | 2025-12-15 06:14:48.785111+00 |
| updated_at | 2025-12-15 06:14:48.785111+00 |
| description | Experimental recoverable parser combinators (procedural parsers). |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1985633 |
| size | 181,322 |
回復可能(recoverable)パーサを組み立てるための、実験的なパーサコンビネータ群です。
この crate のコアは「手続きがそのままパーサになる」ところにあります。
つまり、|i: In<...>| { ... } という関数(クロージャ)自体が ParserOnce/ParserMut/Parser として動作し、In のメソッドを呼びながら手続き的にパースできます。
Err は例外ではなく 出力の一部(呼び出し側が受け取って回復を組む)。maybe: Result<T, E> -> Option<T>(Err を消すので入力も戻す)attempt: Result<T, E> -> bool(成功/失敗だけを見るので入力も戻す)save/load)は combinator が必要な範囲だけ使う:
many 系:終端判定の最後の失敗だけ戻すchoice/or 系:別枝を試すための局所探索Input: 1要素ずつ読む入力。pos() を持つ(比較可能な位置)。In<'a, I, E, L>: 実際にパースに渡す「入力+環境」。
env / local を持つ(巻き戻しポリシーは合意に従う。現状 In の Back は入力のみ巻き戻し)。プリミティブ(例: parser::item::any)や In のメソッドからパースを記述できます。
use chasa_recover::input::In;
use chasa_recover::parser::ParserOnce;
use chasa_recover::parser::item::any;
use std::ops::ControlFlow;
let mut s = "abc!def";
let out: String = any
.flow(String::new(), |mut st, r| match r {
Ok('!') | Err(_) => ControlFlow::Break(st),
Ok(c) => { st.push(c); ControlFlow::Continue(st) }
})
.run_once(In::new(&mut s));
assert_eq!(out, "abc");
assert_eq!(s, "def");
また、In 自体にもプリミティブを生やしているので、
より手続き的に(「関数=パーサ」を前提に)書けます。
use chasa_recover::input::In;
let mut s = "ab]c";
let mut i = In::new(&mut s);
let v = i.take_until(|c: &char| *c == ']'); // stop文字は差し戻し
assert_eq!(v, vec!['a','b']);
assert_eq!(s, "]c");
one_of("abc") / none_of("abc")(ItemSet)any / eoitag("abc"):先頭一致。失敗時は「失敗した文字を含む、消費した全て」を TagError::consumed に入れて返す(入力は戻さない)。take_while(pred):最初に pred == false の文字は差し戻して終了(エラーなし)。take_while1(pred):1文字目が不一致なら Err(1文字目は消費)、それ以外の不一致は差し戻して Ok 終了。take_until(stop):stop文字は差し戻して終了。take_until1(stop):1文字目が stop なら Err(1文字目は消費)、それ以外は take_until と同様。many: Result<T, E> を繰り返し、Err が出た回は 入力を戻して終了(終端判定)。many1: 最初が Err なら 入力を戻さず Err を返す。最初が Ok なら、その後は many と同様。many_map / many1_map: iterator を渡して集計をカスタマイズできる。map / map_err / and_thenor_else: Err(E) を受け取り、追加でパースして Result<O, E2> を返す(回復して Ok(O) にもできる)。recover: Err(E) を受け取り、値パーサに切り替えて O を返す。ignore: Result<T, E> -> ()(成功/失敗に関わらず出力を捨て、入力も戻す)map / map_ok のように、「通常出力」と「Result 出力」は分けています。
left: P: O と Q: () を合成して O を返す。Q は常に実行される。left_ok: P: Result<O, E> と Q: () を合成して Result<O, E> を返す。Q は Ok のときだけ実行される。right: P: () と Q: O を合成して O を返す。P の後に Q を実行する。right_ok: P: () と Q: Result<O, E> を合成して Result<O, E> を返す。この crate の設計意図・合意済みの細かい挙動は crates/chasa-recover/AGENTS.md にもまとめています。