Mercurial > pub > ImplabNet
comparison Implab/JSON/JSONScanner.cs @ 55:c0bf853aa04f
Added initial JSON support
+JSONParser
+JSONWriter
| author | cin |
|---|---|
| date | Sun, 15 Jun 2014 19:39:11 +0400 |
| parents | |
| children | 10c7337d29e7 |
comparison
equal
deleted
inserted
replaced
| 51:2c332a9c64c0 | 55:c0bf853aa04f |
|---|---|
| 1 using Implab.Parsing; | |
| 2 using System; | |
| 3 using System.Collections.Generic; | |
| 4 using System.Globalization; | |
| 5 using System.Linq; | |
| 6 using System.Text; | |
| 7 using System.Threading.Tasks; | |
| 8 | |
| 9 namespace Implab.JSON { | |
| 10 /// <summary> | |
| 11 /// Сканнер, разбивающий поток символов на токены JSON. | |
| 12 /// </summary> | |
| 13 public class JSONScanner : Scanner { | |
| 14 char[] m_stringBuffer; | |
| 15 DFAStateDescriptior[] m_stringDFA; | |
| 16 int[] m_stringAlphabet; | |
| 17 | |
| 18 public JSONScanner() | |
| 19 : base(JSONGrammar.Instance.JsonDFA) { | |
| 20 m_stringBuffer = new char[1024]; | |
| 21 var dfa = JSONGrammar.Instance.JsonStringDFA; | |
| 22 m_stringAlphabet = dfa.Alphabet.GetTranslationMap(); | |
| 23 m_stringDFA = dfa.States; | |
| 24 } | |
| 25 | |
| 26 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { | |
| 27 if (ReadTokenInternal()) { | |
| 28 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) { | |
| 29 case JSONGrammar.TokenType.StringBound: | |
| 30 tokenValue = ReadString(); | |
| 31 tokenType = JsonTokenType.String; | |
| 32 break; | |
| 33 case JSONGrammar.TokenType.Number: | |
| 34 tokenValue = Double.Parse(new String(m_buffer, m_tokenOffset, m_tokenLen), CultureInfo.InvariantCulture); | |
| 35 tokenType = JsonTokenType.Number; | |
| 36 break; | |
| 37 default: | |
| 38 tokenType = (JsonTokenType)m_currentState.tag[0]; | |
| 39 tokenValue = new String(m_buffer, m_tokenOffset, m_tokenLen); | |
| 40 break; | |
| 41 } | |
| 42 return true; | |
| 43 } | |
| 44 tokenValue = null; | |
| 45 tokenType = JsonTokenType.None; | |
| 46 return false; | |
| 47 } | |
| 48 | |
| 49 string ReadString() { | |
| 50 int pos = 0; | |
| 51 Switch(m_stringDFA, m_stringAlphabet); | |
| 52 while (ReadTokenInternal()) { | |
| 53 switch ((JSONGrammar.TokenType)m_currentState.tag[0]) { | |
| 54 case JSONGrammar.TokenType.StringBound: | |
| 55 Restore(); | |
| 56 return new String(m_stringBuffer, 0, pos); | |
| 57 case JSONGrammar.TokenType.UnescapedChar: | |
| 58 EnsureStringBufferSize(pos + m_tokenLen); | |
| 59 Array.Copy(m_buffer, m_tokenOffset, m_stringBuffer, pos, m_tokenLen); | |
| 60 pos += m_tokenLen; | |
| 61 break; | |
| 62 case JSONGrammar.TokenType.EscapedUnicode: | |
| 63 EnsureStringBufferSize(pos + 1); | |
| 64 m_stringBuffer[pos] = StringTranslator.TranslateHexUnicode(m_buffer, m_tokenOffset + 2); | |
| 65 pos++; | |
| 66 break; | |
| 67 case JSONGrammar.TokenType.EscapedChar: | |
| 68 EnsureStringBufferSize(pos + 1); | |
| 69 m_stringBuffer[pos] = StringTranslator.TranslateEscapedChar(m_buffer[m_tokenOffset + 1]); | |
| 70 pos++; | |
| 71 break; | |
| 72 default: | |
| 73 break; | |
| 74 } | |
| 75 | |
| 76 } | |
| 77 | |
| 78 throw new ParserException("Unexpected end of data"); | |
| 79 } | |
| 80 | |
| 81 void EnsureStringBufferSize(int size) { | |
| 82 if (size > m_stringBuffer.Length) { | |
| 83 var newBuffer = new char[size]; | |
| 84 m_stringBuffer.CopyTo(newBuffer, 0); | |
| 85 m_stringBuffer = newBuffer; | |
| 86 } | |
| 87 } | |
| 88 } | |
| 89 } |
