Skip to main content

camxes_rs/
jbo_syntax.rs

1//! Abstract syntax from [JboSyntax.hs](../JboSyntax.hs) (parse tree). Selbri/tag cycles use `Box`.
2
3#![allow(non_camel_case_types)]
4
5pub type Cmavo = String;
6pub type Joik = String;
7pub type Gadri = String;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct Text {
11    pub text_frees: Vec<Free>,
12    pub vaguely_negated_text: bool,
13    pub text_paras: Vec<Paragraph>,
14}
15
16pub type Paragraph = Vec<FragmentOrStatement>;
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub enum FragmentOrStatement {
20    Fragment(Fragment),
21    Statement(Statement),
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub enum Fragment {
26    /// `la NAME` sumti fragment (Haskell shows `[Fragment: "name"]` + `la name.`).
27    FragLaName(String),
28    FragPrenex(Vec<Term>),
29    FragTerms(Vec<Term>),
30    FragCon(Connective),
31    FragQuantifier(Mex),
32    FragNA(Cmavo),
33    FragRels(Vec<RelClause>),
34    FragLinks(Vec<Term>),
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
38pub struct Statement {
39    pub frees: Vec<Free>,
40    pub prenex: Vec<Term>,
41    pub body: Statement1,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct LogJboConnective {
46    pub b1: bool,
47    pub c: char,
48    pub b2: bool,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
52pub enum Statement1 {
53    ConnectedStatement(Connective, Box<Statement1>, Box<Statement1>),
54    StatementSentence {
55        frees: Vec<Free>,
56        sentence: Sentence,
57    },
58    StatementParas {
59        tag: Option<Tag>,
60        paras: Vec<Paragraph>,
61    },
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
65pub struct Subsentence {
66    pub frees: Vec<Free>,
67    pub prenex: Vec<Term>,
68    pub sentence: Box<Sentence>,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct Sentence {
73    pub terms: Vec<Term>,
74    pub tail: Box<BridiTail>,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub enum Free {
79    Bracketed(Box<Text>),
80    Discursive(BridiTail),
81    TruthQ(Option<i32>),
82    Vocative(Vec<COI>, Option<Sumti>),
83    MAI(Mex),
84    XI(Mex),
85    MexPrecedence(BridiTail),
86    SOI(Sumti, Option<Sumti>),
87    Indicator {
88        indicator_nai: bool,
89        indicator_cmavo: Cmavo,
90    },
91    NullFree,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Hash)]
95pub struct COI {
96    pub coi_coi: String,
97    pub coi_nai: bool,
98}
99
100pub type FreeIndex = i32;
101
102#[derive(Debug, Clone, PartialEq, Eq, Hash)]
103pub enum Term {
104    Sumti(Tagged, Sumti),
105    Negation,
106    Termset(Vec<Term>),
107    ConnectedTerms(bool, Connective, Box<Term>, Box<Term>),
108    BareTag(Tag),
109    BareFA(Option<i32>),
110    NullTerm,
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, Hash)]
114pub enum Tagged {
115    Untagged,
116    Tagged(Tag),
117    FATagged(i32),
118    FAITagged,
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122pub enum AbsTag<R, T> {
123    DecoratedTagUnits(Vec<DecoratedAbsTagUnit<R, T>>),
124    ConnectedTag(
125        AbsConnective<R, T>,
126        Box<AbsTag<R, T>>,
127        Box<AbsTag<R, T>>,
128    ),
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
132pub struct DecoratedAbsTagUnit<R, T> {
133    pub tag_nahe: Option<Cmavo>,
134    pub tag_se: Option<i32>,
135    pub tag_nai: bool,
136    pub tag_unit: AbsTagUnit<R, T>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, Hash)]
140pub enum AbsTagUnit<R, T> {
141    TenseCmavo(Cmavo),
142    CAhA(Cmavo),
143    FAhA {
144        faha_has_mohi: bool,
145        faha_cmavo: Cmavo,
146    },
147    ROI {
148        roiroi: Cmavo,
149        roi_is_space: bool,
150        roi_quantifier: AbsMex<R, T>,
151    },
152    TAhE_ZAhO {
153        tahe_zohe_is_space: bool,
154        tahe_zaho_cmavo: Cmavo,
155    },
156    BAI(Cmavo),
157    FIhO(Box<R>),
158    CUhE(Cmavo),
159    KI,
160}
161
162#[derive(Debug, Clone, PartialEq, Eq, Hash)]
163pub enum AbsConnective<R, T> {
164    JboConnLog(Option<Box<AbsTag<R, T>>>, LogJboConnective),
165    JboConnJoik(Option<Box<AbsTag<R, T>>>, Joik),
166}
167
168pub type Connective = AbsConnective<Selbri, Sumti>;
169pub type Tag = AbsTag<Selbri, Sumti>;
170pub type DecoratedTagUnit = DecoratedAbsTagUnit<Selbri, Sumti>;
171pub type TagUnit = AbsTagUnit<Selbri, Sumti>;
172
173#[derive(Debug, Clone, PartialEq, Eq, Hash)]
174pub enum Sumti {
175    ConnectedSumti(
176        bool,
177        Connective,
178        Box<Sumti>,
179        Box<Sumti>,
180        Vec<RelClause>,
181    ),
182    QAtom {
183        frees: Vec<Free>,
184        quant: Option<Mex>,
185        rels: Vec<RelClause>,
186        atom: Box<SumtiAtom>,
187    },
188    QSelbri {
189        quant: Mex,
190        rels: Vec<RelClause>,
191        selbri: Selbri,
192    },
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Hash)]
196pub enum RelClause {
197    Restrictive(Subsentence),
198    Incidental(Subsentence),
199    Descriptive(Subsentence),
200    Assignment(Term),
201    RestrictiveGOI(String, Term),
202    IncidentalGOI(String, Term),
203}
204
205#[derive(Debug, Clone, PartialEq, Eq, Hash)]
206pub enum SumtiAtom {
207    Name(Gadri, Vec<RelClause>, String),
208    Variable(i32),
209    NonAnaphoricProsumti(String),
210    RelVar(i32),
211    LambdaVar(Option<i32>, Option<i32>),
212    SelbriVar,
213    Description(
214        Gadri,
215        Option<Box<Sumti>>,
216        Option<Mex>,
217        EitherSelbriSumti,
218        Vec<RelClause>,
219        Vec<RelClause>,
220    ),
221    Assignable(i32),
222    LerfuString(Vec<Lerfu>),
223    Ri(i32),
224    Ra(Cmavo),
225    MainBridiSumbasti(i32),
226    Quote(Box<Text>),
227    NonJboQuote(String),
228    ErrorQuote(Vec<String>),
229    Word(String),
230    MexLi(Mex),
231    MexMex(Mex),
232    Zohe,
233    SumtiQ(Option<i32>),
234    QualifiedSumti(SumtiQualifier, Vec<RelClause>, Box<Sumti>),
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash)]
238pub enum EitherSelbriSumti {
239    Selbri(Box<Selbri>),
240    Sumti(Box<Sumti>),
241}
242
243#[derive(Debug, Clone, PartialEq, Eq, Hash)]
244pub enum Lerfu {
245    LerfuChar(char),
246    LerfuPA(Cmavo),
247    LerfuValsi(String),
248    LerfuShift(Cmavo),
249    LerfuShifted(Cmavo, Box<Lerfu>),
250    LerfuComposite(Vec<Lerfu>),
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Hash)]
254pub enum SumtiQualifier {
255    LAhE(String),
256    NAhE_BO(String),
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, Hash)]
260pub enum BridiTail {
261    ConnectedBT(Connective, Box<BridiTail>, Box<BridiTail>, Vec<Term>),
262    BridiTail3(Selbri, Vec<Term>),
263    GekSentence(Box<GekSentence>),
264}
265
266#[derive(Debug, Clone, PartialEq, Eq, Hash)]
267pub enum GekSentence {
268    ConnectedGS(Connective, Box<Subsentence>, Box<Subsentence>, Vec<Term>),
269    TaggedGS(Tag, Box<GekSentence>),
270    NegatedGS(Box<GekSentence>),
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Hash)]
274pub enum Selbri {
275    Negated(Box<Selbri>),
276    TaggedSelbri(Box<Tag>, Box<Selbri>),
277    Selbri2(Selbri2),
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Hash)]
281pub enum Selbri2 {
282    SBInverted(Selbri3, Box<Selbri2>),
283    Selbri3(Selbri3),
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Hash)]
287pub enum Selbri3 {
288    SBTanru(Box<Selbri3>, Box<Selbri3>),
289    ConnectedSB(bool, Connective, Box<Selbri>, Box<Selbri3>),
290    BridiBinding(Box<Selbri3>, Box<Selbri3>),
291    ScalarNegatedSB(NAhE, Box<Selbri3>),
292    /// Head — tanru unit with prefix frees / terms (camxes `TanruUnit` with subunits).
293    TanruHead(Vec<Free>, Box<TanruUnit>, Vec<Term>),
294}
295
296pub type NAhE = Cmavo;
297
298#[derive(Debug, Clone, PartialEq, Eq, Hash)]
299pub enum TanruUnit {
300    TUBrivla(String),
301    TUZei(Vec<String>),
302    TUBridiQ(Option<i32>),
303    TUGOhA(String, i32),
304    TUMe(Box<Sumti>),
305    TUMoi(Box<Sumti>, String),
306    TUAbstraction(Abstractor, Subsentence),
307    TUPermuted(i32, Box<TanruUnit>),
308    TUJai(Option<Tag>, Box<TanruUnit>),
309    TUOperator(Operator),
310    TUXOhI(Tag),
311    TUSelbri3(Selbri3),
312}
313
314#[derive(Debug, Clone, PartialEq, Eq, Hash)]
315pub enum Abstractor {
316    NU(Cmavo),
317    NegatedAbstractor(Box<Abstractor>),
318    LogConnectedAbstractor(LogJboConnective, Box<Abstractor>, Box<Abstractor>),
319    JoiConnectedAbstractor(Joik, Box<Abstractor>, Box<Abstractor>),
320}
321
322#[derive(Debug, Clone, PartialEq, Eq, Hash)]
323pub enum AbsMex<R, T> {
324    Operation(Box<AbsOperator<R, T>>, Vec<AbsMex<R, T>>),
325    ConnectedMex(bool, AbsConnective<R, T>, Box<AbsMex<R, T>>, Box<AbsMex<R, T>>),
326    QualifiedMex(SumtiQualifier, Box<AbsMex<R, T>>),
327    MexInt(i32),
328    MexNumeralString(Vec<Numeral>),
329    MexLerfuString(Vec<Lerfu>),
330    MexSelbri(Box<R>),
331    MexSumti(Box<T>),
332    MexArray(Vec<AbsMex<R, T>>),
333}
334
335pub type Mex = AbsMex<Selbri, Sumti>;
336
337#[derive(Debug, Clone, PartialEq, Eq, Hash)]
338pub enum Numeral {
339    PA(Cmavo),
340    NumeralLerfu(Lerfu),
341}
342
343#[derive(Debug, Clone, PartialEq, Eq, Hash)]
344pub enum AbsOperator<R, T> {
345    ConnectedOperator(
346        bool,
347        AbsConnective<R, T>,
348        Box<AbsOperator<R, T>>,
349        Box<AbsOperator<R, T>>,
350    ),
351    OpPermuted(i32, Box<AbsOperator<R, T>>),
352    OpScalarNegated(NAhE, Box<AbsOperator<R, T>>),
353    OpMex(Box<AbsMex<R, T>>),
354    OpSelbri(Box<R>),
355    OpVUhU(Cmavo),
356}
357
358pub type Operator = AbsOperator<Selbri, Sumti>;
359
360// ============================================================================
361// Helper functions from JboSyntax.hs
362// ============================================================================
363
364// Ported from: JboSyntax.hs :: sb3tosb
365/// Convert Selbri3 to Selbri by wrapping in Selbri2
366pub fn sb3_to_sb(sb3: Selbri3) -> Selbri {
367    Selbri::Selbri2(Selbri2::Selbri3(sb3))
368}
369
370// Ported from: JboSyntax.hs :: getsRi
371/// Check if a SumtiAtom gets ri (anaphoric reference)
372pub fn gets_ri(sa: &SumtiAtom) -> bool {
373    match sa {
374        SumtiAtom::Zohe => false,
375        SumtiAtom::Assignable(_) => false,
376        SumtiAtom::LerfuString(_) => false,
377        SumtiAtom::MainBridiSumbasti(_) => false,
378        SumtiAtom::Variable(_) => false,
379        SumtiAtom::NonAnaphoricProsumti(p) => {
380            matches!(p.as_str(), "ti" | "ta" | "tu")
381        }
382        _ => true,
383    }
384}
385
386// Ported from: JboSyntax.hs :: lerfuStringsOfSelbri
387/// Extract lerfu strings from a selbri for anaphora
388pub fn lerfu_strings_of_selbri(selbri: &Selbri) -> Vec<Vec<Lerfu>> {
389    match selbri {
390        Selbri::Negated(sb) => lerfu_strings_of_selbri(sb),
391        Selbri::TaggedSelbri(_, sb) => lerfu_strings_of_selbri(sb),
392        Selbri::Selbri2(sb2) => {
393            let mut result = Vec::new();
394            for s in sb2_to_ls(sb2) {
395                result.push(s.clone());
396                result.push(s.iter().take(1).cloned().collect());
397            }
398            result
399        }
400    }
401}
402
403fn sb2_to_ls(sb2: &Selbri2) -> Vec<Vec<Lerfu>> {
404    match sb2 {
405        Selbri2::SBInverted(sb3, sb2_inner) => {
406            let mut result = sb3_to_ls(sb3);
407            result.extend(sb2_to_ls(sb2_inner));
408            result
409        }
410        Selbri2::Selbri3(sb3) => sb3_to_ls(sb3),
411    }
412}
413
414fn sb3_to_ls(sb3: &Selbri3) -> Vec<Vec<Lerfu>> {
415    match sb3 {
416        Selbri3::SBTanru(sb1, sb2) => {
417            let mut result = sb3_to_ls(sb1);
418            result.extend(sb3_to_ls(sb2));
419            result
420        }
421        Selbri3::ConnectedSB(_, _, sb, sb3) => {
422            let mut result = lerfu_strings_of_selbri(sb);
423            result.extend(sb3_to_ls(sb3));
424            result
425        }
426        Selbri3::BridiBinding(sb3, _) => sb3_to_ls(sb3),
427        Selbri3::ScalarNegatedSB(_, sb3) => sb3_to_ls(sb3),
428        Selbri3::TanruHead(_, tu, _) => tu_to_ls(tu),
429    }
430}
431
432fn tu_to_ls(tu: &TanruUnit) -> Vec<Vec<Lerfu>> {
433    match tu {
434        TanruUnit::TUBrivla(s) => {
435            if let Some(first_char) = s.chars().next() {
436                vec![vec![Lerfu::LerfuChar(first_char)]]
437            } else {
438                vec![]
439            }
440        }
441        TanruUnit::TUZei(vs) => {
442            let full: Vec<Lerfu> = vs.iter()
443                .filter_map(|v| v.chars().next())
444                .map(Lerfu::LerfuChar)
445                .collect();
446            let first = vs.first()
447                .and_then(|v| v.chars().next())
448                .map(|c| vec![Lerfu::LerfuChar(c)])
449                .unwrap_or_default();
450            vec![full, first]
451        }
452        TanruUnit::TUAbstraction(abs, _) => {
453            if let Abstractor::NU(s) = abs {
454                if let Some(first_char) = s.chars().next() {
455                    vec![
456                        vec![Lerfu::LerfuChar(first_char)],
457                        vec![Lerfu::LerfuValsi(s.clone())],
458                    ]
459                } else {
460                    vec![]
461                }
462            } else {
463                vec![]
464            }
465        }
466        TanruUnit::TUSelbri3(sb3) => sb3_to_ls(sb3),
467        _ => vec![],
468    }
469}
470
471// Ported from: JboSyntax.hs :: tagNaiIsScalar
472/// Check if a tag unit's NAI is scalar (ROI, TAhE_ZAhO, CAhA)
473pub fn tag_nai_is_scalar<R, T>(tu: &AbsTagUnit<R, T>) -> bool {
474    matches!(
475        tu,
476        AbsTagUnit::ROI { .. } | AbsTagUnit::TAhE_ZAhO { .. } | AbsTagUnit::CAhA(_)
477    )
478}
479
480// Ported from: JboSyntax.hs :: isTense
481/// Check if a tag is a tense tag (not BAI or FIhO)
482pub fn is_tense<R, T>(tag: &AbsTag<R, T>) -> bool {
483    match tag {
484        AbsTag::ConnectedTag(_, t1, t2) => is_tense(t1) || is_tense(t2),
485        AbsTag::DecoratedTagUnits(dtus) => {
486            dtus.iter().any(|dtu| is_tense_dtu(&dtu.tag_unit))
487        }
488    }
489}
490
491fn is_tense_dtu<R, T>(tu: &AbsTagUnit<R, T>) -> bool {
492    !matches!(tu, AbsTagUnit::BAI(_) | AbsTagUnit::FIhO(_))
493}