Redundant newline.
[virt-top.git] / virt-df / virt_df_lvm2_lexer.mll
1 (* 'df' command for virtual domains.
2    (C) Copyright 2007-2008 Richard W.M. Jones, Red Hat Inc.
3    http://libvirt.org/
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *)
19
20 (* Scanner for LVM2 metadata.
21  * ocamllex tutorial:
22  * http://plus.kaist.ac.kr/~shoh/ocaml/ocamllex-ocamlyacc/ocamllex-tutorial/
23  *)
24
25 {
26   open Printf
27   open Lexing
28
29   open Virt_df
30   open Virt_df_lvm2_parser
31
32   (* Temporary buffer used for parsing strings, etc. *)
33   let tmp = Buffer.create 80
34
35   exception Error of string
36 }
37
38 let digit = ['0'-'9']
39 let alpha = ['a'-'z' 'A'-'Z']
40 let alphau = ['a'-'z' 'A'-'Z' '_']
41 let alnum = ['a'-'z' 'A'-'Z' '0'-'9']
42 let alnumu = ['a'-'z' 'A'-'Z' '0'-'9' '_']
43 let ident = alphau alnumu*
44
45 let whitespace = [' ' '\t' '\r' '\n']+
46
47 let escaped_char = '\\' _
48
49 rule token = parse
50   (* ignore whitespace and comments *)
51   | whitespace
52   | '#' [^ '\n']*
53       { token lexbuf }
54
55   (* scan single character tokens *)
56   | '{'  { LBRACE }
57   | '}'  { RBRACE }
58   | '['  { LSQUARE }
59   | ']'  { RSQUARE }
60   | '='  { EQ }
61   | ','  { COMMA }
62
63   (* strings - see LVM2/lib/config/config.c *)
64   | '"'
65       {
66         Buffer.reset tmp;
67         STRING (dq_string lexbuf)
68       }
69   | '\''
70       {
71         Buffer.reset tmp;
72         STRING (dq_string lexbuf)
73       }
74
75   (* floats *)
76   | ('-'? digit+ '.' digit*) as f
77       {
78         let f = float_of_string f in
79         FLOAT f
80       }
81
82   (* integers *)
83   | ('-'? digit+) as i
84       {
85         let i = Int64.of_string i in
86         INT i
87       }
88
89   (* identifiers *)
90   | ident as id
91       { IDENT id }
92
93   (* end of file *)
94   | eof
95       { EOF }
96
97   | _ as c
98       { raise (Error (sprintf "%c: invalid character in input" c)) }
99
100 and dq_string = parse
101   | '"'
102       { Buffer.contents tmp }
103   | escaped_char as str
104       { Buffer.add_char tmp str.[1]; dq_string lexbuf }
105   | eof
106       { raise (Error "unterminated string in metadata") }
107   | _ as c
108       { Buffer.add_char tmp c; dq_string lexbuf }
109
110 and q_string = parse
111   | '\''
112       { Buffer.contents tmp }
113   | escaped_char as str
114       { Buffer.add_char tmp str.[1]; q_string lexbuf }
115   | eof
116       { raise (Error "unterminated string in metadata") }
117   | _ as c
118       { Buffer.add_char tmp c; q_string lexbuf }
119
120 {
121   (* Demonstration of how to wrap the token function
122      with extra debugging statements:
123   let token lexbuf =
124     try
125       let r = token lexbuf in
126       if debug then
127         eprintf "Lexer: token returned is %s\n"
128           (match r with
129            | LBRACE -> "LBRACE"
130            | RBRACE -> "RBRACE"
131            | LSQUARE -> "LSQUARE"
132            | RSQUARE -> "RSQUARE"
133            | EQ -> "EQ"
134            | COMMA -> "COMMA"
135            | STRING s -> sprintf "STRING(%S)" s
136            | INT i -> sprintf "INT(%Ld)" i
137            | FLOAT f -> sprintf "FLOAT(%g)" f
138            | IDENT s -> sprintf "IDENT(%s)" s
139            | EOF -> "EOF");
140       r
141     with
142       exn ->
143         prerr_endline (Printexc.to_string exn);
144         raise exn
145   *)
146
147   (* Lex and parse input.
148    *
149    * Return the parsed metadata structure if everything went to plan.
150    * Raises [Error msg] if there was some parsing problem.
151    *)
152   let rec parse_lvm2_metadata_from_string str =
153     let lexbuf = Lexing.from_string str in
154     parse_lvm2_metadata lexbuf
155   and parse_lvm2_metadata_from_channel chan =
156     let lexbuf = Lexing.from_channel chan in
157     parse_lvm2_metadata lexbuf
158   and parse_lvm2_metadata lexbuf =
159     try
160       input token lexbuf
161     with
162     | Error _ as exn -> raise exn
163     | Parsing.Parse_error -> raise (Error "Parse error")
164     | exn -> raise (Error ("Exception: " ^ Printexc.to_string exn))
165 }