]> git.saurik.com Git - cycript.git/blame - Cycript.l.in
Fold the E lexer helper macro into RegExp lexeme.
[cycript.git] / Cycript.l.in
CommitLineData
b3378a02
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
d15b59f5
JF
3*/
4
b3378a02 5/* GNU Lesser General Public License, Version 3 {{{ */
d15b59f5 6/*
b3378a02
JF
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
d15b59f5 11 *
b3378a02
JF
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
d15b59f5 16 *
b3378a02
JF
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
d15b59f5
JF
20/* }}} */
21
2155ab92 22/* XXX: supposedly I will be screwed on very very long multi-line comments and need to replace these with a manual lexer. http://websrv.cs.fsu.edu/~engelen/courses/COP5621/Pr2.pdf */
cb02f8ae 23
d15b59f5 24%{
cac61857 25#define YYLTYPE cy::location
63b4c5a8
JF
26#include "Cycript.tab.hh"
27typedef cy::parser::token tk;
693d501b 28
5999c315 29#define YY_EXTRA_TYPE CYDriver *
db5e2840 30
3ea7eed0
JF
31#define F(value) do { \
32 int token(value); \
c34648c0 33 yyextra->nobrace_ = false; \
3ea7eed0
JF
34 return token; \
35} while (false)
36
2eb8215d
JF
37#define A new($pool)
38#define Y apr_pstrmemdup($pool, yytext, yyleng)
39
3ea7eed0 40#define I(type, Type, value) do { \
2eb8215d 41 yylval->type ## _ = A CY ## Type; \
3ea7eed0 42 F(value); \
2eb8215d
JF
43} while (false)
44
697d6fd2 45#define T yylval->newline_ = yyextra->state_ == CYNewLine; BEGIN(Div);
db5e2840
JF
46#define C T yyextra->state_ = CYClear;
47#define R T yyextra->state_ = CYRestricted;
5befe15e
JF
48
49#define N \
50 if (yyextra->state_ != CYNewLine) { \
2eb8215d
JF
51 if (yyextra->state_ != CYRestricted) \
52 yyextra->state_ = CYNewLine; \
53 else { \
5befe15e 54 yyextra->state_ = CYClear; \
3ea7eed0 55 F(tk::NewLine); \
2eb8215d 56 } \
5befe15e
JF
57 }
58
691e4717 59#define V(more) { \
cb02f8ae
JF
60 if (const char *nl = reinterpret_cast<const char *>(memchr(yytext, '\n', yyleng))) { \
61 unsigned lines(0); \
62 size_t left; \
63 do { \
64 ++lines; \
65 left = yyleng - (nl - yytext) - 1; \
66 nl = reinterpret_cast<const char *>(memchr(nl + 1, '\n', left)); \
67 } while (nl != NULL); \
68 yylloc->end.lines(lines); \
69 yylloc->end.columns(left); \
70 yylloc->step(); \
691e4717 71 more \
cb02f8ae
JF
72 } else L \
73}
74
5befe15e
JF
75#define L { \
76 yylloc->step(); \
77 yylloc->columns(yyleng); \
78}
e7ed5354 79
931b816a
JF
80int H(char c) {
81 if (c >= '0' && c <= '9')
82 return c - '0';
83 if (c >= 'a' && c <= 'f')
84 return c - 'a' + 10;
85 if (c >= 'A' && c <= 'F')
86 return c - 'A' + 10;
87 return -1;
88}
89
e7ed5354 90#define YY_INPUT(data, value, size) { \
48e3be8a
JF
91 if (yyextra->file_ != NULL) { \
92 size_t copy(fread(data, 1, size, yyextra->file_)); \
93 value = copy == 0 ? YY_NULL : copy; \
94 } else if (yyextra->size_ == 0) \
e7ed5354
JF
95 value = YY_NULL; \
96 else { \
7c6c5b0a
JF
97 size_t copy(size); \
98 copy = (std::min(copy, yyextra->size_)); \
e7ed5354
JF
99 memcpy(data, yyextra->data_, copy); \
100 yyextra->data_ += copy; \
101 yyextra->size_ -= copy; \
102 value = copy; \
103 } \
104}
105
e5332278
JF
106%}
107
108%option prefix="cy"
109%option bison-bridge
110%option bison-locations
111%option noyywrap
112%option yylineno
113%option nounput
114%option interactive
924f67b2 115%option reentrant
691e4717 116%option stack
e5332278 117
2bf24581 118Exponent [eE][+-]?[0-9]+
367eebb1 119Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n
e5332278 120
63cd45c9
JF
121IdentifierStart [a-zA-Z$_]
122IdentifierPart [a-zA-Z$_0-9]
123
124NonTerminator [^\n]
125BackslashSequence \\{NonTerminator}
126RegularExpressionFirstChar [^\n*\\/]|{BackslashSequence}
127RegularExpressionChar [^\n\\/]|{BackslashSequence}
128RegularExpressionFlags {IdentifierPart}*
129RegularExpressionChars {RegularExpressionChar}*
697d6fd2 130RegularExpressionBody {RegularExpressionFirstChar}{RegularExpressionChars}
63cd45c9 131
691e4717
JF
132@begin E4X
133XMLNameStart [a-zA-Z_:]
134XMLNamePart [a-zA-Z0-9.-_:]
135XMLName {XMLNameStart}{XMLNamePart}*
136@end
137
697d6fd2
JF
138%s Div
139%s RegExp
63cd45c9 140
691e4717
JF
141@begin E4X
142%x XMLContent
143%x XMLTag
144@end
145
e5332278
JF
146%%
147
9205202e 148<RegExp>\/{RegularExpressionBody}\/{RegularExpressionFlags} L C I(literal, RegEx(Y), tk::RegularExpressionLiteral);
63cd45c9 149
66fb559f 150\/\/[^\n]* L
fe123f47
JF
151
152 /* http://ostermiller.org/findcomment.html */
153 /* XXX: unify these two rules using !? */
3ea7eed0 154\/\*!([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/ V() C I(comment, Comment(Y), tk::Comment);
fe123f47 155\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/ V(N)
66fb559f 156
cb02f8ae 157@begin E4X
3ea7eed0
JF
158<RegExp>"<>" L F(tk::LeftRight);
159<XMLContent>"</>" L F(tk::LeftSlashRight);
691e4717 160
3ea7eed0
JF
161<RegExp,XMLContent>\<!\[CDATA\[(\n|[^[]|\[[^[]|\[\[[^>])*]]> V() F(tk::XMLCDATA);
162<RegExp,XMLContent>\<!--(\n|[^-]|-[^-])*--> V() F(tk::XMLComment);
163<RegExp,XMLContent>\<?(\n|[^?]|\?[^>])*?> V() F(tk::XMLPI);
691e4717 164
3ea7eed0
JF
165<XMLTag>"=" L F(tk::Equal);
166<XMLTag>">" L F(tk::Right);
167<XMLTag>"/>" L F(tk::SlashRight);
168<XMLTag>"{" L F(tk::OpenBrace);
691e4717 169
3ea7eed0
JF
170<XMLTag>\"(\n|[^"])*\"|'(\n|[^'])*' V() F(tk::XMLAttributeValue);
171<XMLTag>{XMLName} L F(tk::XMLName);
172<XMLTag>[ \t\r\n] V() F(tk::XMLWhitespace);
db5e2840 173
3ea7eed0
JF
174<XMLContent>"{" L F(tk::OpenBrace);
175<XMLContent>"<" L F(tk::Left);
176<XMLContent>"</" L F(tk::LeftSlash);
691e4717
JF
177@end
178
3ea7eed0 179"..." L C F(tk::PeriodPeriodPeriod);
c8a0500b 180
691e4717 181@begin E4X
3ea7eed0
JF
182"::" L C F(tk::ColonColon);
183".." L C F(tk::PeriodPeriod);
cb02f8ae 184@end
ac9a5ce1 185
313708a9 186@begin E4X ObjectiveC
3ea7eed0 187"@" L C F(tk::At);
313708a9
JF
188@end
189
3ea7eed0
JF
190"&" L C F(tk::Ampersand);
191"&&" L C F(tk::AmpersandAmpersand);
192"&=" L C F(tk::AmpersandEqual);
193"^" L C F(tk::Carrot);
194"^=" L C F(tk::CarrotEqual);
195"=" L C F(tk::Equal);
196"==" L C F(tk::EqualEqual);
197"===" L C F(tk::EqualEqualEqual);
4b2fd91c 198"=>" L C F(tk::EqualRight);
3ea7eed0
JF
199"!" L C F(tk::Exclamation);
200"!=" L C F(tk::ExclamationEqual);
201"!==" L C F(tk::ExclamationEqualEqual);
202"-" L C F(tk::Hyphen);
203"-=" L C F(tk::HyphenEqual);
204"--" L C F(yylval->newline_ ? tk::HyphenHyphen_ : tk::HyphenHyphen);
205"->" L C F(tk::HyphenRight);
206"<" L C F(tk::Left);
207"<=" L C F(tk::LeftEqual);
208"<<" L C F(tk::LeftLeft);
209"<<=" L C F(tk::LeftLeftEqual);
210"%" L C F(tk::Percent);
211"%=" L C F(tk::PercentEqual);
212"." L C F(tk::Period);
213"|" L C F(tk::Pipe);
214"|=" L C F(tk::PipeEqual);
215"||" L C F(tk::PipePipe);
216"+" L C F(tk::Plus);
217"+=" L C F(tk::PlusEqual);
218"++" L C F(yylval->newline_ ? tk::PlusPlus_ : tk::PlusPlus);
219">" L C F(tk::Right);
220">=" L C F(tk::RightEqual);
221">>" L C F(tk::RightRight);
222">>=" L C F(tk::RightRightEqual);
223">>>" L C F(tk::RightRightRight);
224">>>=" L C F(tk::RightRightRightEqual);
225"*" L C F(tk::Star);
226"*=" L C F(tk::StarEqual);
227"~" L C F(tk::Tilde);
228
229<Div>"/" L C F(tk::Slash);
230<Div>"/=" L C F(tk::SlashEqual);
231
232":" L C F(tk::Colon);
233"," L C F(tk::Comma);
234"?" L C F(tk::Question);
235";" L C F(tk::SemiColon);
236
237"(" L C F(tk::OpenParen);
238")" L C F(tk::CloseParen);
239
c34648c0 240"{" L C F(yyextra->nobrace_ ? tk::OpenBrace__ : yylval->newline_ ? tk::OpenBrace_ : tk::OpenBrace);
3ea7eed0
JF
241"}" L C F(tk::CloseBrace);
242
243"[" L C F(tk::OpenBracket);
244"]" L C F(tk::CloseBracket);
5befe15e 245
1ba6903e 246@begin Java
3ea7eed0 247"@class" L C F(tk::AtClass);
1ba6903e
JF
248@end
249
cb02f8ae 250@begin ObjectiveC
3ea7eed0 251"@end" L C F(tk::AtEnd);
066da9f6 252"@implementation" L C F(tk::AtImplementation);
3ea7eed0
JF
253"@import" L C F(tk::AtImport);
254"@selector" L C F(tk::AtSelector);
cb02f8ae 255@end
d35a3b07 256
3ea7eed0
JF
257"false" L C I(false, False(), tk::False);
258"null" L C I(null, Null(), tk::Null);
259"true" L C I(true, True(), tk::True);
260
261"break" L R I(word, Word("break"), tk::Break);
262"case" L C I(word, Word("case"), tk::Case);
263"catch" L C I(word, Word("catch"), tk::Catch);
264"continue" L R I(word, Word("continue"), tk::Continue);
265"default" L C I(word, Word("default"), tk::Default);
266"delete" L C I(word, Word("delete"), tk::Delete);
267"do" L C I(word, Word("do"), tk::Do);
268"else" L C I(word, Word("else"), tk::Else);
269"finally" L C I(word, Word("finally"), tk::Finally);
270"for" L C I(word, Word("for"), tk::For);
066da9f6 271"function" L C I(word, Word("function"), tk::Function);
3ea7eed0
JF
272"if" L C I(word, Word("if"), tk::If);
273"in" L C I(word, Word("in"), yyextra->in_.top() ? tk::In_ : tk::In);
274"instanceof" L C I(word, Word("instanceof"), tk::InstanceOf);
275"new" L C I(word, Word("new"), tk::New);
276"return" L R I(word, Word("return"), tk::Return);
277"switch" L C I(word, Word("switch"), tk::Switch);
278"this" L C I(this, This(), tk::This);
279"throw" L R I(word, Word("throw"), tk::Throw);
280"try" L C I(word, Word("try"), tk::Try);
281"typeof" L C I(word, Word("typeof"), tk::TypeOf);
282"var" L C I(word, Word("var"), tk::Var);
283"void" L C I(word, Word("void"), tk::Void);
284"while" L C I(word, Word("while"), tk::While);
285"with" L C I(word, Word("with"), tk::With);
286
287"debugger" L C I(word, Word("debugger"), tk::Debugger);
288
289"const" L C I(word, Word("const"), tk::Const);
290
291"class" L C I(word, Word("class"), tk::Class);
292"enum" L C I(word, Word("enum"), tk::Enum);
293"export" L C I(word, Word("export"), tk::Export);
294"extends" L C I(word, Word("extends"), tk::Extends);
295"import" L C I(word, Word("import"), tk::Import);
296"super" L C I(word, Word("super"), tk::Super);
297
298"implements" L C I(identifier, Identifier("implements"), tk::Implements);
299"interface" L C I(identifier, Identifier("interface"), tk::Interface);
300"package" L C I(identifier, Identifier("package"), tk::Package);
301"private" L C I(identifier, Identifier("private"), tk::Private);
302"protected" L C I(identifier, Identifier("protected"), tk::Protected);
303"public" L C I(identifier, Identifier("public"), tk::Public);
304"static" L C I(identifier, Identifier("static"), tk::Static);
305
306"abstract" L C I(identifier, Identifier("abstract"), tk::Abstract);
307"boolean" L C I(identifier, Identifier("boolean"), tk::Boolean);
308"byte" L C I(identifier, Identifier("byte"), tk::Byte);
309"char" L C I(identifier, Identifier("char"), tk::Char);
310"double" L C I(identifier, Identifier("double"), tk::Double);
311"final" L C I(identifier, Identifier("final"), tk::Final);
312"float" L C I(identifier, Identifier("float"), tk::Float);
313"goto" L C I(identifier, Identifier("goto"), tk::Goto);
314"int" L C I(identifier, Identifier("int"), tk::Int);
315"long" L C I(identifier, Identifier("long"), tk::Long);
316"native" L C I(identifier, Identifier("native"), tk::Native);
317"short" L C I(identifier, Identifier("short"), tk::Short);
318"synchronized" L C I(identifier, Identifier("synchronized"), tk::Synchronized);
319"throws" L C I(identifier, Identifier("throws"), tk::Throws);
320"transient" L C I(identifier, Identifier("transient"), tk::Transient);
321"volatile" L C I(identifier, Identifier("volatile"), tk::Volatile);
322
323"let" L C I(identifier, Identifier("let"), tk::Let);
324"yield" L C I(identifier, Identifier("yield"), tk::Yield);
325
326"each" L C I(identifier, Identifier("each"), tk::Each);
480c8834 327"of" L C I(identifier, Identifier("of"), tk::Of);
5d646fb5 328
691e4717 329@begin E4X
3ea7eed0
JF
330"namespace" L C I(identifier, Identifier("namespace"), tk::Namespace);
331"xml" L C I(identifier, Identifier("xml"), tk::XML);
691e4717
JF
332@end
333
3ea7eed0 334{IdentifierStart}{IdentifierPart}* L C I(identifier, Identifier(Y), tk::Identifier_);
5d646fb5 335
3ea7eed0 336(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? L C I(number, Number(strtod(yytext, NULL)), tk::NumericLiteral);
5d646fb5 337
3ea7eed0
JF
3380[xX][0-9a-fA-F]+ L C I(number, Number(strtoull(yytext + 2, NULL, 16)), tk::NumericLiteral);
3390[0-7]+ L C I(number, Number(strtoull(yytext + 1, NULL, 8)), tk::NumericLiteral);
3400[bB][0-1]+ L C I(number, Number(strtoull(yytext + 2, NULL, 2)), tk::NumericLiteral);
5befe15e 341
931b816a 342\"([^"\\\n]|{Escape})*\"|'([^'\\\n]|{Escape})*' L C {
2eb8215d 343 char *value(A char[yyleng]);
931b816a
JF
344 char *local(value);
345
66f8d960 346 for (yy_size_t i(1), e(yyleng - 1); i != e; ++i) {
931b816a
JF
347 char next(yytext[i]);
348
349 if (yytext[i] == '\\')
350 switch (next = yytext[++i]) {
367eebb1 351 case '\n': continue;
931b816a
JF
352 case '\\': next = '\\'; break;
353 case '\'': next = '\''; break;
354 case '"': next = '"'; break;
355 case 'b': next = '\b'; break;
356 case 'f': next = '\f'; break;
357 case 'n': next = '\n'; break;
358 case 'r': next = '\r'; break;
359 case 't': next = '\t'; break;
360 case 'v': next = '\v'; break;
361 case '0': next = '\0'; break;
362
363 case 'x':
364 next = H(yytext[i + 1]) << 4 | H(yytext[i + 2]);
365 i += 2;
366 break;
367 }
368
369 *local++ = next;
370 }
371
372 *local = '\0';
3ea7eed0 373 I(string, String(value, local - value), tk::StringLiteral);
931b816a 374}
5befe15e 375
3ea7eed0 376\r?\n|\r|\xe2\x80[\xa8\xa9] yylloc->end.lines(); yylloc->step(); N
5befe15e
JF
377
378[ \t] L
7e5391fd 379
3ea7eed0 380<<EOF>> if (yyextra->auto_) { yyextra->auto_ = false; F(tk::AutoComplete); } L yyterminate();
94d55b5c 381
48e3be8a 382. L {
94d55b5c
JF
383 CYDriver::Error error;
384 error.location_ = *yylloc;
385 error.message_ = "syntax error, unknown token";
386 yyextra->errors_.push_back(error);
387 yyterminate();
388}
924f67b2
JF
389
390%%
391
5999c315 392void CYDriver::ScannerInit() {
924f67b2
JF
393 cylex_init(&scanner_);
394 cyset_extra(this, scanner_);
395}
396
5999c315 397void CYDriver::ScannerDestroy() {
924f67b2
JF
398 cylex_destroy(scanner_);
399}
63cd45c9 400
691e4717
JF
401CYDriver::Condition CYDriver::GetCondition() {
402 switch (yy_top_state(scanner_)) {
403 case RegExp:
404 return RegExpCondition;
405@begin E4X
406 case XMLContent:
407 return XMLContentCondition;
408 case XMLTag:
409 return XMLTagCondition;
410@end
411 default:
412 _assert(false);
413 }
414}
415
416void CYDriver::SetCondition(Condition condition) {
63cd45c9
JF
417 struct yyguts_t *yyg(reinterpret_cast<struct yyguts_t *>(scanner_));
418
419 switch (condition) {
697d6fd2
JF
420 case RegExpCondition:
421 BEGIN(RegExp);
63cd45c9 422 break;
691e4717
JF
423@begin E4X
424 case XMLContentCondition:
425 BEGIN(XMLContent);
426 break;
427 case XMLTagCondition:
428 BEGIN(XMLTag);
429 break;
430@end
63cd45c9
JF
431 default:
432 _assert(false);
433 }
434}
691e4717
JF
435
436void CYDriver::PushCondition(Condition condition) {
437 switch (condition) {
438 case RegExpCondition:
439 yy_push_state(RegExp, scanner_);
440 break;
441@begin E4X
442 case XMLContentCondition:
443 yy_push_state(XMLContent, scanner_);
444 break;
445 case XMLTagCondition:
446 yy_push_state(XMLTag, scanner_);
447 break;
448@end
449 default:
450 _assert(false);
451 }
452}
453
454void CYDriver::PopCondition() {
455 yy_pop_state(scanner_);
456}