| ... | @@ -6,12 +6,12 @@ pub const Token = struct { | ... | @@ -6,12 +6,12 @@ pub const Token = struct { |
| 6 | start: usize, | 6 | start: usize, |
| 7 | end: usize, | 7 | end: usize, |
| 8 | | 8 | |
| 9 | const Keyword = struct { | 9 | pub const Keyword = struct { |
| 10 | bytes: []const u8, | 10 | bytes: []const u8, |
| 11 | id: Id, | 11 | id: Id, |
| 12 | }; | 12 | }; |
| 13 | | 13 | |
| 14 | const keywords = []Keyword { | 14 | pub const keywords = []Keyword { |
| 15 | Keyword{.bytes="align", .id = Id.Keyword_align}, | 15 | Keyword{.bytes="align", .id = Id.Keyword_align}, |
| 16 | Keyword{.bytes="and", .id = Id.Keyword_and}, | 16 | Keyword{.bytes="and", .id = Id.Keyword_and}, |
| 17 | Keyword{.bytes="asm", .id = Id.Keyword_asm}, | 17 | Keyword{.bytes="asm", .id = Id.Keyword_asm}, |
| ... | @@ -62,6 +62,7 @@ pub const Token = struct { | ... | @@ -62,6 +62,7 @@ pub const Token = struct { |
| 62 | Keyword{.bytes="while", .id = Id.Keyword_while}, | 62 | Keyword{.bytes="while", .id = Id.Keyword_while}, |
| 63 | }; | 63 | }; |
| 64 | | 64 | |
| | 65 | // TODO perfect hash at comptime |
| 65 | fn getKeyword(bytes: []const u8) ?Id { | 66 | fn getKeyword(bytes: []const u8) ?Id { |
| 66 | for (keywords) |kw| { | 67 | for (keywords) |kw| { |
| 67 | if (mem.eql(u8, kw.bytes, bytes)) { | 68 | if (mem.eql(u8, kw.bytes, bytes)) { |
| ... | @@ -236,10 +237,15 @@ pub const Tokenizer = struct { | ... | @@ -236,10 +237,15 @@ pub const Tokenizer = struct { |
| 236 | Zero, | 237 | Zero, |
| 237 | IntegerLiteral, | 238 | IntegerLiteral, |
| 238 | IntegerLiteralWithRadix, | 239 | IntegerLiteralWithRadix, |
| | 240 | IntegerLiteralWithRadixHex, |
| 239 | NumberDot, | 241 | NumberDot, |
| | 242 | NumberDotHex, |
| 240 | FloatFraction, | 243 | FloatFraction, |
| | 244 | FloatFractionHex, |
| 241 | FloatExponentUnsigned, | 245 | FloatExponentUnsigned, |
| | 246 | FloatExponentUnsignedHex, |
| 242 | FloatExponentNumber, | 247 | FloatExponentNumber, |
| | 248 | FloatExponentNumberHex, |
| 243 | Ampersand, | 249 | Ampersand, |
| 244 | Caret, | 250 | Caret, |
| 245 | Percent, | 251 | Percent, |
| ... | @@ -839,9 +845,12 @@ pub const Tokenizer = struct { | ... | @@ -839,9 +845,12 @@ pub const Tokenizer = struct { |
| 839 | else => self.checkLiteralCharacter(), | 845 | else => self.checkLiteralCharacter(), |
| 840 | }, | 846 | }, |
| 841 | State.Zero => switch (c) { | 847 | State.Zero => switch (c) { |
| 842 | 'b', 'o', 'x' => { | 848 | 'b', 'o' => { |
| 843 | state = State.IntegerLiteralWithRadix; | 849 | state = State.IntegerLiteralWithRadix; |
| 844 | }, | 850 | }, |
| | 851 | 'x' => { |
| | 852 | state = State.IntegerLiteralWithRadixHex; |
| | 853 | }, |
| 845 | else => { | 854 | else => { |
| 846 | // reinterpret as a normal number | 855 | // reinterpret as a normal number |
| 847 | self.index -= 1; | 856 | self.index -= 1; |
| ... | @@ -862,8 +871,15 @@ pub const Tokenizer = struct { | ... | @@ -862,8 +871,15 @@ pub const Tokenizer = struct { |
| 862 | '.' => { | 871 | '.' => { |
| 863 | state = State.NumberDot; | 872 | state = State.NumberDot; |
| 864 | }, | 873 | }, |
| | 874 | '0'...'9' => {}, |
| | 875 | else => break, |
| | 876 | }, |
| | 877 | State.IntegerLiteralWithRadixHex => switch (c) { |
| | 878 | '.' => { |
| | 879 | state = State.NumberDotHex; |
| | 880 | }, |
| 865 | 'p', 'P' => { | 881 | 'p', 'P' => { |
| 866 | state = State.FloatExponentUnsigned; | 882 | state = State.FloatExponentUnsignedHex; |
| 867 | }, | 883 | }, |
| 868 | '0'...'9', 'a'...'f', 'A'...'F' => {}, | 884 | '0'...'9', 'a'...'f', 'A'...'F' => {}, |
| 869 | else => break, | 885 | else => break, |
| ... | @@ -880,13 +896,32 @@ pub const Tokenizer = struct { | ... | @@ -880,13 +896,32 @@ pub const Tokenizer = struct { |
| 880 | state = State.FloatFraction; | 896 | state = State.FloatFraction; |
| 881 | }, | 897 | }, |
| 882 | }, | 898 | }, |
| | 899 | State.NumberDotHex => switch (c) { |
| | 900 | '.' => { |
| | 901 | self.index -= 1; |
| | 902 | state = State.Start; |
| | 903 | break; |
| | 904 | }, |
| | 905 | else => { |
| | 906 | self.index -= 1; |
| | 907 | result.id = Token.Id.FloatLiteral; |
| | 908 | state = State.FloatFractionHex; |
| | 909 | }, |
| | 910 | }, |
| 883 | State.FloatFraction => switch (c) { | 911 | State.FloatFraction => switch (c) { |
| 884 | 'p', 'P', 'e', 'E' => { | 912 | 'e', 'E' => { |
| 885 | state = State.FloatExponentUnsigned; | 913 | state = State.FloatExponentUnsigned; |
| 886 | }, | 914 | }, |
| 887 | '0'...'9' => {}, | 915 | '0'...'9' => {}, |
| 888 | else => break, | 916 | else => break, |
| 889 | }, | 917 | }, |
| | 918 | State.FloatFractionHex => switch (c) { |
| | 919 | 'p', 'P' => { |
| | 920 | state = State.FloatExponentUnsignedHex; |
| | 921 | }, |
| | 922 | '0'...'9', 'a'...'f', 'A'...'F' => {}, |
| | 923 | else => break, |
| | 924 | }, |
| 890 | State.FloatExponentUnsigned => switch (c) { | 925 | State.FloatExponentUnsigned => switch (c) { |
| 891 | '+', '-' => { | 926 | '+', '-' => { |
| 892 | state = State.FloatExponentNumber; | 927 | state = State.FloatExponentNumber; |
| ... | @@ -897,7 +932,21 @@ pub const Tokenizer = struct { | ... | @@ -897,7 +932,21 @@ pub const Tokenizer = struct { |
| 897 | state = State.FloatExponentNumber; | 932 | state = State.FloatExponentNumber; |
| 898 | } | 933 | } |
| 899 | }, | 934 | }, |
| | 935 | State.FloatExponentUnsignedHex => switch (c) { |
| | 936 | '+', '-' => { |
| | 937 | state = State.FloatExponentNumberHex; |
| | 938 | }, |
| | 939 | else => { |
| | 940 | // reinterpret as a normal exponent number |
| | 941 | self.index -= 1; |
| | 942 | state = State.FloatExponentNumberHex; |
| | 943 | } |
| | 944 | }, |
| 900 | State.FloatExponentNumber => switch (c) { | 945 | State.FloatExponentNumber => switch (c) { |
| | 946 | '0'...'9' => {}, |
| | 947 | else => break, |
| | 948 | }, |
| | 949 | State.FloatExponentNumberHex => switch (c) { |
| 901 | '0'...'9', 'a'...'f', 'A'...'F' => {}, | 950 | '0'...'9', 'a'...'f', 'A'...'F' => {}, |
| 902 | else => break, | 951 | else => break, |
| 903 | }, | 952 | }, |
| ... | @@ -908,8 +957,11 @@ pub const Tokenizer = struct { | ... | @@ -908,8 +957,11 @@ pub const Tokenizer = struct { |
| 908 | State.C, | 957 | State.C, |
| 909 | State.IntegerLiteral, | 958 | State.IntegerLiteral, |
| 910 | State.IntegerLiteralWithRadix, | 959 | State.IntegerLiteralWithRadix, |
| | 960 | State.IntegerLiteralWithRadixHex, |
| 911 | State.FloatFraction, | 961 | State.FloatFraction, |
| | 962 | State.FloatFractionHex, |
| 912 | State.FloatExponentNumber, | 963 | State.FloatExponentNumber, |
| | 964 | State.FloatExponentNumberHex, |
| 913 | State.StringLiteral, // find this error later | 965 | State.StringLiteral, // find this error later |
| 914 | State.MultilineStringLiteralLine, | 966 | State.MultilineStringLiteralLine, |
| 915 | State.Builtin => {}, | 967 | State.Builtin => {}, |
| ... | @@ -928,7 +980,9 @@ pub const Tokenizer = struct { | ... | @@ -928,7 +980,9 @@ pub const Tokenizer = struct { |
| 928 | }, | 980 | }, |
| 929 | | 981 | |
| 930 | State.NumberDot, | 982 | State.NumberDot, |
| | 983 | State.NumberDotHex, |
| 931 | State.FloatExponentUnsigned, | 984 | State.FloatExponentUnsigned, |
| | 985 | State.FloatExponentUnsignedHex, |
| 932 | State.SawAtSign, | 986 | State.SawAtSign, |
| 933 | State.Backslash, | 987 | State.Backslash, |
| 934 | State.MultilineStringLiteralLineBackslash, | 988 | State.MultilineStringLiteralLineBackslash, |
| ... | @@ -1073,7 +1127,7 @@ test "tokenizer" { | ... | @@ -1073,7 +1127,7 @@ test "tokenizer" { |
| 1073 | }); | 1127 | }); |
| 1074 | } | 1128 | } |
| 1075 | | 1129 | |
| 1076 | test "tokenizer - float literal" { | 1130 | test "tokenizer - float literal e exponent" { |
| 1077 | testTokenize("a = 4.94065645841246544177e-324;\n", []Token.Id { | 1131 | testTokenize("a = 4.94065645841246544177e-324;\n", []Token.Id { |
| 1078 | Token.Id.Identifier, | 1132 | Token.Id.Identifier, |
| 1079 | Token.Id.Equal, | 1133 | Token.Id.Equal, |
| ... | @@ -1082,6 +1136,15 @@ test "tokenizer - float literal" { | ... | @@ -1082,6 +1136,15 @@ test "tokenizer - float literal" { |
| 1082 | }); | 1136 | }); |
| 1083 | } | 1137 | } |
| 1084 | | 1138 | |
| | 1139 | test "tokenizer - float literal p exponent" { |
| | 1140 | testTokenize("a = 0x1.a827999fcef32p+1022;\n", []Token.Id { |
| | 1141 | Token.Id.Identifier, |
| | 1142 | Token.Id.Equal, |
| | 1143 | Token.Id.FloatLiteral, |
| | 1144 | Token.Id.Semicolon, |
| | 1145 | }); |
| | 1146 | } |
| | 1147 | |
| 1085 | test "tokenizer - chars" { | 1148 | test "tokenizer - chars" { |
| 1086 | testTokenize("'c'", []Token.Id {Token.Id.CharLiteral}); | 1149 | testTokenize("'c'", []Token.Id {Token.Id.CharLiteral}); |
| 1087 | } | 1150 | } |