File: metascanner.ml

package info (click to toggle)
findlib 0.6.2-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 852 kB
  • ctags: 340
  • sloc: ml: 2,447; sh: 1,068; makefile: 221; xml: 163
file content (206 lines) | stat: -rw-r--r-- 6,927 bytes parent folder | download
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
(* $Id: metascanner.src,v 1.4 2001/10/12 15:02:57 gerd Exp $
 * ----------------------------------------------------------------------
 *
 *)

open Metatoken;;


let scan ch =
  let buf = Lexing.from_channel ch in
  let rec next line pos0 =
    let t = Meta.token buf in
    match t with
      Space -> next line pos0
    | Newline -> next (line + 1) (Lexing.lexeme_end buf)
    | Eof ->
        let pos = Lexing.lexeme_start buf - pos0 in
        Stream.lsing (fun _ -> line, pos, Eof)
    | _ ->
        let pos = Lexing.lexeme_start buf - pos0 in
        Stream.lcons (fun _ -> line, pos, t)
          (Stream.slazy (fun _ -> next line pos0))
  in
  next 1 0
;;


let parse ch =
  let rec mk_set l =
    match l with
      x :: l' -> if List.mem x l' then mk_set l' else x :: mk_set l'
    | [] -> []
  in
  let rec parse_all stream =
    let (strm__ : _ Stream.t) = stream in
    match Stream.peek strm__ with
      Some (line, col, Name n) ->
        Stream.junk strm__;
        let props =
          try parse_properties strm__ with
            Stream.Failure ->
              raise
                (Stream.Error
                   ("Error in 'name = value' clause  in line " ^
                      string_of_int line ^ " position " ^ string_of_int col))
        in
        let rest =
          try parse_all strm__ with
            Stream.Failure ->
              raise
                (Stream.Error
                   ("Error in 'name = value' clause  in line " ^
                      string_of_int line ^ " position " ^ string_of_int col))
        in
        let (args, value) = props in
        (n, (Sort.list ( <= ) (mk_set args), value)) :: rest
    | Some (_, _, Eof) -> Stream.junk strm__; []
    | Some (line, col, _) ->
        Stream.junk strm__;
        raise
          (Stream.Error
             ("Expected 'name = value' clause  in line " ^
                string_of_int line ^ " position " ^ string_of_int col))
    | _ -> raise Stream.Failure
  and parse_properties stream =
    let (strm__ : _ Stream.t) = stream in
    match Stream.peek strm__ with
      Some (line, col, LParen) ->
        Stream.junk strm__;
        begin match Stream.peek strm__ with
          Some (line1, col1, Name n) ->
            Stream.junk strm__;
            let args =
              try parse_arguments strm__ with
                Stream.Failure -> raise (Stream.Error "")
            in
            begin match Stream.peek strm__ with
              Some (line2, col2, Equal) ->
                Stream.junk strm__;
                begin match Stream.peek strm__ with
                  Some (line3, col3, String s) ->
                    Stream.junk strm__; n :: args, s
                | _ ->
                    raise
                      (Stream.Error
                         ("Expected string constant after '=' in line " ^
                            string_of_int line2 ^ " position " ^
                            string_of_int col2))
                end
            | _ ->
                raise
                  (Stream.Error
                     ("'=' expected after '(arguments)' clause in line " ^
                        string_of_int line ^ " position " ^
                        string_of_int col))
            end
        | _ ->
            raise
              (Stream.Error
                 ("After a '(' there must be an argument name in line " ^
                    string_of_int line ^ " position " ^ string_of_int col))
        end
    | Some (line, col, Equal) ->
        Stream.junk strm__;
        begin match Stream.peek strm__ with
          Some (_, _, String s) -> Stream.junk strm__; [], s
        | _ ->
            raise
              (Stream.Error
                 ("'=' must be followed by a string constant in line " ^
                    string_of_int line ^ " position " ^ string_of_int col))
        end
    | Some (line, col, _) ->
        Stream.junk strm__;
        raise
          (Stream.Error
             ("Expected a '=' or a '(arguments,...)=' clause in line " ^
                string_of_int line ^ " position " ^ string_of_int col))
    | _ -> raise Stream.Failure
  and parse_arguments stream =
    let (strm__ : _ Stream.t) = stream in
    match Stream.peek strm__ with
      Some (line, col, Comma) ->
        Stream.junk strm__;
        begin match Stream.peek strm__ with
          Some (line1, col1, Name n) ->
            Stream.junk strm__;
            let args =
              try parse_arguments strm__ with
                Stream.Failure -> raise (Stream.Error "")
            in
            n :: args
        | _ ->
            raise
              (Stream.Error
                 ("Expected argument name after ',' in line " ^
                    string_of_int line ^ " position " ^ string_of_int col))
        end
    | Some (_, _, RParen) -> Stream.junk strm__; []
    | Some (line, col, _) ->
        Stream.junk strm__;
        raise
          (Stream.Error
             ("Another argument or a ')' expected in line " ^
                string_of_int line ^ " position " ^ string_of_int col))
    | _ -> raise Stream.Failure
  in
  let rec check l =
    match l with
      [] -> ()
    | (n, (args, value)) :: l' ->
        List.iter
          (fun (n', (args', value')) ->
             if n = n' & args = args' then
               raise
                 (Stream.Error
                    ("Double definition of '" ^ n ^ "'" ^
                       (if args = [] then ""
                        else "(" ^ String.concat "," args ^ ")"))))
          l';
        check l'
  in
  let l = parse_all (scan ch) in check l; l
;;


let lookup name predicate_list parsed_file =
  let rec search best_n best_value l =
    match l with
      [] -> if best_n >= 0 then best_value else raise Not_found
    | (name', (predicates, value)) :: l' ->
        if name = name' &
           List.for_all (fun p -> List.mem p predicate_list) predicates &
           List.length predicates > best_n then
          search (List.length predicates) value l'
        else search best_n best_value l'
  in
  search (-1) "" parsed_file
;;


(* ======================================================================
 * History:
 *
 * $Log: metascanner.src,v $
 * Revision 1.4  2001/10/12 15:02:57  gerd
 * 	Reverted from '??' syntax to '?' syntax for stream parsers.
 *
 * Revision 1.3  2001/03/06 20:12:54  gerd
 * 	Dropping O'Caml 2 support
 *
 * Revision 1.1  2000/04/26 00:09:20  gerd
 * 	O'Caml 3 changes.
 *
 *
 * Orginal log from metascanner.ml:
 *
 * Revision 1.1  1999/06/20 19:26:26  gerd
 * 	Major change: Added support for META files. In META files, knowlege
 * about compilation options, and dependencies on other packages can be stored.
 * The "ocamlfind query" subcommand has been extended in order to have a
 * direct interface for that. "ocamlfind ocamlc/ocamlopt/ocamlmktop/ocamlcp"
 * subcommands have been added to simplify the invocation of the compiler.
 *
 *
 *)