X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/693d501bb3c190a047d02b897f84917ccb623db6..930aa21ba5c097f9ee6ebfc418c321de0729e076:/Cycript.l?ds=inline diff --git a/Cycript.l b/Cycript.l index 6e2a780..43c9285 100644 --- a/Cycript.l +++ b/Cycript.l @@ -8,7 +8,44 @@ typedef cy::parser::token tk; #define T yylval->newline_ = yyextra->state_ == CYNewLine; #define C T yyextra->state_ = CYClear; #define R T yyextra->state_ = CYRestricted; -#define N if (yyextra->state_ != CYNewLine) { bool restricted(yyextra->state_ == CYRestricted); if (restricted) { yyextra->state_ = CYClear; return tk::NewLine; } else yyextra->state_ = CYNewLine; } + +#define N \ + if (yyextra->state_ != CYNewLine) { \ + bool restricted(yyextra->state_ == CYRestricted); \ + if (restricted) { \ + yyextra->state_ = CYClear; \ + return tk::NewLine; \ + } else \ + yyextra->state_ = CYNewLine; \ + } + +#define L { \ + yylloc->step(); \ + yylloc->columns(yyleng); \ +} + +int H(char c) { + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +#define YY_INPUT(data, value, size) { \ + if (yyextra->size_ == 0) \ + value = YY_NULL; \ + else { \ + size_t copy(std::min(size, yyextra->size_)); \ + memcpy(data, yyextra->data_, copy); \ + yyextra->data_ += copy; \ + yyextra->size_ -= copy; \ + value = copy; \ + } \ +} + %} %option prefix="cy" @@ -21,109 +58,186 @@ typedef cy::parser::token tk; %option reentrant Exponent [eE][+-]?[0-9]+ -Escape \\['"\\bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} +Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4} %% \/\/[^\n]* ; \/\*(\n|[^\*]|\*[^/])\*\/ if (memchr(yytext, '\n', yyleng) != NULL) N // XXX: supposedly I will be screwed on very very long multi-line comments and need to replace this with a manual lexer. http://websrv.cs.fsu.edu/~engelen/courses/COP5621/Pr2.pdf ; XXX: this rule doesn't work anyway, fucking A :( -"&" C return tk::Ampersand; -"&&" C return tk::AmpersandAmpersand; -"&=" C return tk::AmpersandEqual; -"^" C return tk::Carrot; -"^=" C return tk::CarrotEqual; -"=" C return tk::Equal; -"==" C return tk::EqualEqual; -"===" C return tk::EqualEqualEqual; -"!" C return tk::Exclamation; -"!=" C return tk::ExclamationEqual; -"!==" C return tk::ExclamationEqualEqual; -"-" C return tk::Hyphen; -"-=" C return tk::HyphenEqual; -"--" C return yylval->newline_ ? tk::HyphenHyphen_ : tk::HyphenHyphen; -"->" C return tk::HyphenRight; -"<" C return tk::Left; -"<=" C return tk::LeftEqual; -"<<" C return tk::LeftLeft; -"<<=" C return tk::LeftLeftEqual; -"%" C return tk::Percent; -"%=" C return tk::PercentEqual; -"." C return tk::Period; -"|" C return tk::Pipe; -"|=" C return tk::PipeEqual; -"||" C return tk::PipePipe; -"+" C return tk::Plus; -"+=" C return tk::PlusEqual; -"++" C return yylval->newline_ ? tk::PlusPlus_ : tk::PlusPlus; -">" C return tk::Right; -">=" C return tk::RightEqual; -">>" C return tk::RightRight; -">>=" C return tk::RightRightEqual; -">>>" C return tk::RightRightRight; -">>>=" C return tk::RightRightRightEqual; -"/" C return tk::Slash; -"/=" C return tk::SlashEqual; -"*" C return tk::Star; -"*=" C return tk::StarEqual; -"~" C return tk::Tilde; - -":" C return tk::Colon; -"," C return tk::Comma; -"?" C return tk::Question; -";" C return tk::SemiColon; - -"(" C return tk::OpenParen; -")" C return tk::CloseParen; - -"{" C return tk::OpenBrace; -"}" C return tk::CloseBrace; - -"[" C return tk::OpenBracket; -"]" C return tk::CloseBracket; - -"break" R yylval->word_ = new CYWord("break"); return tk::Break; -"case" C yylval->word_ = new CYWord("case"); return tk::Case; -"catch" C yylval->word_ = new CYWord("catch"); return tk::Catch; -"continue" R yylval->word_ = new CYWord("continue"); return tk::Continue; -"default" C yylval->word_ = new CYWord("default"); return tk::Default; -"delete" C yylval->word_ = new CYWord("delete"); return tk::Delete; -"do" C yylval->word_ = new CYWord("do"); return tk::Do; -"else" C yylval->word_ = new CYWord("else"); return tk::Else; -"false" C yylval->false_ = new CYFalse(); return tk::False; -"finally" C yylval->word_ = new CYWord("finally"); return tk::Finally; -"for" C yylval->word_ = new CYWord("for"); return tk::For; -"function" C yylval->word_ = new CYWord("function"); return tk::Function; -"if" C yylval->word_ = new CYWord("if"); return tk::If; -"in" C yylval->word_ = new CYWord("in"); return tk::In; -"instanceof" C yylval->word_ = new CYWord("instanceof"); return tk::InstanceOf; -"new" C yylval->word_ = new CYWord("new"); return tk::New; -"null" C yylval->null_ = new CYNull(); return tk::Null; -"return" R yylval->word_ = new CYWord("return"); return tk::Return; -"switch" C yylval->word_ = new CYWord("switch"); return tk::Switch; -"this" C yylval->this_ = new CYThis(); return tk::This; -"throw" R yylval->word_ = new CYWord("throw"); return tk::Throw; -"true" C yylval->true_ = new CYTrue(); return tk::True; -"try" C yylval->word_ = new CYWord("try"); return tk::Try; -"typeof" C yylval->word_ = new CYWord("typeof"); return tk::TypeOf; -"var" C yylval->word_ = new CYWord("var"); return tk::Var; -"void" C yylval->word_ = new CYWord("void"); return tk::Void; -"while" C yylval->word_ = new CYWord("while"); return tk::While; -"with" C yylval->word_ = new CYWord("with"); return tk::With; - -[a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); C return tk::Identifier; - -(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? yylval->number_ = new CYNumber(strtod(yytext, NULL)); C return tk::NumericLiteral; - -0[xX][0-9a-fA-F]+ C yylval->number_ = new CYNumber(strtoull(yytext + 2, NULL, 16)); return tk::NumericLiteral; - -0[bB][0-1]+ C yylval->number_ = new CYNumber(strtoull(yytext + 2, NULL, 2)); return tk::NumericLiteral; - -\"([^"\\\n]|{Escape})*\" C return tk::StringLiteral; -'([^'\\\n]|{Escape})*' C return tk::StringLiteral; - -\n N -[ \t] ; +"&" L C return tk::Ampersand; +"&&" L C return tk::AmpersandAmpersand; +"&=" L C return tk::AmpersandEqual; +"^" L C return tk::Carrot; +"^=" L C return tk::CarrotEqual; +"=" L C return tk::Equal; +"==" L C return tk::EqualEqual; +"===" L C return tk::EqualEqualEqual; +"!" L C return tk::Exclamation; +"!=" L C return tk::ExclamationEqual; +"!==" L C return tk::ExclamationEqualEqual; +"-" L C return tk::Hyphen; +"-=" L C return tk::HyphenEqual; +"--" L C return yylval->newline_ ? tk::HyphenHyphen_ : tk::HyphenHyphen; +"->" L C return tk::HyphenRight; +"<" L C return tk::Left; +"<=" L C return tk::LeftEqual; +"<<" L C return tk::LeftLeft; +"<<=" L C return tk::LeftLeftEqual; +"%" L C return tk::Percent; +"%=" L C return tk::PercentEqual; +"." L C return tk::Period; +"|" L C return tk::Pipe; +"|=" L C return tk::PipeEqual; +"||" L C return tk::PipePipe; +"+" L C return tk::Plus; +"+=" L C return tk::PlusEqual; +"++" L C return yylval->newline_ ? tk::PlusPlus_ : tk::PlusPlus; +">" L C return tk::Right; +">=" L C return tk::RightEqual; +">>" L C return tk::RightRight; +">>=" L C return tk::RightRightEqual; +">>>" L C return tk::RightRightRight; +">>>=" L C return tk::RightRightRightEqual; +"/" L C return tk::Slash; +"/=" L C return tk::SlashEqual; +"*" L C return tk::Star; +"*=" L C return tk::StarEqual; +"~" L C return tk::Tilde; + +":" L C return tk::Colon; +"," L C return tk::Comma; +"?" L C return tk::Question; +";" L C return tk::SemiColon; + +"(" L C return tk::OpenParen; +")" L C return tk::CloseParen; + +"{" L C return tk::OpenBrace; +"}" L C return tk::CloseBrace; + +"[" L C return tk::OpenBracket; +"]" L C return tk::CloseBracket; + +"@class" L C return tk::AtClass; +"@end" L C return tk::AtEnd; +"@selector" L C return tk::AtSelector; + +"break" L R yylval->word_ = new CYWord("break"); return tk::Break; +"case" L C yylval->word_ = new CYWord("case"); return tk::Case; +"catch" L C yylval->word_ = new CYWord("catch"); return tk::Catch; +"continue" L R yylval->word_ = new CYWord("continue"); return tk::Continue; +"default" L C yylval->word_ = new CYWord("default"); return tk::Default; +"delete" L C yylval->word_ = new CYWord("delete"); return tk::Delete; +"do" L C yylval->word_ = new CYWord("do"); return tk::Do; +"else" L C yylval->word_ = new CYWord("else"); return tk::Else; +"false" L C yylval->false_ = new CYFalse(); return tk::False; +"finally" L C yylval->word_ = new CYWord("finally"); return tk::Finally; +"for" L C yylval->word_ = new CYWord("for"); return tk::For; +"function" L C yylval->word_ = new CYWord("function"); return tk::Function; +"if" L C yylval->word_ = new CYWord("if"); return tk::If; +"in" L C yylval->word_ = new CYWord("in"); return tk::In; +"instanceof" L C yylval->word_ = new CYWord("instanceof"); return tk::InstanceOf; +"new" L C yylval->word_ = new CYWord("new"); return tk::New; +"null" L C yylval->null_ = new CYNull(); return tk::Null; +"return" L R yylval->word_ = new CYWord("return"); return tk::Return; +"switch" L C yylval->word_ = new CYWord("switch"); return tk::Switch; +"this" L C yylval->this_ = new CYThis(); return tk::This; +"throw" L R yylval->word_ = new CYWord("throw"); return tk::Throw; +"true" L C yylval->true_ = new CYTrue(); return tk::True; +"try" L C yylval->word_ = new CYWord("try"); return tk::Try; +"typeof" L C yylval->word_ = new CYWord("typeof"); return tk::TypeOf; +"var" L C yylval->word_ = new CYWord("var"); return tk::Var; +"void" L C yylval->word_ = new CYWord("void"); return tk::Void; +"while" L C yylval->word_ = new CYWord("while"); return tk::While; +"with" L C yylval->word_ = new CYWord("with"); return tk::With; + +"abstract" L C yylval->word_ = new CYWord("abstract"); return tk::Abstract; +"boolean" L C yylval->word_ = new CYWord("boolean"); return tk::Boolean; +"byte" L C yylval->word_ = new CYWord("byte"); return tk::Byte; +"char" L C yylval->word_ = new CYWord("char"); return tk::Char; +"class" L C yylval->word_ = new CYWord("class"); return tk::Class; +"const" L C yylval->word_ = new CYWord("const"); return tk::Const; +"debugger" L C yylval->word_ = new CYWord("debugger"); return tk::Debugger; +"double" L C yylval->word_ = new CYWord("double"); return tk::Double; +"enum" L C yylval->word_ = new CYWord("enum"); return tk::Enum; +"export" L C yylval->word_ = new CYWord("export"); return tk::Export; +"extends" L C yylval->word_ = new CYWord("extends"); return tk::Extends; +"final" L C yylval->word_ = new CYWord("final"); return tk::Final; +"float" L C yylval->word_ = new CYWord("float"); return tk::Float; +"goto" L C yylval->word_ = new CYWord("goto"); return tk::Goto; +"implements" L C yylval->word_ = new CYWord("implements"); return tk::Implements; +"import" L C yylval->word_ = new CYWord("import"); return tk::Import; +"int" L C yylval->word_ = new CYWord("int"); return tk::Int; +"interface" L C yylval->word_ = new CYWord("interface"); return tk::Interface; +"long" L C yylval->word_ = new CYWord("long"); return tk::Long; +"native" L C yylval->word_ = new CYWord("native"); return tk::Native; +"package" L C yylval->word_ = new CYWord("package"); return tk::Package; +"private" L C yylval->word_ = new CYWord("private"); return tk::Private; +"protected" L C yylval->word_ = new CYWord("protected"); return tk::Protected; +"public" L C yylval->word_ = new CYWord("public"); return tk::Public; +"short" L C yylval->word_ = new CYWord("short"); return tk::Short; +"static" L C yylval->word_ = new CYWord("static"); return tk::Static; +"super" L C yylval->word_ = new CYWord("super"); return tk::Super; +"synchronized" L C yylval->word_ = new CYWord("synchronized"); return tk::Synchronized; +"throws" L C yylval->word_ = new CYWord("throws"); return tk::Throws; +"transient" L C yylval->word_ = new CYWord("transient"); return tk::Transient; +"volatile" L C yylval->word_ = new CYWord("volatile"); return tk::Volatile; + +[a-zA-Z$_][a-zA-Z$_0-9]* yylval->identifier_ = new CYIdentifier(apr_pstrmemdup(yyextra->pool_, yytext, yyleng)); L C return tk::Identifier; + +(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?){Exponent}? yylval->number_ = new CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral; + +0[xX][0-9a-fA-F]+ L C yylval->number_ = new CYNumber(strtoull(yytext + 2, NULL, 16)); return tk::NumericLiteral; + +0[bB][0-1]+ L C yylval->number_ = new CYNumber(strtoull(yytext + 2, NULL, 2)); return tk::NumericLiteral; + +\"([^"\\\n]|{Escape})*\"|'([^'\\\n]|{Escape})*' L C { + char *value(reinterpret_cast(apr_palloc(yyextra->pool_, yyleng))); + char *local(value); + + for (int i(1); i != yyleng - 1; ++i) { + char next(yytext[i]); + + if (yytext[i] == '\\') + switch (next = yytext[++i]) { + case '\\': next = '\\'; break; + case '\'': next = '\''; break; + case '"': next = '"'; break; + case 'b': next = '\b'; break; + case 'f': next = '\f'; break; + case 'n': next = '\n'; break; + case 'r': next = '\r'; break; + case 't': next = '\t'; break; + case 'v': next = '\v'; break; + case '0': next = '\0'; break; + + case 'x': + next = H(yytext[i + 1]) << 4 | H(yytext[i + 2]); + i += 2; + break; + } + + *local++ = next; + } + + *local = '\0'; + yylval->string_ = new CYString(value, local - value); + return tk::StringLiteral; +} + +\n yylloc->end.lines(); yylloc->step(); N + +[ \t] L +<> L yyterminate(); + +. { + CYDriver::Error error; + error.location_ = *yylloc; + error.message_ = "syntax error, unknown token"; + yyextra->errors_.push_back(error); + yyterminate(); +} %%