-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjg_highlight.mll
181 lines (159 loc) · 3.78 KB
/
jg_highlight.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
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
{
open Jingoo
let keyword_class = ref "jghl-kw"
let comment_class = ref "jghl-cmt"
let stmt_class = ref "jghl-stmt"
let expr_class = ref "jghl-expr"
let string_class = ref "jghl-str"
let print_string = ref Stdlib.print_string
let print_char = ref Stdlib.print_char
let logic = ref false
let print_class c s =
!print_string (Printf.sprintf "<span class=\"%s\">%s</span>" c s)
let fail ({ Lexing.lex_curr_p = { Lexing.pos_fname ; pos_lnum ; pos_bol ; pos_cnum } ; _ } as l) =
failwith @@
Printf.sprintf "File '%s', line %d, char %d: %s"
pos_fname pos_lnum (pos_cnum - pos_bol) (Lexing.lexeme l)
}
let ident_first_char = [ 'A'-'Z' 'a'-'z' '_' ]
let ident_char = [ 'A'-'Z' 'a'-'z' '_' '0'-'9' ]
rule main = parse
| ( "and"
| "as"
| "autoescape"
| "block"
| "call"
| "context"
| "elif"
| "else"
| "elseif"
| "endautoescape"
| "endblock"
| "endcall"
| "endfilter"
| "endfor"
| "endfunction"
| "endif"
| "endmacro"
| "endraw"
| "endwith"
| "extends"
| "filter"
| "for"
| "from"
| "function"
| "if"
| "import"
| "in"
| "include"
| "is"
| "macro"
| "not"
| "null"
| "or"
| "raw"
| "rawinclude"
| "set"
| "with"
| "without"
| "||"
| "|"
| "&&"
| "&&"
) as s {
if !logic
then print_class !keyword_class s
else !print_string s ;
main lexbuf
}
| ident_first_char ident_char* as s {
!print_string s ;
main lexbuf
}
| "{{" as s {
if !logic then fail lexbuf ;
logic := true ;
print_class !expr_class s ;
main lexbuf
}
| "}}" as s {
if not !logic then fail lexbuf ;
logic := false ;
print_class !expr_class s ;
main lexbuf
}
| ("{%"|"{%-") as s {
if !logic then fail lexbuf ;
logic := true ;
print_class !stmt_class s ;
main lexbuf
}
| ("%}"|"-%}") as s {
if not !logic then fail lexbuf ;
logic := false ;
print_class !stmt_class s ;
main lexbuf
}
| "{#" { comment (Buffer.create 42) lexbuf }
| ("\"" | "'" | """) as s {
if !logic then string (Buffer.create 42) s lexbuf
else begin
!print_string s ;
main lexbuf
end
}
| eof { () }
| _ as c {
if c = '\n' then Lexing.new_line lexbuf ;
!print_char c ;
main lexbuf
}
and comment buffer = parse
| "#}" {
print_class !stmt_class ("{#" ^ Buffer.contents buffer ^ "#}") ;
main lexbuf
}
| _ as c {
if c = '\n' then Lexing.new_line lexbuf ;
Buffer.add_char buffer c ;
comment buffer lexbuf
}
and string buffer term = parse
| '\\' _ as s {
Buffer.add_string buffer s ;
string buffer term lexbuf
}
| ("""|_) as s {
if s = term
then begin
print_class !string_class (Printf.sprintf "%s%s%s" s (Buffer.contents buffer) s) ;
main lexbuf
end
else begin
Buffer.add_string buffer s ;
string buffer term lexbuf
end
}
{
open Jg_types
let highlight_aux s =
let buffer = Buffer.create (String.length s * 2) in
let lexbuf = Lexing.from_string s in
try
logic := false ;
print_string := Buffer.add_string buffer ;
print_char := Buffer.add_char buffer ;
main lexbuf ;
Tstr (Buffer.contents buffer)
with _ ->
let curr = lexbuf.Lexing.lex_curr_p in
let l = curr.Lexing.pos_lnum in
let c = curr.Lexing.pos_cnum - curr.Lexing.pos_bol in
let t = Lexing.lexeme lexbuf in
failwith (Printf.sprintf "Error line %d, col %d, token %s" l c t)
let highlight ?kwargs:_ = function
| Tstr s -> highlight_aux s
| x -> Jg_runtime.failwith_type_error_1 "highlight" x
let () =
Jg_stub.add_func ~namespace:"jg_highlight" ~func_name:"highlight" (func_arg1 highlight)
}