227 lines
5.2 KiB
C#
227 lines
5.2 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
using Godot;
|
|
|
|
namespace Rokojori
|
|
{
|
|
using LexerType = JSONLexerEventType;
|
|
|
|
public class JSONParser
|
|
{
|
|
List<JSONData> stack = new List<JSONData>();
|
|
|
|
JSONArray currentArray = null;
|
|
JSONObject currentObject = null;
|
|
JSONData current = null;
|
|
bool currentIsArray = false;
|
|
JSONData root = null;
|
|
|
|
string identifier = null;
|
|
string source = null;
|
|
bool hasError = false;
|
|
JSONObject errorReport = null;
|
|
|
|
void Reset()
|
|
{
|
|
stack = new List<JSONData>();
|
|
|
|
currentArray = null;
|
|
currentObject = null;
|
|
current = null;
|
|
currentIsArray = false;
|
|
root = null;
|
|
|
|
identifier = null;
|
|
source = null;
|
|
}
|
|
|
|
void ProcessJSONData( JSONData jsonData )
|
|
{
|
|
if ( current == null )
|
|
{
|
|
root = jsonData;
|
|
}
|
|
else if ( currentIsArray )
|
|
{
|
|
currentArray.Push( jsonData );
|
|
}
|
|
else
|
|
{
|
|
currentObject.Set( identifier, jsonData );
|
|
}
|
|
}
|
|
|
|
public static bool SHOW_DEBUG_INFO = false;
|
|
|
|
void OnParse( LexerType type, int offset, int length )
|
|
{
|
|
if ( hasError ) { return; }
|
|
|
|
if ( SHOW_DEBUG_INFO )
|
|
{
|
|
RJLog.Log(type, offset, length );
|
|
|
|
if ( offset < source.Length && length > 0 && ( offset + length ) < source.Length )
|
|
{
|
|
RJLog.Log("'" + source.Substring( offset, length ) + "'" );
|
|
}
|
|
|
|
}
|
|
|
|
switch ( type )
|
|
{
|
|
case LexerType.NUMBER:
|
|
{
|
|
var stringValue = source.Substring( offset, length );
|
|
//double numberValue = 0;
|
|
double numberValue = RegexUtility.ParseDouble( stringValue );
|
|
//System.Double.TryParse( stringValue, out numberValue );
|
|
ProcessJSONData( new JSONValue( numberValue ) );
|
|
}
|
|
break;
|
|
|
|
case LexerType.STRING:
|
|
{
|
|
var stringValue = new StringBuilder();
|
|
JSONStringConverter.Read( stringValue, source, offset, length );
|
|
ProcessJSONData( new JSONValue( stringValue.ToString() ) );
|
|
}
|
|
break;
|
|
|
|
case LexerType.IDENTIFIER:
|
|
{
|
|
var stringValue = new StringBuilder();
|
|
JSONStringConverter.Read( stringValue, source, offset, length );
|
|
identifier = stringValue.ToString();
|
|
}
|
|
break;
|
|
|
|
case LexerType.NULL:
|
|
case LexerType.TRUE:
|
|
case LexerType.FALSE:
|
|
{
|
|
JSONData jsonData = new JSONValue();
|
|
|
|
if ( LexerType.NULL != type )
|
|
{ jsonData = new JSONValue( LexerType.TRUE == type ); }
|
|
|
|
ProcessJSONData( jsonData );
|
|
}
|
|
break;
|
|
|
|
case LexerType.ARRAY_START:
|
|
case LexerType.OBJECT_START:
|
|
{
|
|
var isArrayStart = LexerType.ARRAY_START == type;
|
|
|
|
JSONData jsonData = null;
|
|
if ( isArrayStart ){ jsonData = new JSONArray(); }
|
|
else { jsonData = new JSONObject(); }
|
|
|
|
ProcessJSONData( jsonData );
|
|
|
|
current = jsonData;
|
|
|
|
if ( isArrayStart )
|
|
{
|
|
currentArray = (JSONArray) jsonData;
|
|
currentObject = null;
|
|
}
|
|
else
|
|
{
|
|
currentObject = (JSONObject) jsonData;
|
|
currentArray = null;
|
|
}
|
|
|
|
stack.Add( current );
|
|
currentIsArray = isArrayStart;
|
|
}
|
|
break;
|
|
|
|
case LexerType.ARRAY_END:
|
|
case LexerType.OBJECT_END:
|
|
{
|
|
Lists.Pop( stack );
|
|
current = Lists.Last( stack );
|
|
|
|
if ( current is JSONArray )
|
|
{
|
|
currentArray = (JSONArray) current;
|
|
currentObject = null;
|
|
currentIsArray = true;
|
|
}
|
|
else if ( current is JSONObject )
|
|
{
|
|
currentArray = null;
|
|
currentObject = (JSONObject) current;
|
|
currentIsArray = false;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case LexerType.ARRAY_SEPERATOR:
|
|
case LexerType.IDENTIFIER_SEPERATOR:
|
|
{
|
|
|
|
}
|
|
break;
|
|
|
|
case LexerType.DONE_SUCCESS:
|
|
{
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
// ERRORS:
|
|
default:
|
|
{
|
|
hasError = true;
|
|
CreateErrorReport( type, offset, length );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CreateErrorReport( LexerType type, int offset, int length )
|
|
{
|
|
var linesMapper = new TextLinesMapper();
|
|
linesMapper.Map( source );
|
|
errorReport = new JSONObject();
|
|
|
|
var end = offset + Mathf.Max( length, 0 );
|
|
var linesInfo = linesMapper.GetTextEditorInfo( offset, end );
|
|
var snippet = linesMapper.GetTextEditorSnippet( source, offset, end );
|
|
|
|
errorReport.Set( "errorType", type + "" );
|
|
errorReport.Set( "linesInfo", linesInfo );
|
|
errorReport.Set( "snippet", snippet );
|
|
|
|
}
|
|
|
|
public JSONData Parse( string source )
|
|
{
|
|
Reset();
|
|
|
|
this.source = source;
|
|
|
|
var lexer = new JSONLexer();
|
|
lexer.Lex( source, this.OnParse );
|
|
|
|
if ( hasError )
|
|
{
|
|
RJLog.Log( errorReport.Stringify() );
|
|
return null;
|
|
}
|
|
|
|
return root;
|
|
|
|
}
|
|
}
|
|
} |