package fmlib

  1. Overview
  2. Docs

Source file indent.ml

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
type violation =
    | Indent of int
    | Align of int
    | Align_between of int * int


type t = {
    lb: int;          (* lower bound of the indentation set *)
    ub: int option;   (* upper bound of the indentation set *)
    abs: bool;        (* absolute alignment *)
}



let initial: t = {
    lb = 0;
    ub = None;
    abs = false
}




let check_position (pos: int) (ind: t): violation option =
    let check_indent () =
        if ind.lb <= pos then
            None
        else
            Some (Indent ind.lb)
    in
    match ind.ub with
    | None ->
        check_indent ()
    | Some ub ->
        if not ind.abs then
            check_indent ()
        else if ind.lb <= pos && pos <= ub then
            None
        else if ind.lb = ub then
            Some (Align ind.lb)
        else
            Some (Align_between (ind.lb, ub))





let token (pos: int) (ind: t): t =
    assert (check_position pos ind = None);
    if not ind.abs then
        (* Normal case. Token are all wrapped with '>=' i.e. they can appear to
           the right of the indentation set of the parent. However, if the token
           appears within the indentation set of the parent, then it restricts
           the upper bound of the indentation set of the parent. A parent can
           by definition never be indented more than all its token. *)
        match ind.ub with
        | Some ub when ub <= pos ->
            ind
        | _ ->
            {ind with ub = Some pos}
    else
        (* First token of an aligned parent. Indentation set consists of exactly
           the token position. *)
        {
            lb = pos;
            ub = Some pos;
            abs = false
        }




let align (ind:t): t =
    {
        ind with
        abs = true
    }


let left_align (ind: t): t =
    {
        ind with
        ub = Some ind.lb;
        abs = true;
    }


let start_indent (i: int) (ind: t): t =
    if not ind.abs then
        {
            lb  = ind.lb + i;
            ub  = None;
            abs = false
        }
    else
        ind


let end_indent (i: int) (ind0: t) (ind: t): t =
    if not ind0.abs then
        (* The old lower bound remains. The upper bound must be updated, if the
           new indentation has an upper bound. The upper bound is set to the
           minimum of both. *)
        match ind.ub with
        | None ->
            ind0
        | Some ub ->
            assert (ind0.lb + i <= ub);
            {
                ind0 with
                ub =
                    match ind0.ub with
                    | None ->
                        Some (ub - i)
                    | Some ub0 ->
                        Some (min ub0 (ub - i))
            }
    else
        ind
OCaml

Innovation. Community. Security.