34
35:- module(javascript_grammar,
36 [ js_token//1
37 ]). 38:- use_module(library(dcg/basics)). 39:- use_module(library(pure_input)). 40:- set_prolog_flag(double_quotes, codes). 41
53
57
58js_token(Type) -->
59 token(Type).
60
67
68token(comment) --> comment, !.
69token(string) --> string_literal, !.
70token(number) --> numeric_literal, !.
71token(identifier(Id)) --> identifier_name(Id), !.
72token(regex) --> regex_literal, !.
73token(ws) --> blank, !, blanks.
74token(punct(Char)) --> [Code], { char_code(Char, Code) }.
75
77
-->
79 "/*",
80 !,
81 ( string(_), "*/"
82 -> []
83 ; syntax_error(eof_in_comment)
84 ).
85comment -->
86 "//",
87 !,
88 ( string(_), eol
89 -> []
90 ; string(_), eof
91 -> []
92 ).
93
94
98
99string_literal -->
100 "\"",
101 !,
102 ( q_codes, "\""
103 -> []
104 ; syntax_error(eof_in_string)
105 ).
106string_literal -->
107 "\'",
108 !,
109 ( q_codes, "\'"
110 -> []
111 ; syntax_error(eof_in_string)
112 ).
113
114
118
119numeric_literal -->
120 ( decimal_literal
121 -> []
122 ; hex_integer
123 ),
124 ( ( decimal_digit
125 ; js_id_start(_)
126 )
127 -> syntax_error(js(illegal_number))
128 ; []
129 ).
130
131decimal_literal -->
132 decimal_integer, ".", opt_decimal_digits, opt_exponent.
133decimal_literal -->
134 ".", decimal_digits, opt_exponent.
135decimal_literal -->
136 decimal_integer,
137 opt_exponent.
138
139decimal_integer -->
140 "0",
141 !.
142decimal_integer -->
143 non_zero_digit, opt_decimal_digits.
144
145decimal_digits -->
146 decimal_digit,
147 !,
148 opt_decimal_digits.
149
150opt_decimal_digits -->
151 decimal_digit,
152 !,
153 opt_decimal_digits.
154opt_decimal_digits -->
155 [].
156
157decimal_digit --> [C], { code_type(C, digit) }.
158non_zero_digit --> [C], { code_type(C, digit), C \== 0'0 }.
159
160opt_exponent -->
161 exponent,
162 !.
163opt_exponent -->
164 [].
165
166exponent -->
167 exponent_indictor,
168 signed_integer.
169
170exponent_indictor --> "e", !.
171exponent_indictor --> "E".
172
173signed_integer --> "+", !, decimal_digits.
174signed_integer --> "-", !, decimal_digits.
175signed_integer --> decimal_digits.
176
177hex_integer --> "0", x, hex_digit, hex_digits.
178
179x --> "x".
180x --> "X".
181
182
186
187regex_literal -->
188 "/", regex_body, "/", !, regex_flags.
189
190regex_body -->
191 regex_first_char,
192 regex_chars.
193
194regex_chars --> regex_char, !, regex_chars.
195regex_chars --> [].
196
197regex_first_char -->
198 regex_backslash_sequence.
199regex_first_char -->
200 regex_non_terminator(C),
201 !,
202 { \+ memberchk(C, "*\\/[") }.
203regex_first_char -->
204 regex_class.
205
206regex_char -->
207 regex_backslash_sequence.
208regex_char -->
209 regex_non_terminator(C),
210 !,
211 { \+ memberchk(C, "\\/[") }.
212regex_char -->
213 regex_class.
214
215regex_backslash_sequence -->
216 "\\", !, regex_non_terminator(_).
217
218regex_class -->
219 "[", regex_class_chars, "]".
220
221regex_class_chars --> regex_class_char, !, regex_class_chars.
222regex_class_chars --> "".
223
224regex_class_char -->
225 regex_non_terminator(C),
226 !,
227 { \+ memberchk(C, "]\\") }.
228
229regex_non_terminator(_) -->
230 eol, !, {fail}.
231regex_non_terminator(C) -->
232 source_char(C).
233
234regex_flags -->
235 js_id_conts(_).
236
237source_char(C) -->
238 [C].
239
240
244
245q_codes --> [] ; q_code, q_codes.
246
247q_code --> "\\", !, char_esc.
248q_code --> eol, !, {fail}.
249q_code --> [_].
250
251char_esc --> single_escape_char, !.
252char_esc --> "x", !, hex_digit, hex_digit.
253char_esc --> "u", !, hex_digit, hex_digit, hex_digit, hex_digit.
254char_esc --> eol, !.
255
256hex_digits --> hex_digit, !, hex_digits.
257hex_digits --> [].
258
259hex_digit --> [C], {code_type(C, xdigit(_))}.
260
261single_escape_char --> "'".
262single_escape_char --> "\"".
263single_escape_char --> "\\".
264single_escape_char --> "b".
265single_escape_char --> "f".
266single_escape_char --> "n".
267single_escape_char --> "r".
268single_escape_char --> "t".
269single_escape_char --> "v".
270
271eof -->
272 \+ [_].
273
274
277
278identifier_name(Id) -->
279 js_id_start(C0),
280 !,
281 js_id_conts(Rest),
282 { atom_codes(Id, [C0|Rest]),
283 ( keyword(Id)
284 -> fail, syntax_error(reserved(Id))
285 ; true
286 )
287 }.
288
289
290js_id_start(C) --> [C], {js_id_start(C)}.
291
292js_id_start(C) :- code_type(C, prolog_var_start), !.
293js_id_start(C) :- code_type(C, prolog_atom_start), !.
294js_id_start(0'$).
295
296js_id_conts([H|T]) --> js_id_cont(H), !, js_id_conts(T).
297js_id_conts([]) --> [].
298
299js_id_cont(C) --> [C], {js_id_cont(C)}.
300
301js_id_cont(C) :- code_type(C, prolog_identifier_continue), !.
302js_id_cont(0'$) :- !.
303
304
305keyword(break). 306keyword(do).
307keyword(instanceof).
308keyword(typeof).
309keyword(case).
310keyword(else).
311keyword(new).
312keyword(var).
313keyword(catch).
314keyword(finally).
315keyword(return).
316keyword(void).
317keyword(continue).
318keyword(for).
319keyword(switch).
320keyword(while).
321keyword(debugger).
322keyword(function).
323keyword(this).
324keyword(with).
325keyword(default).
326keyword(if).
327keyword(throw).
328keyword(delete).
329keyword(in).
330keyword(try).
331
332keyword(class). 333keyword(enum).
334keyword(extends).
335keyword(super).
336keyword(const).
337keyword(export).
338keyword(import).
339
340keyword(implements). 341keyword(let).
342keyword(private).
343keyword(public).
344keyword(yield).
345keyword(interface).
346keyword(package).
347keyword(protected).
348keyword(static)