From: Jay Freeman (saurik) Date: Sun, 25 Oct 2009 19:35:14 +0000 (+0000) Subject: Began work on implementing E4X. X-Git-Tag: v0.9.432~255 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/cb02f8aec13cb7ffea9631c401293e80447e6ae7?hp=82149e4b02351e37499d65e3e2aa5942b556d8a7 Began work on implementing E4X. --- diff --git a/Cycript.l b/Cycript.l deleted file mode 100644 index c2142bd..0000000 --- a/Cycript.l +++ /dev/null @@ -1,333 +0,0 @@ -%{ -#define YYLTYPE cy::location -#include "Cycript.tab.hh" -typedef cy::parser::token tk; - -#define YY_EXTRA_TYPE CYDriver * - -#define T yylval->newline_ = yyextra->state_ == CYNewLine; -#define C T yyextra->state_ = CYClear; -#define R T yyextra->state_ = CYRestricted; - -#define E(prefix) L C BEGIN(INITIAL); { \ - char *value(reinterpret_cast(apr_palloc(yyextra->pool_, yyleng + sizeof(prefix)))); \ - memcpy(value, prefix, sizeof(prefix) - 1); \ - memcpy(value + sizeof(prefix) - 1, yytext, yyleng); \ - value[yyleng + sizeof(prefix) - 1] = '\0'; \ - yylval->literal_ = new(yyextra->pool_) CYRegEx(value); \ - return tk::RegularExpressionLiteral; \ -} - -#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->file_ != NULL) { \ - size_t copy(fread(data, 1, size, yyextra->file_)); \ - value = copy == 0 ? YY_NULL : copy; \ - } else 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" -%option bison-bridge -%option bison-locations -%option noyywrap -%option yylineno -%option nounput -%option interactive -%option reentrant - -Exponent [eE][+-]?[0-9]+ -Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n - -IdentifierStart [a-zA-Z$_] -IdentifierPart [a-zA-Z$_0-9] - -NonTerminator [^\n] -BackslashSequence \\{NonTerminator} -RegularExpressionFirstChar [^\n*\\/]|{BackslashSequence} -RegularExpressionChar [^\n\\/]|{BackslashSequence} -RegularExpressionFlags {IdentifierPart}* -RegularExpressionChars {RegularExpressionChar}* -RegularExpressionBody_ {RegularExpressionChars} -RegularExpressionBody {RegularExpressionFirstChar}{RegularExpressionBody_} - -RegularExpressionEnd_ \/{RegularExpressionFlags} -RegularExpressionRest_ {RegularExpressionBody_}{RegularExpressionEnd_} -RegularExpressionStart_ {RegularExpressionBody}{RegularExpressionEnd_} - -%x res -%x rer - -%% - -{RegularExpressionStart_} E("/") -{RegularExpressionRest_} E("/=") - -\/\/[^\n]* L - -\/\*(\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 - - if (const char *nl = reinterpret_cast(memchr(yytext, '\n', yyleng))) { - unsigned lines(0); - size_t left; - - do { - ++lines; - left = yyleng - (nl - yytext) - 1; - nl = reinterpret_cast(memchr(nl + 1, '\n', left)); - } while (nl != NULL); - - yylloc->end.lines(lines); - yylloc->end.columns(left); - yylloc->step(); - - N - } else L -} - -"@" L C return tk::At; - -"&" 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; - -"false" L C yylval->false_ = new(yyextra->pool_) CYFalse(); return tk::False; -"null" L C yylval->null_ = new(yyextra->pool_) CYNull(); return tk::Null; -"true" L C yylval->true_ = new(yyextra->pool_) CYTrue(); return tk::True; - -"break" L R yylval->word_ = new(yyextra->pool_) CYWord("break"); return tk::Break; -"case" L C yylval->word_ = new(yyextra->pool_) CYWord("case"); return tk::Case; -"catch" L C yylval->word_ = new(yyextra->pool_) CYWord("catch"); return tk::Catch; -"continue" L R yylval->word_ = new(yyextra->pool_) CYWord("continue"); return tk::Continue; -"default" L C yylval->word_ = new(yyextra->pool_) CYWord("default"); return tk::Default; -"delete" L C yylval->word_ = new(yyextra->pool_) CYWord("delete"); return tk::Delete; -"do" L C yylval->word_ = new(yyextra->pool_) CYWord("do"); return tk::Do; -"else" L C yylval->word_ = new(yyextra->pool_) CYWord("else"); return tk::Else; -"finally" L C yylval->word_ = new(yyextra->pool_) CYWord("finally"); return tk::Finally; -"for" L C yylval->word_ = new(yyextra->pool_) CYWord("for"); return tk::For; -"function" L C yylval->word_ = new(yyextra->pool_) CYWord("function"); return tk::Function; -"if" L C yylval->word_ = new(yyextra->pool_) CYWord("if"); return tk::If; -"in" L C yylval->word_ = new(yyextra->pool_) CYWord("in"); return tk::In; -"instanceof" L C yylval->word_ = new(yyextra->pool_) CYWord("instanceof"); return tk::InstanceOf; -"new" L C yylval->word_ = new(yyextra->pool_) CYWord("new"); return tk::New; -"return" L R yylval->word_ = new(yyextra->pool_) CYWord("return"); return tk::Return; -"switch" L C yylval->word_ = new(yyextra->pool_) CYWord("switch"); return tk::Switch; -"this" L C yylval->this_ = new(yyextra->pool_) CYThis(); return tk::This; -"throw" L R yylval->word_ = new(yyextra->pool_) CYWord("throw"); return tk::Throw; -"try" L C yylval->word_ = new(yyextra->pool_) CYWord("try"); return tk::Try; -"typeof" L C yylval->word_ = new(yyextra->pool_) CYWord("typeof"); return tk::TypeOf; -"var" L C yylval->word_ = new(yyextra->pool_) CYWord("var"); return tk::Var; -"void" L C yylval->word_ = new(yyextra->pool_) CYWord("void"); return tk::Void; -"while" L C yylval->word_ = new(yyextra->pool_) CYWord("while"); return tk::While; -"with" L C yylval->word_ = new(yyextra->pool_) CYWord("with"); return tk::With; - -"debugger" L C yylval->word_ = new(yyextra->pool_) CYWord("debugger"); return tk::Debugger; - -"const" L C yylval->word_ = new(yyextra->pool_) CYWord("const"); return tk::Const; - -"class" L C yylval->word_ = new(yyextra->pool_) CYWord("class"); return tk::Class; -"enum" L C yylval->word_ = new(yyextra->pool_) CYWord("enum"); return tk::Enum; -"export" L C yylval->word_ = new(yyextra->pool_) CYWord("export"); return tk::Export; -"extends" L C yylval->word_ = new(yyextra->pool_) CYWord("extends"); return tk::Extends; -"import" L C yylval->word_ = new(yyextra->pool_) CYWord("import"); return tk::Import; -"super" L C yylval->word_ = new(yyextra->pool_) CYWord("super"); return tk::Super; - -"implements" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("implements"); return tk::Implements; -"interface" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("interface"); return tk::Interface; -"package" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("package"); return tk::Package; -"private" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("private"); return tk::Private; -"protected" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("protected"); return tk::Protected; -"public" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("public"); return tk::Public; -"static" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("static"); return tk::Static; - -"abstract" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("abstract"); return tk::Abstract; -"boolean" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("boolean"); return tk::Boolean; -"byte" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("byte"); return tk::Byte; -"char" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("char"); return tk::Char; -"double" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("double"); return tk::Double; -"final" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("final"); return tk::Final; -"float" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("float"); return tk::Float; -"goto" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("goto"); return tk::Goto; -"int" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("int"); return tk::Int; -"long" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("long"); return tk::Long; -"native" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("native"); return tk::Native; -"short" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("short"); return tk::Short; -"synchronized" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("synchronized"); return tk::Synchronized; -"throws" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("throws"); return tk::Throws; -"transient" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("transient"); return tk::Transient; -"volatile" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("volatile"); return tk::Volatile; - -"let" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("let"); return tk::Let; -"yield" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("yield"); return tk::Yield; - -"each" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("each"); return tk::Each; - -{IdentifierStart}{IdentifierPart}* yylval->identifier_ = new(yyextra->pool_) 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(yyextra->pool_) CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral; - -0[xX][0-9a-fA-F]+ L C yylval->number_ = new(yyextra->pool_) CYNumber(strtoull(yytext + 2, NULL, 16)); return tk::NumericLiteral; - -0[bB][0-1]+ L C yylval->number_ = new(yyextra->pool_) 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 '\n': continue; - 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(yyextra->pool_) CYString(value, local - value); - return tk::StringLiteral; -} - -\r?\n yylloc->end.lines(); yylloc->step(); N - -[ \t] L -<> L yyterminate(); - -. L { - CYDriver::Error error; - error.location_ = *yylloc; - error.message_ = "syntax error, unknown token"; - yyextra->errors_.push_back(error); - yyterminate(); -} - -%% - -void CYDriver::ScannerInit() { - cylex_init(&scanner_); - cyset_extra(this, scanner_); -} - -void CYDriver::ScannerDestroy() { - cylex_destroy(scanner_); -} - -void CYDriver::SetCondition(Condition condition) { - struct yyguts_t *yyg(reinterpret_cast(scanner_)); - - switch (condition) { - case RegExStart: - BEGIN(res); - break; - case RegExRest: - BEGIN(rer); - break; - default: - _assert(false); - } -} diff --git a/Cycript.l.in b/Cycript.l.in new file mode 100644 index 0000000..f3201bb --- /dev/null +++ b/Cycript.l.in @@ -0,0 +1,350 @@ +%{ +// 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 + +#define YYLTYPE cy::location +#include "Cycript.tab.hh" +typedef cy::parser::token tk; + +#define YY_EXTRA_TYPE CYDriver * + +#define T yylval->newline_ = yyextra->state_ == CYNewLine; +#define C T yyextra->state_ = CYClear; +#define R T yyextra->state_ = CYRestricted; + +#define E(prefix) L C BEGIN(INITIAL); { \ + char *value(reinterpret_cast(apr_palloc(yyextra->pool_, yyleng + sizeof(prefix)))); \ + memcpy(value, prefix, sizeof(prefix) - 1); \ + memcpy(value + sizeof(prefix) - 1, yytext, yyleng); \ + value[yyleng + sizeof(prefix) - 1] = '\0'; \ + yylval->literal_ = new(yyextra->pool_) CYRegEx(value); \ + return tk::RegularExpressionLiteral; \ +} + +#define N \ + if (yyextra->state_ != CYNewLine) { \ + bool restricted(yyextra->state_ == CYRestricted); \ + if (restricted) { \ + yyextra->state_ = CYClear; \ + return tk::NewLine; \ + } else \ + yyextra->state_ = CYNewLine; \ + } + +#define M { \ + if (const char *nl = reinterpret_cast(memchr(yytext, '\n', yyleng))) { \ + unsigned lines(0); \ + size_t left; \ + do { \ + ++lines; \ + left = yyleng - (nl - yytext) - 1; \ + nl = reinterpret_cast(memchr(nl + 1, '\n', left)); \ + } while (nl != NULL); \ + yylloc->end.lines(lines); \ + yylloc->end.columns(left); \ + yylloc->step(); \ + N \ + } else L \ +} + +#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->file_ != NULL) { \ + size_t copy(fread(data, 1, size, yyextra->file_)); \ + value = copy == 0 ? YY_NULL : copy; \ + } else 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" +%option bison-bridge +%option bison-locations +%option noyywrap +%option yylineno +%option nounput +%option interactive +%option reentrant + +Exponent [eE][+-]?[0-9]+ +Escape \\[\\'"bfnrtv]|\\0|\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}|\\\n + +IdentifierStart [a-zA-Z$_] +IdentifierPart [a-zA-Z$_0-9] + +NonTerminator [^\n] +BackslashSequence \\{NonTerminator} +RegularExpressionFirstChar [^\n*\\/]|{BackslashSequence} +RegularExpressionChar [^\n\\/]|{BackslashSequence} +RegularExpressionFlags {IdentifierPart}* +RegularExpressionChars {RegularExpressionChar}* +RegularExpressionBody_ {RegularExpressionChars} +RegularExpressionBody {RegularExpressionFirstChar}{RegularExpressionBody_} + +RegularExpressionEnd_ \/{RegularExpressionFlags} +RegularExpressionRest_ {RegularExpressionBody_}{RegularExpressionEnd_} +RegularExpressionStart_ {RegularExpressionBody}{RegularExpressionEnd_} + +%x RegExp +%x RegExpSlash +%x RegExpSlashEqual +%x RegExpSlashRight + +%% + +{RegularExpressionStart_} E("/") +{RegularExpressionRest_} E("/=") +{RegularExpressionRest_} E("/>") + +\/\/[^\n]* L +\/\*(\n|[^\*]|\*[^/])*\*\/ M + +@begin E4X +\ +\])*]]> +\])*?> + +"@" L C return tk::At; +"::" L C return tk::ColonColon; +"<>" L C return tk::LeftRight; +"" L C return tk::LeftSlashRight; +".." L C return tk::PeriodPeriod; +"/>" L C return tk::SlashRight; +@end + +"&" 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; + +@begin ObjectiveC +"@class" L C return tk::AtClass; +"@end" L C return tk::AtEnd; +"@selector" L C return tk::AtSelector; +@end + +"false" L C yylval->false_ = new(yyextra->pool_) CYFalse(); return tk::False; +"null" L C yylval->null_ = new(yyextra->pool_) CYNull(); return tk::Null; +"true" L C yylval->true_ = new(yyextra->pool_) CYTrue(); return tk::True; + +"break" L R yylval->word_ = new(yyextra->pool_) CYWord("break"); return tk::Break; +"case" L C yylval->word_ = new(yyextra->pool_) CYWord("case"); return tk::Case; +"catch" L C yylval->word_ = new(yyextra->pool_) CYWord("catch"); return tk::Catch; +"continue" L R yylval->word_ = new(yyextra->pool_) CYWord("continue"); return tk::Continue; +"default" L C yylval->word_ = new(yyextra->pool_) CYWord("default"); return tk::Default; +"delete" L C yylval->word_ = new(yyextra->pool_) CYWord("delete"); return tk::Delete; +"do" L C yylval->word_ = new(yyextra->pool_) CYWord("do"); return tk::Do; +"else" L C yylval->word_ = new(yyextra->pool_) CYWord("else"); return tk::Else; +"finally" L C yylval->word_ = new(yyextra->pool_) CYWord("finally"); return tk::Finally; +"for" L C yylval->word_ = new(yyextra->pool_) CYWord("for"); return tk::For; +"function" L C yylval->word_ = new(yyextra->pool_) CYWord("function"); return tk::Function; +"if" L C yylval->word_ = new(yyextra->pool_) CYWord("if"); return tk::If; +"in" L C yylval->word_ = new(yyextra->pool_) CYWord("in"); return tk::In; +"instanceof" L C yylval->word_ = new(yyextra->pool_) CYWord("instanceof"); return tk::InstanceOf; +"new" L C yylval->word_ = new(yyextra->pool_) CYWord("new"); return tk::New; +"return" L R yylval->word_ = new(yyextra->pool_) CYWord("return"); return tk::Return; +"switch" L C yylval->word_ = new(yyextra->pool_) CYWord("switch"); return tk::Switch; +"this" L C yylval->this_ = new(yyextra->pool_) CYThis(); return tk::This; +"throw" L R yylval->word_ = new(yyextra->pool_) CYWord("throw"); return tk::Throw; +"try" L C yylval->word_ = new(yyextra->pool_) CYWord("try"); return tk::Try; +"typeof" L C yylval->word_ = new(yyextra->pool_) CYWord("typeof"); return tk::TypeOf; +"var" L C yylval->word_ = new(yyextra->pool_) CYWord("var"); return tk::Var; +"void" L C yylval->word_ = new(yyextra->pool_) CYWord("void"); return tk::Void; +"while" L C yylval->word_ = new(yyextra->pool_) CYWord("while"); return tk::While; +"with" L C yylval->word_ = new(yyextra->pool_) CYWord("with"); return tk::With; + +"debugger" L C yylval->word_ = new(yyextra->pool_) CYWord("debugger"); return tk::Debugger; + +"const" L C yylval->word_ = new(yyextra->pool_) CYWord("const"); return tk::Const; + +"class" L C yylval->word_ = new(yyextra->pool_) CYWord("class"); return tk::Class; +"enum" L C yylval->word_ = new(yyextra->pool_) CYWord("enum"); return tk::Enum; +"export" L C yylval->word_ = new(yyextra->pool_) CYWord("export"); return tk::Export; +"extends" L C yylval->word_ = new(yyextra->pool_) CYWord("extends"); return tk::Extends; +"import" L C yylval->word_ = new(yyextra->pool_) CYWord("import"); return tk::Import; +"super" L C yylval->word_ = new(yyextra->pool_) CYWord("super"); return tk::Super; + +"implements" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("implements"); return tk::Implements; +"interface" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("interface"); return tk::Interface; +"package" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("package"); return tk::Package; +"private" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("private"); return tk::Private; +"protected" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("protected"); return tk::Protected; +"public" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("public"); return tk::Public; +"static" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("static"); return tk::Static; + +"abstract" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("abstract"); return tk::Abstract; +"boolean" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("boolean"); return tk::Boolean; +"byte" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("byte"); return tk::Byte; +"char" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("char"); return tk::Char; +"double" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("double"); return tk::Double; +"final" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("final"); return tk::Final; +"float" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("float"); return tk::Float; +"goto" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("goto"); return tk::Goto; +"int" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("int"); return tk::Int; +"long" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("long"); return tk::Long; +"native" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("native"); return tk::Native; +"short" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("short"); return tk::Short; +"synchronized" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("synchronized"); return tk::Synchronized; +"throws" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("throws"); return tk::Throws; +"transient" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("transient"); return tk::Transient; +"volatile" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("volatile"); return tk::Volatile; + +"let" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("let"); return tk::Let; +"yield" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("yield"); return tk::Yield; + +"each" L C yylval->identifier_ = new(yyextra->pool_) CYIdentifier("each"); return tk::Each; + +{IdentifierStart}{IdentifierPart}* yylval->identifier_ = new(yyextra->pool_) 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(yyextra->pool_) CYNumber(strtod(yytext, NULL)); L C return tk::NumericLiteral; + +0[xX][0-9a-fA-F]+ L C yylval->number_ = new(yyextra->pool_) CYNumber(strtoull(yytext + 2, NULL, 16)); return tk::NumericLiteral; + +0[bB][0-1]+ L C yylval->number_ = new(yyextra->pool_) 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 '\n': continue; + 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(yyextra->pool_) CYString(value, local - value); + return tk::StringLiteral; +} + +\r?\n yylloc->end.lines(); yylloc->step(); N + +[ \t] L +<> L yyterminate(); + +. L { + CYDriver::Error error; + error.location_ = *yylloc; + error.message_ = "syntax error, unknown token"; + yyextra->errors_.push_back(error); + yyterminate(); +} + +%% + +void CYDriver::ScannerInit() { + cylex_init(&scanner_); + cyset_extra(this, scanner_); +} + +void CYDriver::ScannerDestroy() { + cylex_destroy(scanner_); +} + +void CYDriver::SetCondition(Condition condition) { + struct yyguts_t *yyg(reinterpret_cast(scanner_)); + + switch (condition) { + case RegExpSlash: + BEGIN(RegExpSlash); + break; + case RegExpSlashEqual: + BEGIN(RegExpSlashEqual); + break; + case RegExpSlashRight: + BEGIN(RegExpSlashRight); + break; + default: + _assert(false); + } +} diff --git a/Cycript.y.in b/Cycript.y.in index a0ce2cc..7918f27 100644 --- a/Cycript.y.in +++ b/Cycript.y.in @@ -124,7 +124,17 @@ int cylex(YYSTYPE *lvalp, cy::location *llocp, void *scanner); %parse-param { CYDriver &driver } %lex-param { void *scanner } +@begin E4X %token At "@" +%token ColonColon "::" +%token LeftRight "<>" +%token LeftSlashRight "" +%token PeriodPeriod ".." + +%token XMLCDATA +%token XMLComment +%token XMLPI +@end %token Ampersand "&" %token AmpersandAmpersand "&&" @@ -577,8 +587,11 @@ IdentifierOpt ; RegularExpressionToken - : "/" { $$ = CYDriver::RegExStart; } - | "/=" { $$ = CYDriver::RegExRest; } + : "/" { $$ = CYDriver::RegExpSlash; } + | "/=" { $$ = CYDriver::RegExpSlashEqual; } +@begin E4X + | "/>" { $$ = CYDriver::RegExpSlashRight; } +@end ; RegularExpressionLiteral_ @@ -1461,6 +1474,109 @@ MemberAccess /* }}} */ @end +@begin E4X +/* 8.3 XML Initialiser Input Elements {{{ */ +XMLMarkup + : XMLComment + | XMLCDATA + | XMLPI + ; +/* }}} */ +/* 11.1 Primary Expressions {{{ */ +PrimaryExpression_ + : PropertyIdentifier + | XMLInitialiser + | XMLListInitialiser + ; + +PropertyIdentifier + : AttributeIdentifier + | QualifiedIdentifier + | WildcardIdentifier + ; +/* }}} */ +/* 11.1.1 Attribute Identifiers {{{ */ +AttributeIdentifier + : "@" PropertySelector + | "@" QualifiedIdentifier + | "@" "[" Expression "]" + ; + +PropertySelector + : Identifier + | WildcardIdentifier + ; +/* }}} */ +/* 11.1.2 Qualified Identifiers {{{ */ +QualifiedIdentifier + : PropertySelector "::" PropertySelector + | PropertySelector "::" "[" Expression "]" + ; +/* }}} */ +/* 11.1.3 Wildcard Identifiers {{{ */ +WildcardIdentifier + : "*" + ; +/* }}} */ +/* 11.1.4 XML Initialiser {{{ */ +XMLInitialiser + : XMLMarkup + | XMLElement + ; + +XMLElement + : "<" XMLTagContent XMLWhitespaceOpt "/>" + | "<" XMLTagContent XMLWhitespace ">" XMLElementContentOpt "" + ; + +XMLTagContent + : XMLTagName XMLAttributesOpt + ; + +XMLTagName + : "{" Expression "}" + | XMLName + ; + +XMLAttributes + : XMLWhitespace "{" Expression "}" + | XMLAttributeOpt XMLAttributes + ; + +XMLAttributesOpt + : XMLAttributes + | + ; + +XMLAttribute + : XMLWhitespace XMLName XMLWhitespaceOpt "=" XMLWhitespaceOpt "{" Expression "}" + | XMLWhitespace XMLName XMLWhitespaceOpt "=" XMLWhitespaceOpt XMLAttributeValue + ; + +XMLAttributeOpt + : XMLAttribute + | + ; + +XMLElementContent + : "{" Expression "}" XMLElementContentOpt + | XMLMarkup XMLElementContentOpt + | XMLText XMLElementContentOpt + | XMLElement XMLElementContentOpt + ; + +XMLElementContentOpt + : XMLElementContent + | + ; +/* }}} */ +/* 11.1.5 XMLList Initialiser {{{ */ +XMLListInitialiser + : "<>" XMLElementContent "" + ; +/* }}} */ +@end + /* ECMAScript5: Object Literal Trailing Comma {{{ */ PropertyNameAndValueList_ : "," { $$ = NULL; } diff --git a/Parser.hpp b/Parser.hpp index 86b7d17..578b515 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -310,8 +310,9 @@ class CYDriver { bool strict_; enum Condition { - RegExStart, - RegExRest + RegExpSlash, + RegExpSlashEqual, + RegExpSlashRight, }; std::string filename_; diff --git a/makefile b/makefile index fbcc62f..f85f998 100644 --- a/makefile +++ b/makefile @@ -89,7 +89,10 @@ libcycript.plist: Bridge.def echo '})'; \ } >$@ -Cycript.y: Cycript.y.in +%.y: %.y.in + ./Filter.sh <$< >$@ $(filters) + +%.l: %.l.in ./Filter.sh <$< >$@ $(filters) Cycript.tab.cc Cycript.tab.hh location.hh position.hh: Cycript.y