summaryrefslogtreecommitdiff
path: root/src/lib/process.ml
blob: 10b2945b2c40241a6c4092836d3540ea6d22d207 (plain)
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
open StdLabels
module M(T:Sounds.T) = struct

  type voyel = (T.t * T.t )

  type consonants =
    { ending : T.t option option
    ; opening : T.t list
    ; following : T.t option }

  type group = voyel * consonants option

  type modifier = (group * T.t option option)  -> (group * T.t option option)

  (** Apply all the modifiers to the syllabic group in order to correct the
      relation between the elements

      This is just a fold_left list, and the order matter : for example
      nasalisation shall be applied after the S vocalisation

  *)
  let apply_modifiers
    : group * T.t option option -> modifier list -> group * T.t option option
    = fun e m ->
      List.fold_left m
        ~init:e
        ~f:(fun e f -> f e)

  (** The Nasal modifier transform a voyel followed by N and a consonant
      into a nasal voyel.

      Does this min that nasal voyel are not a distinct element, but just a
      merge from two distinct elements ? *)
  let nasal
    : modifier
    = fun init ->
      let (((v1, v2), c) , ending) = init in
      let ending = Option.bind ending (fun x -> x) in
      match ending with
      | None -> init
      | Some ending ->
        match T.is_nasal ending with
        | false -> init
        | true ->
          (* Remove the ending consonant, and transform the voyel into
             the nasal form  *)
          ( ( (T.nasal v1, T.nasal v2)
            , c )
          , None )

  let vocalize_s
    : modifier
    = fun init ->
      let (((v1, v2), c) , ending) = init in

      match c with
      | None -> init
      | Some op -> match op.opening, op.ending with
        | hd::[], None when T.code hd = T.SZ ->
          let c = Some { op with opening = [T.z ()] } in
          (((v1, v2), c) , ending)
        | _ -> init

  let rec _rebuild ~(m:modifier list) acc ending_consonant : group list -> T.t list
    = function
      | [] -> acc
      | hd::tl ->

        let modifier_ = vocalize_s :: nasal :: m in
        let (voyel, consonants), ending_consonant =
          apply_modifiers
            (hd, ending_consonant)
            modifier_  in

        (* Add the last consonant and the voyel *)
        let m, acc = match ending_consonant with
          | None -> modifier_, (snd voyel)::acc
          | Some s ->
            let default = modifier_, (fst voyel) :: acc in
            match s with
            | None -> default
            | Some s ->

              modifier_, (fst voyel) :: s::acc  in

        match consonants with
        | None -> _rebuild ~m acc None tl
        | Some {ending; opening; following} ->

          let acc = match following with
            | None -> acc
            | Some s -> s::acc in

          match opening with
          | [] ->_rebuild ~m acc ending tl
          | opening -> _rebuild ~m (opening @ acc) ending tl

  (** Rebuild the list in the normal order

      The voyels have to be choosen, depending either they are followed by a
      consonant or not

      Some consonants may be changed depending of the following voyel

      The list has to be reversed

      and so one

  *)
  let rebuild
    : T.t option option -> group list -> T.t list
    = fun  ending elems ->
      _rebuild ~m:[] [] ending elems

end