"/"  L C F(tk::Slash, hi::Operator);
"/=" L C F(tk::SlashEqual, hi::Operator);
":"    L C F(tk::Colon, hi::Structure);
","    L C F(tk::Comma, hi::Structure);
"?"    L C F(tk::Question, hi::Structure);
";"    L C F(tk::SemiColon, hi::Structure);
"("    L C F(tk::OpenParen, hi::Structure);
")"    L C F(tk::CloseParen, hi::Structure);
"{"    L C F(yyextra->no_.OpenBrace ? tk::OpenBrace__ : yylval->newline_ ? tk::OpenBrace_ : tk::OpenBrace, hi::Structure);
"}"    L C F(tk::CloseBrace, hi::Structure);
"["    L C F(tk::OpenBracket, hi::Structure);
"]"    L C F(tk::CloseBracket, hi::Structure);
"@error"          L C F(tk::AtError, hi::Error);
@begin Java
"@class"          L C F(tk::AtClass, hi::Meta);
@end
@begin C
"typedef"         L C I(identifier, Identifier("typedef"), tk::Typedef, hi::Meta);
"unsigned"        L C I(identifier, Identifier("unsigned"), tk::Unsigned, hi::Type);
"signed"          L C I(identifier, Identifier("signed"), tk::Signed, hi::Type);
"extern"          L C I(identifier, Identifier("extern"), tk::Extern, hi::Type);
@end
@begin C
"@encode"         L C F(tk::AtEncode, hi::Meta);
@end
@begin ObjectiveC
"@end"            L C F(tk::AtEnd, hi::Meta);
"@implementation" L C F(yyextra->no_.AtImplementation ? tk::AtImplementation_ : tk::AtImplementation, hi::Meta);
"@import"         L C F(tk::AtImport, hi::Special);
"@selector"       L C F(tk::AtSelector, hi::Meta);
"@null"           L C F(tk::AtNull, hi::Constant);
"@YES"            L C F(tk::AtYes, hi::Constant);
"@NO"             L C F(tk::AtNo, hi::Constant);
"@true"           L C F(tk::AtTrue, hi::Constant);
"@false"          L C F(tk::AtFalse, hi::Constant);
"NULL"         L C I(identifier, Identifier("NULL"), tk::Identifier_, hi::Constant);
"nil"          L C I(identifier, Identifier("nil"), tk::Identifier_, hi::Constant);
"YES"          L C I(identifier, Identifier("YES"), tk::Yes, hi::Constant);
"NO"           L C I(identifier, Identifier("NO"), tk::No, hi::Constant);
"bool"         L C I(identifier, Identifier("bool"), tk::Identifier_, hi::Type);
"BOOL"         L C I(identifier, Identifier("BOOL"), tk::Identifier_, hi::Type);
"id"           L C I(identifier, Identifier("id"), tk::Identifier_, hi::Type);
"SEL"          L C I(identifier, Identifier("SEL"), tk::Identifier_, hi::Type);
@end
"undefined"    L C I(identifier, Identifier("undefined"), tk::Identifier_, hi::Operator);
"false"        L C F(tk::False, hi::Constant);
"null"         L C F(tk::Null, hi::Constant);
"true"         L C F(tk::True, hi::Constant);
"auto"         L C F(tk::Auto, hi::Meta);
"break"        L R F(tk::Break, hi::Control);
"case"         L C F(tk::Case, hi::Control);
"catch"        L C F(tk::Catch, hi::Control);
"continue"     L R F(tk::Continue, hi::Control);
"default"      L C F(tk::Default, hi::Control);
"delete"       L C F(tk::Delete, hi::Operator);
"do"           L C F(tk::Do, hi::Control);
"else"         L C F(tk::Else, hi::Control);
"finally"      L C F(tk::Finally, hi::Control);
"for"          L C F(tk::For, hi::Control);
"function"     L C F(yyextra->no_.Function ? tk::Function_ : tk::Function, hi::Meta);
"if"           L C F(tk::If, hi::Control);
"in"           L C F(yyextra->in_.top() ? tk::In_ : tk::In, hi::Operator);
"instanceof"   L C F(tk::InstanceOf, hi::Operator);
"new"          L C F(tk::New, hi::Operator);
"return"       L R F(tk::Return, hi::Control);
"switch"       L C F(tk::Switch, hi::Control);
"this"         L C F(tk::This, hi::Constant);
"throw"        L R F(tk::Throw, hi::Control);
"try"          L C F(tk::Try, hi::Control);
"typeof"       L C F(tk::TypeOf, hi::Operator);
"var"          L C F(tk::Var, hi::Meta);
"void"         L C F(tk::Void, hi::Operator);
"while"        L C F(tk::While, hi::Control);
"with"         L C F(tk::With, hi::Control);
"debugger"     L C F(tk::Debugger, hi::Meta);
"const"        L C F(tk::Const, hi::Meta);
"class"        L C F(tk::Class, hi::Meta);
"enum"         L C F(tk::Enum, hi::Meta);
"export"       L C F(tk::Export, hi::Meta);
"extends"      L C F(tk::Extends, hi::Meta);
"import"       L C F(tk::Import, hi::Meta);
"super"        L C F(tk::Super, hi::Constant);
"implements"   L C I(identifier, Identifier("implements"), tk::Implements, hi::Meta);
"interface"    L C I(identifier, Identifier("interface"), tk::Interface, hi::Meta);
"package"      L C I(identifier, Identifier("package"), tk::Package, hi::Meta);
"private"      L C I(identifier, Identifier("private"), tk::Private, hi::Meta);
"protected"    L C I(identifier, Identifier("protected"), tk::Protected, hi::Meta);
"public"       L C I(identifier, Identifier("public"), tk::Public, hi::Meta);
"static"       L C I(identifier, Identifier("static"), tk::Static, hi::Meta);
"abstract"     L C I(identifier, Identifier("abstract"), tk::Abstract, hi::Meta);
"boolean"      L C I(identifier, Identifier("boolean"), tk::Boolean, hi::Type);
"byte"         L C I(identifier, Identifier("byte"), tk::Byte, hi::Type);
"char"         L C I(identifier, Identifier("char"), tk::Char, hi::Type);
"double"       L C I(identifier, Identifier("double"), tk::Double, hi::Type);
"final"        L C I(identifier, Identifier("final"), tk::Final, hi::Meta);
"float"        L C I(identifier, Identifier("float"), tk::Float, hi::Type);
"goto"         L C I(identifier, Identifier("goto"), tk::Goto, hi::Control);
"int"          L C I(identifier, Identifier("int"), tk::Int, hi::Type);
"long"         L C I(identifier, Identifier("long"), tk::Long, hi::Type);
"native"       L C I(identifier, Identifier("native"), tk::Native, hi::Meta);
"short"        L C I(identifier, Identifier("short"), tk::Short, hi::Type);
"synchronized" L C I(identifier, Identifier("synchronized"), tk::Synchronized, hi::Meta);
"throws"       L C I(identifier, Identifier("throws"), tk::Throws, hi::Meta);
"transient"    L C I(identifier, Identifier("transient"), tk::Transient, hi::Meta);
"volatile"     L C I(identifier, Identifier("volatile"), tk::Volatile, hi::Meta);
"let"          L C I(identifier, Identifier("let"), tk::Let, hi::Meta);
"yield"        L R I(identifier, Identifier("yield"), tk::Yield, hi::Control);
"each"         L C I(identifier, Identifier("each"), tk::Each, hi::Control);
"of"           L C I(identifier, Identifier("of"), tk::Of, hi::Operator);
@begin E4X
"namespace"    L C I(identifier, Identifier("namespace"), tk::Namespace, hi::Meta);
"xml"          L C I(identifier, Identifier("xml"), tk::XML, hi::Meta);
@end
{UnicodeStart}{UnicodePart}* L C I(identifier, Identifier(Y), tk::Identifier_, hi::Identifier);
{IdentifierStart}{IdentifierPart}* L C {
    char *value(A char[yyleng + 1]);
    char *local(value);
    for (yy_size_t i(0), e(yyleng); i != e; ++i) {
        char next(yytext[i]);
        if (next != '\\')
            *local++ = next;
        else
            U(local, yytext, ++i);
    }
    *local = '\0';
    I(identifier, Identifier(value), tk::Identifier_, hi::Identifier);
}
({IdentifierStart}{IdentifierPart}*)?{IdentifierFail} L E("invalid identifier")
0[0-7]+ L C I(number, Number(strtoull(yytext + 1, NULL, 8)), tk::NumericLiteral, hi::Constant);
0[0-9]+ L C I(number, Number(strtoull(yytext + 1, NULL, 10)), tk::NumericLiteral, hi::Constant);
0[xX][0-9a-fA-F]+ L C I(number, Number(strtoull(yytext + 2, NULL, 16)), tk::NumericLiteral, hi::Constant);
0[oO][0-7]+ L C I(number, Number(strtoull(yytext + 2, NULL, 8)), tk::NumericLiteral, hi::Constant);
0[bB][0-1]+ L C I(number, Number(strtoull(yytext + 2, NULL, 2)), tk::NumericLiteral, hi::Constant);
(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?)([eE][+-]?[0-9]+)? L C I(number, Number(strtod(yytext, NULL)), tk::NumericLiteral, hi::Constant);
(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?)[eE][+-]?{IdentifierScrap} L E("invalid exponent")
(\.?[0-9]|(0|[1-9][0-9]*)\.){IdentifierScrap} L E("invalid number")
'{SingleString}'|\"{DoubleString}\" L C {
    char *value(A char[yyleng]);
    char *local(value);
    for (yy_size_t i(1), e(yyleng - 1); i != e; ++i) {
        char next(yytext[i]);
        if (yytext[i] == '\\')
            // XXX: support more line continuation characters
            if (false) line: {
                yylloc->end.lines(1);
                yylloc->end.columns(yyleng - i);
            } else switch (next = yytext[++i]) {
                case '\n': goto line;
                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': case '1': case '2': case '3':
                    if (yytext[i + 1] < '0' || yytext[i + 1] > '7')
                        next = H(yytext[i]), i += 0;
                    else if (yytext[i + 2] < '0' || yytext[i + 2] > '7')
                        next = H(yytext[i]) << 3 | H(yytext[i + 1]), i += 1;
                    else
                        next = H(yytext[i]) << 6 | H(yytext[i + 1]) << 3 | H(yytext[i + 2]), i += 2;
                break;
                case '4': case '5': case '6': case '7':
                    if (yytext[i + 1] < '0' || yytext[i + 1] > '7')
                        next = H(yytext[i]), i += 0;
                    else
                        next = H(yytext[i]) << 3 | H(yytext[i + 1]), i += 1;
                break;
                case 'x':
                    U(local, H(yytext[i + 1]) << 4 | H(yytext[i + 2]));
                    i += 2;
                continue;
                case 'u':
                    U(local, yytext, i);
                continue;
            }
        *local++ = next;
    }
    *local = '\0';
    I(string, String(value, local - value), tk::StringLiteral, hi::Constant);
}
{StringPrefix}\\(x.{0,2}|u([^{].{0,3}|\{[^}]*)?|{UnicodeFail})? L E("invalid escape")
{StringPrefix} L E("invalid string")
{LineTerminatorSequence} yylloc->step(); yylloc->end.lines(); N
{WhiteSpace} L
<> if (yyextra->auto_) { yyextra->auto_ = false; F(tk::AutoComplete, hi::Nothing); } L yyterminate();
@({UnicodeStart}{UnicodeScrap}|{UnicodeFail}) L E("invalid keyword")
. L E("invalid character")
%%
void CYDriver::ScannerInit() {
    cylex_init(&scanner_);
    cyset_extra(this, scanner_);
}
void CYDriver::ScannerDestroy() {
    cylex_destroy(scanner_);
}
CYDriver::Condition CYDriver::GetCondition() {
    switch (yy_top_state(scanner_)) {
        case RegExp:
            return RegExpCondition;
@begin E4X
        case XMLContent:
            return XMLContentCondition;
        case XMLTag:
            return XMLTagCondition;
@end
        default:
            _assert(false);
    }
}
void CYDriver::SetCondition(Condition condition) {
    struct yyguts_t *yyg(reinterpret_cast(scanner_));
    switch (condition) {
        case RegExpCondition:
            BEGIN(RegExp);
            break;
@begin E4X
        case XMLContentCondition:
            BEGIN(XMLContent);
            break;
        case XMLTagCondition:
            BEGIN(XMLTag);
            break;
@end
        default:
            _assert(false);
    }
}
void CYDriver::PushCondition(Condition condition) {
    switch (condition) {
        case RegExpCondition:
            yy_push_state(RegExp, scanner_);
            break;
@begin E4X
        case XMLContentCondition:
            yy_push_state(XMLContent, scanner_);
            break;
        case XMLTagCondition:
            yy_push_state(XMLTag, scanner_);
            break;
@end
        default:
            _assert(false);
    }
}
void CYDriver::PopCondition() {
    yy_pop_state(scanner_);
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif