-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlexer.mll
138 lines (122 loc) · 3.6 KB
/
lexer.mll
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
(* File lexer.mll *)
{
open Parser (* The type token is defined in parser.mli *)
exception Error of string
let mkhash l =
let h = Hashtbl.create (List.length l) in
List.iter (fun (s, k) -> Hashtbl.add h s k) l; h
let dot_keyword_table =
mkhash [
".true." , TRUE;
".false." , FALSE;
".not." , NOT;
".and." , AND;
".or." , OR;
".eqv." , EQV;
".neqv." , NEQV;
".eq." , EQEQ;
".ne." , NEQ;
".lt." , LESS;
".le." , LEQ;
".gt." , GREATER;
".ge." , GEQ;
]
let keyword_table =
mkhash [
"if" , IF;
"then" , THEN;
"else" , ELSE;
"while" , WHILE;
"case" , CASE;
"select" , SELECT;
"do" , DO;
"program" , PROGRAM;
"end" , END;
"contains" , CONTAINS;
"subroutine" , SUBROUTINE;
"function" , FUNCTION;
"call" , CALL;
"return" , RETURN;
"stop" , STOP;
"dimension" , DIMENSION;
"pointer" , POINTER;
"parameter" , PARAMETER;
"allocatable" , ALLOCATABLE;
"real" , REAL;
"integer" , INTEGER;
"complex" , COMPLEX;
"logical" , LOGICAL;
"go" , GO;
"to" , TO;
"goto" , GOTO;
]
let loc = ref (-1, -1, -1)
let line = ref 1
let target = ref ""
let chars = ref 0
let line_chars = ref 1
let count lexbuf =
let i = Lexing.lexeme_start lexbuf in
let j = Lexing.lexeme_end lexbuf in
j - i
let sum lexbuf =
line_chars := !line_chars + count lexbuf
let update_loc lexbuf =
let i = Lexing.lexeme_start lexbuf in
let j = Lexing.lexeme_end lexbuf in
loc := (!line, i - !chars + 1, j - !chars + 1)
let set_taget lexbuf =
target := Lexing.lexeme lexbuf
let update lexbuf =
sum lexbuf; update_loc lexbuf; set_taget lexbuf
let endline lexbuf =
incr line;
chars := !line_chars + !chars + 1;
line_chars := 0
}
let head = ['A'-'Z' 'a'-'z']
let char = ['A'-'Z' 'a'-'z' '_' '0'-'9']
rule token = parse
'!' [^ '\n'] * '\n' { endline lexbuf; update lexbuf; BR }
| '&' ' ' * '\n' { endline lexbuf; update lexbuf; token lexbuf }
| [' ' '\t'] { incr line_chars; token lexbuf } (* skip blanks *)
| '\n' { endline lexbuf; BR }
| ['0'-'9']+ as lxm { update lexbuf; INT (int_of_string lxm) }
| ('0' | ['1'-'9'] ['0'-'9']*) '.' ['0'-'9']*
as lxm { update lexbuf; FLOAT lxm }
| '+' { update lexbuf; PLUS }
| '-' { update lexbuf; MINUS }
| '*' { update lexbuf; MUL }
| '/' { update lexbuf; DIV }
| '(' { update lexbuf; LPAREN }
| ')' { update lexbuf; RPAREN }
| '[' { update lexbuf; LBRACE }
| ']' { update lexbuf; RBRACE }
| "(/" { update lexbuf; LPAREN_S }
| "/)" { update lexbuf; S_RPAREN }
| "==" { update lexbuf; EQEQ }
| '=' { update lexbuf; EQ }
| "::" { update lexbuf; COLCOL }
| "!=" { update lexbuf; NEQ }
| "<=" { update lexbuf; LEQ }
| ">=" { update lexbuf; GEQ }
| ',' { update lexbuf; COMMA }
| ':' { update lexbuf; COLON }
| '<' { update lexbuf; LESS }
| '>' { update lexbuf; GREATER }
| '.' char * '.' {
let s = Lexing.lexeme lexbuf in
update lexbuf;
try
Hashtbl.find dot_keyword_table s
with
Not_found -> failwith "dot_keyword_table"
}
| head char * {
let s = Lexing.lexeme lexbuf in
update lexbuf;
try
Hashtbl.find keyword_table s
with Not_found -> IDENT s
}
| eof { EOF }