##// END OF EJS Templates
Bound promise to CancellationToken...
Bound promise to CancellationToken Added new states to ExecutionSate enum. Added Safe.Guard() method to handle cleanup of the result of the promise

File last commit:

r208:7d07503621fe v2
r209:a867536c68fc v2
Show More
JSONParser.cs
293 lines | 11.0 KiB | text/x-csharp | CSharpLexer
cin
DFA refactoring
r165 using System;
cin
JSON moved to Formats namespace...
r163 using System.Diagnostics;
using System.IO;
cin
DFA refactoring
r165 using Implab.Automaton;
using Implab.Automaton.RegularExpressions;
using System.Linq;
using Implab.Components;
cin
refactoring complete, JSONParser rewritten
r180 using System.Collections.Generic;
cin
JSON moved to Formats namespace...
r163
cin
DFA refactoring
r165 namespace Implab.Formats.JSON {
cin
JSON moved to Formats namespace...
r163 /// <summary>
/// Pull парсер JSON данных.
/// </summary>
/// <remarks>
/// Следует отметить отдельную интерпретацию свойства <see cref="Level"/>,
/// оно означает текущий уровень вложенности объектов, однако закрывающий
/// элемент объекта и массива имеет уровень меньше, чем сам объект.
/// <code>
/// { // Level = 1
/// "name" : "Peter", // Level = 1
/// "address" : { // Level = 2
/// city : "Stern" // Level = 2
/// } // Level = 1
/// } // Level = 0
/// </code>
/// </remarks>
cin
DFA refactoring
r165 public class JSONParser : Disposable {
cin
JSON moved to Formats namespace...
r163
enum MemberContext {
MemberName,
MemberValue
}
cin
working on JSON parser
r178 #region Parser rules
cin
DFA refactoring
r165 struct ParserContext {
cin
working on JSON parser
r178 readonly int[,] m_dfa;
int m_state;
readonly JSONElementContext m_elementContext;
cin
DFA refactoring
r165
cin
working on JSON parser
r178 public ParserContext(int[,] dfa, int state, JSONElementContext context) {
m_dfa = dfa;
m_state = state;
m_elementContext = context;
}
public bool Move(JsonTokenType token) {
cin
refactoring complete, JSONParser rewritten
r180 var next = m_dfa[m_state, (int)token];
cin
working on JSON parser
r178 if (next == AutomatonConst.UNREACHABLE_STATE)
return false;
m_state = next;
cin
refactoring complete, JSONParser rewritten
r180 return true;
cin
working on JSON parser
r178 }
public JSONElementContext ElementContext {
get { return m_elementContext; }
}
}
cin
JSON moved to Formats namespace...
r163
cin
refactoring complete, JSONParser rewritten
r180 static readonly ParserContext _jsonContext;
static readonly ParserContext _objectContext;
static readonly ParserContext _arrayContext;
cin
JSON moved to Formats namespace...
r163 static JSONParser() {
cin
refactoring complete, JSONParser rewritten
r180 var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String);
var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression);
cin
JSON moved to Formats namespace...
r163
var objectExpression = memberExpression
.Cat(
cin
refactoring complete, JSONParser rewritten
r180 MakeToken(JsonTokenType.ValueSeparator)
cin
JSON moved to Formats namespace...
r163 .Cat(memberExpression)
.EClosure()
)
.Optional()
cin
refactoring complete, JSONParser rewritten
r180 .Cat(MakeToken(JsonTokenType.EndObject))
cin
working on JSON parser
r178 .End();
cin
JSON moved to Formats namespace...
r163 var arrayExpression = valueExpression
.Cat(
cin
refactoring complete, JSONParser rewritten
r180 MakeToken(JsonTokenType.ValueSeparator)
cin
JSON moved to Formats namespace...
r163 .Cat(valueExpression)
.EClosure()
)
.Optional()
cin
refactoring complete, JSONParser rewritten
r180 .Cat(MakeToken(JsonTokenType.EndArray))
cin
working on JSON parser
r178 .End();
cin
JSON moved to Formats namespace...
r163
cin
working on JSON parser
r178 var jsonExpression = valueExpression.End();
cin
JSON moved to Formats namespace...
r163
cin
refactoring complete, JSONParser rewritten
r180 _jsonContext = CreateParserContext(jsonExpression, JSONElementContext.None);
_objectContext = CreateParserContext(objectExpression, JSONElementContext.Object);
_arrayContext = CreateParserContext(arrayExpression, JSONElementContext.Array);
cin
JSON moved to Formats namespace...
r163 }
cin
refactoring complete, JSONParser rewritten
r180 static Token MakeToken(params JsonTokenType[] input) {
cin
working on JSON parser
r178 return Token.New( input.Select(t => (int)t).ToArray() );
cin
DFA refactoring
r165 }
cin
working on JSON parser
r178 static ParserContext CreateParserContext(Token expr, JSONElementContext context) {
var dfa = new DFATable();
var builder = new RegularExpressionVisitor(dfa);
cin
JSON moved to Formats namespace...
r163 expr.Accept(builder);
cin
working on JSON parser
r178 builder.BuildDFA();
cin
JSON moved to Formats namespace...
r163
cin
working on JSON parser
r178 return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context);
cin
JSON moved to Formats namespace...
r163 }
cin
working on JSON parser
r178 #endregion
cin
refactoring complete, JSONParser rewritten
r180 readonly JSONScanner m_scanner;
cin
JSON moved to Formats namespace...
r163 MemberContext m_memberContext;
JSONElementType m_elementType;
object m_elementValue;
cin
refactoring complete, JSONParser rewritten
r180 string m_memberName = String.Empty;
Stack<ParserContext> m_stack = new Stack<ParserContext>();
ParserContext m_context = _jsonContext;
cin
JSON moved to Formats namespace...
r163
/// <summary>
/// Создает новый парсер на основе строки, содержащей JSON
/// </summary>
/// <param name="text"></param>
cin
refactoring complete, JSONParser rewritten
r180 public JSONParser(string text) {
cin
JSON moved to Formats namespace...
r163 Safe.ArgumentNotEmpty(text, "text");
cin
refactoring complete, JSONParser rewritten
r180 m_scanner = new JSONScanner(text);
cin
JSON moved to Formats namespace...
r163 }
/// <summary>
/// Создает новый экземпляр парсера, на основе текстового потока.
/// </summary>
/// <param name="reader">Текстовый поток.</param>
cin
refactoring complete, JSONParser rewritten
r180 public JSONParser(TextReader reader) {
cin
JSON moved to Formats namespace...
r163 Safe.ArgumentNotNull(reader, "reader");
cin
refactoring complete, JSONParser rewritten
r180 m_scanner = new JSONScanner(reader);
}
public int Level {
get { return m_stack.Count; }
cin
JSON moved to Formats namespace...
r163 }
/// <summary>
/// Тип текущего элемента на котором стоит парсер.
/// </summary>
public JSONElementType ElementType {
get { return m_elementType; }
}
/// <summary>
/// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда
/// пустая строка.
/// </summary>
public string ElementName {
cin
refactoring complete, JSONParser rewritten
r180 get { return m_memberName; }
cin
JSON moved to Formats namespace...
r163 }
/// <summary>
/// Значение элемента. Только для элементов типа <see cref="JSONElementType.Value"/>, для остальных <c>null</c>
/// </summary>
public object ElementValue {
get { return m_elementValue; }
}
/// <summary>
/// Читает слеюудущий объект из потока
/// </summary>
/// <returns><c>true</c> - операция чтения прошла успешно, <c>false</c> - конец данных</returns>
public bool Read() {
object tokenValue;
JsonTokenType tokenType;
cin
refactoring complete, JSONParser rewritten
r180
m_memberName = String.Empty;
cin
JSON moved to Formats namespace...
r163 while (m_scanner.ReadToken(out tokenValue, out tokenType)) {
cin
refactoring complete, JSONParser rewritten
r180 if(!m_context.Move(tokenType))
cin
JSON moved to Formats namespace...
r163 UnexpectedToken(tokenValue, tokenType);
cin
refactoring complete, JSONParser rewritten
r180
cin
JSON moved to Formats namespace...
r163 switch (tokenType) {
case JsonTokenType.BeginObject:
cin
refactoring complete, JSONParser rewritten
r180 m_stack.Push(m_context);
m_context = _objectContext;
cin
JSON moved to Formats namespace...
r163 m_elementValue = null;
m_memberContext = MemberContext.MemberName;
m_elementType = JSONElementType.BeginObject;
return true;
case JsonTokenType.EndObject:
cin
refactoring complete, JSONParser rewritten
r180 if (m_stack.Count == 0)
UnexpectedToken(tokenValue, tokenType);
m_context = m_stack.Pop();
cin
JSON moved to Formats namespace...
r163 m_elementValue = null;
m_elementType = JSONElementType.EndObject;
return true;
case JsonTokenType.BeginArray:
cin
refactoring complete, JSONParser rewritten
r180 m_stack.Push(m_context);
m_context = _arrayContext;
cin
JSON moved to Formats namespace...
r163 m_elementValue = null;
m_memberContext = MemberContext.MemberValue;
m_elementType = JSONElementType.BeginArray;
return true;
case JsonTokenType.EndArray:
cin
refactoring complete, JSONParser rewritten
r180 if (m_stack.Count == 0)
UnexpectedToken(tokenValue, tokenType);
m_context = m_stack.Pop();
cin
JSON moved to Formats namespace...
r163 m_elementValue = null;
m_elementType = JSONElementType.EndArray;
return true;
case JsonTokenType.String:
if (m_memberContext == MemberContext.MemberName) {
cin
refactoring complete, JSONParser rewritten
r180 m_memberName = (string)tokenValue;
cin
JSON moved to Formats namespace...
r163 break;
}
m_elementType = JSONElementType.Value;
m_elementValue = tokenValue;
return true;
case JsonTokenType.Number:
m_elementType = JSONElementType.Value;
m_elementValue = tokenValue;
return true;
case JsonTokenType.Literal:
m_elementType = JSONElementType.Value;
m_elementValue = ParseLiteral((string)tokenValue);
return true;
case JsonTokenType.NameSeparator:
m_memberContext = MemberContext.MemberValue;
break;
case JsonTokenType.ValueSeparator:
cin
refactoring complete, JSONParser rewritten
r180 m_memberContext = m_context.ElementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue;
cin
JSON moved to Formats namespace...
r163 break;
default:
UnexpectedToken(tokenValue, tokenType);
break;
}
}
cin
refactoring complete, JSONParser rewritten
r180 if (m_context.ElementContext != JSONElementContext.None)
cin
JSON moved to Formats namespace...
r163 throw new ParserException("Unexpedted end of data");
cin
refactoring complete, JSONParser rewritten
r180
EOF = true;
cin
JSON moved to Formats namespace...
r163 return false;
}
object ParseLiteral(string literal) {
switch (literal) {
case "null":
return null;
case "false":
return false;
case "true":
return true;
default:
UnexpectedToken(literal, JsonTokenType.Literal);
return null; // avoid compliler error
}
}
void UnexpectedToken(object value, JsonTokenType tokenType) {
throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value));
}
/// <summary>
/// Признак конца потока
/// </summary>
public bool EOF {
cin
refactoring complete, JSONParser rewritten
r180 get;
private set;
cin
JSON moved to Formats namespace...
r163 }
cin
DFA refactoring
r165 protected override void Dispose(bool disposing) {
cin
refactoring complete, JSONParser rewritten
r180 if (disposing)
cin
RunnableComponent.Dispose(bool,Exception) changed to standart Dispose(bool)...
r208 m_scanner.Dispose();
cin
JSON moved to Formats namespace...
r163 }
/// <summary>
/// Переходит в конец текущего объекта.
/// </summary>
public void SeekElementEnd() {
var level = Level - 1;
Debug.Assert(level >= 0);
while (Level != level)
Read();
}
}
}