blob: bfa4e2b57b06f077cd393b790d98ea4c4a2b820b (
plain)
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
|
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
{
open Lexing
open Coqpp_parse
type mode =
| OCaml
| Extend
exception Lex_error of Coqpp_ast.loc * string
let loc lexbuf = {
Coqpp_ast.loc_start = lexeme_start_p lexbuf;
Coqpp_ast.loc_end = lexeme_end_p lexbuf;
}
let newline lexbuf =
let pos = lexbuf.lex_curr_p in
let pos = { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } in
lexbuf.lex_curr_p <- pos
let num_comments = ref 0
let num_braces = ref 0
let mode () = if !num_braces = 0 then Extend else OCaml
let comment_buf = Buffer.create 512
let ocaml_buf = Buffer.create 512
let string_buf = Buffer.create 512
let lex_error lexbuf msg =
raise (Lex_error (loc lexbuf, msg))
let lex_unexpected_eof lexbuf where =
lex_error lexbuf (Printf.sprintf "Unexpected end of file in %s" where)
let start_comment _ =
let () = incr num_comments in
Buffer.add_string comment_buf "(*"
let end_comment lexbuf =
let () = decr num_comments in
let () = Buffer.add_string comment_buf "*)" in
if !num_comments < 0 then lex_error lexbuf "Unexpected end of comment"
else if !num_comments = 0 then
let s = Buffer.contents comment_buf in
let () = Buffer.reset comment_buf in
Some (COMMENT s)
else
None
let start_ocaml _ =
let () = match mode () with
| OCaml -> Buffer.add_string ocaml_buf "{"
| Extend -> ()
in
incr num_braces
let end_ocaml lexbuf =
let () = decr num_braces in
if !num_braces < 0 then lex_error lexbuf "Unexpected end of OCaml code"
else if !num_braces = 0 then
let s = Buffer.contents ocaml_buf in
let () = Buffer.reset ocaml_buf in
Some (CODE { Coqpp_ast.code = s })
else
let () = Buffer.add_string ocaml_buf "}" in
None
}
let letter = ['a'-'z' 'A'-'Z']
let letterlike = ['_' 'a'-'z' 'A'-'Z']
let alphanum = ['_' 'a'-'z' 'A'-'Z' '0'-'9' '\'']
let ident = letterlike alphanum*
let qualid = ident ('.' ident)*
let space = [' ' '\t' '\r']
let number = [ '0'-'9' ]
rule extend = parse
| "(*" { start_comment (); comment lexbuf }
| "{" { start_ocaml (); ocaml lexbuf }
| "GRAMMAR" { GRAMMAR }
| "VERNAC" { VERNAC }
| "TACTIC" { TACTIC }
| "EXTEND" { EXTEND }
| "END" { END }
| "DECLARE" { DECLARE }
| "PLUGIN" { PLUGIN }
| "DEPRECATED" { DEPRECATED }
(** Camlp5 specific keywords *)
| "GLOBAL" { GLOBAL }
| "FIRST" { FIRST }
| "LAST" { LAST }
| "BEFORE" { BEFORE }
| "AFTER" { AFTER }
| "LEVEL" { LEVEL }
| "LEFTA" { LEFTA }
| "RIGHTA" { RIGHTA }
| "NONA" { NONA }
(** Standard *)
| ident { IDENT (Lexing.lexeme lexbuf) }
| qualid { QUALID (Lexing.lexeme lexbuf) }
| number { INT (int_of_string (Lexing.lexeme lexbuf)) }
| space { extend lexbuf }
| '\"' { string lexbuf }
| '\n' { newline lexbuf; extend lexbuf }
| '[' { LBRACKET }
| ']' { RBRACKET }
| '|' { PIPE }
| "->" { ARROW }
| ',' { COMMA }
| ':' { COLON }
| ';' { SEMICOLON }
| '(' { LPAREN }
| ')' { RPAREN }
| '=' { EQUAL }
| _ { lex_error lexbuf "syntax error" }
| eof { EOF }
and ocaml = parse
| "{" { start_ocaml (); ocaml lexbuf }
| "}" { match end_ocaml lexbuf with Some tk -> tk | None -> ocaml lexbuf }
| '\n' { newline lexbuf; Buffer.add_char ocaml_buf '\n'; ocaml lexbuf }
| '\"' { Buffer.add_char ocaml_buf '\"'; ocaml_string lexbuf }
| (_ as c) { Buffer.add_char ocaml_buf c; ocaml lexbuf }
| eof { lex_unexpected_eof lexbuf "OCaml code" }
and comment = parse
| "*)" { match end_comment lexbuf with Some _ -> extend lexbuf | None -> comment lexbuf }
| "(*" { start_comment lexbuf; comment lexbuf }
| '\n' { newline lexbuf; Buffer.add_char comment_buf '\n'; comment lexbuf }
| (_ as c) { Buffer.add_char comment_buf c; comment lexbuf }
| eof { lex_unexpected_eof lexbuf "comment" }
and string = parse
| '\"'
{
let s = Buffer.contents string_buf in
let () = Buffer.reset string_buf in
STRING s
}
| "\\\"" { Buffer.add_char string_buf '\"'; string lexbuf }
| '\n' { newline lexbuf; Buffer.add_char string_buf '\n'; string lexbuf }
| (_ as c) { Buffer.add_char string_buf c; string lexbuf }
| eof { lex_unexpected_eof lexbuf "string" }
and ocaml_string = parse
| "\\\"" { Buffer.add_string ocaml_buf "\\\""; ocaml_string lexbuf }
| '\"' { Buffer.add_char ocaml_buf '\"'; ocaml lexbuf }
| (_ as c) { Buffer.add_char ocaml_buf c; ocaml_string lexbuf }
| eof { lex_unexpected_eof lexbuf "OCaml string" }
{
let token lexbuf = match mode () with
| OCaml -> ocaml lexbuf
| Extend -> extend lexbuf
}
|