| author | |
| committer | |
| log | 530f79576923989928afeeb8b50b7e40b95a529f |
| tree | bfb369729475fce98d03cb25b7229725b2eed0fe |
| parent | b80398b3558be09d0950415b0a8feeb09bc2f55d |
3 files changed, 535 insertions(+), 62 deletions(-)
std/zig/ast.zig+60-1| ... | ... | @@ -20,6 +20,7 @@ pub const Node = struct { |
| 20 | 20 | IntegerLiteral, |
| 21 | 21 | FloatLiteral, |
| 22 | 22 | StringLiteral, |
| 23 | UndefinedLiteral, | |
| 23 | 24 | BuiltinCall, |
| 24 | 25 | LineComment, |
| 25 | 26 | TestDecl, |
| ... | ... | @@ -38,6 +39,7 @@ pub const Node = struct { |
| 38 | 39 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), |
| 39 | 40 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), |
| 40 | 41 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), |
| 42 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index), | |
| 41 | 43 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), |
| 42 | 44 | Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index), |
| 43 | 45 | Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index), |
| ... | ... | @@ -57,6 +59,7 @@ pub const Node = struct { |
| 57 | 59 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), |
| 58 | 60 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), |
| 59 | 61 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), |
| 62 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(), | |
| 60 | 63 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), |
| 61 | 64 | Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(), |
| 62 | 65 | Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(), |
| ... | ... | @@ -76,6 +79,7 @@ pub const Node = struct { |
| 76 | 79 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), |
| 77 | 80 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), |
| 78 | 81 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), |
| 82 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(), | |
| 79 | 83 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), |
| 80 | 84 | Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(), |
| 81 | 85 | Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(), |
| ... | ... | @@ -309,9 +313,47 @@ pub const NodeInfixOp = struct { |
| 309 | 313 | rhs: &Node, |
| 310 | 314 | |
| 311 | 315 | const InfixOp = enum { |
| 312 | EqualEqual, | |
| 316 | Add, | |
| 317 | AddWrap, | |
| 318 | ArrayCat, | |
| 319 | ArrayMult, | |
| 320 | Assign, | |
| 321 | AssignBitAnd, | |
| 322 | AssignBitOr, | |
| 323 | AssignBitShiftLeft, | |
| 324 | AssignBitShiftRight, | |
| 325 | AssignBitXor, | |
| 326 | AssignDiv, | |
| 327 | AssignMinus, | |
| 328 | AssignMinusWrap, | |
| 329 | AssignMod, | |
| 330 | AssignPlus, | |
| 331 | AssignPlusWrap, | |
| 332 | AssignTimes, | |
| 333 | AssignTimesWarp, | |
| 313 | 334 | BangEqual, |
| 335 | BitAnd, | |
| 336 | BitOr, | |
| 337 | BitShiftLeft, | |
| 338 | BitShiftRight, | |
| 339 | BitXor, | |
| 340 | BoolAnd, | |
| 341 | BoolOr, | |
| 342 | Div, | |
| 343 | EqualEqual, | |
| 344 | ErrorUnion, | |
| 345 | GreaterOrEqual, | |
| 346 | GreaterThan, | |
| 347 | LessOrEqual, | |
| 348 | LessThan, | |
| 349 | MergeErrorSets, | |
| 350 | Mod, | |
| 351 | Mult, | |
| 352 | MultWrap, | |
| 314 | 353 | Period, |
| 354 | Sub, | |
| 355 | SubWrap, | |
| 356 | UnwrapMaybe, | |
| 315 | 357 | }; |
| 316 | 358 | |
| 317 | 359 | pub fn iterate(self: &NodeInfixOp, index: usize) ?&Node { |
| ... | ... | @@ -464,6 +506,23 @@ pub const NodeStringLiteral = struct { |
| 464 | 506 | } |
| 465 | 507 | }; |
| 466 | 508 | |
| 509 | pub const NodeUndefinedLiteral = struct { | |
| 510 | base: Node, | |
| 511 | token: Token, | |
| 512 | ||
| 513 | pub fn iterate(self: &NodeUndefinedLiteral, index: usize) ?&Node { | |
| 514 | return null; | |
| 515 | } | |
| 516 | ||
| 517 | pub fn firstToken(self: &NodeUndefinedLiteral) Token { | |
| 518 | return self.token; | |
| 519 | } | |
| 520 | ||
| 521 | pub fn lastToken(self: &NodeUndefinedLiteral) Token { | |
| 522 | return self.token; | |
| 523 | } | |
| 524 | }; | |
| 525 | ||
| 467 | 526 | pub const NodeLineComment = struct { |
| 468 | 527 | base: Node, |
| 469 | 528 | lines: ArrayList(Token), |
std/zig/parser.zig+193-56| ... | ... | @@ -371,6 +371,13 @@ pub const Parser = struct { |
| 371 | 371 | try stack.append(State.AfterOperand); |
| 372 | 372 | continue; |
| 373 | 373 | }, |
| 374 | Token.Id.Keyword_undefined => { | |
| 375 | try stack.append(State { | |
| 376 | .Operand = &(try self.createUndefined(arena, token)).base | |
| 377 | }); | |
| 378 | try stack.append(State.AfterOperand); | |
| 379 | continue; | |
| 380 | }, | |
| 374 | 381 | Token.Id.Builtin => { |
| 375 | 382 | const node = try arena.create(ast.NodeBuiltinCall); |
| 376 | 383 | *node = ast.NodeBuiltinCall { |
| ... | ... | @@ -414,56 +421,41 @@ pub const Parser = struct { |
| 414 | 421 | // or a postfix operator (like () or {}), |
| 415 | 422 | // otherwise this expression is done (like on a ; or else). |
| 416 | 423 | var token = self.getNextToken(); |
| 417 | switch (token.id) { | |
| 418 | Token.Id.EqualEqual => { | |
| 419 | try stack.append(State { | |
| 420 | .InfixOp = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.EqualEqual) | |
| 421 | }); | |
| 422 | try stack.append(State.ExpectOperand); | |
| 423 | continue; | |
| 424 | }, | |
| 425 | Token.Id.BangEqual => { | |
| 424 | if (tokenIdToInfixOp(token.id)) |infix_id| { | |
| 426 | 425 | try stack.append(State { |
| 427 | .InfixOp = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BangEqual) | |
| 426 | .InfixOp = try self.createInfixOp(arena, token, infix_id) | |
| 428 | 427 | }); |
| 429 | 428 | try stack.append(State.ExpectOperand); |
| 430 | 429 | continue; |
| 431 | }, | |
| 432 | Token.Id.Period => { | |
| 433 | try stack.append(State { | |
| 434 | .InfixOp = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.Period) | |
| 435 | }); | |
| 436 | try stack.append(State.ExpectOperand); | |
| 437 | continue; | |
| 438 | }, | |
| 439 | else => { | |
| 440 | // no postfix/infix operator after this operand. | |
| 441 | self.putBackToken(token); | |
| 442 | // reduce the stack | |
| 443 | var expression: &ast.Node = stack.pop().Operand; | |
| 444 | while (true) { | |
| 445 | switch (stack.pop()) { | |
| 446 | State.Expression => |dest_ptr| { | |
| 447 | // we're done | |
| 448 | try dest_ptr.store(expression); | |
| 449 | break; | |
| 450 | }, | |
| 451 | State.InfixOp => |infix_op| { | |
| 452 | infix_op.rhs = expression; | |
| 453 | infix_op.lhs = stack.pop().Operand; | |
| 454 | expression = &infix_op.base; | |
| 455 | continue; | |
| 456 | }, | |
| 457 | State.PrefixOp => |prefix_op| { | |
| 458 | prefix_op.rhs = expression; | |
| 459 | expression = &prefix_op.base; | |
| 460 | continue; | |
| 461 | }, | |
| 462 | else => unreachable, | |
| 463 | } | |
| 430 | ||
| 431 | // TODO: Parse postfix operator | |
| 432 | } else { | |
| 433 | // no postfix/infix operator after this operand. | |
| 434 | self.putBackToken(token); | |
| 435 | // reduce the stack | |
| 436 | var expression: &ast.Node = stack.pop().Operand; | |
| 437 | while (true) { | |
| 438 | switch (stack.pop()) { | |
| 439 | State.Expression => |dest_ptr| { | |
| 440 | // we're done | |
| 441 | try dest_ptr.store(expression); | |
| 442 | break; | |
| 443 | }, | |
| 444 | State.InfixOp => |infix_op| { | |
| 445 | infix_op.rhs = expression; | |
| 446 | infix_op.lhs = stack.pop().Operand; | |
| 447 | expression = &infix_op.base; | |
| 448 | continue; | |
| 449 | }, | |
| 450 | State.PrefixOp => |prefix_op| { | |
| 451 | prefix_op.rhs = expression; | |
| 452 | expression = &prefix_op.base; | |
| 453 | continue; | |
| 454 | }, | |
| 455 | else => unreachable, | |
| 464 | 456 | } |
| 465 | continue; | |
| 466 | }, | |
| 457 | } | |
| 458 | continue; | |
| 467 | 459 | } |
| 468 | 460 | }, |
| 469 | 461 | |
| ... | ... | @@ -706,6 +698,53 @@ pub const Parser = struct { |
| 706 | 698 | } |
| 707 | 699 | } |
| 708 | 700 | |
| 701 | fn tokenIdToInfixOp(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp { | |
| 702 | return switch (*id) { | |
| 703 | Token.Id.Ampersand => ast.NodeInfixOp.InfixOp.BitAnd, | |
| 704 | Token.Id.AmpersandEqual => ast.NodeInfixOp.InfixOp.AssignBitAnd, | |
| 705 | Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp.BitShiftLeft, | |
| 706 | Token.Id.AngleBracketAngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftLeft, | |
| 707 | Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp.BitShiftRight, | |
| 708 | Token.Id.AngleBracketAngleBracketRightEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftRight, | |
| 709 | Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp.LessThan, | |
| 710 | Token.Id.AngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.LessOrEqual, | |
| 711 | Token.Id.AngleBracketRight => ast.NodeInfixOp.InfixOp.GreaterThan, | |
| 712 | Token.Id.AngleBracketRightEqual => ast.NodeInfixOp.InfixOp.GreaterOrEqual, | |
| 713 | Token.Id.Asterisk => ast.NodeInfixOp.InfixOp.Mult, | |
| 714 | Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp.ArrayMult, | |
| 715 | Token.Id.AsteriskEqual => ast.NodeInfixOp.InfixOp.AssignTimes, | |
| 716 | Token.Id.AsteriskPercent => ast.NodeInfixOp.InfixOp.MultWrap, | |
| 717 | Token.Id.AsteriskPercentEqual => ast.NodeInfixOp.InfixOp.AssignTimesWarp, | |
| 718 | Token.Id.Bang => ast.NodeInfixOp.InfixOp.ErrorUnion, | |
| 719 | Token.Id.BangEqual => ast.NodeInfixOp.InfixOp.BangEqual, | |
| 720 | Token.Id.Caret => ast.NodeInfixOp.InfixOp.BitXor, | |
| 721 | Token.Id.CaretEqual => ast.NodeInfixOp.InfixOp.AssignBitXor, | |
| 722 | Token.Id.Equal => ast.NodeInfixOp.InfixOp.Assign, | |
| 723 | Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp.EqualEqual, | |
| 724 | Token.Id.Keyword_and => ast.NodeInfixOp.InfixOp.BoolAnd, | |
| 725 | Token.Id.Keyword_or => ast.NodeInfixOp.InfixOp.BoolOr, | |
| 726 | Token.Id.Minus => ast.NodeInfixOp.InfixOp.Sub, | |
| 727 | Token.Id.MinusEqual => ast.NodeInfixOp.InfixOp.AssignMinus, | |
| 728 | Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp.SubWrap, | |
| 729 | Token.Id.MinusPercentEqual => ast.NodeInfixOp.InfixOp.AssignMinusWrap, | |
| 730 | Token.Id.Percent => ast.NodeInfixOp.InfixOp.Mod, | |
| 731 | Token.Id.PercentEqual => ast.NodeInfixOp.InfixOp.AssignMod, | |
| 732 | Token.Id.Period => ast.NodeInfixOp.InfixOp.Period, | |
| 733 | Token.Id.Pipe => ast.NodeInfixOp.InfixOp.BitOr, | |
| 734 | Token.Id.PipeEqual => ast.NodeInfixOp.InfixOp.AssignBitOr, | |
| 735 | Token.Id.PipePipe => ast.NodeInfixOp.InfixOp.MergeErrorSets, | |
| 736 | Token.Id.Plus => ast.NodeInfixOp.InfixOp.Add, | |
| 737 | Token.Id.PlusEqual => ast.NodeInfixOp.InfixOp.AssignPlus, | |
| 738 | Token.Id.PlusPercent => ast.NodeInfixOp.InfixOp.AddWrap, | |
| 739 | Token.Id.PlusPercentEqual => ast.NodeInfixOp.InfixOp.AssignPlusWrap, | |
| 740 | Token.Id.PlusPlus => ast.NodeInfixOp.InfixOp.ArrayCat, | |
| 741 | Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp.UnwrapMaybe, | |
| 742 | Token.Id.Slash => ast.NodeInfixOp.InfixOp.Div, | |
| 743 | Token.Id.SlashEqual => ast.NodeInfixOp.InfixOp.AssignDiv, | |
| 744 | else => null, | |
| 745 | }; | |
| 746 | } | |
| 747 | ||
| 709 | 748 | fn initNode(self: &Parser, id: ast.Node.Id) ast.Node { |
| 710 | 749 | if (self.pending_line_comment_node) |comment_node| { |
| 711 | 750 | self.pending_line_comment_node = null; |
| ... | ... | @@ -867,6 +906,16 @@ pub const Parser = struct { |
| 867 | 906 | return node; |
| 868 | 907 | } |
| 869 | 908 | |
| 909 | fn createUndefined(self: &Parser, arena: &mem.Allocator, token: &const Token) !&ast.NodeUndefinedLiteral { | |
| 910 | const node = try arena.create(ast.NodeUndefinedLiteral); | |
| 911 | ||
| 912 | *node = ast.NodeUndefinedLiteral { | |
| 913 | .base = self.initNode(ast.Node.Id.UndefinedLiteral), | |
| 914 | .token = *token, | |
| 915 | }; | |
| 916 | return node; | |
| 917 | } | |
| 918 | ||
| 870 | 919 | fn createAttachIdentifier(self: &Parser, arena: &mem.Allocator, dest_ptr: &const DestPtr, name_token: &const Token) !&ast.NodeIdentifier { |
| 871 | 920 | const node = try self.createIdentifier(arena, name_token); |
| 872 | 921 | try dest_ptr.store(&node.base); |
| ... | ... | @@ -1173,17 +1222,51 @@ pub const Parser = struct { |
| 1173 | 1222 | ast.Node.Id.InfixOp => { |
| 1174 | 1223 | const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base); |
| 1175 | 1224 | try stack.append(RenderState { .Expression = prefix_op_node.rhs }); |
| 1176 | switch (prefix_op_node.op) { | |
| 1177 | ast.NodeInfixOp.InfixOp.EqualEqual => { | |
| 1178 | try stack.append(RenderState { .Text = " == "}); | |
| 1179 | }, | |
| 1180 | ast.NodeInfixOp.InfixOp.BangEqual => { | |
| 1181 | try stack.append(RenderState { .Text = " != "}); | |
| 1182 | }, | |
| 1183 | ast.NodeInfixOp.InfixOp.Period => { | |
| 1184 | try stack.append(RenderState { .Text = "."}); | |
| 1185 | }, | |
| 1186 | } | |
| 1225 | const text = switch (prefix_op_node.op) { | |
| 1226 | ast.NodeInfixOp.InfixOp.Add => " + ", | |
| 1227 | ast.NodeInfixOp.InfixOp.AddWrap => " +% ", | |
| 1228 | ast.NodeInfixOp.InfixOp.ArrayCat => " ++ ", | |
| 1229 | ast.NodeInfixOp.InfixOp.ArrayMult => " ** ", | |
| 1230 | ast.NodeInfixOp.InfixOp.Assign => " = ", | |
| 1231 | ast.NodeInfixOp.InfixOp.AssignBitAnd => " &= ", | |
| 1232 | ast.NodeInfixOp.InfixOp.AssignBitOr => " |= ", | |
| 1233 | ast.NodeInfixOp.InfixOp.AssignBitShiftLeft => " <<= ", | |
| 1234 | ast.NodeInfixOp.InfixOp.AssignBitShiftRight => " >>= ", | |
| 1235 | ast.NodeInfixOp.InfixOp.AssignBitXor => " ^= ", | |
| 1236 | ast.NodeInfixOp.InfixOp.AssignDiv => " /= ", | |
| 1237 | ast.NodeInfixOp.InfixOp.AssignMinus => " -= ", | |
| 1238 | ast.NodeInfixOp.InfixOp.AssignMinusWrap => " -%= ", | |
| 1239 | ast.NodeInfixOp.InfixOp.AssignMod => " %= ", | |
| 1240 | ast.NodeInfixOp.InfixOp.AssignPlus => " += ", | |
| 1241 | ast.NodeInfixOp.InfixOp.AssignPlusWrap => " +%= ", | |
| 1242 | ast.NodeInfixOp.InfixOp.AssignTimes => " *= ", | |
| 1243 | ast.NodeInfixOp.InfixOp.AssignTimesWarp => " *%= ", | |
| 1244 | ast.NodeInfixOp.InfixOp.BangEqual => " != ", | |
| 1245 | ast.NodeInfixOp.InfixOp.BitAnd => " & ", | |
| 1246 | ast.NodeInfixOp.InfixOp.BitOr => " | ", | |
| 1247 | ast.NodeInfixOp.InfixOp.BitShiftLeft => " << ", | |
| 1248 | ast.NodeInfixOp.InfixOp.BitShiftRight => " >> ", | |
| 1249 | ast.NodeInfixOp.InfixOp.BitXor => " ^ ", | |
| 1250 | ast.NodeInfixOp.InfixOp.BoolAnd => " and ", | |
| 1251 | ast.NodeInfixOp.InfixOp.BoolOr => " or ", | |
| 1252 | ast.NodeInfixOp.InfixOp.Div => " / ", | |
| 1253 | ast.NodeInfixOp.InfixOp.EqualEqual => " == ", | |
| 1254 | ast.NodeInfixOp.InfixOp.ErrorUnion => "!", | |
| 1255 | ast.NodeInfixOp.InfixOp.GreaterOrEqual => " >= ", | |
| 1256 | ast.NodeInfixOp.InfixOp.GreaterThan => " > ", | |
| 1257 | ast.NodeInfixOp.InfixOp.LessOrEqual => " <= ", | |
| 1258 | ast.NodeInfixOp.InfixOp.LessThan => " < ", | |
| 1259 | ast.NodeInfixOp.InfixOp.MergeErrorSets => " || ", | |
| 1260 | ast.NodeInfixOp.InfixOp.Mod => " % ", | |
| 1261 | ast.NodeInfixOp.InfixOp.Mult => " * ", | |
| 1262 | ast.NodeInfixOp.InfixOp.MultWrap => " *% ", | |
| 1263 | ast.NodeInfixOp.InfixOp.Period => ".", | |
| 1264 | ast.NodeInfixOp.InfixOp.Sub => " - ", | |
| 1265 | ast.NodeInfixOp.InfixOp.SubWrap => " -% ", | |
| 1266 | ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ", | |
| 1267 | }; | |
| 1268 | ||
| 1269 | try stack.append(RenderState { .Text = text }); | |
| 1187 | 1270 | try stack.append(RenderState { .Expression = prefix_op_node.lhs }); |
| 1188 | 1271 | }, |
| 1189 | 1272 | ast.Node.Id.PrefixOp => { |
| ... | ... | @@ -1224,6 +1307,10 @@ pub const Parser = struct { |
| 1224 | 1307 | const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base); |
| 1225 | 1308 | try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token)); |
| 1226 | 1309 | }, |
| 1310 | ast.Node.Id.UndefinedLiteral => { | |
| 1311 | const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); | |
| 1312 | try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token)); | |
| 1313 | }, | |
| 1227 | 1314 | ast.Node.Id.BuiltinCall => { |
| 1228 | 1315 | const builtin_call = @fieldParentPtr(ast.NodeBuiltinCall, "base", base); |
| 1229 | 1316 | try stream.print("{}(", self.tokenizer.getTokenSlice(builtin_call.builtin_token)); |
| ... | ... | @@ -1473,4 +1560,54 @@ test "zig fmt" { |
| 1473 | 1560 | \\} |
| 1474 | 1561 | \\ |
| 1475 | 1562 | ); |
| 1563 | ||
| 1564 | try testCanonical( | |
| 1565 | \\test "operators" { | |
| 1566 | \\ var i = undefined; | |
| 1567 | \\ i = 2; | |
| 1568 | \\ i *= 2; | |
| 1569 | \\ i |= 2; | |
| 1570 | \\ i ^= 2; | |
| 1571 | \\ i <<= 2; | |
| 1572 | \\ i >>= 2; | |
| 1573 | \\ i &= 2; | |
| 1574 | \\ i *= 2; | |
| 1575 | \\ i *%= 2; | |
| 1576 | \\ i -= 2; | |
| 1577 | \\ i -%= 2; | |
| 1578 | \\ i += 2; | |
| 1579 | \\ i +%= 2; | |
| 1580 | \\ i /= 2; | |
| 1581 | \\ i %= 2; | |
| 1582 | \\ _ = i == i; | |
| 1583 | \\ _ = i != i; | |
| 1584 | \\ _ = i != i; | |
| 1585 | \\ _ = i.i; | |
| 1586 | \\ _ = i || i; | |
| 1587 | \\ _ = i!i; | |
| 1588 | \\ _ = i ** i; | |
| 1589 | \\ _ = i ++ i; | |
| 1590 | \\ _ = i ?? i; | |
| 1591 | \\ _ = i % i; | |
| 1592 | \\ _ = i / i; | |
| 1593 | \\ _ = i *% i; | |
| 1594 | \\ _ = i * i; | |
| 1595 | \\ _ = i -% i; | |
| 1596 | \\ _ = i - i; | |
| 1597 | \\ _ = i +% i; | |
| 1598 | \\ _ = i + i; | |
| 1599 | \\ _ = i << i; | |
| 1600 | \\ _ = i >> i; | |
| 1601 | \\ _ = i & i; | |
| 1602 | \\ _ = i ^ i; | |
| 1603 | \\ _ = i | i; | |
| 1604 | \\ _ = i >= i; | |
| 1605 | \\ _ = i <= i; | |
| 1606 | \\ _ = i > i; | |
| 1607 | \\ _ = i < i; | |
| 1608 | \\ _ = i and i; | |
| 1609 | \\ _ = i or i; | |
| 1610 | \\} | |
| 1611 | \\ | |
| 1612 | ); | |
| 1476 | 1613 | } |
std/zig/tokenizer.zig+282-5| ... | ... | @@ -77,6 +77,7 @@ pub const Token = struct { |
| 77 | 77 | Builtin, |
| 78 | 78 | Bang, |
| 79 | 79 | Pipe, |
| 80 | PipePipe, | |
| 80 | 81 | PipeEqual, |
| 81 | 82 | Equal, |
| 82 | 83 | EqualEqual, |
| ... | ... | @@ -85,18 +86,45 @@ pub const Token = struct { |
| 85 | 86 | RParen, |
| 86 | 87 | Semicolon, |
| 87 | 88 | Percent, |
| 89 | PercentEqual, | |
| 88 | 90 | LBrace, |
| 89 | 91 | RBrace, |
| 90 | 92 | Period, |
| 91 | 93 | Ellipsis2, |
| 92 | 94 | Ellipsis3, |
| 95 | Caret, | |
| 96 | CaretEqual, | |
| 97 | Plus, | |
| 98 | PlusPlus, | |
| 99 | PlusEqual, | |
| 100 | PlusPercent, | |
| 101 | PlusPercentEqual, | |
| 93 | 102 | Minus, |
| 103 | MinusEqual, | |
| 104 | MinusPercent, | |
| 105 | MinusPercentEqual, | |
| 106 | Asterisk, | |
| 107 | AsteriskEqual, | |
| 108 | AsteriskAsterisk, | |
| 109 | AsteriskPercent, | |
| 110 | AsteriskPercentEqual, | |
| 94 | 111 | Arrow, |
| 95 | 112 | Colon, |
| 96 | 113 | Slash, |
| 114 | SlashEqual, | |
| 97 | 115 | Comma, |
| 98 | 116 | Ampersand, |
| 99 | 117 | AmpersandEqual, |
| 118 | QuestionMark, | |
| 119 | QuestionMarkQuestionMark, | |
| 120 | AngleBracketLeft, | |
| 121 | AngleBracketLeftEqual, | |
| 122 | AngleBracketAngleBracketLeft, | |
| 123 | AngleBracketAngleBracketLeftEqual, | |
| 124 | AngleBracketRight, | |
| 125 | AngleBracketRightEqual, | |
| 126 | AngleBracketAngleBracketRight, | |
| 127 | AngleBracketAngleBracketRightEqual, | |
| 100 | 128 | IntegerLiteral, |
| 101 | 129 | FloatLiteral, |
| 102 | 130 | LineComment, |
| ... | ... | @@ -200,6 +228,9 @@ pub const Tokenizer = struct { |
| 200 | 228 | Bang, |
| 201 | 229 | Pipe, |
| 202 | 230 | Minus, |
| 231 | MinusPercent, | |
| 232 | Asterisk, | |
| 233 | AsteriskPercent, | |
| 203 | 234 | Slash, |
| 204 | 235 | LineComment, |
| 205 | 236 | Zero, |
| ... | ... | @@ -210,6 +241,15 @@ pub const Tokenizer = struct { |
| 210 | 241 | FloatExponentUnsigned, |
| 211 | 242 | FloatExponentNumber, |
| 212 | 243 | Ampersand, |
| 244 | Caret, | |
| 245 | Percent, | |
| 246 | QuestionMark, | |
| 247 | Plus, | |
| 248 | PlusPercent, | |
| 249 | AngleBracketLeft, | |
| 250 | AngleBracketAngleBracketLeft, | |
| 251 | AngleBracketRight, | |
| 252 | AngleBracketAngleBracketRight, | |
| 213 | 253 | Period, |
| 214 | 254 | Period2, |
| 215 | 255 | SawAtSign, |
| ... | ... | @@ -291,9 +331,25 @@ pub const Tokenizer = struct { |
| 291 | 331 | break; |
| 292 | 332 | }, |
| 293 | 333 | '%' => { |
| 294 | result.id = Token.Id.Percent; | |
| 295 | self.index += 1; | |
| 296 | break; | |
| 334 | state = State.Percent; | |
| 335 | }, | |
| 336 | '*' => { | |
| 337 | state = State.Asterisk; | |
| 338 | }, | |
| 339 | '+' => { | |
| 340 | state = State.Plus; | |
| 341 | }, | |
| 342 | '?' => { | |
| 343 | state = State.QuestionMark; | |
| 344 | }, | |
| 345 | '<' => { | |
| 346 | state = State.AngleBracketLeft; | |
| 347 | }, | |
| 348 | '>' => { | |
| 349 | state = State.AngleBracketRight; | |
| 350 | }, | |
| 351 | '^' => { | |
| 352 | state = State.Caret; | |
| 297 | 353 | }, |
| 298 | 354 | '{' => { |
| 299 | 355 | result.id = Token.Id.LBrace; |
| ... | ... | @@ -356,6 +412,107 @@ pub const Tokenizer = struct { |
| 356 | 412 | break; |
| 357 | 413 | }, |
| 358 | 414 | }, |
| 415 | ||
| 416 | State.Asterisk => switch (c) { | |
| 417 | '=' => { | |
| 418 | result.id = Token.Id.AsteriskEqual; | |
| 419 | self.index += 1; | |
| 420 | break; | |
| 421 | }, | |
| 422 | '*' => { | |
| 423 | result.id = Token.Id.AsteriskAsterisk; | |
| 424 | self.index += 1; | |
| 425 | break; | |
| 426 | }, | |
| 427 | '%' => { | |
| 428 | state = State.AsteriskPercent; | |
| 429 | }, | |
| 430 | else => { | |
| 431 | result.id = Token.Id.Asterisk; | |
| 432 | break; | |
| 433 | } | |
| 434 | }, | |
| 435 | ||
| 436 | State.AsteriskPercent => switch (c) { | |
| 437 | '=' => { | |
| 438 | result.id = Token.Id.AsteriskPercentEqual; | |
| 439 | self.index += 1; | |
| 440 | break; | |
| 441 | }, | |
| 442 | else => { | |
| 443 | result.id = Token.Id.AsteriskPercent; | |
| 444 | break; | |
| 445 | } | |
| 446 | }, | |
| 447 | ||
| 448 | State.QuestionMark => switch (c) { | |
| 449 | '?' => { | |
| 450 | result.id = Token.Id.QuestionMarkQuestionMark; | |
| 451 | self.index += 1; | |
| 452 | break; | |
| 453 | }, | |
| 454 | else => { | |
| 455 | result.id = Token.Id.QuestionMark; | |
| 456 | break; | |
| 457 | }, | |
| 458 | }, | |
| 459 | ||
| 460 | State.Percent => switch (c) { | |
| 461 | '=' => { | |
| 462 | result.id = Token.Id.PercentEqual; | |
| 463 | self.index += 1; | |
| 464 | break; | |
| 465 | }, | |
| 466 | else => { | |
| 467 | result.id = Token.Id.Percent; | |
| 468 | break; | |
| 469 | }, | |
| 470 | }, | |
| 471 | ||
| 472 | State.Plus => switch (c) { | |
| 473 | '=' => { | |
| 474 | result.id = Token.Id.PlusEqual; | |
| 475 | self.index += 1; | |
| 476 | break; | |
| 477 | }, | |
| 478 | '+' => { | |
| 479 | result.id = Token.Id.PlusPlus; | |
| 480 | self.index += 1; | |
| 481 | break; | |
| 482 | }, | |
| 483 | '%' => { | |
| 484 | state = State.PlusPercent; | |
| 485 | }, | |
| 486 | else => { | |
| 487 | result.id = Token.Id.Plus; | |
| 488 | break; | |
| 489 | }, | |
| 490 | }, | |
| 491 | ||
| 492 | State.PlusPercent => switch (c) { | |
| 493 | '=' => { | |
| 494 | result.id = Token.Id.PlusPercentEqual; | |
| 495 | self.index += 1; | |
| 496 | break; | |
| 497 | }, | |
| 498 | else => { | |
| 499 | result.id = Token.Id.PlusPercent; | |
| 500 | break; | |
| 501 | }, | |
| 502 | }, | |
| 503 | ||
| 504 | State.Caret => switch (c) { | |
| 505 | '=' => { | |
| 506 | result.id = Token.Id.CaretEqual; | |
| 507 | self.index += 1; | |
| 508 | break; | |
| 509 | }, | |
| 510 | else => { | |
| 511 | result.id = Token.Id.Caret; | |
| 512 | break; | |
| 513 | } | |
| 514 | }, | |
| 515 | ||
| 359 | 516 | State.Identifier => switch (c) { |
| 360 | 517 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, |
| 361 | 518 | else => { |
| ... | ... | @@ -417,6 +574,11 @@ pub const Tokenizer = struct { |
| 417 | 574 | self.index += 1; |
| 418 | 575 | break; |
| 419 | 576 | }, |
| 577 | '|' => { | |
| 578 | result.id = Token.Id.PipePipe; | |
| 579 | self.index += 1; | |
| 580 | break; | |
| 581 | }, | |
| 420 | 582 | else => { |
| 421 | 583 | result.id = Token.Id.Pipe; |
| 422 | 584 | break; |
| ... | ... | @@ -441,12 +603,86 @@ pub const Tokenizer = struct { |
| 441 | 603 | self.index += 1; |
| 442 | 604 | break; |
| 443 | 605 | }, |
| 606 | '=' => { | |
| 607 | result.id = Token.Id.MinusEqual; | |
| 608 | self.index += 1; | |
| 609 | break; | |
| 610 | }, | |
| 611 | '%' => { | |
| 612 | state = State.MinusPercent; | |
| 613 | }, | |
| 444 | 614 | else => { |
| 445 | 615 | result.id = Token.Id.Minus; |
| 446 | 616 | break; |
| 447 | 617 | }, |
| 448 | 618 | }, |
| 449 | 619 | |
| 620 | State.MinusPercent => switch (c) { | |
| 621 | '=' => { | |
| 622 | result.id = Token.Id.MinusPercentEqual; | |
| 623 | self.index += 1; | |
| 624 | break; | |
| 625 | }, | |
| 626 | else => { | |
| 627 | result.id = Token.Id.MinusPercent; | |
| 628 | break; | |
| 629 | } | |
| 630 | }, | |
| 631 | ||
| 632 | State.AngleBracketLeft => switch (c) { | |
| 633 | '<' => { | |
| 634 | state = State.AngleBracketAngleBracketLeft; | |
| 635 | }, | |
| 636 | '=' => { | |
| 637 | result.id = Token.Id.AngleBracketLeftEqual; | |
| 638 | self.index += 1; | |
| 639 | break; | |
| 640 | }, | |
| 641 | else => { | |
| 642 | result.id = Token.Id.AngleBracketLeft; | |
| 643 | break; | |
| 644 | }, | |
| 645 | }, | |
| 646 | ||
| 647 | State.AngleBracketAngleBracketLeft => switch (c) { | |
| 648 | '=' => { | |
| 649 | result.id = Token.Id.AngleBracketAngleBracketLeftEqual; | |
| 650 | self.index += 1; | |
| 651 | break; | |
| 652 | }, | |
| 653 | else => { | |
| 654 | result.id = Token.Id.AngleBracketAngleBracketLeft; | |
| 655 | break; | |
| 656 | }, | |
| 657 | }, | |
| 658 | ||
| 659 | State.AngleBracketRight => switch (c) { | |
| 660 | '>' => { | |
| 661 | state = State.AngleBracketAngleBracketRight; | |
| 662 | }, | |
| 663 | '=' => { | |
| 664 | result.id = Token.Id.AngleBracketRightEqual; | |
| 665 | self.index += 1; | |
| 666 | break; | |
| 667 | }, | |
| 668 | else => { | |
| 669 | result.id = Token.Id.AngleBracketRight; | |
| 670 | break; | |
| 671 | }, | |
| 672 | }, | |
| 673 | ||
| 674 | State.AngleBracketAngleBracketRight => switch (c) { | |
| 675 | '=' => { | |
| 676 | result.id = Token.Id.AngleBracketAngleBracketRightEqual; | |
| 677 | self.index += 1; | |
| 678 | break; | |
| 679 | }, | |
| 680 | else => { | |
| 681 | result.id = Token.Id.AngleBracketAngleBracketRight; | |
| 682 | break; | |
| 683 | }, | |
| 684 | }, | |
| 685 | ||
| 450 | 686 | State.Period => switch (c) { |
| 451 | 687 | '.' => { |
| 452 | 688 | state = State.Period2; |
| ... | ... | @@ -474,6 +710,11 @@ pub const Tokenizer = struct { |
| 474 | 710 | result.id = Token.Id.LineComment; |
| 475 | 711 | state = State.LineComment; |
| 476 | 712 | }, |
| 713 | '=' => { | |
| 714 | result.id = Token.Id.SlashEqual; | |
| 715 | self.index += 1; | |
| 716 | break; | |
| 717 | }, | |
| 477 | 718 | else => { |
| 478 | 719 | result.id = Token.Id.Slash; |
| 479 | 720 | break; |
| ... | ... | @@ -609,6 +850,42 @@ pub const Tokenizer = struct { |
| 609 | 850 | State.Pipe => { |
| 610 | 851 | result.id = Token.Id.Pipe; |
| 611 | 852 | }, |
| 853 | State.AngleBracketAngleBracketRight => { | |
| 854 | result.id = Token.Id.AngleBracketAngleBracketRight; | |
| 855 | }, | |
| 856 | State.AngleBracketRight => { | |
| 857 | result.id = Token.Id.AngleBracketRight; | |
| 858 | }, | |
| 859 | State.AngleBracketAngleBracketLeft => { | |
| 860 | result.id = Token.Id.AngleBracketAngleBracketLeft; | |
| 861 | }, | |
| 862 | State.AngleBracketLeft => { | |
| 863 | result.id = Token.Id.AngleBracketLeft; | |
| 864 | }, | |
| 865 | State.PlusPercent => { | |
| 866 | result.id = Token.Id.PlusPercent; | |
| 867 | }, | |
| 868 | State.Plus => { | |
| 869 | result.id = Token.Id.Plus; | |
| 870 | }, | |
| 871 | State.QuestionMark => { | |
| 872 | result.id = Token.Id.QuestionMark; | |
| 873 | }, | |
| 874 | State.Percent => { | |
| 875 | result.id = Token.Id.Percent; | |
| 876 | }, | |
| 877 | State.Caret => { | |
| 878 | result.id = Token.Id.Caret; | |
| 879 | }, | |
| 880 | State.AsteriskPercent => { | |
| 881 | result.id = Token.Id.AsteriskPercent; | |
| 882 | }, | |
| 883 | State.Asterisk => { | |
| 884 | result.id = Token.Id.Asterisk; | |
| 885 | }, | |
| 886 | State.MinusPercent => { | |
| 887 | result.id = Token.Id.MinusPercent; | |
| 888 | }, | |
| 612 | 889 | } |
| 613 | 890 | } |
| 614 | 891 | if (result.id == Token.Id.Eof) { |
| ... | ... | @@ -752,8 +1029,8 @@ test "tokenizer - string identifier and builtin fns" { |
| 752 | 1029 | |
| 753 | 1030 | test "tokenizer - pipe and then invalid" { |
| 754 | 1031 | testTokenize("||=", []Token.Id{ |
| 755 | Token.Id.Pipe, | |
| 756 | Token.Id.PipeEqual, | |
| 1032 | Token.Id.PipePipe, | |
| 1033 | Token.Id.Equal, | |
| 757 | 1034 | }); |
| 758 | 1035 | } |
| 759 | 1036 |