/Parser/ScannerKeywordsJumpTableGenerator.pas

https://github.com/Zoxc/JassParser · Pascal · 233 lines · 175 code · 52 blank · 6 comment · 22 complexity · fb231c309b815a22a1ee5a89153aad04 MD5 · raw file

  1. unit ScannerKeywordsJumpTableGenerator;
  2. interface
  3. uses SysUtils, IniFiles, Classes;
  4. procedure IdentifierProc;
  5. procedure InitKeywords;
  6. implementation
  7. uses Dialogs, Scanner, Tokens, SearchCode, HashExplorer, ComCtrls, Math, GeneratorCommon;
  8. type
  9. PKeywordArray = ^TKeywordArray;
  10. TKeywordArray = record
  11. Hash: Byte;
  12. Node: TTreeNode;
  13. Lengths: array of TTokenType;
  14. Keywords: array of TTokenType;
  15. end;
  16. PKeywordPair = ^TKeywordPair;
  17. TKeywordPair = record
  18. Hash: Byte;
  19. Keyword: TTokenType;
  20. end;
  21. var
  22. Hashes: array of TKeywordArray;
  23. procedure IdentifierProc;
  24. begin
  25. end;
  26. procedure AddEntry(Hash: Byte; TokenType: TTokenType);
  27. var i: Integer;
  28. procedure Add;
  29. begin
  30. SetLength(Hashes[i].Keywords, Length(Hashes[i].Keywords) + 1);
  31. Hashes[i].Keywords[High(Hashes[i].Keywords)] := TokenType;
  32. HashEx.TreeView.Items.AddChild(Hashes[i].Node, TokenName[TokenType]);
  33. Hashes[i].Node.Expand(False);
  34. end;
  35. begin
  36. for i := 0 to High(Hashes) do
  37. if Hashes[i].Hash = Hash then
  38. begin
  39. Add;
  40. Exit;
  41. end;
  42. i := Length(Hashes);
  43. SetLength(Hashes, i + 1);
  44. Hashes[i].Hash := Hash;
  45. Hashes[i].Node := HashEx.TreeView.Items.AddChild(nil, IntToHex(Hash, 2));
  46. Add;
  47. end;
  48. function Compare(Item1, Item2: Pointer): Integer;
  49. begin
  50. Result := PKeywordPair(Item1).Hash - PKeywordPair(Item2).Hash;
  51. end;
  52. procedure InitKeywords;
  53. var
  54. i: TTokenType;
  55. Hash: Byte;
  56. Keyword: PAnsiChar;
  57. x, y,Len,z, lenlow, lenhigh: Integer;
  58. Test: TList;
  59. Pair: PKeywordPair;
  60. procedure FindHash;
  61. var i: Integer;
  62. begin
  63. for i := 0 to High(Hashes) do
  64. if Hashes[i].Hash = x then
  65. begin
  66. y := i;
  67. Exit;
  68. end;
  69. y := -1;
  70. end;
  71. begin
  72. Test := TList.Create;
  73. lenlow := High(Integer);
  74. lenhigh := Low(Integer);
  75. for i := ttGlobals to High(TTokenType) do
  76. begin
  77. Hash := 0;
  78. Keyword := TokenName[i];
  79. lenlow := Min(lenlow, StrLen(Keyword));
  80. lenhigh := Max(lenhigh, StrLen(Keyword));
  81. {$RANGECHECKS OFF}
  82. {$OVERFLOWCHECKS OFF}
  83. while Keyword^ <> #0 do
  84. begin
  85. Hash := Hash + Byte(Keyword^);
  86. Inc(Keyword);
  87. end;
  88. {$OVERFLOWCHECKS ON}
  89. {$RANGECHECKS ON}
  90. New(Pair);
  91. Pair.Hash := Hash;
  92. Pair.Keyword := i;
  93. Test.Add(Pair);
  94. end;
  95. Test.Sort(@Compare);
  96. for x := 0 to Test.Count - 1 do
  97. begin
  98. AddEntry(PKeywordPair(Test[x]).Hash, PKeywordPair(Test[x]).Keyword);
  99. Dispose(Test[x]);
  100. end;
  101. SearchForm.Memo.Lines.Add(' sub edx, ' + IntToStr(lenlow));
  102. SearchForm.Memo.Lines.Add(' cmp edx, ' + IntToStr(lenhigh - lenlow));
  103. SearchForm.Memo.Lines.Add(' jbe @CheckKeywords');
  104. SearchForm.Memo.Lines.Add(' ret');
  105. SearchForm.Memo.Lines.Add('');
  106. SearchForm.Memo.Lines.Add('@CheckKeywords:');
  107. SearchForm.Memo.Lines.Add(' jmp dword ptr [@JumpTable + eax * 4]');
  108. SearchForm.Memo.Lines.Add('');
  109. SearchForm.Memo.Lines.Add('@Return:');
  110. SearchForm.Memo.Lines.Add(' ret');
  111. SearchForm.Memo.Lines.Add('');
  112. SearchForm.Memo.Lines.Add('@JumpTable:');
  113. for x := 0 to 255 do
  114. begin
  115. FindHash;
  116. if y = -1 then
  117. SearchForm.Memo.Lines.Add(' dd @Return')
  118. else
  119. SearchForm.Memo.Lines.Add(' dd @Check' + IntToHex(x, 2));
  120. end;
  121. // Generate length checks
  122. for x := 0 to High(Hashes) do
  123. begin
  124. SearchForm.Memo.Lines.Add('');
  125. SearchForm.Memo.Lines.Add('@Check' + IntToHex(Hashes[x].Hash, 2) + ':');
  126. Test.Clear;
  127. for y := 0 to High(Hashes[x].Keywords) do
  128. begin
  129. len := StrLen(TokenName[Hashes[x].Keywords[y]]);
  130. if Test.IndexOf(Pointer(len)) = -1 then
  131. Test.Add(Pointer(len));
  132. end;
  133. for y := 0 to Test.Count -1 do
  134. begin
  135. SearchForm.Memo.Lines.Add(' cmp edx, ' + IntToStr(Integer(Test[y]) - lenlow));
  136. SearchForm.Memo.Lines.Add(' je @Compare' + IntToHex(Hashes[x].Hash, 2) + '_' + IntToStr(Integer(Test[y]))+'_0');
  137. end;
  138. SearchForm.Memo.Lines.Add(' ret');
  139. end;
  140. // Full comparasions
  141. for x := 0 to High(Hashes) do
  142. begin
  143. Test.Clear;
  144. for y := 0 to High(Hashes[x].Keywords) do
  145. begin
  146. len := StrLen(TokenName[Hashes[x].Keywords[y]]);
  147. if Test.IndexOf(Pointer(len)) = -1 then
  148. Test.Add(Pointer(len));
  149. end;
  150. SearchForm.Memo.Lines.Add(' ');
  151. for z := 0 to Test.Count -1 do
  152. begin
  153. len := 0;
  154. for y := 0 to High(Hashes[x].Keywords) do
  155. if StrLen(TokenName[Hashes[x].Keywords[y]]) = Cardinal(Test[z]) then
  156. Inc(len);
  157. SearchForm.Memo.Lines.Add('@Compare' + IntToHex(Hashes[x].Hash, 2) + '_' + IntToStr(Integer(Test[z]))+'_' + IntToStr(len)+':');
  158. end;
  159. SearchForm.Memo.Lines.Add(' ret');
  160. for z := 0 to Test.Count -1 do
  161. begin
  162. len := 0;
  163. for y := 0 to High(Hashes[x].Keywords) do
  164. if StrLen(TokenName[Hashes[x].Keywords[y]]) = Cardinal(Test[z]) then
  165. begin
  166. SearchForm.Memo.Lines.Add('');
  167. SearchForm.Memo.Lines.Add('@Compare' + IntToHex(Hashes[x].Hash, 2) + '_' + IntToStr(Integer(Test[z]))+'_' + IntToStr(len)+':');
  168. CompareKeyword(TokenName[Hashes[x].Keywords[y]], 'ecx', '@Compare' + IntToHex(Hashes[x].Hash, 2) + '_' + IntToStr(Integer(Test[z]))+'_' + IntToStr(len + 1));
  169. SearchForm.Memo.Lines.Add('');
  170. SearchForm.Memo.Lines.Add(' mov [Token.Token], tt' + TokenName[Hashes[x].Keywords[y]]);
  171. SearchForm.Memo.Lines.Add(' ret');
  172. Inc(len);
  173. end;
  174. end;
  175. SearchForm.Memo.Lines.Add('');
  176. end;
  177. SearchForm.Show;
  178. HashExplorer.HashEx.Show;
  179. Test.Free;
  180. end;
  181. end.