PageRenderTime 117ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/Scripting/Parser/Construct/Expressions/Texts.cs

http://github.com/polyethene/IronAHK
C# | 297 lines | 267 code | 29 blank | 1 comment | 107 complexity | c5e721dbeb21433df74103b2ba2a5459 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.Text;
  3. namespace IronAHK.Scripting
  4. {
  5. partial class Parser
  6. {
  7. List<object> SplitTokens(string code)
  8. {
  9. var list = new List<object>();
  10. bool json = false;
  11. for (int i = 0; i < code.Length; i++)
  12. {
  13. char sym = code[i];
  14. #region Spaces
  15. if (IsSpace(sym))
  16. continue;
  17. #endregion
  18. #region Comments
  19. else if (IsCommentAt(code, i))
  20. MoveToEOL(code, ref i);
  21. #endregion
  22. #region Identifiers
  23. else if (IsIdentifier(sym) || sym == Resolve || (sym == Concatenate && i + 1 < code.Length && IsIdentifier(code[i + 1])))
  24. {
  25. var id = new StringBuilder(code.Length);
  26. id.Append(sym);
  27. i++;
  28. // UNDONE: optimise split tokens
  29. for (; i < code.Length; i++)
  30. {
  31. sym = code[i];
  32. if ((sym == 'e' || sym == 'E') && IsPrimativeObject(id.ToString()) && id.ToString().IndexOf("0x") != 0 && i + 1 < code.Length)
  33. {
  34. id.Append(sym);
  35. sym = code[++i];
  36. if (!(sym == '+' || sym == '-' || char.IsDigit(sym)))
  37. throw new ParseException(ExInvalidExponent);
  38. id.Append(sym);
  39. }
  40. else if (IsIdentifier(sym) || sym == Resolve || (sym == Concatenate && (i + 1 < code.Length ? code[i + 1] != Equal : true)))
  41. id.Append(sym);
  42. else
  43. {
  44. if (sym == ParenOpen && !IsKeyword(id.ToString()) && !id.ToString().Contains(Concatenate.ToString()))
  45. id.Append(ParenOpen);
  46. else
  47. i--;
  48. break;
  49. }
  50. }
  51. string seq = id.ToString();
  52. var parts = IsPrimativeObject(seq) ? new[] { seq } : seq.Split(Concatenate);
  53. if (parts[0].Length != 0)
  54. list.Add(parts[0]);
  55. for (int n = 1; n < parts.Length; n++)
  56. {
  57. list.Add(ArrayOpen.ToString());
  58. string str = StringBound.ToString();
  59. list.Add(string.Concat(str, parts[n], str));
  60. list.Add(ArrayClose.ToString());
  61. }
  62. }
  63. #endregion
  64. #region Strings
  65. else if (sym == StringBound)
  66. {
  67. var str = new StringBuilder(code.Length);
  68. str.Append(StringBound);
  69. i++;
  70. for (int max = code.Length + 1; i < max; i++)
  71. {
  72. if (i == code.Length)
  73. throw new ParseException(ExUntermStr);
  74. sym = code[i];
  75. str.Append(sym);
  76. if (sym == StringBound)
  77. {
  78. int n = i + 1;
  79. if (n < code.Length && code[n] == StringBound)
  80. i = n;
  81. else
  82. break;
  83. }
  84. }
  85. list.Add(str.ToString());
  86. }
  87. #endregion
  88. #region Operators
  89. else
  90. {
  91. var op = new StringBuilder(3);
  92. int n = i + 1;
  93. char symNext = n < code.Length ? code[n] : Reserved;
  94. bool tri = false;
  95. #region 3x
  96. if (sym == symNext)
  97. {
  98. bool peekAssign = false;
  99. switch (sym)
  100. {
  101. case Divide:
  102. case Greater:
  103. case Less:
  104. peekAssign = true;
  105. goto case Add;
  106. case Add:
  107. case Minus:
  108. case Multiply:
  109. case BitOR:
  110. case BitAND:
  111. op.Append(sym);
  112. op.Append(symNext);
  113. i++;
  114. tri = true;
  115. if (peekAssign)
  116. {
  117. n = i + 1;
  118. if (n < code.Length && code[n] == Equal)
  119. {
  120. op.Append(code[n]);
  121. i = n;
  122. }
  123. }
  124. break;
  125. }
  126. }
  127. #endregion
  128. if (!tri)
  129. {
  130. #region 2x
  131. if (symNext == Equal)
  132. {
  133. switch (sym)
  134. {
  135. case AssignPre:
  136. case Add:
  137. case Minus:
  138. case Multiply:
  139. case Divide:
  140. case Concatenate:
  141. case BitAND:
  142. case BitXOR:
  143. case BitOR:
  144. case Not:
  145. case Equal:
  146. case Greater:
  147. case Less:
  148. op.Append(sym);
  149. op.Append(symNext);
  150. i++;
  151. break;
  152. }
  153. }
  154. else if ((sym == Less && symNext == Greater) || (sym == TernaryA && symNext == TernaryA))
  155. {
  156. op.Append(sym);
  157. op.Append(symNext);
  158. i++;
  159. }
  160. #endregion
  161. #region 1x
  162. else
  163. {
  164. switch (sym)
  165. {
  166. case Add:
  167. case Minus:
  168. case Multiply:
  169. case Not:
  170. case BitNOT:
  171. case BitAND:
  172. case Greater:
  173. case Less:
  174. case BitXOR:
  175. case BitOR:
  176. case ParenOpen:
  177. case ParenClose:
  178. case Equal:
  179. case Concatenate:
  180. case TernaryB:
  181. case Divide:
  182. case ArrayOpen:
  183. case ArrayClose:
  184. op.Append(sym);
  185. break;
  186. case BlockOpen:
  187. if (json)
  188. {
  189. op.Append(sym);
  190. break;
  191. }
  192. blockOpen = true;
  193. int j = i + 2;
  194. if (j < code.Length && !IsCommentAt(code, j))
  195. {
  196. blockOpen = false;
  197. json = true;
  198. goto case BlockOpen;
  199. }
  200. j--;
  201. if (j < code.Length)
  202. {
  203. if (code[j] == BlockClose)
  204. {
  205. json = true;
  206. goto case BlockClose;
  207. }
  208. else if (!IsSpace(code[j]))
  209. throw new ParseException(ExUnexpected);
  210. }
  211. return list;
  212. case BlockClose:
  213. if (!json)
  214. goto default;
  215. op.Append(sym);
  216. break;
  217. default:
  218. if (sym == Resolve || sym == Multicast)
  219. goto case Add;
  220. throw new ParseException(ExUnexpected);
  221. }
  222. }
  223. #endregion
  224. }
  225. if (op.Length == 0)
  226. op.Append(sym);
  227. list.Add(op.ToString());
  228. }
  229. #endregion
  230. }
  231. return list;
  232. }
  233. void RemoveExcessParentheses(List<object> parts)
  234. {
  235. while (parts.Count > 1)
  236. {
  237. int level = 0;
  238. int last = parts.Count - 1;
  239. if (!(--last > 1 &&
  240. parts[0] is string && ((string)parts[0]).Length == 1 && ((string)parts[0])[0] == ParenOpen &&
  241. parts[last] is string && ((string)parts[last]).Length == 1 && ((string)parts[last])[0] == ParenClose))
  242. return;
  243. for (int i = 0; i < last; i++)
  244. {
  245. var check = parts[i] as string;
  246. if (string.IsNullOrEmpty(check))
  247. continue;
  248. switch (check[check.Length - 1])
  249. {
  250. case ParenOpen:
  251. level++;
  252. break;
  253. case ParenClose:
  254. if (check.Length != 1)
  255. break;
  256. else if (--level < 0)
  257. throw new ParseException(ExUnbalancedParens);
  258. break;
  259. }
  260. }
  261. if (level != 0)
  262. return;
  263. parts.RemoveAt(last);
  264. parts.RemoveAt(0);
  265. }
  266. }
  267. }
  268. }