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
124
125
126
127
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<Spanned<Environment>>,
    description: Option<Spanned<String>>,
  },
  Import {
    path: Vec<Spanned<String>>,
    absolute: bool,
    names: Vec<Spanned<String>>,
  },
  Language {
    id: Spanned<String>,
    parent: Option<Spanned<String>>,
    name: Option<Spanned<String>>,
  },
  Word {
    gloss: Spanned<String>,
    pronunciation: Spanned<Vec<String>>,
    definitions: Vec<Definition>,
  },
  Class {
    label: Spanned<String>,
    class: Class,
  },
  Trait {
    label: Spanned<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<Spanned<String>>,
  pub definition: Spanned<String>,
}

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

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

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

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