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 }