source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/contrib-2.1.0/apps/LwipMibCompiler/SharpSnmpLib/Mib/Lexer.cs@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csharp;charset=UTF-8
File size: 18.5 KB
Line 
1/*
2 * Created by SharpDevelop.
3 * User: lextm
4 * Date: 2008/5/17
5 * Time: 16:50
6 *
7 * To change this template use Tools | Options | Coding | Edit Standard Headers.
8 */
9
10using System;
11using System.Collections.Generic;
12using System.IO;
13using System.Text;
14using Lextm.SharpSnmpLib.Mib.Elements.Types;
15
16namespace Lextm.SharpSnmpLib.Mib
17{
18 /// <summary>
19 /// Lexer class that parses MIB files into symbol list.
20 /// </summary>
21 public sealed class Lexer
22 {
23 private readonly SymbolList _symbols = new SymbolList();
24
25 public Lexer(string file)
26 : this(file, new StreamReader(file))
27 {
28 }
29
30 public Lexer(string file, TextReader stream)
31 {
32 this.Parse(file, stream);
33 }
34
35
36 public ISymbolEnumerator GetEnumerator()
37 {
38 return _symbols.GetSymbolEnumerator();
39 }
40
41
42 #region Parsing of MIB File
43
44 private class ParseParams
45 {
46 public string File;
47 public StringBuilder Temp = new StringBuilder();
48 public bool StringSection = false;
49 public bool AssignSection = false;
50 public bool AssignAhead = false;
51 public bool DotSection = false;
52
53 }
54
55 /// <summary>
56 /// Parses MIB file to symbol list.
57 /// </summary>
58 /// <param name="file">File</param>
59 /// <param name="stream">File stream</param>
60 private void Parse(string file, TextReader stream)
61 {
62 if (stream == null)
63 {
64 throw new ArgumentNullException("stream");
65 }
66
67 ParseParams pp = new ParseParams();
68 pp.File = file;
69
70 string line;
71 int row = 0;
72 while ((line = stream.ReadLine()) != null)
73 {
74 if (!pp.StringSection && line.TrimStart().StartsWith("--", StringComparison.Ordinal))
75 {
76 row++;
77 continue; // commented line
78 }
79
80 ParseLine(pp, line, row);
81 row++;
82 }
83 }
84
85 private void ParseLine(ParseParams pp, string line, int row)
86 {
87 line = line + "\n";
88 int count = line.Length;
89 for (int i = 0; i < count; i++)
90 {
91 char current = line[i];
92 bool moveNext = Parse(pp, current, row, i);
93 if (moveNext)
94 {
95 break;
96 }
97 }
98 }
99
100 private bool Parse(ParseParams pp, char current, int row, int column)
101 {
102 switch (current)
103 {
104 case '\n':
105 case '{':
106 case '}':
107 case '(':
108 case ')':
109 case '[':
110 case ']':
111 case ';':
112 case ',':
113 case '|':
114 if (!pp.StringSection)
115 {
116 bool moveNext = ParseLastSymbol(pp, row, column);
117 if (moveNext)
118 {
119 _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column));
120 return true;
121 }
122
123 _symbols.Add(CreateSpecialSymbol(pp.File, current, row, column));
124 return false;
125 }
126
127 break;
128 case '"':
129 pp.StringSection = !pp.StringSection;
130 break;
131 case '\r':
132 return false;
133 default:
134 if ((int)current == 0x1A)
135 {
136 // IMPORTANT: ignore invisible characters such as SUB.
137 return false;
138 }
139
140 if (Char.IsWhiteSpace(current) && !pp.AssignSection && !pp.StringSection)
141 {
142 bool moveNext = ParseLastSymbol(pp, row, column);
143 if (moveNext)
144 {
145 _symbols.Add(CreateSpecialSymbol(pp.File, '\n', row, column));
146 return true;
147 }
148
149 return false;
150 }
151
152 if (pp.AssignAhead)
153 {
154 pp.AssignAhead = false;
155 ParseLastSymbol(pp, row, column);
156 break;
157 }
158
159 if (pp.DotSection && current != '.')
160 {
161 ParseLastSymbol(pp, row, column);
162 pp.DotSection = false;
163 }
164
165 if (current == '.' && !pp.StringSection)
166 {
167 if (!pp.DotSection)
168 {
169 ParseLastSymbol(pp, row, column);
170 pp.DotSection = true;
171 }
172 }
173
174 if (current == ':' && !pp.StringSection)
175 {
176 if (!pp.AssignSection)
177 {
178 ParseLastSymbol(pp, row, column);
179 }
180
181 pp.AssignSection = true;
182 }
183
184 if (current == '=' && !pp.StringSection)
185 {
186 pp.AssignSection = false;
187 pp.AssignAhead = true;
188 }
189
190 break;
191 }
192
193 pp.Temp.Append(current);
194 return false;
195 }
196
197 private bool ParseLastSymbol(ParseParams pp, int row, int column)
198 {
199 if (pp.Temp.Length > 0)
200 {
201 Symbol s = new Symbol(pp.File, pp.Temp.ToString(), row, column);
202
203 pp.Temp.Length = 0;
204
205 if (s.ToString().StartsWith(Symbol.Comment.ToString()))
206 {
207 // ignore the rest symbols on this line because they are in comment.
208 return true;
209 }
210
211 _symbols.Add(s);
212 }
213
214 return false;
215 }
216
217 private static Symbol CreateSpecialSymbol(string file, char value, int row, int column)
218 {
219 string str;
220 switch (value)
221 {
222 case '\n':
223 str = Environment.NewLine;
224 break;
225 case '{':
226 str = "{";
227 break;
228 case '}':
229 str = "}";
230 break;
231 case '(':
232 str = "(";
233 break;
234 case ')':
235 str = ")";
236 break;
237 case '[':
238 str = "[";
239 break;
240 case ']':
241 str = "]";
242 break;
243 case ';':
244 str = ";";
245 break;
246 case ',':
247 str = ",";
248 break;
249 case '|':
250 str = "|";
251 break;
252 default:
253 throw new ArgumentException("value is not a special character");
254 }
255
256 return new Symbol(file, str, row, column);
257 }
258
259 #endregion
260
261 #region Static Parse Helper
262
263 public static ITypeAssignment ParseBasicTypeDef(IModule module, string name, ISymbolEnumerator symbols, bool isMacroSyntax = false)
264 {
265 Symbol current = symbols.NextNonEOLSymbol();
266
267 if (current == Symbol.Bits)
268 {
269 return new BitsType(module, name, symbols);
270 }
271 if (IntegerType.IsIntegerType(current))
272 {
273 return new IntegerType(module, name, current, symbols);
274 }
275 if (UnsignedType.IsUnsignedType(current))
276 {
277 return new UnsignedType(module, name, current, symbols);
278 }
279 if (current == Symbol.Opaque)
280 {
281 return new OpaqueType(module, name, symbols);
282 }
283 if (current == Symbol.IpAddress)
284 {
285 return new IpAddressType(module, name, symbols);
286 }
287 if (current == Symbol.TextualConvention)
288 {
289 return new TextualConvention(module, name, symbols);
290 }
291 if (current == Symbol.Octet)
292 {
293 Symbol next = symbols.NextNonEOLSymbol();
294
295 if (next == Symbol.String)
296 {
297 return new OctetStringType(module, name, symbols);
298 }
299
300 symbols.PutBack(next);
301 }
302 if (current == Symbol.Object)
303 {
304 Symbol next = symbols.NextNonEOLSymbol();
305
306 if (next == Symbol.Identifier)
307 {
308 return new ObjectIdentifierType(module, name, symbols);
309 }
310
311 symbols.PutBack(next);
312 }
313 if (current == Symbol.Sequence)
314 {
315 Symbol next = symbols.NextNonEOLSymbol();
316
317 if (next == Symbol.Of)
318 {
319 return new SequenceOf(module, name, symbols);
320 }
321 else
322 {
323 symbols.PutBack(next);
324 return new Sequence(module, name, symbols);
325 }
326 }
327 if (current == Symbol.Choice)
328 {
329 return new Choice(module, name, symbols);
330 }
331
332
333 return new TypeAssignment(module, name, current, symbols, isMacroSyntax);
334 }
335
336 public static void ParseOidValue(ISymbolEnumerator symbols, out string parent, out uint value)
337 {
338 parent = null;
339 value = 0;
340
341 Symbol current = symbols.NextNonEOLSymbol();
342 current.Expect(Symbol.OpenBracket);
343
344 Symbol previous = null;
345 StringBuilder longParent = new StringBuilder();
346
347 current = symbols.NextNonEOLSymbol();
348 longParent.Append(current);
349
350 while ((current = symbols.NextNonEOLSymbol()) != null)
351 {
352 bool succeeded;
353
354 if (current == Symbol.OpenParentheses)
355 {
356 longParent.Append(current);
357
358 current = symbols.NextNonEOLSymbol();
359 succeeded = UInt32.TryParse(current.ToString(), out value);
360 current.Assert(succeeded, "not a decimal");
361 longParent.Append(current);
362 current = symbols.NextNonEOLSymbol();
363 current.Expect(Symbol.CloseParentheses);
364 longParent.Append(current);
365 continue;
366 }
367
368 if (current == Symbol.CloseBracket)
369 {
370 parent = longParent.ToString();
371 return;
372 }
373
374 succeeded = UInt32.TryParse(current.ToString(), out value);
375 if (succeeded)
376 {
377 // numerical way
378 while ((current = symbols.NextNonEOLSymbol()) != Symbol.CloseBracket)
379 {
380 longParent.Append(".").Append(value);
381 succeeded = UInt32.TryParse(current.ToString(), out value);
382 current.Assert(succeeded, "not a decimal");
383 }
384
385 current.Expect(Symbol.CloseBracket);
386 parent = longParent.ToString();
387 return;
388 }
389
390 longParent.Append(".");
391 longParent.Append(current);
392 current = symbols.NextNonEOLSymbol();
393 current.Expect(Symbol.OpenParentheses);
394 longParent.Append(current);
395 current = symbols.NextNonEOLSymbol();
396 succeeded = UInt32.TryParse(current.ToString(), out value);
397 current.Assert(succeeded, "not a decimal");
398 longParent.Append(current);
399 current = symbols.NextNonEOLSymbol();
400 current.Expect(Symbol.CloseParentheses);
401 longParent.Append(current);
402 previous = current;
403 }
404
405 throw MibException.Create("end of file reached", previous);
406 }
407
408
409 public static ValueRanges DecodeRanges(ISymbolEnumerator symbols)
410 {
411 ValueRanges result = new ValueRanges();
412
413 Symbol startSymbol = symbols.NextNonEOLSymbol();
414 Symbol current = startSymbol;
415 current.Expect(Symbol.OpenParentheses);
416
417 while (current != Symbol.CloseParentheses)
418 {
419 Symbol value1Symbol = symbols.NextNonEOLSymbol();
420
421 if ((value1Symbol == Symbol.Size) && !result.IsSizeDeclaration)
422 {
423 result.IsSizeDeclaration = true;
424 symbols.NextNonEOLSymbol().Expect(Symbol.OpenParentheses);
425 continue;
426 }
427
428 // check for valid number
429 Int64? value1 = DecodeNumber(value1Symbol);
430 if (!value1.HasValue)
431 {
432 value1Symbol.Assert(false, "Invalid range declaration!");
433 }
434
435 // process next symbol
436 ValueRange range;
437 current = symbols.NextNonEOLSymbol();
438
439 if (current == Symbol.DoubleDot)
440 {
441 // its a continous range
442 Symbol value2Symbol = symbols.NextNonEOLSymbol();
443 Int64? value2 = DecodeNumber(value2Symbol);
444 value2Symbol.Assert(value2.HasValue && (value2.Value >= value1.Value), "Invalid range declaration!");
445
446 if (value2.Value == value1.Value)
447 {
448 range = new ValueRange(value1.Value, null);
449 }
450 else
451 {
452 range = new ValueRange(value1.Value, value2.Value);
453 }
454
455 current = symbols.NextNonEOLSymbol();
456 }
457 else
458 {
459 // its a single number
460 range = new ValueRange(value1.Value, null);
461 }
462
463 // validate range
464 if (result.IsSizeDeclaration)
465 {
466 value1Symbol.Assert(range.Start >= 0, "Invalid range declaration! Size must be greater than 0");
467 }
468
469 result.Add(range);
470
471 // check next symbol
472 current.Expect(Symbol.Pipe, Symbol.CloseParentheses);
473 }
474
475 if (result.IsSizeDeclaration)
476 {
477 current = symbols.NextNonEOLSymbol();
478 current.Expect(Symbol.CloseParentheses);
479 }
480
481 // validate ranges in between
482 for (int i=0; i<result.Count; i++)
483 {
484 for (int k=i+1; k<result.Count; k++)
485 {
486 startSymbol.Assert(!result[i].IntersectsWith(result[k]), "Invalid range declaration! Overlapping of ranges!");
487 }
488 }
489
490 return result;
491 }
492
493 public static Int64? DecodeNumber(Symbol number)
494 {
495 Int64 result;
496 string numString = (number != null) ? number.ToString() : null;
497
498 if (!String.IsNullOrEmpty(numString))
499 {
500 if (numString.StartsWith("'") && (numString.Length > 3))
501 {
502 // search second apostrophe
503 int end = numString.IndexOf('\'', 1);
504 if (end == (numString.Length - 2))
505 {
506 try
507 {
508 switch (numString[numString.Length - 1])
509 {
510 case 'b':
511 case 'B':
512 result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 2);
513 return result;
514 case 'h':
515 case 'H':
516 result = Convert.ToInt64(numString.Substring(1, numString.Length - 3), 16);
517 return result;
518 }
519 }
520 catch
521 {
522 }
523 }
524 }
525 else if (Int64.TryParse(numString, out result))
526 {
527 return result;
528 }
529 }
530
531 return null;
532 }
533
534 public static ValueMap DecodeEnumerations(ISymbolEnumerator symbols)
535 {
536 Symbol current = symbols.NextNonEOLSymbol();
537 current.Expect(Symbol.OpenBracket);
538
539 ValueMap map = new ValueMap();
540 do
541 {
542 current = symbols.NextNonEOLSymbol();
543 string identifier = current.ToString();
544
545 current = symbols.NextNonEOLSymbol();
546 current.Expect(Symbol.OpenParentheses);
547
548 current = symbols.NextNonEOLSymbol();
549 Int64 enumValue;
550 if (Int64.TryParse(current.ToString(), out enumValue))
551 {
552 try
553 {
554 // Have to include the number as it seems repeated identifiers are allowed ??
555 map.Add(enumValue, String.Format("{0}({1})", identifier, enumValue));
556 }
557 catch (ArgumentException ex)
558 {
559 current.Assert(false, ex.Message);
560 }
561 }
562 else
563 {
564 // Need to get "DefinedValue".
565 }
566
567 current = symbols.NextNonEOLSymbol();
568 current.Expect(Symbol.CloseParentheses);
569
570 current = symbols.NextNonEOLSymbol();
571 } while (current == Symbol.Comma);
572
573 current.Expect(Symbol.CloseBracket);
574
575 return map;
576 }
577
578 #endregion
579
580 }
581}
Note: See TracBrowser for help on using the repository browser.