-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlexer.mll
More file actions
executable file
·237 lines (217 loc) · 7.81 KB
/
lexer.mll
File metadata and controls
executable file
·237 lines (217 loc) · 7.81 KB
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
{
(* Poling: Proof Of Linearizability Generator
* Poling is built on top of CAVE and shares the same license with CAVE
* See LICENSE.txt for license.
* Contact: He Zhu, Department of Computer Science, Purdue University
* Email: zhu103@purdue.edu
*)
(******************************************************************************)
(* __ ___ CAVE: Concurrent Algorithm VErifier *)
(* / /\ \ / | Copyright (c) 2010, Viktor Vafeiadis *)
(* | /--\ \ / |--- *)
(* \__ / \ \/ |___ See LICENSE.txt for license. *)
(* *)
(******************************************************************************)
open Lexing
open Parser
(* association list of keywords *)
let keyword_ht = Hashtbl.create 71
let _ =
List.iter (fun (s,tok) -> Hashtbl.replace keyword_ht s tok)
["_", UNDERSCORE;
"action", ACTION;
"as", AS;
"assume", ASSUME;
"break", BREAK;
"class", CLASS;
"comment", COMMENT;
"constructor", CONSTRUCTOR;
"continue", CONTINUE;
"dispose", DISPOSE;
"do", DO;
"else", ELSE;
"emp", EMPTY;
"ensures", ENSURES;
"if", IF;
"interfere", INTERFERE;
"invariant", INVARIANT;
"let", LET;
"new", NEW;
"par", PAR;
"requires", REQUIRES;
"resource", RESOURCE;
"return", RETURN;
"then", THEN;
"void", VOID;
"when", WHEN;
"while", WHILE;
"with", WITH;
"true" , BOOL true;
"false", BOOL false;
"NULL", NAT 0;
"qualif", QUALIF;
"squalif", SINGLE_QUALIF;
"purespec", PURESPEC;
"effspec", EFFSPEC;
"setspec", SETDECL;
"thread_desc", TDESC;
]
(* To store the position of the beginning of a string and comment *)
let string_start_loc = ref Location.none;;
let comment_start_loc = ref [];;
let in_comment () = !comment_start_loc <> [];;
let lexbuf_stack = ref []
(* Update the current location with absolute line number. *)
let update_currentline lexbuf line =
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_lnum = line }
(* Update the current location with file name. *)
let update_fname lexbuf fname =
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = fname }
let update_newline lexbuf =
let pos = lexbuf.lex_curr_p in
lexbuf.lex_curr_p <-
{ pos with
pos_lnum = pos.pos_lnum + 1;
pos_bol = pos.pos_cnum; }
(* Initialize file name and starting position *)
let init lexbuf fname =
Location.lexbuf := Some lexbuf;
update_fname lexbuf fname;
update_currentline lexbuf 1;
lexbuf.lex_start_p <- lexbuf.lex_curr_p
(* Initialize file name and starting position *)
let init_fname fname =
let lexbuf = Lexing.from_channel (open_in fname) in
Location.lexbuf := Some lexbuf;
update_fname lexbuf fname;
update_currentline lexbuf 1;
lexbuf.lex_start_p <- lexbuf.lex_curr_p;
lexbuf
let init_stdin () =
let lexbuf = Lexing.from_channel stdin in
Location.lexbuf := Some lexbuf;
update_fname lexbuf "<stdin>";
update_currentline lexbuf 1;
lexbuf.lex_start_p <- lexbuf.lex_curr_p;
lexbuf
let parse_eof k =
match !lexbuf_stack with
| [] -> EOF
| b::l ->
Location.lexbuf := Some b;
lexbuf_stack := l;
k b
}
(* regular expressions *)
let newline = ('\010' | '\013' | "\013\010")
let blank = [' ' '\009' '\012']
let letter = ['A'-'Z' '_' 'a'-'z']
let digit = ['0'-'9']
let alphanum = digit | letter
let ident = letter alphanum*
let qident = '_' ident
let fident = '@' ident
let num = digit+
let str = '"' ([^'"' '\013' '\010'] | "\\\"")* '"'
(* entry points *)
rule token = parse
| newline { update_newline lexbuf; token lexbuf }
| blank { token lexbuf }
| '#' { hash lexbuf }
| "//" [^ '\010' '\013']* newline
{ update_newline lexbuf; token lexbuf }
| "/*" { comment_start_loc := [lexbuf.lex_curr_p];
comment lexbuf;
token lexbuf }
| "|->" { POINTSTO }
| "," { COMMA }
| "{" { LBRACE }
| "[" { LBRACKET }
| "(" { LPAREN }
| "->" { MINUSGREATER }
| "}" { RBRACE }
| "]" { RBRACKET }
| ")" { RPAREN }
| ";" { SEMI }
| "&&" { AMPERAMPER }
| "||" { BARBAR }
| ":" { COLON }
| "=" { EQUAL }
| "!" { UNARYOP(Lexing.lexeme lexbuf) }
| "==" | "!="
| "<" | "<=" | ">" | ">=" { INFIXOP1(Lexing.lexeme lexbuf) }
| "+" | "-" { INFIXOP2(Lexing.lexeme lexbuf) }
| "/" | "%" | "^" { INFIXOP3(Lexing.lexeme lexbuf) }
| "*" { STAR }
| "." { DOT }
| "~" { TILDE }
| "{<" { LBRACELESS }
| ">}" { GREATERRBRACE }
| "@" { WILD }
| "<<" { IN }
| "++" { UNION }
| "::" { CONCAT }
| "$$" { REC }
| "=>" { IMPLIES }
| num { NAT(int_of_string(Lexing.lexeme lexbuf)) }
| ident { let s = Lexing.lexeme lexbuf in
try Hashtbl.find keyword_ht s
with Not_found -> IDENT(s) }
| qident { QIDENT(Lexing.lexeme lexbuf) }
| fident { FIDENT(Lexing.lexeme lexbuf) }
| str { let s = Lexing.lexeme lexbuf in
STRING (String.sub s 1 (String.length s - 2)) }
| eof { parse_eof token }
| _ { raise(Location.Parse_error
("Illegal character (" ^ Char.escaped (Lexing.lexeme_char lexbuf 0) ^ ").",
Location.mkloc(lexbuf.lex_start_p) (lexbuf.lex_curr_p))) }
and comment = parse
"/*" { comment_start_loc := lexbuf.lex_curr_p :: !comment_start_loc;
comment lexbuf }
| "*/" { match !comment_start_loc with
| [] -> assert false
| [_] -> comment_start_loc := [];
| _ :: l -> comment_start_loc := l; comment lexbuf }
| eof { match !comment_start_loc with
| [] -> assert false
| loc :: _ -> comment_start_loc := [];
raise(Location.Parse_error
("Unterminated comment.",
Location.mkloc loc (lexbuf.lex_curr_p))) }
| newline { update_newline lexbuf; comment lexbuf }
| _ { comment lexbuf }
(* # <line number> <file name> ... *)
and hash = parse
newline { update_newline lexbuf; token lexbuf}
| blank { hash lexbuf}
| num { let s = Lexing.lexeme lexbuf in
update_currentline lexbuf (int_of_string s - 1);
file lexbuf }
(* | "include" blank+ (str as fname)
{ lexbuf_stack := lexbuf :: !lexbuf_stack;
let f = (String.sub fname 1 ((String.length fname) - 2)) in
let newbuf =
try init_fname (Filename.concat (Filename.dirname lexbuf.lex_start_p.pos_fname) f)
with Sys_error _ ->
try init_fname f
with Sys_error s -> raise (Location.Parse_error
(s, Location.mkloc(lexbuf.lex_start_p) (lexbuf.lex_curr_p)))
in
token newbuf }
*)
| _ { raise(Location.Parse_error
("Illegal character (" ^ Char.escaped (Lexing.lexeme_char lexbuf 0) ^ ") after #. Line number expected.",
Location.mkloc(lexbuf.lex_start_p) (lexbuf.lex_curr_p))) }
and file = parse
newline { update_newline lexbuf; token lexbuf }
| blank { file lexbuf }
| str { let n = Lexing.lexeme lexbuf in
update_fname lexbuf (String.sub n 1 ((String.length n) - 2));
endline lexbuf }
| _ { endline lexbuf }
and endline = parse
newline { update_newline lexbuf; token lexbuf }
| eof { parse_eof token }
| _ { endline lexbuf }
{ (* trailer *)
}