-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.ml
129 lines (96 loc) · 4.08 KB
/
parser.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
120
121
122
123
124
125
126
127
128
129
open Angstrom
let legal_modes = ["kappa";"kappaSym";"degree";"simple"]
let legal_output = ["positive" ; "negative"]
type base_type = Complete | Sparse | Tree
type share_type = MinShare of int | Adjust of int
type command =
| Help
| Mode of string
| Add of string
| Add_named of (int list * int list) list * string
| List
| Debug
| Safe
| Build of string*string
| Load of string
| Output of bool
| Shell of string * string array
| Exit
| Reset
| Blank
| BaseShape of base_type
| Sharing of share_type
| MaxStep of int
let ws = skip_while (function ' ' -> true | _ -> false)
let ws1 = take_while1 (function ' ' -> true | _ -> false)
let inst name alt ret =
string name *> ws *>
(if alt = [] then take_while (function _ -> true) else choice (List.map string alt)) >>| fun mode_result ->
ret mode_result
let mode mlist = inst "mode" mlist (fun x -> Mode x)
let load = inst "load" [] (fun x -> Load x)
let output olist = inst "output" olist (fun x -> Output (if x="positive" then true else false))
let exit_p = inst "exit" [] (fun _ -> Exit)
let list_parser p = char '[' *> ws *> sep_by (ws *> (char ';') *> ws) p <* ws <* char ']'
let pos_number = take_while1 (function '0'..'9' -> true | _ -> false) >>| fun s -> int_of_string s
let neg_number = char '-' *> take_while1 (function '0'..'9' -> true | _ -> false) >>| fun s -> -(int_of_string s)
let number = choice [pos_number ; neg_number]
let number_or_nothing = choice [(number >>| fun i -> Some i) ; ws >>| fun () -> None]
let arg = take_while1 (function ' ' -> false | _ -> true)
let args_parser = sep_by ws1 arg
let shell = char '!' *> args_parser >>| function
| arg::tl as l ->
let args = Array.make (List.length l) ""
in
let _ =
List.fold_left
(fun i argument -> args.(i) <- argument ; i+1
) 0 l
in
Shell (arg,args)
| [] -> Shell ("",Array.make 0 "")
let tuple elt_parser ret =
char '(' *> ws *> elt_parser >>= fun elt1 ->
ws *> char ',' *> ws *> elt_parser >>= fun elt2 ->
ws *> char ')' *> return (ret (elt1,elt2))
let name = take_while (function 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '^' | '-' | '\'' -> true | _ -> false)
let int_list_tuple = tuple (list_parser number) (fun x -> x)
let nodes = list_parser int_list_tuple
let add = string "add" *> ws *> name >>| fun name_result -> Add name_result
let sharing = string "sharing" *> ws *> pos_number >>| fun i -> Sharing (MinShare i)
let self = string "adjust" *> ws *> pos_number >>| fun i -> Sharing (Adjust i)
let sparse = string "sparse" *> ws >>| fun () -> BaseShape Sparse
let tree = string "treelike" *> ws >>| fun () -> BaseShape Tree
let complete = string "complete" *> ws >>| fun () -> BaseShape Complete
let step = string "step" *> ws *> number >>| fun i -> MaxStep i
let help = string "help" *> ws >>| fun () -> Help
let set = string "set" *> ws *> choice [sharing ; sparse ; tree ; self ; complete ; step ; help ]
let blank = ws *> return Blank
let add_named =
string "add" *> ws *> nodes >>= fun nodes_result ->
ws *> string "as" *> ws *> name >>| fun name_result ->
Add_named (nodes_result,name_result)
let list = string "list" *> return List
let debug = string "debug" *> return Debug
let safe = string "safe" *> return Safe
let build =
string "build" *> ws1 *> tuple name (fun (x,y)-> Build (x,y))
let global p = ws *> p <* end_of_input
let reset = string "reset" *> ws *> return Reset
let line = choice
(List.map global [mode legal_modes;
set ;
add;
debug ;
safe ;
add_named;
list;
build ;
load ;
output legal_output ;
exit_p ;
shell ;
reset ;
blank ;
])
let parse = parse_string line