NTP Analyzer  0.8.2
Analyze the operation of time servers
Tokenizer.cs
Go to the documentation of this file.
1 //
2 // Copyright (c) 2013-2017 Carsten Sonne Larsen <cs@innolan.net>
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 
22 using System;
23 using System.Linq;
24 using System.Text;
25 using Ntp.Analyzer.Config.Table;
26 
27 namespace Ntp.Analyzer.Config.Compiler
28 {
29  public sealed class Tokenizer : IDisposable
30  {
31  public Tokenizer(string file)
32  {
33  reader = new ConfigFileReader(file);
35  }
36 
37  private readonly ConfigFileReader reader;
38 
39  public Token Token { get; private set; }
40 
41  public int LineNumber => reader.Line;
42 
43  public int ColumnNumber => reader.Position;
44 
48  public void Consume()
49  {
50  bool pass = true;
51  do
52  {
53  char c = reader.Peek();
54  switch (c)
55  {
56  case ' ':
57  case '\t':
58  reader.Read();
60  break;
61  case '#':
62  ConsumeComment();
63  break;
64  case '\n':
65  reader.Read();
66  reader.NextLine();
68  break;
69  case '\r':
70  reader.Read();
71  if (reader.Peek() == '\n')
72  reader.Read();
73 
74  reader.NextLine();
76  break;
77  default:
78  pass = false;
79  break;
80  }
81  } while (pass);
82  }
83 
87  public void ConsumeWhiteSpaces()
88  {
89  while (reader.Peek() == ' ' || reader.Peek() == '\t')
90  {
92  if (reader.Peek() == '#')
93  ConsumeComment();
94  else
95  reader.Read();
96  }
97  }
98 
99  public Token GetNext()
100  {
101  Token = GetNextToken();
102  return Token;
103  }
104 
105  public Token PeekNext()
106  {
107  if (reader.Peek() == '\0')
108  return Token.EndOfFile;
109 
110  switch (reader.Peek())
111  {
112  case '\r':
113  case '\n':
114  return Token.NewLine;
115  case ' ':
116  case '\t':
117  return Token.Whitespace;
118  default:
119  return Token.Undefined;
120  }
121  }
122 
123  private void ConsumeComment()
124  {
125  if (reader.Peek() != '#')
126  return;
127 
128  reader.Read();
129  while (reader.Peek() != '\r' && reader.Peek() != '\n' && reader.Peek() != '\0')
130  reader.Read();
131 
132  switch (reader.Peek())
133  {
134  case '\n':
135  reader.Read();
136  reader.NextLine();
137  Token = Token.NewLine;
138  return;
139  case '\r':
140  reader.Read();
141  if (reader.Peek() == '\n')
142  reader.Read();
143 
144  reader.NextLine();
145  Token = Token.NewLine;
146  break;
147  }
148  }
149 
150  private Token GetNextToken()
151  {
152  while (reader.Peek() != '\0')
153  {
154  switch (reader.Peek())
155  {
156  case '\n':
157  reader.Read();
158  reader.NextLine();
159  return Token.NewLine;
160  case '\r':
161  reader.Read();
162  if (reader.Peek() == '\n')
163  reader.Read();
164 
165  reader.NextLine();
166  return Token.NewLine;
167  }
168 
169  while (char.IsWhiteSpace(reader.Peek()))
170  {
171  reader.Read();
172  return Token.Whitespace;
173  }
174 
175  if (reader.Peek() == '\0')
176  {
177  return new SymbolToken(Symbol.EndOfFile);
178  }
179 
180  var c = reader.Peek();
181  switch (c)
182  {
183  case '{':
184  reader.Read();
185  return new SymbolToken(Symbol.OpeningBrace);
186  case '}':
187  reader.Read();
188  return new SymbolToken(Symbol.ClosingBrace);
189  }
190 
191  var token = ParseQuotedIdent() ?? ParseLiteral();
192  return token;
193  }
194 
195  return new SymbolToken(Symbol.EndOfFile);
196  }
197 
198  private static Token ParseBoolean(string text)
199  {
200  switch (text.ToLower())
201  {
202  case "0":
203  return new SymbolToken(Symbol.Zero);
204  case "1":
205  return new SymbolToken(Symbol.One);
206  case "no":
207  case "off":
208  case "false":
209  return new SymbolToken(Symbol.BooleanFalse);
210  case "on":
211  case "yes":
212  case "true":
213  return new SymbolToken(Symbol.BooleanTrue);
214  default:
215  return null;
216  }
217  }
218 
219  private static Token ParseDigitValue(string text)
220  {
221  int value;
222  if (int.TryParse(text, out value))
223  {
224  switch (value)
225  {
226  case 0:
227  return new SymbolToken(Symbol.Zero);
228  case 1:
229  return new SymbolToken(Symbol.One);
230  default:
231  return new IntegerToken(value);
232  }
233  }
234 
235  if (text.ToCharArray().Count(c => "0123456789.".Contains(c)) != text.Length)
236  return null;
237 
238  if (text.ToCharArray().Count(c => c == '.') > 1)
239  return null;
240 
241  double dvalue;
242  return double.TryParse(text, out dvalue) ? new NumericToken(dvalue) : null;
243  }
244 
245  private Token ParseLiteral()
246  {
247  var text = new StringBuilder();
248  while (!char.IsWhiteSpace(reader.Peek()) && reader.Peek() != '\r' && reader.Peek() != '\n' &&
249  reader.Peek() != '\0')
250  text.Append(reader.Read());
251 
252  string tokenText = text.ToString();
253 
254  var token = ParseBoolean(tokenText) ?? ParseDigitValue(tokenText);
255  if (token != null)
256  return token;
257 
258  string search = tokenText.ToLower();
259  var keyword = Keyword.Keywords.FirstOrDefault(k => k.LowerText == search);
260 
261  return keyword != null
262  ? new KeywordToken(keyword, tokenText)
263  : (Token) new LiteralToken(tokenText);
264  }
265 
267  {
268  if (reader.Peek() != '"')
269  return null;
270 
271  reader.Read();
272 
273  var text = new StringBuilder();
274  while (reader.Peek() != '\0' && reader.Peek() != '"')
275  text.Append(reader.Read());
276 
277  if (reader.Peek() == '"')
278  reader.Read();
279 
280  return new QuotedIdentToken(text.ToString());
281  }
282 
283  #region IDisposable Support
284 
285  private bool disposedValue;
286 
287  private void Dispose(bool disposing)
288  {
289  if (disposedValue)
290  return;
291 
292  if (disposing)
293  {
294  reader.Dispose();
295  }
296 
297  disposedValue = true;
298  }
299 
301  {
302  Dispose(false);
303  }
304 
305  public void Dispose()
306  {
307  Dispose(true);
308  GC.SuppressFinalize(this);
309  }
310 
311  #endregion
312  }
313 }
static Token ParseDigitValue(string text)
Definition: Tokenizer.cs:219
readonly ConfigFileReader reader
Definition: Tokenizer.cs:37
void ConsumeWhiteSpaces()
Consume white spaces and comments.
Definition: Tokenizer.cs:87
void Consume()
Consume white spaces, line breaks and comments.
Definition: Tokenizer.cs:48
static IEnumerable< Keyword > Keywords
Definition: Keyword.cs:47
static Token ParseBoolean(string text)
Definition: Tokenizer.cs:198
var c
Definition: bootstrap.min.js:6