1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
//! This file defines the behaviour of the Atomic languages, and
//! provides a default implementation.
//!
//! Here I do not to substitute external packages' implementations in
//! the future, so why define a trait for the atomic languages?
//! Because this way I can easily substitute other implementations if
//! I have better ideas in the future.
use grammar::{Error as GrammarError, Grammar, TNT};
use nfa::{DOption, LabelType, Nfa};
use std::ops::Deref;
/// The expected behaviours of an atomic language.
pub trait Atom: Nfa<LabelType<TNT>> + Deref<Target = Grammar> {
/// Return the index of a node representing the derivative of the
/// left-linear null closure of `nt` with respect to `t`.
fn atom(&self, nt: usize, t: usize) -> Result<Option<usize>, GrammarError>;
/// A type that iterates through the rule positions.
type Iter<'a>: Iterator<Item = usize> + 'a
where
Self: 'a;
/// Return an iterator of rule positions responsible for an edge
/// from the virtual node corresponding to the non-terminal `nt`
/// and terminal `t` to `target`.
fn trace(&self, nt: usize, t: usize, target: usize) -> Option<<Self as Atom>::Iter<'_>>;
/// Return the index of the empty state.
fn empty(&self) -> usize;
/// Tell whether a node is accepting.
fn is_accepting(&self, node_id: usize) -> Result<bool, GrammarError>;
/// Return the bound for `is_accepting`.
fn accepting_len(&self) -> usize;
}
pub mod default;
pub use default::DefaultAtom;
#[cfg(test)]
mod tests {
use super::*;
use grammar::test_grammar_helper::*;
#[cfg(feature = "test-print-viz")]
use graph::Graph;
#[test]
fn atom() -> Result<(), Box<dyn std::error::Error>> {
let grammar = new_notes_grammar()?;
let atom = DefaultAtom::from_grammar(grammar)?;
println!("atom = {atom}");
#[cfg(feature = "test-print-viz")]
{
println!("virtual frag for 1, 3: ");
for (index, frag) in atom
.generate_virtual_frags(1, 3, None)
.iter()
.flatten()
.enumerate()
{
crate::item::default::print_labels(&atom, *frag)?;
frag.print_viz(&format!("frag {index}.gv"))?;
}
}
Ok(())
}
}
|