PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NUnit/UiException/CSharpParser/Lexer.cs

#
C# | 233 lines | 202 code | 8 blank | 23 comment | 0 complexity | 5200a2757dfcd1f04febc05be4e15040 MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // This is free software licensed under the NUnit license. You may
  3. // obtain a copy of the license at http://nunit.org
  4. // ****************************************************************
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. namespace NUnit.UiException.CodeFormatters
  9. {
  10. /// <summary>
  11. /// Splits a text formatted as C# code into a list of identified tokens.
  12. /// </summary>
  13. public class Lexer
  14. {
  15. /// <summary>
  16. /// Reading position in the current text.
  17. /// </summary>
  18. private int _position;
  19. /// <summary>
  20. /// Text where to fetch tokens.
  21. /// </summary>
  22. private string _text;
  23. /// <summary>
  24. /// Last identified token.
  25. /// </summary>
  26. private InternalToken _token;
  27. /// <summary>
  28. /// Holds pre-defined sequences.
  29. /// </summary>
  30. private TokenDictionary _dictionary;
  31. /// <summary>
  32. /// Builds a new instance of Lexer.
  33. /// </summary>
  34. public Lexer()
  35. {
  36. _position = 0;
  37. _text = "";
  38. _dictionary = new TokenDictionary();
  39. _dictionary.Add("/*", LexerTag.CommentC_Open);
  40. _dictionary.Add("*/", LexerTag.CommentC_Close);
  41. _dictionary.Add("//", LexerTag.CommentCpp);
  42. // Here: definition of one lengthed sequences
  43. _dictionary.Add("\\", LexerTag.Text);
  44. _dictionary.Add(" ", LexerTag.Separator);
  45. _dictionary.Add("\t", LexerTag.Separator);
  46. _dictionary.Add("\r", LexerTag.Separator);
  47. _dictionary.Add(".", LexerTag.Separator);
  48. _dictionary.Add(";", LexerTag.Separator);
  49. _dictionary.Add("[", LexerTag.Separator);
  50. _dictionary.Add("]", LexerTag.Separator);
  51. _dictionary.Add("(", LexerTag.Separator);
  52. _dictionary.Add(")", LexerTag.Separator);
  53. _dictionary.Add("#", LexerTag.Separator);
  54. _dictionary.Add(":", LexerTag.Separator);
  55. _dictionary.Add("<", LexerTag.Separator);
  56. _dictionary.Add(">", LexerTag.Separator);
  57. _dictionary.Add("=", LexerTag.Separator);
  58. _dictionary.Add(",", LexerTag.Separator);
  59. _dictionary.Add("\n", LexerTag.EndOfLine);
  60. _dictionary.Add("'", LexerTag.SingleQuote);
  61. _dictionary.Add("\"", LexerTag.DoubleQuote);
  62. return;
  63. }
  64. public TokenDictionary Dictionary
  65. {
  66. get { return (_dictionary); }
  67. }
  68. /// <summary>
  69. /// Clear all previously defined sequences.
  70. /// </summary>
  71. protected void Clear()
  72. {
  73. _dictionary = new TokenDictionary();
  74. return;
  75. }
  76. /// <summary>
  77. /// Setup the text to be splitted in tokens.
  78. ///
  79. /// Client code must call Next() first before getting
  80. /// the first available token (if any).
  81. /// </summary>
  82. public void Parse(string codeCSharp)
  83. {
  84. UiExceptionHelper.CheckNotNull(codeCSharp, "text");
  85. _text = codeCSharp;
  86. _position = 0;
  87. return;
  88. }
  89. /// <summary>
  90. /// Gets the token identifed after a call to Next().
  91. /// The value may be null if the end of the text has been reached.
  92. /// </summary>
  93. public LexToken CurrentToken
  94. {
  95. get { return (_token); }
  96. }
  97. /// <summary>
  98. /// Checks whether there are none visited tokens.
  99. /// </summary>
  100. public bool HasNext()
  101. {
  102. return (_position < _text.Length);
  103. }
  104. /// <summary>
  105. /// Call this method to visit iteratively all tokens in the source text.
  106. /// Each time a token has been identifier, the method returns true and the
  107. /// identified Token is place under the CurrentToken property.
  108. /// When there is not more token to visit, the method returns false
  109. /// and null is set in CurrentToken property.
  110. /// </summary>
  111. public bool Next()
  112. {
  113. char c;
  114. LexToken token;
  115. string prediction;
  116. int pos;
  117. int count;
  118. int prediction_length;
  119. _token = null;
  120. if (!HasNext())
  121. return (false);
  122. pos = _position;
  123. _token = new InternalToken(pos);
  124. prediction_length = _dictionary[0].Text.Length;
  125. while (pos < _text.Length)
  126. {
  127. c = _text[pos];
  128. _token.AppendsChar(c);
  129. prediction = "";
  130. if (pos + 1 < _text.Length)
  131. {
  132. count = Math.Min(prediction_length, _text.Length - pos - 1);
  133. prediction = _text.Substring(pos + 1, count);
  134. }
  135. token = _dictionary.TryMatch(_token.Text, prediction);
  136. if (token != null)
  137. {
  138. _token.SetText(token.Text);
  139. _token.SetIndex(_position);
  140. _token.SetLexerTag(token.Tag);
  141. _position += _token.Text.Length;
  142. break;
  143. }
  144. pos++;
  145. }
  146. return (true);
  147. }
  148. #region InternalToken
  149. class InternalToken :
  150. LexToken
  151. {
  152. /// <summary>
  153. /// Builds a concrete instance of LexToken. By default, created instance
  154. /// are setup with LexerTag.Text value.
  155. /// </summary>
  156. /// <param name="startingPosition">The starting startingPosition of this token in the text.</param>
  157. public InternalToken(int index)
  158. {
  159. _tag = LexerTag.Text;
  160. _text = "";
  161. _start = index;
  162. return;
  163. }
  164. /// <summary>
  165. /// Appends this character to this token.
  166. /// </summary>
  167. public void AppendsChar(char c)
  168. {
  169. _text += c;
  170. }
  171. /// <summary>
  172. /// Removes the "count" ending character of this token.
  173. /// </summary>
  174. public void PopChars(int count)
  175. {
  176. _text = _text.Remove(_text.Length - count);
  177. }
  178. /// <summary>
  179. /// Set a new value to the Tag property.
  180. /// </summary>
  181. public void SetLexerTag(LexerTag tag)
  182. {
  183. _tag = tag;
  184. }
  185. public void SetText(string text)
  186. {
  187. _text = text;
  188. }
  189. public void SetIndex(int index)
  190. {
  191. _start = index;
  192. }
  193. }
  194. #endregion
  195. }
  196. }