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 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
(********************************************************************)
(* *)
(* The Why3 Verification Platform / The Why3 Development Team *)
(* Copyright 2010-2025 -- Inria - CNRS - Paris-Saclay University *)
(* *)
(* This software is distributed under the terms of the GNU Lesser *)
(* General Public License version 2.1, with the special exception *)
(* on linking described in file LICENSE. *)
(********************************************************************)
(* This is a copy of [src/parser/lexer.mll], with the following minor changes:
* addition of keywords:
*)
{
open Why3
open Coma_parser
let keywords = Hashtbl.create 97
let span_aliases = Hashtbl.create 16
let attribute_aliases = Hashtbl.create 16
let () =
List.iter
(fun (x,y) -> Hashtbl.add keywords x y)
[
"absurd", ABSURD;
"return", RETURN;
"abstract", ABSTRACT;
"alias", ALIAS;
"any", ANY;
"as", AS;
"assert", ASSERT;
"assume", ASSUME;
"at", AT;
"axiom", AXIOM;
"begin", BEGIN;
"break", BREAK;
"by", BY;
"check", CHECK;
"clone", CLONE;
"coinductive", COINDUCTIVE;
"constant", CONSTANT;
"continue", CONTINUE;
"diverges", DIVERGES;
"do", DO;
"done", DONE;
"downto", DOWNTO;
"else", ELSE;
"end", END;
"ensures", ENSURES;
"epsilon", EPSILON;
"exception", EXCEPTION;
"exists", EXISTS;
"export", EXPORT;
"false", FALSE;
"float", FLOAT; (* contextual *)
"for", FOR;
"forall", FORALL;
"fun", FUN;
"function", FUNCTION;
"ghost", GHOST;
"goal", GOAL;
"if", IF;
"import", IMPORT;
"in", IN;
"inductive", INDUCTIVE;
"invariant", INVARIANT;
"label", LABEL;
"lemma", LEMMA;
"let", LET;
"match", MATCH;
"meta", META;
"module", MODULE;
"mutable", MUTABLE;
"not", NOT;
"old", OLD;
"partial", PARTIAL;
"predicate", PREDICATE;
"private", PRIVATE;
"pure", PURE;
"raise", RAISE;
"raises", RAISES;
"range", RANGE; (* contextual *)
"reads", READS;
"rec", REC;
"ref", REF; (* contextual *)
"requires", REQUIRES;
"returns", RETURNS;
"scope", SCOPE;
"so", SO;
"then", THEN;
"theory", THEORY;
"to", TO;
"true", TRUE;
"try", TRY;
"type", TYPE;
"use", USE;
"val", VAL;
"variant", VARIANT;
"while", WHILE;
"with", WITH;
"writes", WRITES;
]
}
let space = [' ' '\t' '\r']
let quote = '\''
let bin = ['0' '1']
let oct = ['0'-'7']
let dec = ['0'-'9']
let hex = ['0'-'9' 'a'-'f' 'A'-'F']
let bin_sep = ['0' '1' '_']
let oct_sep = ['0'-'7' '_']
let dec_sep = ['0'-'9' '_']
let hex_sep = ['0'-'9' 'a'-'f' 'A'-'F' '_']
let lalpha = ['a'-'z']
let ualpha = ['A'-'Z']
let alpha = ['a'-'z' 'A'-'Z']
let suffix = (alpha | quote* dec_sep)* quote*
let lident = ['a'-'z' '_'] suffix
let uident = ['A'-'Z'] suffix
let core_suffix = quote alpha suffix
let core_lident = lident core_suffix+
let core_uident = uident core_suffix+
let op_char_1 = ['=' '<' '>' '~']
let op_char_2 = ['+' '-']
let op_char_3 = ['*' '/' '\\' '%']
let op_char_4 = ['!' '$' '&' '?' '@' '^' '.' ':' '|' '#']
let op_char_34 = op_char_3 | op_char_4
let op_char_234 = op_char_2 | op_char_34
let op_char_1234 = op_char_1 | op_char_234
let op_char_pref = ['!' '?']
rule token = parse
| "[##" space* ("\"" ([^ '\010' '\013' '"' ]* as file) "\"")?
space* (dec+ as line) space* (dec+ as char) space* "]"
{ let file =
Option.map (Lexlib.resolve_file Lexing.(lexbuf.lex_curr_p.pos_fname)) file
in
Lexlib.update_loc lexbuf file (int_of_string line) (int_of_string char);
token lexbuf }
| "[%#" space* (lident as lid) space* "]"
{ try
let (file, bline, bchar, eline, echar) = Hashtbl.find span_aliases lid in
POSITION (Loc.user_position file bline bchar eline echar)
with Not_found -> Loc.errorm "File alias unknown." }
| "[#" space* "\"" ([^ '\010' '\013' '"' ]* as file) "\"" space*
(dec+ as bline) space* (dec+ as bchar) space*
(dec+ as eline) space* (dec+ as echar) space* "]"
{ let file = Lexlib.resolve_file Lexing.(lexbuf.lex_curr_p.pos_fname) file in
POSITION (Loc.user_position file
(int_of_string bline) (int_of_string bchar)
(int_of_string eline) (int_of_string echar)) }
| "let%span" space+ (lident as lid) space* "=" space* "\"" ([^ '\010' '\013' '"' ]* as file) "\""
space* (dec+ as bline) space* (dec+ as bchar) space* (dec+ as eline) space* (dec+ as echar) space*
{ let file = Lexlib.resolve_file Lexing.(lexbuf.lex_curr_p.pos_fname) file in
Hashtbl.replace span_aliases lid (file, int_of_string bline, int_of_string bchar, int_of_string eline, int_of_string echar);
token lexbuf }
| "let%attr" space+ (lident as lid) space* "=" space* ([^ '\n']+ as cattr)
{ Hashtbl.replace attribute_aliases lid cattr;
token lexbuf }
| "[%@" space* (lident (' '+ [^ ' ' '\n' ']']+ as lid)) space* ']'
{ try
ATTRIBUTE (Hashtbl.find attribute_aliases lid)
with Not_found -> Loc.errorm "Attribute alias unknown." }
| "[@" space* ([^ ' ' '\n' ']']+ (' '+ [^ ' ' '\n' ']']+)* as lbl) space* ']'
{ ATTRIBUTE lbl }
| '\n'
{ Lexing.new_line lexbuf; token lexbuf }
| space+
{ token lexbuf }
| '_'
{ UNDERSCORE }
| lident as id
{ try Hashtbl.find keywords id with Not_found -> LIDENT id }
| core_lident as id
{ CORE_LIDENT id }
| uident as id
{ UIDENT id }
| core_uident as id
{ CORE_UIDENT id }
| dec dec_sep* as s
{ INTEGER Number.(int_literal ILitDec ~neg:false (Lexlib.remove_underscores s)) }
| '0' ['x' 'X'] (hex hex_sep* as s)
{ INTEGER Number.(int_literal ILitHex ~neg:false (Lexlib.remove_underscores s)) }
| '0' ['o' 'O'] (oct oct_sep* as s)
{ INTEGER Number.(int_literal ILitOct ~neg:false (Lexlib.remove_underscores s)) }
| '0' ['b' 'B'] (bin bin_sep* as s)
{ INTEGER Number.(int_literal ILitBin ~neg:false (Lexlib.remove_underscores s)) }
| (dec+ as i) ".."
{ Lexlib.backjump lexbuf 2; INTEGER Number.(int_literal ILitDec ~neg:false i) }
| '0' ['x' 'X'] (hex+ as i) ".."
{ Lexlib.backjump lexbuf 2; INTEGER Number.(int_literal ILitHex ~neg:false i) }
| (dec+ as i) ("" as f) ['e' 'E'] (['-' '+']? dec+ as e)
| (dec+ as i) '.' (dec* as f) (['e' 'E'] (['-' '+']? dec+ as e))?
| (dec* as i) '.' (dec+ as f) (['e' 'E'] (['-' '+']? dec+ as e))?
{ REAL (Number.real_literal ~radix:10 ~neg:false ~int:i ~frac:f ~exp:(Option.map Lexlib.remove_leading_plus e)) }
| '0' ['x' 'X'] (hex+ as i) ("" as f) ['p' 'P'] (['-' '+']? dec+ as e)
| '0' ['x' 'X'] (hex+ as i) '.' (hex* as f)
(['p' 'P'] (['-' '+']? dec+ as e))?
| '0' ['x' 'X'] (hex* as i) '.' (hex+ as f)
(['p' 'P'] (['-' '+']? dec+ as e))?
{ REAL (Number.real_literal ~radix:16 ~neg:false ~int:i ~frac:f ~exp:(Option.map Lexlib.remove_leading_plus e)) }
| "(*)"
{ Lexlib.backjump lexbuf 2; LEFTPAR }
| "(*"
{ Lexlib.comment lexbuf; token lexbuf }
| "'" (lalpha suffix as id)
{ QUOTE_LIDENT id }
| ","
{ COMMA }
| "("
{ LEFTPAR }
| ")"
{ RIGHTPAR }
| "{"
{ LEFTBRC }
| "}"
{ RIGHTBRC }
| ":"
{ COLON }
| ";"
{ SEMICOLON }
| "->"
{ ARROW }
| "->'"
{ Lexlib.backjump lexbuf 1; ARROW }
| "<-"
{ LARROW }
| "<->"
{ LRARROW }
| "&&"
{ AMPAMP }
| "||"
{ BARBAR }
| "/\\"
{ AND }
| "\\/"
{ OR }
| "."
{ DOT }
| ".."
{ DOTDOT }
| "&"
{ AMP }
| "|"
{ BAR }
| "<"
{ LT }
| ">"
{ GT }
| "<>"
{ LTGT }
| "="
{ EQUAL }
| "-"
{ MINUS }
| "["
{ LEFTSQ }
| "]"
{ RIGHTSQ }
| "]" (quote+ as s)
{ RIGHTSQ_QUOTE s }
| ")" ('\'' alpha suffix core_suffix* as s)
{ RIGHTPAR_QUOTE s }
| ")" ('_' alpha suffix core_suffix* as s)
{ RIGHTPAR_USCORE s }
| "[|"
{ LEFTSQBAR }
| "|]"
{ BARRIGHTSQ }
| "-{"
{ LEFTMINBRC }
| "}-"
{ RIGHTMINBRC }
(* begin coma *)
| "!"
{ BANG }
| "?"
{ QUESTION }
(* | "/"
{ SLASH } *)
(* | "/" space* "&"
{ SLASHAMP } *)
| "--" [ ^ '\n' ]*
{ token lexbuf }
(* end coma *)
| op_char_pref op_char_4* quote* as s
{ OPPREF s }
| op_char_1234* op_char_1 op_char_1234* quote* as s
{ OP1 s }
| op_char_234* op_char_2 op_char_234* quote* as s
{ OP2 s }
| op_char_34* op_char_3 op_char_34* quote* as s
{ OP3 s }
| op_char_4+ as s
{ OP4 s }
| "\""
{ STRING (Lexlib.string lexbuf) }
| eof
{ EOF }
| _ as c
{ Lexlib.illegal_character c lexbuf }
{
let () = Exn_printer.register (fun fmt exn -> match exn with
| Coma_parser.Error -> Format.pp_print_string fmt "syntax error"
| _ -> raise exn)
let parse_channel file c =
let lb = Lexing.from_channel c in
Loc.set_file file lb;
try
Coma_parser.top_level token lb
with
Coma_parser.Error as e ->
raise (Loc.Located
(Loc.extract (lb.Lexing.lex_start_p, lb.Lexing.lex_curr_p),e))
}
|