| ... | @@ -31,7 +31,6 @@ pub const Token = struct { | ... | @@ -31,7 +31,6 @@ pub const Token = struct { |
| 31 | PipeEqual, | 31 | PipeEqual, |
| 32 | Equal, | 32 | Equal, |
| 33 | EqualEqual, | 33 | EqualEqual, |
| 34 | EqualAngleBracketRight, | | |
| 35 | LParen, | 34 | LParen, |
| 36 | RParen, | 35 | RParen, |
| 37 | LBrace, | 36 | LBrace, |
| ... | @@ -39,7 +38,6 @@ pub const Token = struct { | ... | @@ -39,7 +38,6 @@ pub const Token = struct { |
| 39 | LBracket, | 38 | LBracket, |
| 40 | RBracket, | 39 | RBracket, |
| 41 | Period, | 40 | Period, |
| 42 | PeriodAsterisk, | | |
| 43 | Ellipsis, | 41 | Ellipsis, |
| 44 | Caret, | 42 | Caret, |
| 45 | CaretEqual, | 43 | CaretEqual, |
| ... | @@ -253,7 +251,7 @@ pub const Token = struct { | ... | @@ -253,7 +251,7 @@ pub const Token = struct { |
| 253 | pub const Tokenizer = struct { | 251 | pub const Tokenizer = struct { |
| 254 | source: *Source, | 252 | source: *Source, |
| 255 | index: usize = 0, | 253 | index: usize = 0, |
| 256 | prev_tok_id: @TagType(Token.Id), | 254 | prev_tok_id: @TagType(Token.Id) = .Invalid, |
| 257 | | 255 | |
| 258 | pub fn next(self: *Tokenizer) Token { | 256 | pub fn next(self: *Tokenizer) Token { |
| 259 | const start_index = self.index; | 257 | const start_index = self.index; |
| ... | @@ -296,6 +294,7 @@ pub const Tokenizer = struct { | ... | @@ -296,6 +294,7 @@ pub const Tokenizer = struct { |
| 296 | Minus, | 294 | Minus, |
| 297 | Slash, | 295 | Slash, |
| 298 | Ampersand, | 296 | Ampersand, |
| | 297 | Hash, |
| 299 | LineComment, | 298 | LineComment, |
| 300 | MultiLineComment, | 299 | MultiLineComment, |
| 301 | MultiLineCommentAsterisk, | 300 | MultiLineCommentAsterisk, |
| ... | @@ -329,9 +328,6 @@ pub const Tokenizer = struct { | ... | @@ -329,9 +328,6 @@ pub const Tokenizer = struct { |
| 329 | '\r' => { | 328 | '\r' => { |
| 330 | state = .Cr; | 329 | state = .Cr; |
| 331 | }, | 330 | }, |
| 332 | ' ', '\t' => { | | |
| 333 | result.start = self.index + 1; | | |
| 334 | }, | | |
| 335 | '"' => { | 331 | '"' => { |
| 336 | result.id = .{ .StringLiteral = .None }; | 332 | result.id = .{ .StringLiteral = .None }; |
| 337 | state = .StringLiteral; | 333 | state = .StringLiteral; |
| ... | @@ -449,6 +445,9 @@ pub const Tokenizer = struct { | ... | @@ -449,6 +445,9 @@ pub const Tokenizer = struct { |
| 449 | '&' => { | 445 | '&' => { |
| 450 | state = .Ampersand; | 446 | state = .Ampersand; |
| 451 | }, | 447 | }, |
| | 448 | '#' => { |
| | 449 | state = .Hash; |
| | 450 | }, |
| 452 | '0' => { | 451 | '0' => { |
| 453 | state = .Zero; | 452 | state = .Zero; |
| 454 | }, | 453 | }, |
| ... | @@ -456,9 +455,7 @@ pub const Tokenizer = struct { | ... | @@ -456,9 +455,7 @@ pub const Tokenizer = struct { |
| 456 | state = .IntegerLiteral; | 455 | state = .IntegerLiteral; |
| 457 | }, | 456 | }, |
| 458 | else => { | 457 | else => { |
| 459 | result.id = .Invalid; | 458 | result.start = self.index + 1; |
| 460 | self.index += 1; | | |
| 461 | break; | | |
| 462 | }, | 459 | }, |
| 463 | }, | 460 | }, |
| 464 | .Cr => switch (c) { | 461 | .Cr => switch (c) { |
| ... | @@ -833,6 +830,17 @@ pub const Tokenizer = struct { | ... | @@ -833,6 +830,17 @@ pub const Tokenizer = struct { |
| 833 | break; | 830 | break; |
| 834 | }, | 831 | }, |
| 835 | }, | 832 | }, |
| | 833 | .Hash => switch (c) { |
| | 834 | '#' => { |
| | 835 | result.id = .HashHash; |
| | 836 | self.index += 1; |
| | 837 | break; |
| | 838 | }, |
| | 839 | else => { |
| | 840 | result.id = .Hash; |
| | 841 | break; |
| | 842 | }, |
| | 843 | }, |
| 836 | .LineComment => switch (c) { | 844 | .LineComment => switch (c) { |
| 837 | '\n' => { | 845 | '\n' => { |
| 838 | result.id = .LineComment; | 846 | result.id = .LineComment; |
| ... | @@ -1069,6 +1077,7 @@ pub const Tokenizer = struct { | ... | @@ -1069,6 +1077,7 @@ pub const Tokenizer = struct { |
| 1069 | .Minus => result.id = .Minus, | 1077 | .Minus => result.id = .Minus, |
| 1070 | .Slash => result.id = .Slash, | 1078 | .Slash => result.id = .Slash, |
| 1071 | .Ampersand => result.id = .Ampersand, | 1079 | .Ampersand => result.id = .Ampersand, |
| | 1080 | .Hash => result.id = .Hash, |
| 1072 | .Period => result.id = .Period, | 1081 | .Period => result.id = .Period, |
| 1073 | .Pipe => result.id = .Pipe, | 1082 | .Pipe => result.id = .Pipe, |
| 1074 | .AngleBracketAngleBracketRight => result.id = .AngleBracketAngleBracketRight, | 1083 | .AngleBracketAngleBracketRight => result.id = .AngleBracketAngleBracketRight, |
| ... | @@ -1089,16 +1098,192 @@ pub const Tokenizer = struct { | ... | @@ -1089,16 +1098,192 @@ pub const Tokenizer = struct { |
| 1089 | } | 1098 | } |
| 1090 | }; | 1099 | }; |
| 1091 | | 1100 | |
| | 1101 | test "operators" { |
| | 1102 | expectTokens( |
| | 1103 | \\ ! != | || |= = == |
| | 1104 | \\ ( ) { } [ ] . .. ... |
| | 1105 | \\ ^ ^= + ++ += - -- -= |
| | 1106 | \\ * *= % %= -> : ; / /= |
| | 1107 | \\ , & && &= ? < <= << |
| | 1108 | \\ <<= > >= >> >>= ~ # ## |
| | 1109 | \\ |
| | 1110 | , |
| | 1111 | &[_]Token.Id{ |
| | 1112 | .Bang, |
| | 1113 | .BangEqual, |
| | 1114 | .Pipe, |
| | 1115 | .PipePipe, |
| | 1116 | .PipeEqual, |
| | 1117 | .Equal, |
| | 1118 | .EqualEqual, |
| | 1119 | .Nl, |
| | 1120 | |
| | 1121 | .LParen, |
| | 1122 | .RParen, |
| | 1123 | .LBrace, |
| | 1124 | .RBrace, |
| | 1125 | .LBracket, |
| | 1126 | .RBracket, |
| | 1127 | .Period, |
| | 1128 | .Period, |
| | 1129 | .Period, |
| | 1130 | .Ellipsis, |
| | 1131 | .Nl, |
| | 1132 | |
| | 1133 | .Caret, |
| | 1134 | .CaretEqual, |
| | 1135 | .Plus, |
| | 1136 | .PlusPlus, |
| | 1137 | .PlusEqual, |
| | 1138 | .Minus, |
| | 1139 | .MinusMinus, |
| | 1140 | .MinusEqual, |
| | 1141 | .Nl, |
| | 1142 | |
| | 1143 | .Asterisk, |
| | 1144 | .AsteriskEqual, |
| | 1145 | .Percent, |
| | 1146 | .PercentEqual, |
| | 1147 | .Arrow, |
| | 1148 | .Colon, |
| | 1149 | .Semicolon, |
| | 1150 | .Slash, |
| | 1151 | .SlashEqual, |
| | 1152 | .Nl, |
| | 1153 | |
| | 1154 | .Comma, |
| | 1155 | .Ampersand, |
| | 1156 | .AmpersandAmpersand, |
| | 1157 | .AmpersandEqual, |
| | 1158 | .QuestionMark, |
| | 1159 | .AngleBracketLeft, |
| | 1160 | .AngleBracketLeftEqual, |
| | 1161 | .AngleBracketAngleBracketLeft, |
| | 1162 | .Nl, |
| | 1163 | |
| | 1164 | .AngleBracketAngleBracketLeftEqual, |
| | 1165 | .AngleBracketRight, |
| | 1166 | .AngleBracketRightEqual, |
| | 1167 | .AngleBracketAngleBracketRight, |
| | 1168 | .AngleBracketAngleBracketRightEqual, |
| | 1169 | .Tilde, |
| | 1170 | .Hash, |
| | 1171 | .HashHash, |
| | 1172 | .Nl, |
| | 1173 | }, |
| | 1174 | ); |
| | 1175 | } |
| | 1176 | |
| | 1177 | test "keywords" { |
| | 1178 | expectTokens( |
| | 1179 | \\auto break case char const continue default do |
| | 1180 | \\double else enum extern float for goto if int |
| | 1181 | \\long register return short signed sizeof static |
| | 1182 | \\struct switch typedef union unsigned void volatile |
| | 1183 | \\while _Bool _Complex _Imaginary inline restrict _Alignas |
| | 1184 | \\_Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local |
| | 1185 | \\ |
| | 1186 | , &[_]Token.Id{ |
| | 1187 | .Keyword_auto, |
| | 1188 | .Keyword_break, |
| | 1189 | .Keyword_case, |
| | 1190 | .Keyword_char, |
| | 1191 | .Keyword_const, |
| | 1192 | .Keyword_continue, |
| | 1193 | .Keyword_default, |
| | 1194 | .Keyword_do, |
| | 1195 | .Nl, |
| | 1196 | |
| | 1197 | .Keyword_double, |
| | 1198 | .Keyword_else, |
| | 1199 | .Keyword_enum, |
| | 1200 | .Keyword_extern, |
| | 1201 | .Keyword_float, |
| | 1202 | .Keyword_for, |
| | 1203 | .Keyword_goto, |
| | 1204 | .Keyword_if, |
| | 1205 | .Keyword_int, |
| | 1206 | .Nl, |
| | 1207 | |
| | 1208 | .Keyword_long, |
| | 1209 | .Keyword_register, |
| | 1210 | .Keyword_return, |
| | 1211 | .Keyword_short, |
| | 1212 | .Keyword_signed, |
| | 1213 | .Keyword_sizeof, |
| | 1214 | .Keyword_static, |
| | 1215 | .Nl, |
| | 1216 | |
| | 1217 | .Keyword_struct, |
| | 1218 | .Keyword_switch, |
| | 1219 | .Keyword_typedef, |
| | 1220 | .Keyword_union, |
| | 1221 | .Keyword_unsigned, |
| | 1222 | .Keyword_void, |
| | 1223 | .Keyword_volatile, |
| | 1224 | .Nl, |
| | 1225 | |
| | 1226 | .Keyword_while, |
| | 1227 | .Keyword_bool, |
| | 1228 | .Keyword_complex, |
| | 1229 | .Keyword_imaginary, |
| | 1230 | .Keyword_inline, |
| | 1231 | .Keyword_restrict, |
| | 1232 | .Keyword_alignas, |
| | 1233 | .Nl, |
| | 1234 | |
| | 1235 | .Keyword_alignof, |
| | 1236 | .Keyword_atomic, |
| | 1237 | .Keyword_generic, |
| | 1238 | .Keyword_noreturn, |
| | 1239 | .Keyword_static_assert, |
| | 1240 | .Keyword_thread_local, |
| | 1241 | .Nl, |
| | 1242 | }); |
| | 1243 | } |
| | 1244 | |
| | 1245 | test "preprocessor keywords" { |
| | 1246 | expectTokens( |
| | 1247 | \\#include <test> |
| | 1248 | \\#define |
| | 1249 | \\#ifdef |
| | 1250 | \\#ifndef |
| | 1251 | \\#error |
| | 1252 | \\#pragma |
| | 1253 | \\ |
| | 1254 | , &[_]Token.Id{ |
| | 1255 | .Hash, |
| | 1256 | .Keyword_include, |
| | 1257 | .MacroString, |
| | 1258 | .Nl, |
| | 1259 | .Hash, |
| | 1260 | .Keyword_define, |
| | 1261 | .Nl, |
| | 1262 | .Hash, |
| | 1263 | .Keyword_ifdef, |
| | 1264 | .Nl, |
| | 1265 | .Hash, |
| | 1266 | .Keyword_ifndef, |
| | 1267 | .Nl, |
| | 1268 | .Hash, |
| | 1269 | .Keyword_error, |
| | 1270 | .Nl, |
| | 1271 | .Hash, |
| | 1272 | .Keyword_pragma, |
| | 1273 | .Nl, |
| | 1274 | }); |
| | 1275 | } |
| | 1276 | |
| 1092 | fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) void { | 1277 | fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) void { |
| 1093 | var tokenizer = Tokenizer{ | 1278 | var tokenizer = Tokenizer{ |
| 1094 | .source = .{ | 1279 | .source = &Source{ |
| 1095 | .buffer = source, | 1280 | .buffer = source, |
| 1096 | .file_name = undefined, | 1281 | .file_name = undefined, |
| 1097 | }, | 1282 | }, |
| 1098 | }; | 1283 | }; |
| 1099 | for (expected_tokens) |expected_token_id| { | 1284 | for (expected_tokens) |expected_token_id| { |
| 1100 | const token = tokenizer.next(); | 1285 | const token = tokenizer.next(); |
| 1101 | if (token.id != expected_token_id) { | 1286 | if (!std.meta.eql(token.id, expected_token_id)) { |
| 1102 | std.debug.panic("expected {}, found {}\n", .{ @tagName(expected_token_id), @tagName(token.id) }); | 1287 | std.debug.panic("expected {}, found {}\n", .{ @tagName(expected_token_id), @tagName(token.id) }); |
| 1103 | } | 1288 | } |
| 1104 | } | 1289 | } |