That makes saving complex property data difficult and XML is in this case for a single property file to big.
I thought a string property definition in AS3 style could be handy. For example a list/array:
[12123,1.123,'entry1']
or an object
{love:'hate',ying:'yang'}
A parser for that is easy for simple objects. Much more difficult is when the data is encapsulated like:
[12123,1.123,{love:[ {a1:'string,with,comma and also \" double quote \" ',a2:'SimpleString'} ,3]},{b2:345,b3:1.04}]
A big problem for me was the delimiter "'" that i wanted to keep the same for a list types (object/Array).
The first version of the parser is done. Validation needs to be included and maybe speed can be optimized by ordering things differently .?.
Code below.
Looks like a lot but creation of object of a complex property doesn't take longer than 3 ms on my machine. I wonder how I can make it shorter.
package com.fourddigital.parser
{
public class StringListParser
{
public function StringListParser()
{}
public function parse(value:*):*{
return getNext( cleanWhitespace( value.toString() ) )[0];
}
protected function getNext(value:String,startIndex:int=0,objectMode:Boolean=false):Array{
if(startIndex >= value.length -1)
return null
var i :int = startIndex;
if(objectMode ){ // starting point is assumed to be a property name because we are parsing an object
exp = /[^:]+/g;
exp.lastIndex = i;
name = exp.exec( value )[0];
if(!name)
throw new Error('Object malformed at char '+ i);
i = exp.lastIndex+1;
}
var result:Array = new Array(3);//to be filled wit o = object, i = lastIndex, name=property name if object Mode
var o : *;
var name:String;
var isString:String;
var isObject:Boolean;
var isArray:Boolean;
var overflow:int=0;// just in case :)
var exp:RegExp = /[\{\[\}\],\'"]/g; //search for command character
exp.lastIndex = i;
var command:* = exp.exec( value );
while(command && command.index == i && overflow < 1000)
{
switch(command[0].toString()){
case '"':
case "'":
isString = command[0].toString();
command = null;
break;
case "{":
isObject=true;
command = null;
break;
case "[":
isArray=true;
command = null;
break;
case '}': //closures
case ',':
case '}':
command = exp.exec( value );
break;
}
i++;
}
if(!isObject && !isArray){ //is primitive
exp = isString ? new RegExp("(? exp.lastIndex = i;
exp.exec( value );
o = getPrimitive( value.substring(i,isString ? exp.lastIndex -1 : exp.lastIndex));
i = exp.lastIndex;
}
else{
var comp:* = isObject ? {} : new Array();
var child:Array = getNext(value,i,isObject );
overflow=0;
while(child && overflow<1000){
overflow++;
i= child[1];
if(isObject)
comp[child[2]] = child[0];
else
(comp as Array).push(child[0]);
if(value.charAt(i).search(/[\}\]]/) == 0){
i++;
break;
}
child = getNext(value,i+1,isObject);
}
o=comp;
}
result[0] = o;
result[1] = i;
result[2] = name;
return result ;
}
protected function getPrimitive(value:String):*{
if(value.length > 1){ //number check
var exp:RegExp = /^\d*\.\d+/;
if(exp.test(value))
return Number(value);
}
if( int(value) ) return int(value);
else if( value == 'true' || value == 'false') return value == 'true'
return value;
}
protected function cleanWhitespace( value:String ):*{
return value.replace(/\s+(?=\{|\||\[)|(?<=\}|\||\])\s+/gsm,'');
}
}
}
No comments:
Post a Comment