File: parser_hints.ml

package info (click to toggle)
otags 4.01.1-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 592 kB
  • ctags: 533
  • sloc: ml: 2,695; sh: 496; makefile: 239
file content (119 lines) | stat: -rw-r--r-- 2,996 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
(* Otags reloaded
 * 
 * Hendrik Tews Copyright (C) 2010 - 2012
 * 
 * This file is part of "Otags reloaded".
 * 
 * "Otags reloaded" is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * "Otags reloaded" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License in file COPYING in this or one of the parent
 * directories for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with "Otags reloaded". If not, see
 * <http://www.gnu.org/licenses/>.
 * 
 * $Id: parser_hints.ml,v 1.1 2012/05/21 09:29:29 tews Exp $
 * 
 * parser hints functionality
 * 
 *)

module U = Unix

open Misc
open Camlp4_names


let hints = Hashtbl.create 2039

let try_split_last_colon line =
  let i = ref ((String.length line) - 1) in
  while !i >= 0 && (line.[!i] = ' ' || line.[!i] = '\t') do
    decr i
  done;
  if !i >= 0 && line.[!i] = ':'
  then Some(String.sub line 0 !i)
  else None

let normalize_parser_list parsers =
  List.fold_left
    (fun (internal, res) new_parser ->
      try
	(internal, res @ (normalize_parser res new_parser))
      with
	| Not_found -> (false, res @ [new_parser])
    )
    (true, [])
    parsers



let process_hints_file ic file =
  let parser_info = ref (true, []) in
  try
    while true do
      let line = input_line ic in
      if String.length line > 0 && line.[0] <> '#' 
      then
	match try_split_last_colon line with
	  | Some line_without_colon ->
	    parser_info := 
	      normalize_parser_list (string_split ' ' line_without_colon)
	  | None ->
	    if snd !parser_info = [] 
	    then begin
	      Printf.eprintf 
		("Parser hints error in %s:\n" ^^
		    "First non-empty line must specify a parser list\n")
		file;
	      exit 2;
	    end
	    else
	      Hashtbl.add hints (strip_white_space line) !parser_info
    done
  with
    | End_of_file -> ()	    
		

let rec process_parser_hint file =
  if is_directory file true
  then process_parser_hint_dir file
  else 
    try
      let ic = open_in file in
      process_hints_file ic file;
      close_in ic
    with
      | Sys_error sys_msg ->
	Printf.eprintf "Cannot read %s\n%!" sys_msg;
	exit 2

and process_parser_hint_dir dir =
  let handle = U.opendir dir in
  let not_finished = ref true in
  while !not_finished do
    match
      try Some(U.readdir handle) with End_of_file -> None
    with
      | Some entry ->
	if entry = Filename.current_dir_name ||
	  entry = Filename.parent_dir_name
	then ()
	else process_parser_hint (Filename.concat dir entry)
      | None ->
	not_finished := false
  done
	

let process_parser_hints =
  List.iter process_parser_hint


let parser_hint file = Hashtbl.find hints file