MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

hyper-optimize next()

+465 -163
+1 -1
meson.build
··· 96 96 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 97 97 98 98 version_conf = configuration_data() 99 - version_conf.set('ANT_VERSION', '0.3.2.18') 99 + version_conf.set('ANT_VERSION', '0.3.2.19') 100 100 version_conf.set('ANT_GIT_HASH', git_hash) 101 101 version_conf.set('ANT_BUILD_DATE', build_date) 102 102
+464 -162
src/ant.c
··· 3576 3576 return parsekeyword(decoded, decoded_len); 3577 3577 } 3578 3578 3579 - static uint8_t next(struct js *js) { 3580 - if (js->consumed == 0) return js->tok; 3579 + #define CHAR_DIGIT 0x01 3580 + #define CHAR_XDIGIT 0x02 3581 + #define CHAR_ALPHA 0x04 3582 + #define CHAR_IDENT 0x08 3583 + #define CHAR_IDENT1 0x10 3584 + #define CHAR_WS 0x20 3585 + #define CHAR_OCTAL 0x40 3586 + 3587 + static const uint8_t char_type[256] = { 3588 + ['\t'] = CHAR_WS, ['\n'] = CHAR_WS, ['\r'] = CHAR_WS, [' '] = CHAR_WS, 3589 + ['0'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3590 + ['1'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3591 + ['2'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3592 + ['3'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3593 + ['4'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3594 + ['5'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3595 + ['6'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3596 + ['7'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT | CHAR_OCTAL, 3597 + ['8'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT, 3598 + ['9'] = CHAR_DIGIT | CHAR_XDIGIT | CHAR_IDENT, 3599 + ['A'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3600 + ['B'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3601 + ['C'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3602 + ['D'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3603 + ['E'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3604 + ['F'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3605 + ['a'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3606 + ['b'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3607 + ['c'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3608 + ['d'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3609 + ['e'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3610 + ['f'] = CHAR_XDIGIT | CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3611 + ['G'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['H'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3612 + ['I'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['J'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3613 + ['K'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['L'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3614 + ['M'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['N'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3615 + ['O'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['P'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3616 + ['Q'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['R'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3617 + ['S'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['T'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3618 + ['U'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['V'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3619 + ['W'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['X'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3620 + ['Y'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['Z'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3621 + ['g'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['h'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3622 + ['i'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['j'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3623 + ['k'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['l'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3624 + ['m'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['n'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3625 + ['o'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['p'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3626 + ['q'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['r'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3627 + ['s'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['t'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3628 + ['u'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['v'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3629 + ['w'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['x'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3630 + ['y'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, ['z'] = CHAR_ALPHA | CHAR_IDENT | CHAR_IDENT1, 3631 + ['_'] = CHAR_IDENT | CHAR_IDENT1, 3632 + ['$'] = CHAR_IDENT | CHAR_IDENT1, 3633 + }; 3634 + 3635 + #define IS_DIGIT(c) (char_type[(uint8_t)(c)] & CHAR_DIGIT) 3636 + #define IS_XDIGIT(c) (char_type[(uint8_t)(c)] & CHAR_XDIGIT) 3637 + #define IS_IDENT(c) (char_type[(uint8_t)(c)] & CHAR_IDENT) 3638 + #define IS_IDENT1(c) (char_type[(uint8_t)(c)] & CHAR_IDENT1) 3639 + #define IS_OCTAL(c) (char_type[(uint8_t)(c)] & CHAR_OCTAL) 3640 + 3641 + #define likely(x) __builtin_expect(!!(x), 1) 3642 + #define unlikely(x) __builtin_expect(!!(x), 0) 3643 + 3644 + static const uint8_t single_char_tok[128] = { 3645 + ['('] = TOK_LPAREN, 3646 + [')'] = TOK_RPAREN, 3647 + ['{'] = TOK_LBRACE, 3648 + ['}'] = TOK_RBRACE, 3649 + ['['] = TOK_LBRACKET, 3650 + [']'] = TOK_RBRACKET, 3651 + [';'] = TOK_SEMICOLON, 3652 + [','] = TOK_COMMA, 3653 + [':'] = TOK_COLON, 3654 + ['~'] = TOK_TILDA, 3655 + ['#'] = TOK_HASH, 3656 + }; 3657 + 3658 + static inline jsoff_t parse_decimal(const char *buf, jsoff_t maxlen, double *out) { 3659 + double val = 0.0; 3660 + jsoff_t i = 0; 3661 + 3662 + while (i < maxlen && (IS_DIGIT(buf[i]) || buf[i] == '_')) { 3663 + if (buf[i] != '_') val = val * 10.0 + (buf[i] - '0'); 3664 + i++; 3665 + } 3666 + 3667 + if (i < maxlen && buf[i] == '.') { 3668 + i++; 3669 + double frac = 0.1; 3670 + while (i < maxlen && (IS_DIGIT(buf[i]) || buf[i] == '_')) { 3671 + if (buf[i] != '_') { val += (buf[i] - '0') * frac; frac *= 0.1; } 3672 + i++; 3673 + } 3674 + } 3675 + 3676 + if (i < maxlen && (buf[i] == 'e' || buf[i] == 'E')) { 3677 + i++; 3678 + int exp_sign = 1, exp_val = 0; 3679 + if (i < maxlen && (buf[i] == '+' || buf[i] == '-')) { 3680 + exp_sign = (buf[i] == '-') ? -1 : 1; 3681 + i++; 3682 + } 3683 + while (i < maxlen && (IS_DIGIT(buf[i]) || buf[i] == '_')) { 3684 + if (buf[i] != '_') exp_val = exp_val * 10 + (buf[i] - '0'); 3685 + i++; 3686 + } 3687 + static const double pow10[] = { 3688 + 1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10, 3689 + 1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20 3690 + }; 3691 + 3692 + if (exp_val <= 20) { 3693 + val = (exp_sign > 0) ? val * pow10[exp_val] : val / pow10[exp_val]; 3694 + } else val *= pow(10.0, exp_sign * exp_val); 3695 + } 3696 + 3697 + *out = val; 3698 + return i; 3699 + } 3700 + 3701 + static inline jsoff_t parse_binary(const char *buf, jsoff_t maxlen, double *out) { 3702 + double val = 0; 3703 + jsoff_t i = 2; 3704 + while (i < maxlen && (buf[i] == '0' || buf[i] == '1' || buf[i] == '_')) { 3705 + if (buf[i] != '_') val = val * 2 + (buf[i] - '0'); 3706 + i++; 3707 + } 3708 + *out = val; 3709 + return i; 3710 + } 3711 + 3712 + static inline jsoff_t parse_octal(const char *buf, jsoff_t maxlen, double *out) { 3713 + double val = 0; 3714 + jsoff_t i = 2; 3715 + while (i < maxlen && (IS_OCTAL(buf[i]) || buf[i] == '_')) { 3716 + if (buf[i] != '_') val = val * 8 + (buf[i] - '0'); 3717 + i++; 3718 + } 3719 + *out = val; 3720 + return i; 3721 + } 3722 + 3723 + static inline jsoff_t parse_legacy_octal(const char *buf, jsoff_t maxlen, double *out) { 3724 + double val = 0; 3725 + jsoff_t i = 1; 3726 + while (i < maxlen && IS_OCTAL(buf[i])) { 3727 + val = val * 8 + (buf[i] - '0'); 3728 + i++; 3729 + } 3730 + *out = val; 3731 + return i; 3732 + } 3733 + 3734 + static inline jsoff_t parse_hex(const char *buf, jsoff_t maxlen, double *out) { 3735 + double val = 0; 3736 + jsoff_t i = 2; 3737 + while (i < maxlen && (IS_XDIGIT(buf[i]) || buf[i] == '_')) { 3738 + if (buf[i] != '_') { 3739 + int d = 3740 + (buf[i] >= 'a') ? (buf[i] - 'a' + 10) : 3741 + (buf[i] >= 'A') ? (buf[i] - 'A' + 10) : (buf[i] - '0'); 3742 + val = val * 16 + d; 3743 + } i++; 3744 + } 3745 + *out = val; 3746 + return i; 3747 + } 3748 + 3749 + static inline uint8_t parse_number(struct js *js, const char *buf, jsoff_t remaining) { 3750 + double value = 0; 3751 + jsoff_t numlen = 0; 3752 + 3753 + if (buf[0] == '0' && remaining > 1) { 3754 + char c1 = buf[1] | 0x20; 3755 + if (c1 == 'b') { 3756 + numlen = parse_binary(buf, remaining, &value); 3757 + } else if (c1 == 'o') { 3758 + numlen = parse_octal(buf, remaining, &value); 3759 + } else if (c1 == 'x') { 3760 + numlen = parse_hex(buf, remaining, &value); 3761 + } else if (IS_OCTAL(buf[1])) { 3762 + if (js->flags & F_STRICT) { 3763 + js->tok = TOK_ERR; 3764 + js->tlen = 1; 3765 + return TOK_ERR; 3766 + } 3767 + numlen = parse_legacy_octal(buf, remaining, &value); 3768 + } else numlen = parse_decimal(buf, remaining, &value); 3769 + } else numlen = parse_decimal(buf, remaining, &value); 3581 3770 3771 + js->tval = tov(value); 3772 + if (numlen < remaining && buf[numlen] == 'n') { 3773 + js->tok = TOK_BIGINT; 3774 + js->tlen = numlen + 1; 3775 + } else { 3776 + js->tok = TOK_NUMBER; 3777 + js->tlen = numlen; 3778 + } 3779 + 3780 + return js->tok; 3781 + } 3782 + 3783 + static inline uint8_t scan_string(struct js *js, const char *buf, jsoff_t rem, char quote) { 3784 + jsoff_t i = 1; 3785 + 3786 + while (i < rem) { 3787 + const char *p = buf + i; 3788 + jsoff_t search_len = rem - i; 3789 + 3790 + const char *q = memchr(p, quote, search_len); 3791 + const char *b = memchr(p, '\\', search_len); 3792 + 3793 + if (q == NULL) { 3794 + js->tok = TOK_ERR; 3795 + js->tlen = rem; 3796 + return TOK_ERR; 3797 + } 3798 + 3799 + if (b == NULL || q < b) { 3800 + i = (q - buf) + 1; 3801 + js->tok = TOK_STRING; 3802 + js->tlen = i; 3803 + return TOK_STRING; 3804 + } 3805 + 3806 + jsoff_t esc_pos = b - buf; 3807 + if (esc_pos + 1 >= rem) { 3808 + js->tok = TOK_ERR; 3809 + js->tlen = rem; 3810 + return TOK_ERR; 3811 + } 3812 + 3813 + char esc_char = buf[esc_pos + 1]; 3814 + jsoff_t skip = 2; 3815 + 3816 + if (esc_char == 'x') { skip = 4; } else if (esc_char == 'u') { 3817 + skip = (esc_pos + 2 < rem && buf[esc_pos + 2] == '{') ? 0 : 6; 3818 + if (skip == 0) { 3819 + jsoff_t j = esc_pos + 3; 3820 + while (j < rem && buf[j] != '}') j++; 3821 + skip = (j < rem) ? (j - esc_pos + 1) : (rem - esc_pos); 3822 + } 3823 + } 3824 + 3825 + if (esc_pos + skip > rem) { 3826 + js->tok = TOK_ERR; 3827 + js->tlen = rem; 3828 + return TOK_ERR; 3829 + } 3830 + 3831 + i = esc_pos + skip; 3832 + } 3833 + 3834 + js->tok = TOK_ERR; 3835 + js->tlen = rem; 3836 + return TOK_ERR; 3837 + } 3838 + 3839 + static inline uint8_t scan_template(struct js *js, const char *buf, jsoff_t rem) { 3840 + jsoff_t i = 1; 3841 + 3842 + while (i < rem) { 3843 + const char *p = buf + i; 3844 + jsoff_t search_len = rem - i; 3845 + 3846 + const char *q = memchr(p, '`', search_len); 3847 + const char *b = memchr(p, '\\', search_len); 3848 + 3849 + if (q == NULL) { 3850 + js->tok = TOK_ERR; 3851 + js->tlen = rem; 3852 + return TOK_ERR; 3853 + } 3854 + 3855 + if (b == NULL || q < b) { 3856 + i = (q - buf) + 1; 3857 + js->tok = TOK_TEMPLATE; 3858 + js->tlen = i; 3859 + return TOK_TEMPLATE; 3860 + } 3861 + 3862 + jsoff_t esc_pos = b - buf; 3863 + i = esc_pos + 2; 3864 + if (i > rem) { 3865 + js->tok = TOK_ERR; 3866 + js->tlen = rem; 3867 + return TOK_ERR; 3868 + } 3869 + } 3870 + 3871 + js->tok = TOK_ERR; 3872 + js->tlen = rem; 3873 + return TOK_ERR; 3874 + } 3875 + 3876 + static inline uint8_t parse_operator(struct js *js, const char *buf, jsoff_t rem) { 3877 + #define MATCH2(c1,c2) (rem >= 2 && buf[1] == (c2)) 3878 + #define MATCH3(c1,c2,c3) (rem >= 3 && buf[1] == (c2) && buf[2] == (c3)) 3879 + #define MATCH4(c1,c2,c3,c4) (rem >= 4 && buf[1]==(c2) && buf[2]==(c3) && buf[3]==(c4)) 3880 + 3881 + switch (buf[0]) { 3882 + case '?': 3883 + if (MATCH3('?','?','=')) { js->tok = TOK_NULLISH_ASSIGN; js->tlen = 3; } 3884 + else if (MATCH2('?','?')) { js->tok = TOK_NULLISH; js->tlen = 2; } 3885 + else if (MATCH2('?','.')) { js->tok = TOK_OPTIONAL_CHAIN; js->tlen = 2; } 3886 + else { js->tok = TOK_Q; js->tlen = 1; } 3887 + break; 3888 + 3889 + case '!': 3890 + if (MATCH3('!','=','=')) { js->tok = TOK_SNE; js->tlen = 3; } 3891 + else if (MATCH2('!','=')) { js->tok = TOK_NE; js->tlen = 2; } 3892 + else { js->tok = TOK_NOT; js->tlen = 1; } 3893 + break; 3894 + 3895 + case '=': 3896 + if (MATCH3('=','=','=')) { js->tok = TOK_SEQ; js->tlen = 3; } 3897 + else if (MATCH2('=','=')) { js->tok = TOK_EQ; js->tlen = 2; } 3898 + else if (MATCH2('=','>')) { js->tok = TOK_ARROW; js->tlen = 2; } 3899 + else { js->tok = TOK_ASSIGN; js->tlen = 1; } 3900 + break; 3901 + 3902 + case '<': 3903 + if (MATCH3('<','<','=')) { js->tok = TOK_SHL_ASSIGN; js->tlen = 3; } 3904 + else if (MATCH2('<','<')) { js->tok = TOK_SHL; js->tlen = 2; } 3905 + else if (MATCH2('<','=')) { js->tok = TOK_LE; js->tlen = 2; } 3906 + else { js->tok = TOK_LT; js->tlen = 1; } 3907 + break; 3908 + 3909 + case '>': 3910 + if (MATCH4('>','>','>','=')) { js->tok = TOK_ZSHR_ASSIGN; js->tlen = 4; } 3911 + else if (MATCH3('>','>','>')) { js->tok = TOK_ZSHR; js->tlen = 3; } 3912 + else if (MATCH3('>','>','=')) { js->tok = TOK_SHR_ASSIGN; js->tlen = 3; } 3913 + else if (MATCH2('>','>')) { js->tok = TOK_SHR; js->tlen = 2; } 3914 + else if (MATCH2('>','=')) { js->tok = TOK_GE; js->tlen = 2; } 3915 + else { js->tok = TOK_GT; js->tlen = 1; } 3916 + break; 3917 + 3918 + case '&': 3919 + if (MATCH3('&','&','=')) { js->tok = TOK_LAND_ASSIGN; js->tlen = 3; } 3920 + else if (MATCH2('&','&')) { js->tok = TOK_LAND; js->tlen = 2; } 3921 + else if (MATCH2('&','=')) { js->tok = TOK_AND_ASSIGN; js->tlen = 2; } 3922 + else { js->tok = TOK_AND; js->tlen = 1; } 3923 + break; 3924 + 3925 + case '|': 3926 + if (MATCH3('|','|','=')) { js->tok = TOK_LOR_ASSIGN; js->tlen = 3; } 3927 + else if (MATCH2('|','|')) { js->tok = TOK_LOR; js->tlen = 2; } 3928 + else if (MATCH2('|','=')) { js->tok = TOK_OR_ASSIGN; js->tlen = 2; } 3929 + else { js->tok = TOK_OR; js->tlen = 1; } 3930 + break; 3931 + 3932 + case '+': 3933 + if (MATCH2('+','+')) { js->tok = TOK_POSTINC; js->tlen = 2; } 3934 + else if (MATCH2('+','=')) { js->tok = TOK_PLUS_ASSIGN; js->tlen = 2; } 3935 + else { js->tok = TOK_PLUS; js->tlen = 1; } 3936 + break; 3937 + 3938 + case '-': 3939 + if (MATCH2('-','-')) { js->tok = TOK_POSTDEC; js->tlen = 2; } 3940 + else if (MATCH2('-','=')) { js->tok = TOK_MINUS_ASSIGN; js->tlen = 2; } 3941 + else { js->tok = TOK_MINUS; js->tlen = 1; } 3942 + break; 3943 + 3944 + case '*': 3945 + if (MATCH2('*','*')) { js->tok = TOK_EXP; js->tlen = 2; } 3946 + else if (MATCH2('*','=')) { js->tok = TOK_MUL_ASSIGN; js->tlen = 2; } 3947 + else { js->tok = TOK_MUL; js->tlen = 1; } 3948 + break; 3949 + 3950 + case '/': 3951 + if (MATCH2('/','=')) { js->tok = TOK_DIV_ASSIGN; js->tlen = 2; } 3952 + else { js->tok = TOK_DIV; js->tlen = 1; } 3953 + break; 3954 + 3955 + case '%': 3956 + if (MATCH2('%','=')) { js->tok = TOK_REM_ASSIGN; js->tlen = 2; } 3957 + else { js->tok = TOK_REM; js->tlen = 1; } 3958 + break; 3959 + 3960 + case '^': 3961 + if (MATCH2('^','=')) { js->tok = TOK_XOR_ASSIGN; js->tlen = 2; } 3962 + else { js->tok = TOK_XOR; js->tlen = 1; } 3963 + break; 3964 + 3965 + case '.': 3966 + if (MATCH3('.','.', '.')) { js->tok = TOK_REST; js->tlen = 3; } 3967 + else if (rem > 1 && IS_DIGIT(buf[1])) { 3968 + double val; 3969 + js->tlen = parse_decimal(buf, rem, &val); 3970 + js->tval = tov(val); 3971 + js->tok = TOK_NUMBER; 3972 + } 3973 + else { js->tok = TOK_DOT; js->tlen = 1; } 3974 + break; 3975 + 3976 + default: 3977 + return 0; 3978 + } 3979 + 3980 + #undef MATCH2 3981 + #undef MATCH3 3982 + #undef MATCH4 3983 + 3984 + return js->tok; 3985 + } 3986 + 3987 + static uint8_t next(struct js *js) { 3988 + if (likely(js->consumed == 0)) return js->tok; 3989 + 3582 3990 js->consumed = 0; 3583 3991 js->tok = TOK_ERR; 3584 3992 js->toff = js->pos = skiptonext(js->code, js->clen, js->pos, &js->had_newline); 3585 3993 js->tlen = 0; 3586 - 3994 + 3995 + if (unlikely(js->toff >= js->clen)) { 3996 + js->tok = TOK_EOF; 3997 + return TOK_EOF; 3998 + } 3999 + 3587 4000 const char *buf = js->code + js->toff; 3588 - if (js->toff >= js->clen) { js->tok = TOK_EOF; return js->tok; } 3589 - 3590 - #define TOK(T, LEN) { js->tok = T; js->tlen = (LEN); break; } 3591 - #define LOOK(OFS, CH) js->toff + OFS < js->clen && buf[OFS] == CH 3592 - 3593 - switch (buf[0]) { 3594 - case '?': if (LOOK(1, '?') && LOOK(2, '=')) TOK(TOK_NULLISH_ASSIGN, 3); if (LOOK(1, '?')) TOK(TOK_NULLISH, 2); if (LOOK(1, '.')) TOK(TOK_OPTIONAL_CHAIN, 2); TOK(TOK_Q, 1); 3595 - case ':': TOK(TOK_COLON, 1); 3596 - case '(': TOK(TOK_LPAREN, 1); 3597 - case ')': TOK(TOK_RPAREN, 1); 3598 - case '{': TOK(TOK_LBRACE, 1); 3599 - case '}': TOK(TOK_RBRACE, 1); 3600 - case '[': TOK(TOK_LBRACKET, 1); 3601 - case ']': TOK(TOK_RBRACKET, 1); 3602 - case ';': TOK(TOK_SEMICOLON, 1); 3603 - case ',': TOK(TOK_COMMA, 1); 3604 - case '!': if (LOOK(1, '=') && LOOK(2, '=')) TOK(TOK_SNE, 3); if (LOOK(1, '=')) TOK(TOK_NE, 2); TOK(TOK_NOT, 1); 3605 - 3606 - case '.': 3607 - if (LOOK(1, '.') && LOOK(2, '.')) TOK(TOK_REST, 3); 3608 - if (js->toff + 1 < js->clen && is_digit(buf[1])) { 3609 - char clean[64]; 3610 - jsoff_t ci = 0, numlen = 0; 3611 - while (js->toff + numlen < js->clen && (is_digit(buf[numlen]) || buf[numlen] == '.' || buf[numlen] == 'e' || buf[numlen] == 'E' || buf[numlen] == '+' || buf[numlen] == '-' || buf[numlen] == '_') && ci < 63) { 3612 - if (numlen > 0 && (buf[numlen] == '+' || buf[numlen] == '-') && buf[numlen-1] != 'e' && buf[numlen-1] != 'E') break; 3613 - if (buf[numlen] != '_') clean[ci++] = buf[numlen]; 3614 - numlen++; 3615 - } 3616 - clean[ci] = '\0'; 3617 - js->tval = tov(strtod(clean, NULL)); 3618 - TOK(TOK_NUMBER, numlen); 3619 - } 3620 - TOK(TOK_DOT, 1); 3621 - 3622 - case '~': TOK(TOK_TILDA, 1); 3623 - case '-': if (LOOK(1, '-')) TOK(TOK_POSTDEC, 2); if (LOOK(1, '=')) TOK(TOK_MINUS_ASSIGN, 2); TOK(TOK_MINUS, 1); 3624 - case '+': if (LOOK(1, '+')) TOK(TOK_POSTINC, 2); if (LOOK(1, '=')) TOK(TOK_PLUS_ASSIGN, 2); TOK(TOK_PLUS, 1); 3625 - case '*': if (LOOK(1, '*')) TOK(TOK_EXP, 2); if (LOOK(1, '=')) TOK(TOK_MUL_ASSIGN, 2); TOK(TOK_MUL, 1); 3626 - case '/': if (LOOK(1, '=')) TOK(TOK_DIV_ASSIGN, 2); TOK(TOK_DIV, 1); 3627 - case '%': if (LOOK(1, '=')) TOK(TOK_REM_ASSIGN, 2); TOK(TOK_REM, 1); 3628 - case '&': if (LOOK(1, '&') && LOOK(2, '=')) TOK(TOK_LAND_ASSIGN, 3); if (LOOK(1, '&')) TOK(TOK_LAND, 2); if (LOOK(1, '=')) TOK(TOK_AND_ASSIGN, 2); TOK(TOK_AND, 1); 3629 - case '|': if (LOOK(1, '|') && LOOK(2, '=')) TOK(TOK_LOR_ASSIGN, 3); if (LOOK(1, '|')) TOK(TOK_LOR, 2); if (LOOK(1, '=')) TOK(TOK_OR_ASSIGN, 2); TOK(TOK_OR, 1); 3630 - case '=': if (LOOK(1, '=') && LOOK(2, '=')) TOK(TOK_SEQ, 3); if (LOOK(1, '=')) TOK(TOK_EQ, 2); if (LOOK(1, '>')) TOK(TOK_ARROW, 2); TOK(TOK_ASSIGN, 1); 3631 - case '<': if (LOOK(1, '<') && LOOK(2, '=')) TOK(TOK_SHL_ASSIGN, 3); if (LOOK(1, '<')) TOK(TOK_SHL, 2); if (LOOK(1, '=')) TOK(TOK_LE, 2); TOK(TOK_LT, 1); 3632 - case '>': if (LOOK(1, '>') && LOOK(2, '>') && LOOK(3, '=')) TOK(TOK_ZSHR_ASSIGN, 4); if (LOOK(1, '>') && LOOK(2, '>')) TOK(TOK_ZSHR, 3); if (LOOK(1, '>') && LOOK(2, '=')) TOK(TOK_SHR_ASSIGN, 3); if (LOOK(1, '>')) TOK(TOK_SHR, 2); if (LOOK(1, '=')) TOK(TOK_GE, 2); TOK(TOK_GT, 1); 3633 - case '^': if (LOOK(1, '=')) TOK(TOK_XOR_ASSIGN, 2); TOK(TOK_XOR, 1); 3634 - case '#': TOK(TOK_HASH, 1); 3635 - case '`': 3636 - js->tlen++; 3637 - while (js->toff + js->tlen < js->clen && buf[js->tlen] != '`') { 3638 - uint8_t increment = 1; 3639 - if (buf[js->tlen] == '\\') { 3640 - if (js->toff + js->tlen + 2 > js->clen) break; 3641 - increment = 2; 3642 - } 3643 - js->tlen += increment; 3644 - } 3645 - if (buf[js->tlen] == '`') js->tok = TOK_TEMPLATE, js->tlen++; 3646 - break; 3647 - case '"': case '\'': 3648 - js->tlen++; 3649 - while (js->toff + js->tlen < js->clen && buf[js->tlen] != buf[0]) { 3650 - uint8_t increment = 1; 3651 - if (buf[js->tlen] == '\\') { 3652 - if (js->toff + js->tlen + 2 > js->clen) break; 3653 - increment = 2; 3654 - if (buf[js->tlen + 1] == 'x') { 3655 - if (js->toff + js->tlen + 4 > js->clen) break; 3656 - increment = 4; 3657 - } else if (buf[js->tlen + 1] == 'u') { 3658 - if (js->toff + js->tlen + 6 > js->clen) break; 3659 - increment = 6; 3660 - } 3661 - } 3662 - js->tlen += increment; 3663 - } 3664 - if (buf[0] == buf[js->tlen]) js->tok = TOK_STRING, js->tlen++; 3665 - break; 3666 - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { 3667 - if ((js->flags & F_STRICT) && buf[0] == '0' && js->toff + 1 < js->clen && 3668 - is_digit(buf[1]) && buf[1] != 'x' && buf[1] != 'X' && buf[1] != 'b' && buf[1] != 'B' && buf[1] != 'o' && buf[1] != 'O') { 3669 - js->tok = TOK_ERR; 3670 - js->tlen = 1; 3671 - break; 3672 - } 3673 - 3674 - char *end; 3675 - double value = 0; 3676 - jsoff_t numlen = 0; 3677 - 3678 - if (buf[0] == '0' && js->toff + 2 < js->clen) { 3679 - if (buf[1] == 'b' || buf[1] == 'B') { 3680 - numlen = 2; 3681 - while (js->toff + numlen < js->clen && (buf[numlen] == '0' || buf[numlen] == '1' || buf[numlen] == '_')) { 3682 - if (buf[numlen] != '_') value = value * 2 + (buf[numlen] - '0'); 3683 - numlen++; 3684 - } 3685 - js->tval = tov(value); 3686 - } else if (buf[1] == 'o' || buf[1] == 'O') { 3687 - numlen = 2; 3688 - while (js->toff + numlen < js->clen && ((buf[numlen] >= '0' && buf[numlen] <= '7') || buf[numlen] == '_')) { 3689 - if (buf[numlen] != '_') value = value * 8 + (buf[numlen] - '0'); 3690 - numlen++; 3691 - } 3692 - js->tval = tov(value); 3693 - } else if (buf[1] == 'x' || buf[1] == 'X') { 3694 - char clean[64]; 3695 - jsoff_t ci = 0; 3696 - numlen = 0; 3697 - while (js->toff + numlen < js->clen && (is_xdigit(buf[numlen]) || buf[numlen] == 'x' || buf[numlen] == 'X' || buf[numlen] == '_') && ci < 63) { 3698 - if (buf[numlen] != '_') clean[ci++] = buf[numlen]; 3699 - numlen++; 3700 - } 3701 - clean[ci] = '\0'; 3702 - js->tval = tov(strtod(clean, &end)); 3703 - } else if (buf[1] >= '0' && buf[1] <= '7') { 3704 - numlen = 1; 3705 - while (js->toff + numlen < js->clen && buf[numlen] >= '0' && buf[numlen] <= '7') { 3706 - value = value * 8 + (buf[numlen] - '0'); 3707 - numlen++; 3708 - } 3709 - js->tval = tov(value); 3710 - } else { 3711 - char clean[64]; 3712 - jsoff_t ci = 0; 3713 - numlen = 0; 3714 - while (js->toff + numlen < js->clen && (is_digit(buf[numlen]) || buf[numlen] == '.' || buf[numlen] == 'e' || buf[numlen] == 'E' || buf[numlen] == '+' || buf[numlen] == '-' || buf[numlen] == '_') && ci < 63) { 3715 - if (numlen > 0 && (buf[numlen] == '+' || buf[numlen] == '-') && buf[numlen-1] != 'e' && buf[numlen-1] != 'E') break; 3716 - if (buf[numlen] != '_') clean[ci++] = buf[numlen]; 3717 - numlen++; 3718 - } 3719 - clean[ci] = '\0'; 3720 - js->tval = tov(strtod(clean, &end)); 3721 - } 3722 - } else { 3723 - char clean[64]; 3724 - jsoff_t ci = 0; 3725 - numlen = 0; 3726 - while (js->toff + numlen < js->clen && (is_digit(buf[numlen]) || buf[numlen] == '.' || buf[numlen] == 'e' || buf[numlen] == 'E' || buf[numlen] == '+' || buf[numlen] == '-' || buf[numlen] == '_') && ci < 63) { 3727 - if (numlen > 0 && (buf[numlen] == '+' || buf[numlen] == '-') && buf[numlen-1] != 'e' && buf[numlen-1] != 'E') break; 3728 - if (buf[numlen] != '_') clean[ci++] = buf[numlen]; 3729 - numlen++; 3730 - } 3731 - clean[ci] = '\0'; 3732 - js->tval = tov(strtod(clean, &end)); 3733 - } 3734 - 3735 - if (js->toff + numlen < js->clen && buf[numlen] == 'n') { 3736 - js->tok = TOK_BIGINT; 3737 - js->tlen = numlen + 1; 3738 - } else { 3739 - TOK(TOK_NUMBER, numlen); 3740 - } 3741 - break; 4001 + jsoff_t rem = js->clen - js->toff; 4002 + uint8_t c = (uint8_t)buf[0]; 4003 + 4004 + if (likely(c < 128)) { 4005 + uint8_t simple_tok = single_char_tok[c]; 4006 + if (simple_tok != 0) { 4007 + js->tok = simple_tok; 4008 + js->tlen = 1; 4009 + js->pos = js->toff + 1; 4010 + return simple_tok; 3742 4011 } 3743 - default: js->tok = parseident(buf, js->clen - js->toff, &js->tlen); break; 3744 4012 } 3745 - 3746 - if (js->tlen == 0) js->tlen = 1; 3747 - js->pos = js->toff + js->tlen; 3748 - return js->tok; 4013 + 4014 + if (likely(IS_IDENT1(c))) { 4015 + js->tok = parseident(buf, rem, &js->tlen); 4016 + js->pos = js->toff + js->tlen; 4017 + return js->tok; 4018 + } 4019 + 4020 + if (IS_DIGIT(c)) { 4021 + parse_number(js, buf, rem); 4022 + if (js->tlen == 0) js->tlen = 1; 4023 + js->pos = js->toff + js->tlen; 4024 + return js->tok; 4025 + } 4026 + 4027 + if (c == '"' || c == '\'') { 4028 + scan_string(js, buf, rem, c); 4029 + if (js->tlen == 0) js->tlen = 1; 4030 + js->pos = js->toff + js->tlen; 4031 + return js->tok; 4032 + } 4033 + 4034 + if (c == '`') { 4035 + scan_template(js, buf, rem); 4036 + if (js->tlen == 0) js->tlen = 1; 4037 + js->pos = js->toff + js->tlen; 4038 + return js->tok; 4039 + } 4040 + 4041 + if (parse_operator(js, buf, rem)) { 4042 + if (js->tlen == 0) js->tlen = 1; 4043 + js->pos = js->toff + js->tlen; 4044 + return js->tok; 4045 + } 4046 + 4047 + js->tok = TOK_ERR; 4048 + js->tlen = 1; 4049 + js->pos = js->toff + 1; 4050 + return TOK_ERR; 3749 4051 } 3750 4052 3751 4053 static inline uint8_t lookahead(struct js *js) {