forked from fram-lang/cpspg
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLexer.mll
More file actions
185 lines (147 loc) · 5.44 KB
/
Copy pathLexer.mll
File metadata and controls
185 lines (147 loc) · 5.44 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
{
open Raw
open Parser
open Lexing
exception UnexpectedInput of (char option)
let add_c = Buffer.add_char
let add_s = Buffer.add_string
let update_loc lexbuf file line =
let pos = lexbuf.lex_curr_p in
let file = Option.value ~default:pos.pos_fname file in
lexbuf.lex_curr_p
<- { pos with pos_fname = file; pos_lnum = line; pos_bol = pos.pos_cnum }
;;
let sync buf lexbuf = Lexing.lexeme lexbuf |> Buffer.add_string buf
let wrapped pre post f lexbuf =
let buf = Buffer.create 64
and pos = lexbuf.lex_start_p in
Buffer.add_string buf pre;
let res = f (sync buf) lexbuf in
Buffer.add_string buf post;
lexbuf.lex_start_p <- pos;
Buffer.contents buf, res
;;
let keyword_of_string = function
| "$startpos" -> KwStartpos
| "$endpos" -> KwEndpos
| "$symbolstartpos" -> KwSymbolstartpos
| "$startofs" -> KwStartofs
| "$endofs" -> KwEndofs
| "$symbolstartofs" -> KwSymbolstartofs
| "$loc" -> KwLoc
| "$sloc" -> KwSloc
| _ -> assert false
;;
}
let newline = '\r'* '\n'
let blank = [' ' '\009' '\012']
let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
let identchar = ['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
rule main = parse
| newline { new_line lexbuf; main lexbuf }
| blank { main lexbuf }
| "#" blank* (['0'-'9']+ as num) blank*
('"' ([^ '\r' '\n' '"']* as name) '"')?
[^ '\r' '\n']* newline
{ update_loc lexbuf name (int_of_string num); main lexbuf }
| "(*" { wrapped "" "" (comment 0) lexbuf |> ignore; main lexbuf }
| "/*" { ccomment lexbuf; main lexbuf }
| "//" { ccomment_line lexbuf; main lexbuf }
| "%token" { DTOKEN}
| "%term" { DTOKEN }
| "%type" { DTYPE }
| "%start" { DSTART }
| "%left" { DLEFT }
| "%right" { DRIGHT }
| "%nonassoc" { DNONASSOC }
| "%binary" { DNONASSOC }
| "%%" { DSEP }
| "%{" { DCODE (wrapped " " " " (dcode 0) lexbuf |> fst) }
| "%inline" { DINLINE }
| "%prec" { DPREC }
| "%when" { DWHEN }
| "%\\" { DSEP }
| "%<" { DLEFT }
| "%>" { DRIGHT }
| "%0" { DTOKEN }
| "%2" { DNONASSOC }
| "|" { BAR }
| ":" { COLON }
| "," { COMMA }
| "=" { EQ }
| "+" { PLUS }
| "?" { QMARK }
| ";" { SEMI }
| "*" { STAR }
| "(" { LPAREN }
| ")" { RPAREN }
| lowercase identchar* as i { ID i }
| uppercase identchar* as i { TID i }
| '<' { TYPE (wrapped " " " " (tag 0) lexbuf |> fst) }
| "{" { CODE (wrapped " " " " (code 0 []) lexbuf) }
| eof { EOF }
| _ as c { raise (UnexpectedInput (Some c)) }
and tag depth eat = parse
| '[' | '(' { eat lexbuf; tag (depth + 1) eat lexbuf }
| ']' | ')' { eat lexbuf; tag (depth - 1) eat lexbuf }
| "->" { eat lexbuf; tag depth eat lexbuf }
| '>' { if depth > 0 then (eat lexbuf; tag depth eat lexbuf) }
| newline { new_line lexbuf; eat lexbuf; tag depth eat lexbuf }
| eof { raise (UnexpectedInput None) }
| _ { eat lexbuf; tag depth eat lexbuf }
and code depth kw eat = parse
| '[' | '(' | '{' { eat lexbuf; code (depth + 1) kw eat lexbuf }
| ']' | ')' { eat lexbuf; code (depth - 1) kw eat lexbuf }
| "}" { if depth > 0 then (eat lexbuf; code (depth - 1) kw eat lexbuf) else kw }
| "$startpos"
| "$endpos"
| "$symbolstartpos"
| "$startofs"
| "$endofs"
| "$symbolstartofs"
| "$loc"
| "$sloc" as k
{ let k = keyword_of_string k, (lexbuf.lex_start_p, lexbuf.lex_curr_p) in
eat lexbuf;
code depth (k :: kw) eat lexbuf }
| '$' (['0'-'9']+ as i)
{ let k = KwArg (int_of_string i), (lexbuf.lex_start_p, lexbuf.lex_curr_p) in
eat lexbuf;
code depth (k :: kw) eat lexbuf }
| '"' { eat lexbuf; string eat lexbuf; eat lexbuf; code depth kw eat lexbuf }
| "(*" { eat lexbuf; comment 0 eat lexbuf; eat lexbuf; code depth kw eat lexbuf }
| newline { new_line lexbuf; eat lexbuf; code depth kw eat lexbuf }
| eof { raise (UnexpectedInput None) }
| _ { eat lexbuf; code depth kw eat lexbuf }
and dcode depth eat = parse
| '[' | '(' | '{' { eat lexbuf; dcode (depth + 1) eat lexbuf }
| ']' | ')' | '}' { eat lexbuf; dcode (depth - 1) eat lexbuf }
| "%}" { if depth > 0 then (eat lexbuf; dcode (depth - 1) eat lexbuf) }
| '"' { eat lexbuf; string eat lexbuf; eat lexbuf; dcode depth eat lexbuf }
| "(*" { eat lexbuf; comment 0 eat lexbuf; eat lexbuf; dcode depth eat lexbuf }
| newline { new_line lexbuf; eat lexbuf; dcode depth eat lexbuf }
| eof { raise (UnexpectedInput None) }
| _ { eat lexbuf; dcode depth eat lexbuf }
and string eat = parse
| "\\\\" { eat lexbuf; string eat lexbuf }
| "\\\"" { eat lexbuf; string eat lexbuf }
| '"' { }
| newline { new_line lexbuf; eat lexbuf; string eat lexbuf }
| eof { raise (UnexpectedInput None) }
| _ { eat lexbuf; string eat lexbuf }
and comment depth eat = parse
| "(*" { eat lexbuf; comment (depth + 1) eat lexbuf }
| "*)" { if depth > 0 then (eat lexbuf; comment (depth - 1) eat lexbuf) }
| '"' { eat lexbuf; string eat lexbuf; eat lexbuf; comment depth eat lexbuf }
| newline { new_line lexbuf; eat lexbuf; comment depth eat lexbuf }
| eof { raise (UnexpectedInput None) }
| _ { eat lexbuf; comment depth eat lexbuf }
and ccomment = parse
| "*/" { }
| eof { raise (UnexpectedInput None) }
| _ { ccomment lexbuf }
and ccomment_line = parse
| "\n" { }
| eof { raise (UnexpectedInput None) }
| _ { ccomment_line lexbuf }