this repo has no description
at master 131 lines 4.2 kB view raw
1using GDWeave.Godot; 2using GDWeave.Godot.Variants; 3using static GDWeave.Godot.TokenType; 4 5namespace Teemaw.Calico.Util; 6 7public static class TokenUtil 8{ 9 public static IEnumerable<Token> ReplaceAssignmentsAsDeferred(IEnumerable<Token> tokens, 10 HashSet<string>? ignoredIdentifiers = null) 11 { 12 Token? lastToken = null; 13 var inAssignmentStatement = false; 14 var skipLine = false; 15 foreach (var t in tokens) 16 { 17 switch (t) 18 { 19 case { Type: Newline }: 20 skipLine = false; 21 break; 22 case { Type: PrVar }: 23 skipLine = true; 24 break; 25 default: 26 { 27 if (lastToken is IdentifierToken identifier && 28 (ignoredIdentifiers == null || !ignoredIdentifiers.Contains(identifier.Name)) && 29 t is { Type: OpAssign } && !skipLine) 30 { 31 inAssignmentStatement = true; 32 yield return new IdentifierToken("set_deferred"); 33 yield return new Token(ParenthesisOpen); 34 yield return new ConstantToken(new StringVariant(identifier.Name)); 35 yield return new Token(Comma); 36 // Don't return the last token or current token 37 lastToken = null; 38 continue; 39 } 40 41 break; 42 } 43 } 44 45 if (t.Type == Newline && inAssignmentStatement) 46 { 47 inAssignmentStatement = false; 48 if (lastToken != null) 49 yield return lastToken; 50 // Close out the set_deferred call... 51 yield return new Token(ParenthesisClose); 52 // ...before the Newline token. 53 yield return t; 54 } 55 else if (lastToken != null) 56 yield return lastToken; 57 58 lastToken = inAssignmentStatement && t is { Type: Identifier } ? StripAssociatedData(t) : t; 59 } 60 61 if (lastToken != null) 62 yield return lastToken; 63 } 64 65 public static Token ReplaceToken(Token cursor, Token target, Token replacement) 66 { 67 return TokenEquals(cursor, target) ? replacement : cursor; 68 } 69 70 public static IEnumerable<Token> ReplaceTokens(IEnumerable<Token> haystack, IEnumerable<Token> needle, 71 IEnumerable<Token> replacements) 72 { 73 var haystackList = haystack.ToList(); 74 var needleList = needle.ToList(); 75 var replacementsList = replacements.ToList(); 76 77 if (needleList.Count == 0) return haystackList; 78 79 var result = new List<Token>(); 80 var i = 0; 81 82 while (i < haystackList.Count) 83 { 84 if (IsMatch(haystackList, needleList, i)) 85 { 86 result.AddRange(replacementsList); 87 i += needleList.Count; 88 } 89 else 90 { 91 result.Add(haystackList[i]); 92 i++; 93 } 94 } 95 96 return result; 97 } 98 99 private static bool IsMatch(List<Token> haystack, List<Token> needle, int startIndex) 100 { 101 if (startIndex + needle.Count > haystack.Count) 102 return false; 103 104 for (int i = 0; i < needle.Count; i++) 105 { 106 if (!TokenEquals(haystack[startIndex + i], needle[i])) 107 return false; 108 } 109 110 return true; 111 } 112 113 private static bool TokenEquals(Token token, Token token1) 114 { 115 if (token is IdentifierToken id && token1 is IdentifierToken id1) 116 { 117 return id.Name == id1.Name; 118 } 119 if (token is ConstantToken constant && token1 is ConstantToken constant1) 120 { 121 return constant.Value.Equals(constant1.Value); 122 } 123 return token.Type == token1.Type && token.AssociatedData == token1.AssociatedData; 124 } 125 126 private static Token StripAssociatedData(Token token) 127 { 128 token.AssociatedData = null; 129 return token; 130 } 131}