Mercurial > pub > ImplabNet
annotate Implab/Formats/JSON/JSONScanner.cs @ 210:5dc21f6a3222 v2
Code review for RunnableComponent
Added StaApartment class based on System.Windows.Forms.Application message loop
author | cin |
---|---|
date | Mon, 20 Mar 2017 17:44:18 +0300 |
parents | 7d07503621fe |
children |
rev | line source |
---|---|
165 | 1 using System; |
163 | 2 using System.Globalization; |
165 | 3 using Implab.Automaton; |
176 | 4 using System.Text; |
5 using Implab.Components; | |
6 using System.IO; | |
163 | 7 |
165 | 8 namespace Implab.Formats.JSON { |
163 | 9 /// <summary> |
10 /// Сканнер (лексер), разбивающий поток символов на токены JSON. | |
11 /// </summary> | |
176 | 12 public class JSONScanner : Disposable { |
13 readonly StringBuilder m_builder = new StringBuilder(); | |
14 | |
179 | 15 readonly ScannerContext<JSONGrammar.TokenType> m_jsonContext = JSONGrammar.Instance.JsonExpression; |
16 readonly ScannerContext<JSONGrammar.TokenType> m_stringContext = JSONGrammar.Instance.JsonStringExpression; | |
176 | 17 |
18 | |
19 readonly TextScanner m_scanner; | |
163 | 20 |
21 /// <summary> | |
22 /// Создает новый экземпляр сканнера | |
23 /// </summary> | |
176 | 24 public JSONScanner(string text) { |
25 Safe.ArgumentNotEmpty(text, "text"); | |
26 | |
27 m_scanner = new StringScanner(text); | |
28 } | |
29 | |
30 public JSONScanner(TextReader reader, int bufferMax, int chunkSize) { | |
31 Safe.ArgumentNotNull(reader, "reader"); | |
32 | |
177 | 33 m_scanner = new ReaderScanner(reader, bufferMax, chunkSize); |
163 | 34 } |
35 | |
180 | 36 public JSONScanner(TextReader reader) : this(reader, 1024*1024, 1024){ |
37 } | |
38 | |
163 | 39 /// <summary> |
40 /// Читает следующий лексический элемент из входных данных. | |
41 /// </summary> | |
42 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param> | |
43 /// <param name="tokenType">Возвращает тип прочитанного токена.</param> | |
44 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns> | |
45 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. | |
46 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks> | |
47 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { | |
176 | 48 JSONGrammar.TokenType[] tag; |
183 | 49 while (m_jsonContext.Execute(m_scanner, out tag)) { |
176 | 50 switch (tag[0]) { |
163 | 51 case JSONGrammar.TokenType.StringBound: |
52 tokenValue = ReadString(); | |
53 tokenType = JsonTokenType.String; | |
54 break; | |
55 case JSONGrammar.TokenType.Number: | |
176 | 56 tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture); |
163 | 57 tokenType = JsonTokenType.Number; |
58 break; | |
183 | 59 case JSONGrammar.TokenType.Whitespace: |
60 continue; | |
163 | 61 default: |
176 | 62 tokenType = (JsonTokenType)tag[0]; |
63 tokenValue = m_scanner.GetTokenValue(); | |
163 | 64 break; |
65 } | |
66 return true; | |
67 } | |
68 tokenValue = null; | |
69 tokenType = JsonTokenType.None; | |
70 return false; | |
71 } | |
72 | |
73 string ReadString() { | |
74 int pos = 0; | |
177 | 75 var buf = new char[6]; // the buffer for unescaping chars |
176 | 76 |
77 JSONGrammar.TokenType[] tag; | |
78 m_builder.Clear(); | |
79 | |
177 | 80 while (m_stringContext.Execute(m_scanner, out tag)) { |
176 | 81 switch (tag[0]) { |
163 | 82 case JSONGrammar.TokenType.StringBound: |
176 | 83 return m_builder.ToString(); |
163 | 84 case JSONGrammar.TokenType.UnescapedChar: |
176 | 85 m_scanner.CopyTokenTo(m_builder); |
163 | 86 break; |
176 | 87 case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence |
88 m_scanner.CopyTokenTo(buf, 0); | |
89 m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2)); | |
163 | 90 pos++; |
91 break; | |
176 | 92 case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence |
93 m_scanner.CopyTokenTo(buf, 0); | |
94 m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1])); | |
163 | 95 break; |
96 } | |
97 | |
98 } | |
99 | |
100 throw new ParserException("Unexpected end of data"); | |
101 } | |
177 | 102 |
103 protected override void Dispose(bool disposing) { | |
104 if (disposing) | |
208
7d07503621fe
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)
cin
parents:
183
diff
changeset
|
105 m_scanner.Dispose(); |
177 | 106 base.Dispose(disposing); |
107 } | |
163 | 108 } |
109 } |