Parse.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. #########
  3. ############
  4. #############
  5. ## ###########
  6. ### ###### #####
  7. ### ####### ####
  8. ### ########## ####
  9. #### ########### ####
  10. #### ########### #####
  11. ##### ### ######## #####
  12. ##### ### ######## ######
  13. ###### ### ########### ######
  14. ###### #### ############## ######
  15. ####### ##################### ######
  16. ####### ###################### ######
  17. ####### ###### ################# ######
  18. ####### ###### ###### ######### ######
  19. ####### ## ###### ###### ######
  20. ####### ###### ##### #####
  21. ###### ##### ##### ####
  22. ##### #### ##### ###
  23. ##### ### ### #
  24. ### ### ###
  25. ## ### ###
  26. __________#_______####_______####______________
  27. 我们的未来没有BUG
  28. * ==============================================================================
  29. * Filename: Parse
  30. * Created: 2018/7/13 14:29:22
  31. * Author: エル・プサイ・コングリィ
  32. * Purpose:
  33. * ==============================================================================
  34. */
  35. #if UNITY_EDITOR || USE_LUA_PROFILER
  36. using System;
  37. using System.Collections.Generic;
  38. namespace MikuLuaProfiler
  39. {
  40. public static class Parse
  41. {
  42. public static readonly string LOCAL_PROFILER =
  43. "local BeginMikuSample = MikuLuaProfiler.LuaProfiler.BeginSample "
  44. + "local EndMikuSample = MikuLuaProfiler.LuaProfiler.EndSample " + "local miku_unpack_return_value = miku_unpack_return_value ";
  45. #region parse
  46. public static string InsertSample(string value, string name)
  47. {
  48. LLex l = new LLex(new StringLoadInfo(value), name);
  49. string sampleStr = string.Format("{0}BeginMikuSample(\"[lua]:require {1},{1}&line:1\")", LOCAL_PROFILER, name);
  50. l.InsertString(0, sampleStr);
  51. int lastPos = 0;
  52. int nextPos = l.pos;
  53. l.Next();
  54. int tokenType = l.Token.TokenType;
  55. lastPos = nextPos;
  56. nextPos = l.pos;
  57. InsertSample(l, ref lastPos, ref nextPos, tokenType, false);
  58. return l.code;
  59. }
  60. static void InsertSample(LLex l, ref int lastPos, ref int nextPos, int tokenType, bool onlyFun)
  61. {
  62. Stack<int> tokens = new Stack<int>();
  63. List<Token> history = new List<Token>(16);
  64. bool needLastSample = true;
  65. bool hasReturn = false;
  66. int lastStackToken = -1;
  67. while (tokenType != (int)TK.EOS)
  68. {
  69. switch (tokenType)
  70. {
  71. case (int)TK.FUNCTION:
  72. hasReturn = false;
  73. tokens.Push(tokenType);
  74. lastStackToken = tokenType;
  75. string funName = "";
  76. bool isLeft = false;
  77. bool isForward = false;
  78. int index = history.Count - 2;
  79. if (index >= 0)
  80. {
  81. var hisToken = history[index];
  82. while (hisToken is JumpToken)
  83. {
  84. index--;
  85. if (index < 0) break;
  86. hisToken = history[index];
  87. }
  88. isForward = hisToken.TokenType == (int)'=';
  89. index--;
  90. if (isForward && index >= 0)
  91. {
  92. hisToken = history[index];
  93. while (hisToken is JumpToken)
  94. {
  95. index--;
  96. if (index < 0) break;
  97. hisToken = history[index];
  98. }
  99. while (!(hisToken is JumpToken))
  100. {
  101. if (hisToken is NameToken)
  102. {
  103. funName = ((NameToken)hisToken).SemInfo + funName;
  104. }
  105. else if ((hisToken.TokenType == (int)':'))
  106. {
  107. funName = ':' + funName;
  108. }
  109. else if ((hisToken.TokenType == (int)'.')
  110. || (hisToken.TokenType == (int)'['))
  111. {
  112. funName = '.' + funName;
  113. }
  114. else if (hisToken is StringToken)
  115. {
  116. funName = ((StringToken)hisToken).SemInfo + funName;
  117. }
  118. else
  119. {
  120. break;
  121. }
  122. index--;
  123. if (index < 0) break;
  124. hisToken = history[index];
  125. }
  126. }
  127. }
  128. while (tokenType != (int)TK.EOS)
  129. {
  130. l.Next();
  131. tokenType = l.Token.TokenType;
  132. lastPos = nextPos;
  133. nextPos = l.pos;
  134. if (!isLeft && !isForward)
  135. {
  136. if (l.Token is NameToken)
  137. {
  138. funName += ((NameToken)l.Token).SemInfo;
  139. }
  140. else if ((l.Token.TokenType == (int)':'))
  141. {
  142. funName += ':';
  143. }
  144. else if ((l.Token.TokenType == (int)'.'))
  145. {
  146. funName += '.';
  147. }
  148. }
  149. if (tokenType == (int)'(')
  150. {
  151. isLeft = true;
  152. }
  153. if (tokenType == (int)')')
  154. {
  155. if (string.IsNullOrEmpty(funName))
  156. {
  157. funName = "";
  158. }
  159. string profilerStr = string.Format(" BeginMikuSample(\"[lua]:{0},{1}&line:{2}\") ", funName, l.Source, l.LineNumber);
  160. l.InsertString(nextPos - 1, profilerStr);
  161. nextPos = l.pos;
  162. break;
  163. }
  164. }
  165. break;
  166. case (int)TK.IF:
  167. case (int)TK.FOR:
  168. case (int)TK.WHILE:
  169. if (tokens.Count > 0)
  170. {
  171. tokens.Push(tokenType);
  172. lastStackToken = tokenType;
  173. }
  174. break;
  175. case (int)TK.RETURN:
  176. int insertPos = lastPos - 1;
  177. if (tokens.Count == 0)
  178. {
  179. needLastSample = false;
  180. }
  181. while (tokenType != (int)TK.EOS)
  182. {
  183. l.Next();
  184. tokenType = l.Token.TokenType;
  185. if (!(l.Token is JumpToken))
  186. {
  187. lastPos = nextPos;
  188. nextPos = l.pos;
  189. }
  190. if (tokenType == (int)TK.FUNCTION)
  191. {
  192. InsertSample(l, ref lastPos, ref nextPos, tokenType, true);
  193. tokenType = l.Token.TokenType;
  194. }
  195. if (tokenType == (int)TK.END
  196. || tokenType == (int)TK.ELSEIF
  197. || tokenType == (int)TK.ELSE
  198. || tokenType == (int)TK.EOS)
  199. {
  200. lastPos = lastPos - 1;
  201. string returnStr = l.ReadString(insertPos, lastPos - 1);
  202. returnStr = " return miku_unpack_return_value(" + returnStr.Substring(6, returnStr.Length - 6) + ") ";
  203. l.Replace(insertPos, lastPos - 1, returnStr);
  204. nextPos = l.pos;
  205. if (tokenType == (int)TK.END)
  206. {
  207. if (tokens.Count > 0)
  208. tokens.Pop();
  209. if (onlyFun && tokens.Count <= 0)
  210. {
  211. l.Next();
  212. if (!(l.Token is JumpToken))
  213. {
  214. lastPos = nextPos;
  215. nextPos = l.pos;
  216. }
  217. return;
  218. }
  219. }
  220. break;
  221. }
  222. }
  223. if (lastStackToken != (int)TK.IF)
  224. {
  225. hasReturn = true;
  226. }
  227. break;
  228. case (int)TK.END:
  229. if (tokens.Count > 0)
  230. {
  231. int token = tokens.Pop();
  232. if (token == (int)TK.FUNCTION)
  233. {
  234. if (!hasReturn)
  235. {
  236. l.InsertString(lastPos - 1, " EndMikuSample() ");
  237. lastPos = nextPos;
  238. nextPos = l.pos;
  239. }
  240. if (onlyFun && tokens.Count <= 0)
  241. {
  242. l.Next();
  243. if (!(l.Token is JumpToken))
  244. {
  245. lastPos = nextPos;
  246. nextPos = l.pos;
  247. }
  248. return;
  249. }
  250. }
  251. if (tokens.Count > 0)
  252. {
  253. var tA = tokens.ToArray();
  254. lastStackToken = tA[tA.Length - 1];
  255. }
  256. hasReturn = false;
  257. }
  258. break;
  259. }
  260. l.Next();
  261. history.Add(l.Token);
  262. if (history.Count >= 16)
  263. {
  264. history.RemoveAt(0);
  265. }
  266. tokenType = l.Token.TokenType;
  267. lastPos = nextPos;
  268. nextPos = l.pos;
  269. }
  270. if (needLastSample)
  271. {
  272. l.InsertString(nextPos, "\n EndMikuSample()");
  273. }
  274. }
  275. #endregion
  276. }
  277. }
  278. #endif