Source file bcfg_query.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
module Fmt = struct
let string = Format.pp_print_string
let box ?(ident = 0) pp_value ppf value =
let open Format in
pp_open_box ppf ident;
pp_value ppf value;
pp_close_box ppf ()
let surround s0 s1 pp_value ppf value =
let open Format in
pp_print_string ppf s0;
pp_value ppf value;
pp_print_string ppf s1
let brackets pp_value = box ~ident:1 (surround "[" "]" pp_value)
let cut ppf _ = Format.pp_print_cut ppf ()
let iter ?(sep = cut) iter pp_value ppf value =
let is_first = ref true in
let pp_value value =
if !is_first then is_first := false else sep ppf ();
pp_value ppf value
in
iter pp_value value
let sp ppf _ = Format.pp_print_space ppf ()
let semi ppf _ =
Format.pp_print_string ppf ";";
sp ppf ()
let list ?sep pp_value = iter ?sep List.iter pp_value
let flist pp_value = brackets (list ~sep:semi (box pp_value))
let pf = Format.fprintf
let fmt fmt ppf = pf ppf fmt
end
type pattern =
| PWord of string
| PAny
| PEval of expr
| PNot of pattern
| PAnd of pattern * pattern
| POr of pattern * pattern
and expr =
| EGet_parameter of expr * string
| EGet_subdirective of expr * expr
| EDirective of expr * pattern
| EParameter of pattern * expr
| EChild of pattern * expr
| ENot_parameter of pattern * expr
| ENot_child of pattern * expr
| EWord of string
| EPattern of pattern
let is_safe_char = function
| 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '{' | '}' | '~' -> true
| _ -> false
let is_safe str =
let res = ref (String.length str > 0) in
String.iter (fun chr -> if not (is_safe_char chr) then res := false) str;
!res
let pp_word ppf str =
if is_safe str then Fmt.string ppf str
else begin
Fmt.string ppf "'";
String.iter
(fun chr ->
match chr with
| '\'' -> Fmt.string ppf "\\'"
| '\\' -> Fmt.string ppf "\\\\"
| ' ' .. '~' -> Format.pp_print_char ppf chr
| chr -> Fmt.pf ppf "\\x%02x" (Char.code chr))
str;
Fmt.string ppf "'"
end
let rec pp_pattern ppf = function
| PWord s -> pp_word ppf s
| PAny -> Fmt.string ppf "*"
| PEval e -> Fmt.pf ppf "@(%a)" pp_expr e
| PNot p -> Fmt.pf ppf "!%a" pp_pattern_atom p
| PAnd (a, b) -> Fmt.pf ppf "%a&%a" pp_pattern a pp_pattern_atom b
| POr (a, b) -> Fmt.pf ppf "%a|%a" pp_pattern a pp_pattern_atom b
and pp_pattern_atom ppf = function
| (PAnd _ | POr _) as p -> Fmt.pf ppf "(%a)" pp_pattern p
| p -> pp_pattern ppf p
and pp_expr ppf = function
| EGet_parameter (e, idx) -> Fmt.pf ppf "%a[%a]" pp_expr e pp_word idx
| EGet_subdirective (e0, e1) -> Fmt.pf ppf "%a.%a" pp_expr e0 pp_expr e1
| EDirective (e, p) -> Fmt.pf ppf "(%a)%a" pp_pattern p pp_expr e
| EParameter (p, e) -> Fmt.pf ppf "%a(%a)" pp_expr e pp_pattern p
| EChild (p, e) -> Fmt.pf ppf "%a(:%a)" pp_expr e pp_pattern p
| ENot_parameter (p, e) -> Fmt.pf ppf "%a(^%a)" pp_expr e pp_pattern p
| ENot_child (p, e) -> Fmt.pf ppf "%a(:^%a)" pp_expr e pp_pattern p
| EWord s -> pp_word ppf s
| EPattern p -> Fmt.pf ppf "(%a)" pp_pattern p