| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | '0': \ |
| 31 | 31 | case DIGIT_NON_ZERO |
| 32 | 32 | |
| 33 | | #define ALPHA_EXCEPT_C \ |
| 33 | #define ALPHA_EXCEPT_CR \ |
| 34 | 34 | 'a': \ |
| 35 | 35 | case 'b': \ |
| 36 | 36 | /*case 'c':*/ \ |
| ... | ... | @@ -48,7 +48,7 @@ |
| 48 | 48 | case 'o': \ |
| 49 | 49 | case 'p': \ |
| 50 | 50 | case 'q': \ |
| 51 | | case 'r': \ |
| 51 | /*case 'r':*/ \ |
| 52 | 52 | case 's': \ |
| 53 | 53 | case 't': \ |
| 54 | 54 | case 'u': \ |
| ... | ... | @@ -85,11 +85,17 @@ |
| 85 | 85 | case 'Z' |
| 86 | 86 | |
| 87 | 87 | #define ALPHA \ |
| 88 | | ALPHA_EXCEPT_C: \ |
| 89 | | case 'c' |
| 88 | ALPHA_EXCEPT_CR: \ |
| 89 | case 'c': \ |
| 90 | case 'r' |
| 90 | 91 | |
| 91 | 92 | #define SYMBOL_CHAR \ |
| 92 | | ALPHA: \ |
| 93 | SYMBOL_CHAR_EXCEPT_C: \ |
| 94 | case 'c' |
| 95 | |
| 96 | #define SYMBOL_CHAR_EXCEPT_C \ |
| 97 | ALPHA_EXCEPT_CR: \ |
| 98 | case 'r': \ |
| 93 | 99 | case DIGIT: \ |
| 94 | 100 | case '_' |
| 95 | 101 | |
| ... | ... | @@ -118,12 +124,17 @@ enum TokenizeState { |
| 118 | 124 | TokenizeStateStart, |
| 119 | 125 | TokenizeStateSymbol, |
| 120 | 126 | TokenizeStateSymbolFirst, |
| 127 | TokenizeStateSymbolFirstRaw, |
| 128 | TokenizeStateFirstR, |
| 121 | 129 | TokenizeStateZero, // "0", which might lead to "0x" |
| 122 | 130 | TokenizeStateNumber, // "123", "0x123" |
| 123 | 131 | TokenizeStateFloatFraction, // "123.456", "0x123.456" |
| 124 | 132 | TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p" |
| 125 | 133 | TokenizeStateFloatExponentNumber, // "123.456e-", "123.456e5", "123.456e5e-5" |
| 126 | 134 | TokenizeStateString, |
| 135 | TokenizeStateRawString, |
| 136 | TokenizeStateRawStringContents, |
| 137 | TokenizeStateRawStringMaybeEnd, |
| 127 | 138 | TokenizeStateCharLiteral, |
| 128 | 139 | TokenizeStateSawStar, |
| 129 | 140 | TokenizeStateSawSlash, |
| ... | ... | @@ -162,6 +173,9 @@ struct Tokenize { |
| 162 | 173 | Token *cur_tok; |
| 163 | 174 | int multi_line_comment_count; |
| 164 | 175 | Tokenization *out; |
| 176 | int raw_string_id_start; |
| 177 | int raw_string_id_end; |
| 178 | int raw_string_id_cmp_pos; |
| 165 | 179 | }; |
| 166 | 180 | |
| 167 | 181 | __attribute__ ((format (printf, 2, 3))) |
| ... | ... | @@ -193,6 +207,8 @@ static void begin_token(Tokenize *t, TokenId id) { |
| 193 | 207 | token->radix = 0; |
| 194 | 208 | token->decimal_point_pos = 0; |
| 195 | 209 | token->exponent_marker_pos = 0; |
| 210 | token->raw_string_start = 0; |
| 211 | token->raw_string_end = 0; |
| 196 | 212 | t->cur_tok = token; |
| 197 | 213 | } |
| 198 | 214 | |
| ... | ... | @@ -324,7 +340,11 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 324 | 340 | t.state = TokenizeStateSymbolFirst; |
| 325 | 341 | begin_token(&t, TokenIdSymbol); |
| 326 | 342 | break; |
| 327 | | case ALPHA_EXCEPT_C: |
| 343 | case 'r': |
| 344 | t.state = TokenizeStateFirstR; |
| 345 | begin_token(&t, TokenIdSymbol); |
| 346 | break; |
| 347 | case ALPHA_EXCEPT_CR: |
| 328 | 348 | case '_': |
| 329 | 349 | t.state = TokenizeStateSymbol; |
| 330 | 350 | begin_token(&t, TokenIdSymbol); |
| ... | ... | @@ -821,6 +841,43 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 821 | 841 | continue; |
| 822 | 842 | } |
| 823 | 843 | break; |
| 844 | case TokenizeStateSymbolFirstRaw: |
| 845 | switch (c) { |
| 846 | case '"': |
| 847 | t.cur_tok->id = TokenIdStringLiteral; |
| 848 | t.state = TokenizeStateRawString; |
| 849 | t.raw_string_id_start = t.pos + 1; |
| 850 | break; |
| 851 | case SYMBOL_CHAR: |
| 852 | t.state = TokenizeStateSymbol; |
| 853 | break; |
| 854 | default: |
| 855 | t.pos -= 1; |
| 856 | end_token(&t); |
| 857 | t.state = TokenizeStateStart; |
| 858 | continue; |
| 859 | } |
| 860 | break; |
| 861 | case TokenizeStateFirstR: |
| 862 | switch (c) { |
| 863 | case '"': |
| 864 | t.cur_tok->id = TokenIdStringLiteral; |
| 865 | t.state = TokenizeStateRawString; |
| 866 | t.raw_string_id_start = t.pos + 1; |
| 867 | break; |
| 868 | case 'c': |
| 869 | t.state = TokenizeStateSymbolFirstRaw; |
| 870 | break; |
| 871 | case SYMBOL_CHAR_EXCEPT_C: |
| 872 | t.state = TokenizeStateSymbol; |
| 873 | break; |
| 874 | default: |
| 875 | t.pos -= 1; |
| 876 | end_token(&t); |
| 877 | t.state = TokenizeStateStart; |
| 878 | continue; |
| 879 | } |
| 880 | break; |
| 824 | 881 | case TokenizeStateSymbol: |
| 825 | 882 | switch (c) { |
| 826 | 883 | case SYMBOL_CHAR: |
| ... | ... | @@ -838,10 +895,44 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 838 | 895 | end_token(&t); |
| 839 | 896 | t.state = TokenizeStateStart; |
| 840 | 897 | break; |
| 898 | case '\n': |
| 899 | tokenize_error(&t, "use raw string for multiline string literal"); |
| 900 | break; |
| 841 | 901 | default: |
| 842 | 902 | break; |
| 843 | 903 | } |
| 844 | 904 | break; |
| 905 | case TokenizeStateRawString: |
| 906 | if (c == '(') { |
| 907 | t.raw_string_id_end = t.pos; |
| 908 | t.cur_tok->raw_string_start = t.pos + 1; |
| 909 | t.state = TokenizeStateRawStringContents; |
| 910 | } |
| 911 | break; |
| 912 | case TokenizeStateRawStringContents: |
| 913 | if (c == ')') { |
| 914 | t.state = TokenizeStateRawStringMaybeEnd; |
| 915 | t.raw_string_id_cmp_pos = t.raw_string_id_start; |
| 916 | t.cur_tok->raw_string_end = t.pos; |
| 917 | } |
| 918 | break; |
| 919 | case TokenizeStateRawStringMaybeEnd: |
| 920 | if (t.raw_string_id_cmp_pos >= t.raw_string_id_end && |
| 921 | c == '"') |
| 922 | { |
| 923 | end_token(&t); |
| 924 | t.state = TokenizeStateStart; |
| 925 | } else if (c != buf_ptr(t.buf)[t.raw_string_id_cmp_pos]) { |
| 926 | if (c == ')') { |
| 927 | t.raw_string_id_cmp_pos = t.raw_string_id_start; |
| 928 | t.cur_tok->raw_string_end = t.pos; |
| 929 | } else { |
| 930 | t.state = TokenizeStateRawStringContents; |
| 931 | } |
| 932 | } else { |
| 933 | t.raw_string_id_cmp_pos += 1; |
| 934 | } |
| 935 | break; |
| 845 | 936 | case TokenizeStateCharLiteral: |
| 846 | 937 | switch (c) { |
| 847 | 938 | case '\'': |
| ... | ... | @@ -1002,11 +1093,18 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1002 | 1093 | case TokenizeStateString: |
| 1003 | 1094 | tokenize_error(&t, "unterminated string"); |
| 1004 | 1095 | break; |
| 1096 | case TokenizeStateRawString: |
| 1097 | case TokenizeStateRawStringContents: |
| 1098 | case TokenizeStateRawStringMaybeEnd: |
| 1099 | tokenize_error(&t, "unterminated raw string"); |
| 1100 | break; |
| 1005 | 1101 | case TokenizeStateCharLiteral: |
| 1006 | 1102 | tokenize_error(&t, "unterminated character literal"); |
| 1007 | 1103 | break; |
| 1008 | 1104 | case TokenizeStateSymbol: |
| 1009 | 1105 | case TokenizeStateSymbolFirst: |
| 1106 | case TokenizeStateSymbolFirstRaw: |
| 1107 | case TokenizeStateFirstR: |
| 1010 | 1108 | case TokenizeStateZero: |
| 1011 | 1109 | case TokenizeStateNumber: |
| 1012 | 1110 | case TokenizeStateFloatFraction: |