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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::ops::Range;

pub type Span = Range<usize>;
pub type Spanned<T> = (Span, T);

#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
  SoundChange {
    source: Spanned<Source>,
    target: Spanned<Target>,
    environment: Option<Environment>,
    description: Option<String>,
  },
  Import(Vec<Spanned<String>>),
  Language {
    id: String,
    parent: Option<String>,
    name: Option<String>,
  },
  Word {
    gloss: String,
    pronunciation: Vec<String>,
    definitions: Vec<Definition>,
  },
  Class {
    label: String,
    class: Class,
  },
  Trait {
    label: String,
    members: Vec<TraitMember>,
  },
  Milestone {
    time: Option<Spanned<Time>>,
    language: Option<Spanned<String>>,
  }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Source {
  Pattern(Pattern),
  Empty,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Target {
  Modification(Vec<Feature>),
  Pattern(Pattern),
  Empty,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Feature {
  Positive(String),
  Negative(String),
}

pub type Pattern = Vec<Segment>;

#[derive(Debug, Clone, PartialEq)]
pub enum Segment {
  Category(Category),
  Phonemes(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Category {
  pub base_class: Option<char>,
  pub features: Vec<Feature>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Environment {
  pub before: Option<EnvPattern>,
  pub after: Option<EnvPattern>,
}

pub type EnvPattern = Vec<EnvElement>;

#[derive(Debug, Clone, PartialEq)]
pub enum EnvElement {
  Segment(Segment),
  SyllableBoundary,
  WordBoundary,
}


#[derive(Debug, Clone, PartialEq)]
pub struct Definition {
  pub pos: Option<String>,
  pub definition: String,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Class {
  Full {
    encodes: Vec<String>,
    annotates: Vec<String>,
    phonemes: Vec<PhonemeDef>,
  },
  Category(Category),
  List(Vec<String>),
}

#[derive(Debug, Clone, PartialEq)]
pub struct PhonemeDef {
  pub label: String,
  pub traits: Vec<String>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct TraitMember {
  pub labels: Vec<String>,
  pub notation: Option<String>,
  pub default: bool,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Time {
  Instant(i64),
  Range(i64, i64),
}