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 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
(****************************************************************************)
(* the diy toolsuite *)
(* *)
(* Jade Alglave, University College London, UK. *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France. *)
(* *)
(* Copyright 2010-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved. *)
(* *)
(* This software is governed by the CeCILL-B license under French law and *)
(* abiding by the rules of distribution of free software. You can use, *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt. *)
(****************************************************************************)
{
open Lexing
open LexMisc
(* Result of splitter *)
type info = string * string
type result =
{
arch : Archs.t ;
name : Name.t ;
info : info list ;
locs : Pos.pos2 * Pos.pos2 * Pos.pos2 *Pos.pos2 ;
start : Lexing.position ;
}
module type Config = sig
include LexUtils.Config
val check_rename : string -> string option
end
module Default = struct
include LexUtils.Default
let check_rename _ = None
end
let add_info buff k v =
Buffer.add_string buff k ;
Buffer.add_char buff '=' ;
Buffer.add_string buff v ;
Buffer.add_char buff '\n'
module Make(O:Config) = struct
module LU = LexUtils.Make(O)
open LU
}
let digit = [ '0'-'9' ]
let alpha = [ 'a'-'z' 'A'-'Z']
let blank = [' ' '\t' '\r']
let bool = "true" | "false"
let name = alpha (alpha|digit|'_' | '/' | '.' | '-')*
(* yes some test names are such *)
let testname = (alpha|digit|'_' | '/' | '.' | '-' | '+'|'['|']')+
let num = digit+
rule main_pos = parse
| ""
{
let start = lexeme_start_p lexbuf in
main start lexbuf
}
and main start = parse
| blank* (alpha|digit|'_')+ as arch
blank+
(testname as tname)
blank*
('(' (name as texname) ')' blank*) ?
( ('\n'? as line) blank*'"'([^'"']* as doc) '"' blank*) ? (* '"' *)
';' ?
{ begin match line with Some _ -> incr_lineno lexbuf | None -> () end ;
let arch =
match Archs.parse arch with
| Some a -> a
| None ->
Warn.user_error "%s is not an implemented architecture" arch in
let (info,init1,(init2,prog1)) = find_init [] lexbuf in
let do_skip_comments = match arch with
| `C|`CPP -> false (* We can't skip comments in C, because "(*" is legal and frequent syntax *)
| _ -> true in
let is_empty,prog2 = inside_prog do_skip_comments lexbuf in
let constr2 =
if is_empty then prog2 else inside_constr lexbuf in
let loc_eof = find_eof lexbuf in
let tname =
if tname = "--" then
Filename.chop_extension
(Filename.basename init1.pos_fname)
else
(* GRR follow litmus here *)
Misc.clean_name tname in
let tname = match O.check_rename tname with
| None -> tname
| Some n -> n in
let names =
{ Name.name = tname ;
file = init1.pos_fname ;
texname = Misc.proj_opt tname texname ;
doc = Misc.proj_opt "" doc ; } in
{ arch = arch ;
name = names ;
info = info ;
locs = ((init1,init2),(prog1,prog2),(prog2,constr2),(constr2,loc_eof)) ;
start = start ;
}
}
| "" { error "first line" lexbuf }
and find_init info = parse
| '\n' { incr_lineno lexbuf ; find_init info lexbuf }
| "(*" { skip_comment lexbuf ; find_init info lexbuf }
| '{'
{ let loc1 = lexeme_end_p lexbuf in
let loc2 = inside_init (Buffer.create 16) 0 lexbuf in
List.rev info,loc1,loc2 }
| (name as key) blank* '=' blank* ([^'\n''\r']* as value) '\r'?'\n'
{ incr_lineno lexbuf ; find_init ((key,value)::info) lexbuf }
| [^'\n''{']+ { find_init info lexbuf }
| "" { error "find init section" lexbuf }
(* Courtesy of Luc - remove this comment when upstreaming *)
and inside_init buff depth = parse
| '{' { Buffer.add_char buff '{'; inside_init buff (depth+1) lexbuf }
| '\n' { incr_lineno lexbuf ; inside_init buff depth lexbuf }
| '}' { if depth > 0 then begin
Buffer.add_char buff '}';
inside_init buff (depth -1) lexbuf
end else
lexeme_start_p lexbuf,lexeme_end_p lexbuf
}
| "" { error "inside init section" lexbuf }
| _ as c { Buffer.add_char buff c; inside_init buff depth lexbuf }
and inside_prog do_skip_comments = parse
| '\n' { incr_lineno lexbuf ; inside_prog do_skip_comments lexbuf }
(* Had to erase comments to handle C-code *)
| "(*"
{ if do_skip_comments then begin
skip_comment lexbuf
end ;
inside_prog do_skip_comments lexbuf }
| "\"" { skip_string lexbuf ; inside_prog do_skip_comments lexbuf }
(* | "<<" *) (* Had to erase this to handle C-code *)
|eof
{ true,lexeme_start_p lexbuf } (* boolean -> empty constraint *)
(* | "+" *) (* Had to erase this to handle C-code, why here ?? *)
| "final"
| "forall"
| ('~' blank* "exists" )
| "exists"
| "cases" (* not sure if this line should still be here *)
| "observed"|"Observed"
| "locations"
| "filter"
{ false,lexeme_start_p lexbuf }
(* name is for longest match to avoid confusion, in case of eg. forallx *)
| (name | _) { inside_prog do_skip_comments lexbuf }
| "" { error "inside_prog" lexbuf }
and inside_constr = parse
| '\n' { incr_lineno lexbuf ; inside_constr lexbuf }
| "(*" { skip_comment lexbuf ; inside_constr lexbuf }
| "<<"| eof { lexeme_start_p lexbuf }
| _ { inside_constr lexbuf }
| "" { error "inside_constr" lexbuf }
and find_eof = parse
| '\n' { incr_lineno lexbuf ; find_eof lexbuf }
| [^'\n']+ { find_eof lexbuf }
| eof { lexeme_start_p lexbuf }
(* Change info in the init section *)
and change_main buff p = parse
| blank* (alpha|digit|'_')+
blank+
testname
blank*
('(' name ')' blank*) ?
( ('\n'? as line) blank*'"'[^'"']* '"' blank*) ? (* '"' *)
[^'\n']* '\n' as lexed
{ begin match line with Some _ -> incr_lineno lexbuf | None -> () end ;
incr_lineno lexbuf ;
Buffer.add_string buff lexed ;
change_info false p buff lexbuf }
and change_info found p buff = parse
| eof
{ () }
| '\n'
{ incr_lineno lexbuf ;
Buffer.add_char buff '\n' ;
change_info found p buff lexbuf }
| '\n'* '{' as lexed
{ incr_lineno lexbuf ;
if not found then begin
let k,v = p in
add_info buff k v
end ;
Buffer.add_string buff lexed ;
change_info found p buff lexbuf }
| (name as key) blank* '=' blank* [^'\n']* '\n' as line
{ incr_lineno lexbuf ;
let k,v = p in
if O.debug then Printf.eprintf "Found key: %s\n%!" key ;
let found =
if k = key then begin
if not found then add_info buff k v ;
true
end else begin
Buffer.add_string buff line ;
found
end in
change_info found p buff lexbuf }
| [^'\n''{']+ as lexed
{ Buffer.add_string buff lexed ;
change_info found p buff lexbuf }
| "" { error "change info" lexbuf }
{
(* Useful for debug *)
(*
let pp_opt chan = function
| None -> ()
| Some s -> output_string chan s
*)
let pp_loc chan (i1,i2) =
Printf.fprintf chan "%i-%i" i1.pos_cnum i2.pos_cnum
let show r =
let loc_init,loc_prog,loc_constr,loc_cfgs = r.locs in
Printf.eprintf
"Test (arch=%s, name=%s, texname=%s, doc=%s)\nSplited as: init=%a, prog=%a, constr=%a, cfgs=%a\n"
(Archs.pp r.arch)
r.name.Name.name
r.name.Name.texname
r.name.Name.doc
pp_loc loc_init
pp_loc loc_prog
pp_loc loc_constr
pp_loc loc_cfgs
let split_lexbuf name lexbuf =
lexbuf.lex_curr_p <-
{pos_fname = name; pos_lnum = 1;
pos_bol = 0; pos_cnum = 0};
let r =
try main_pos lexbuf
with
| LexMisc.Error (msg,loc) ->
failwith (Printf.sprintf "%s: splitter error in sublexer %s" (Pos.str_pos loc) msg)
| Assert_failure _ as e -> raise e
| e ->
failwith (Printf.sprintf "%s: Uncaught exception in splitter %s" (Pos.str_pos lexbuf.lex_curr_p) (Printexc.to_string e))
in
if O.debug then show r ;
r
let reinfo p lexbuf =
let buff = Buffer.create 32 in
change_main buff p lexbuf ;
Buffer.contents buff
let rehash v lexbuf = reinfo (MiscParser.hash_key,v) lexbuf
let split name chan =
let lexbuf = from_channel chan in
split_lexbuf name lexbuf
let split_string name s =
let lexbuf = from_string s in
split_lexbuf name lexbuf
end
}
|