PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/branch/futaba/library/NetTopologySuite_Silverlight/Utilities/RToolsUtil/ParseUtil.cs

#
C# | 454 lines | 256 code | 51 blank | 147 comment | 64 complexity | 1d434bbb12ed47b5c53a620ddf0a53f4 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception
  1. // ParseUtil.cs
  2. //
  3. // Copyright (C) 2002-2004 Ryan Seghers
  4. //
  5. // This software is provided AS IS. No warranty is granted,
  6. // neither expressed nor implied. USE THIS SOFTWARE AT YOUR OWN RISK.
  7. // NO REPRESENTATION OF MERCHANTABILITY or FITNESS FOR ANY
  8. // PURPOSE is given.
  9. //
  10. // License to use this software is limited by the following terms:
  11. // 1) This code may be used in any program, including programs developed
  12. // for commercial purposes, provided that this notice is included verbatim.
  13. //
  14. // Also, in return for using this code, please attempt to make your fixes and
  15. // updates available in some way, such as by sending your updates to the
  16. // author.
  17. //
  18. using System;
  19. using System.Collections;
  20. using System.Collections.Generic;
  21. namespace RTools_NTS.Util
  22. {
  23. /// <summary>
  24. /// A start on some utility methods for parsing in conjunction with
  25. /// StreamTokenizer. These currently use Token[] but could be adapted
  26. /// for ArrayList.
  27. /// </summary>
  28. public class ParseUtil
  29. {
  30. /// <summary>
  31. /// Build an Array of a particular type from a list of tokens.
  32. /// The Type must be one that can be built with Convert.ChangeType.
  33. /// There are various ways to specify how many elements to parse.
  34. /// WARNING: This will throw an exception if any tokens cannot be
  35. /// converted.
  36. /// </summary>
  37. /// <param name="tokens">The ArrayList of tokens.</param>
  38. /// <param name="i">The starting (and ending) index. This is
  39. /// modified, and left pointing at the last used token.</param>
  40. /// <param name="type">The Type of the array elements.</param>
  41. /// <param name="endToken">An optional end Token to look for.
  42. /// Parsing stops when a token equal to this is found.
  43. /// If this is null, then it is not used.</param>
  44. /// <param name="maxLength">The maximum number of array elements
  45. /// to parse. If this is negative, then it is not used.</param>
  46. /// <param name="log">A Logger to use for messages.</param>
  47. /// <returns>The Array, or null for error.</returns>
  48. public static Array BuildArray(List<Token> tokens, ref int i, Type type,
  49. Token endToken, int maxLength, Logger log)
  50. {
  51. int len = tokens.Count;
  52. if (i >= len)
  53. {
  54. log.Error("BuildArray: Input index too large.");
  55. return(null);
  56. }
  57. // put the objects into an array list first, since we don't
  58. // know length
  59. List<object> list = new List<object>();
  60. // allow null endToken specified
  61. if (endToken == null) endToken = new EofToken();
  62. Token token = null;
  63. token = (Token)tokens[i++];
  64. int arrayLength = 0;
  65. while ((!(token is EofToken)) && (token != endToken) && (i < len)
  66. && ((maxLength < 0) || (arrayLength < maxLength)))
  67. {
  68. Object o = token.ConvertToType(type);
  69. list.Add(o);
  70. arrayLength++;
  71. token = (Token)tokens[i++];
  72. }
  73. i--; // went one past
  74. return(list.ToArray());
  75. }
  76. /// <summary>
  77. /// Given a Token[] and a reference int, skip forward
  78. /// in the token array until a WordToken is found,
  79. /// and leave the reference int at that index.
  80. /// </summary>
  81. /// <param name="tokens">The token array.</param>
  82. /// <param name="i">The start index, and the result index.</param>
  83. /// <returns>bool - true for success, false for
  84. /// hit the end of the tokens.</returns>
  85. public static bool SkipToWord(Token[] tokens, ref int i)
  86. {
  87. while (!(tokens[i] is WordToken))
  88. {
  89. i++;
  90. if (i >= tokens.Length) return(false);
  91. }
  92. return(true);
  93. }
  94. /// <summary>
  95. /// Given a Token[], a reference int and a string, skip forward
  96. /// in the token array until a token matches the string
  97. /// and leave the reference int at that index.
  98. /// </summary>
  99. /// <param name="tokens">The token array.</param>
  100. /// <param name="i">The start index, and the result index.</param>
  101. /// <param name="s">The string to look for.</param>
  102. /// <returns>bool - true for success, false for
  103. /// hit the end of the tokens.</returns>
  104. public static bool SkipToStringValue(Token[] tokens, ref int i,
  105. string s)
  106. {
  107. while (tokens[i] != s)
  108. {
  109. i++;
  110. if (i >= tokens.Length) return(false);
  111. }
  112. return(true);
  113. }
  114. /// <summary>
  115. /// Given a Token[] and a reference int, skip forward
  116. /// in the token array until a WordToken is found,
  117. /// and leave the reference int at that index.
  118. /// </summary>
  119. /// <param name="tokens">The token array.</param>
  120. /// <param name="i">The start index, and the result index.</param>
  121. /// <param name="c">The char to look for.</param>
  122. /// <returns>bool - true for success, false for
  123. /// hit the end of the tokens.</returns>
  124. public static bool SkipToChar(Token[] tokens, ref int i,
  125. char c)
  126. {
  127. while(tokens[i] != c)
  128. {
  129. i++;
  130. if (i >= tokens.Length) return(false);
  131. }
  132. return(true);
  133. }
  134. /// <summary>
  135. /// Given a Token[] and a reference int, skip forward
  136. /// in the token array until a WordToken is found,
  137. /// and leave the reference int at that index.
  138. /// </summary>
  139. /// <param name="tokens">The token array.</param>
  140. /// <param name="i">The start index, and the result index.</param>
  141. /// <returns>bool - true for success, false for
  142. /// hit the end of the tokens.</returns>
  143. public static bool SkipWs(Token[] tokens, ref int i)
  144. {
  145. while (tokens[i] is WhitespaceToken)
  146. {
  147. i++;
  148. if (i >= tokens.Length) return(false);
  149. }
  150. return(true);
  151. }
  152. /// <summary>
  153. /// Given a Token[] and a reference int, skip forward
  154. /// in the token array until a WordToken is found,
  155. /// and leave the reference int at that index.
  156. /// </summary>
  157. /// <param name="tokens">The token array.</param>
  158. /// <param name="i">The start index, and the result index.</param>
  159. /// <returns>bool - true for success, false for
  160. /// hit the end of the tokens.</returns>
  161. public static bool SkipToEol(Token[] tokens, ref int i)
  162. {
  163. if ((i < 0) || (i >= tokens.Length)) return(false);
  164. while (!(tokens[i] is EolToken))
  165. {
  166. i++;
  167. if (i >= tokens.Length) return(false);
  168. }
  169. return(true);
  170. }
  171. /// <summary>
  172. /// Given a Token[] and a reference int, skip forward
  173. /// in the token array until a WordToken is found,
  174. /// and leave the reference int at that index.
  175. /// </summary>
  176. /// <param name="tokens">The token array.</param>
  177. /// <param name="dropTokens">The tokens to drop.</param>
  178. /// <returns>bool - true for success, false for
  179. /// hit the end of the tokens.</returns>
  180. public static Token[] DropTokens(Token[] tokens,
  181. Token[] dropTokens)
  182. {
  183. List<Token> outputList = new List<Token>();
  184. int i = 0;
  185. for (i = 0; i < tokens.Length; i++)
  186. {
  187. bool dropIt = false;
  188. for (int j = 0; j < dropTokens.Length; j++)
  189. {
  190. if (tokens[i].Equals(dropTokens[j])) dropIt = true;
  191. }
  192. if (!dropIt) outputList.Add(tokens[i]);
  193. }
  194. // copy to array
  195. Token[] outputTokens = new Token[outputList.Count];
  196. i = 0;
  197. foreach(Token t in outputList) outputTokens[i++] = t;
  198. return(outputTokens);
  199. }
  200. /// <summary>
  201. /// Find matching closing character.
  202. /// The matchable pairs of characters are parenthesis (),
  203. /// square brackets [], and curly braces {}.
  204. /// Given a Token[] and a reference int containing the index
  205. /// in the Token[] of a matchable? char, skip forward
  206. /// in the token array until the matching character is found.
  207. /// </summary>
  208. /// <remarks>
  209. /// This implicitly skips matching characters in quotes and
  210. /// comments if they are hidden in the tokens. So if you grab
  211. /// comments and quotes when you tokenize, the characters in those
  212. /// tokens are not looked at by this function.
  213. /// </remarks>
  214. /// <param name="tokens">The token array.</param>
  215. /// <param name="i">The start index, and the result index.</param>
  216. /// <param name="c">The start character whose match is to be found.</param>
  217. /// <returns>bool - true for success, false for
  218. /// hit the end of the tokens.</returns>
  219. public static bool FindMatch(Token[] tokens, ref int i,
  220. char c)
  221. {
  222. char endChar;
  223. if (c == '(') endChar = ')';
  224. else if (c == '{') endChar = '}';
  225. else if (c == '[') endChar = ']';
  226. else return(false);
  227. int nestLevel = 1; // count first one
  228. // i'th token must be the start character
  229. if (tokens[i] != c)
  230. {
  231. return(false);
  232. }
  233. i++;
  234. // terminate when we hit an end char and that takes us to
  235. // nest level 0
  236. while (nestLevel > 0)
  237. {
  238. if (tokens[i] == c) nestLevel++;
  239. else if (tokens[i] == endChar) nestLevel--;
  240. i++;
  241. if (i >= tokens.Length) return(false);
  242. }
  243. i--; // went one past
  244. return(true);
  245. }
  246. /// <summary>
  247. /// Simple test of some ParseUtil methods.
  248. /// </summary>
  249. /// <returns>bool - true for all passed, false otherwise</returns>
  250. public static bool TestSelf()
  251. {
  252. Logger log = new Logger("ParseUtil: TestSelf");
  253. log.Info("Starting...");
  254. StreamTokenizer tokenizer = new StreamTokenizer();
  255. tokenizer.Verbosity = VerbosityLevel.Warn;
  256. // FindMatch
  257. List<Token> alist = new List<Token>();
  258. tokenizer.TokenizeString("{ [ ] '}' }", alist);
  259. foreach(Token t in alist) log.Debug("Token = {0}", t);
  260. Token[] tarray = alist.ToArray();
  261. int i = 0;
  262. if (!FindMatch(tarray, ref i, '{'))
  263. {
  264. log.Error("FindMatch failed to match { char");
  265. return(false);
  266. }
  267. if (i != 4)
  268. {
  269. log.Error("FindMatch got the wrong answer {0}", i);
  270. return(false);
  271. }
  272. else log.Info("FindMatch worked.");
  273. //
  274. // try BuildArray
  275. //
  276. List<Token> tokens = new List<Token>();
  277. tokenizer.TokenizeString("1 2 3 4 5", tokens);
  278. foreach(Token t in tokens) log.Debug("Token = {0}", t);
  279. i = 0;
  280. Int16[] shorts = (short[])BuildArray(tokens, ref i, typeof(Int16), null,
  281. -1, log);
  282. if (shorts == null)
  283. {
  284. log.Error("Unable to BuildArray of shorts.");
  285. return(false);
  286. }
  287. log.Info("Parsed shorts:");
  288. foreach(Int16 s in shorts)
  289. {
  290. log.Write("{0}, ", s);
  291. }
  292. log.WriteLine(String.Empty);
  293. //
  294. // try BuildArray of floats, char terminated
  295. //
  296. tokens.Clear();
  297. tokenizer.TokenizeString("1 2 ; 3 4", tokens);
  298. foreach(Token t in tokens) log.Debug("Token = {0}", t);
  299. i = 0;
  300. Single[] floats = (float[])BuildArray(tokens, ref i, typeof(Single),
  301. new CharToken(';'), -1, log);
  302. if (floats == null)
  303. {
  304. log.Error("Unable to BuildArray of floats.");
  305. return(false);
  306. }
  307. log.Info("Parsed floats:");
  308. foreach(float f in floats)
  309. {
  310. log.Write("{0}, ", f);
  311. }
  312. log.WriteLine(String.Empty);
  313. if (i != 2)
  314. {
  315. log.Error("BuildArray left i = {0} which is incorrect");
  316. return(false);
  317. }
  318. //
  319. // try BuildArray on high-precision floats
  320. //
  321. tokens.Clear();
  322. float f1 = 1.23456f;
  323. float f2 = 2.34567f;
  324. tokenizer.TokenizeString(String.Format("{0:f6} {1:f6}", f1,f2), tokens);
  325. foreach(Token t in tokens) log.Debug("Token = {0}", t);
  326. i = 0;
  327. floats = (float[])BuildArray(tokens, ref i, typeof(Single),
  328. null, -1, log);
  329. if (floats == null)
  330. {
  331. log.Error("Unable to BuildArray of floats.");
  332. return(false);
  333. }
  334. log.Info("Parsed floats:");
  335. foreach(float f in floats)
  336. {
  337. log.Write("{0}, ", f);
  338. }
  339. log.WriteLine(String.Empty);
  340. if (floats[0] != f1)
  341. {
  342. log.Error("BuildArray produced float {0:f6} instead of {1:f6}",
  343. floats[0], f1);
  344. return(false);
  345. }
  346. //
  347. // try BuildArray of chars, maxLength terminated
  348. //
  349. log.Info("Chars, terminated by maxLength");
  350. tokens.Clear();
  351. tokenizer.TokenizeString("12 2 ; 3 4", tokens);
  352. foreach(Token t in tokens) log.Debug("Token = {0}", t);
  353. i = 0;
  354. char[] chars = (char[])BuildArray(tokens, ref i, typeof(Char),
  355. null, 3, log);
  356. if (chars == null)
  357. {
  358. log.Error("Unable to BuildArray of chars.");
  359. return(false);
  360. }
  361. log.Info("Parsed chars:");
  362. foreach(char f in chars)
  363. {
  364. log.Write("{0}, ", f);
  365. }
  366. log.WriteLine(String.Empty);
  367. if (i != 4)
  368. {
  369. log.Error("BuildArray left i = {0} which is incorrect", i);
  370. return(false);
  371. }
  372. //
  373. // try BuildArray of hex numbers
  374. //
  375. log.Info("Hex numbers");
  376. tokens.Clear();
  377. tokenizer.Settings.ParseHexNumbers = true;
  378. tokenizer.TokenizeString("0xfff, 0xffe", tokens);
  379. foreach(Token t in tokens) log.Debug("Token = {0}", t);
  380. i = 0;
  381. ushort[] ushorts = (ushort[])BuildArray(tokens, ref i, typeof(ushort),
  382. null, 3, log);
  383. if (ushorts == null)
  384. {
  385. log.Error("Unable to BuildArray of ushorts.");
  386. return(false);
  387. }
  388. log.Info("Parsed ushorts:");
  389. foreach(ushort us in ushorts)
  390. {
  391. log.Write("{0}, ", us);
  392. }
  393. log.WriteLine(String.Empty);
  394. // if (i != 4)
  395. // {
  396. // log.Error("BuildArray left i = {0} which is incorrect", i);
  397. // return(false);
  398. // }
  399. log.Info("All PASSED");
  400. return(true);
  401. }
  402. }
  403. }