/**
* Parses a single Line of Dialogue from a String.
* Note that since SDT still parses commented lines, the DialogueChecker has to do so as well.
* Certain severe issues don't care that a line is unused, for instance.
* @param lineText the string that should be converted to a Line object.
* @param lineIndex the index of the line in the array - used for determining lineNumber.
* @return a line object if possible, nothing otherwise.
*/
private function parseLine(lineText:String, lineIndex:uint):Line {
var lineNumber:uint = lineIndex + 1;
var lineName:String = "";
var rawLine:String = lineText;
var lineContent:Array = new Array();
var lineExcess:Array = ["", "", ""];
var lineAttribute:LineAttribute = null;
var lineAttributeValueArray:Array = new Array();
var lineAttributes:Array = new Array();
var lineAttributesString:String = "";
var lineContentString:String = "";
var line:Line = null;
//1|intro:"Hi!" {"style":"Him"}
//2|general : "Hello"
//3|help"me"{"next":"pls"}
//4|held:Let go!{"held":"true"}
//5|under_line"Testing!"
//6|font:Arial
var source:String = lineText;
var nameEnd:uint = 0;
if (source.indexOf(":") != -1 || source.indexOf("\"") != -1) {
//valid for all 6 examples.
//Needs : or " to be a line. Otherwise it's not parsable.
if (source.indexOf(":") != -1) {
nameEnd = source.indexOf(":");
} else {
nameEnd = source.indexOf("\"");
}
} else {
return null; //Comment Filter!
}
lineName = source.substr(0, nameEnd);
source = source.substring(nameEnd);
//1|:"Hi!" {"style":"Him"}
//2|: "Hello"
//3|:"pls"}
//4|:Let go!{"held":"true"}
//5|"Testing!"
//6|:Arial
var contentStart:int = 0;
if (source.indexOf(":") == 0) {
source = source.substring(1);
//1|"Hi!" {"style":"Him"}
//2| "Hello"
//3|"pls"}
//4|Let go!{"held":"true"}
//6|Arial
contentStart = source.indexOf("\"");
}
if (contentStart >= 0 && lineName != "initial_settings") {
lineExcess[0] = source.substr(0, contentStart);
source = source.substr(contentStart);
}
//1|"Hi!" {"style":"Him"}
//2|"Hello"
//3|"pls"}
//4|"held":"true"}
//5|"Coming5|"Testing!"
//6|Arial
var contentString:String = "";
if (source.indexOf("\"") == 0 && source.indexOf("\"", 1) != -1 && lineName != "initial_settings") {
contentString = source.substr(0, source.indexOf("\"", 1) + 1);
source = source.substr(source.indexOf("\"", 1) + 1);
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|Arial
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Coming5|"Testing!"
//6|
if (contentString == "" && lineName != "initial_settings") {
contentString = source;
source = "";
}
lineContentString = contentString;
//Parse contentString
//When parsing a contentString, you're treating everything as normal string until...
//Б - change to delayString (new normal string, keep until different character)
//% - change to special char (new normal string, parse next 2 chars, keep that as pattern, then parse until pattern is broken)
//* - change to VariableInsertion/VariableSubstitution (Treat as Insertion until YOU/ME/YOUR/MY/FINISHES is detected)
//[ - change to Trigger
var contentParseMode:String = "Normal"; //Remember kids, Stringly-typed code is bad! What I'm doing here is bad! So don't do it! (Even although it makes things easier sometimes...)
var currentContentSegment:String = "";
while (contentString != "") {
if (contentParseMode == "Normal") {
//The problem: 4 functions give 4 values. Which function gives the lowest positive value?
var checkArray:Array = new Array();
checkArray.push([contentString.indexOf("Б"), "Б"]);
checkArray.push([contentString.indexOf("%"), "%"]);
checkArray.push([contentString.indexOf("*"), "*"]);
checkArray.push([contentString.indexOf("["), "["]);
checkArray.sortOn([0], [Array.NUMERIC]);
var nextIssue:int = -1;
var nextChar:String = "";
for (var i:uint = 0, isize:uint = checkArray.length; i < isize; i++) {
if (checkArray[i][0] != -1) {
nextIssue = checkArray[i][0];
nextChar = checkArray[i][1];
i = isize;
}
}
if (nextChar == "Б" || nextChar == "%" || nextChar == "*" || nextChar == "[") {
if (nextChar == "Б") {
contentParseMode = "Delay";
} else if (nextChar == "*" || (nextChar == "%" && contentString.indexOf("%2A") == nextIssue)) {
contentParseMode = "Insertion";
} else if (nextChar == "%") {
//trace(contentString.indexOf("%2A")); //commented because it was just extra noise for me as dev and I don't know why I had put this in (v2.13)
contentParseMode = "SpecialChar";
} else if (nextChar == "[") {
contentParseMode = "Trigger";
}
currentContentSegment = contentString.substr(0, nextIssue);
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = contentString.substr(nextIssue);
} else {
currentContentSegment = contentString;
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = "";
}
} else if (contentParseMode == "Delay") {
//Loop until next char is not delay char. Add all looped chars to content array, strip from content string. Evaluate next section.
while (contentString.length > 0 && contentString.indexOf("Б") == 0) {
currentContentSegment += "Б";
contentString = contentString.substr(1);
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "SpecialChar") {
//Identify special char type, loop until pattern is not next section of string. Add all looped chars to content array, strip from content string. Evaluate next section.
var specialCharPattern:String = contentString.substr(0, 3);
//check if it's actually a percent encoded value here
var hexString:String = "0123456789ABCDEFabcdef";
if (!(specialCharPattern.length == 3 && hexString.indexOf(specialCharPattern.charAt(1)) != -1 && hexString.indexOf(specialCharPattern.charAt(2)) != -1)) {
//it's not a proper percent encoded value.
//treat the % as %25, and strip only 1 character.
currentContentSegment = specialCharPattern;
contentString = contentString.substring(1); //strip 1 char
} else {
while (contentString.length > 0 && contentString.indexOf(specialCharPattern) == 0) {
currentContentSegment += specialCharPattern;
contentString = contentString.substr(specialCharPattern.length);
}
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Trigger") {
//Find trigger and identify trigger if possible...?
//TODO: Identify variable insertions within triggers
if (contentString.indexOf("[") != 0) {
ErrorManager.showDevelopmentError("Line parsing - trigger doesn't start with [");
contentString = "";
break;
}
var trigger:String = "";
if (contentString.indexOf("]") != -1) {
trigger = contentString.substr(1, contentString.indexOf("]") - 1);
contentString = contentString.substr(contentString.indexOf("]") + 1);
} else {
//user error, so ignore it. Act like rest of line is trigger.
trigger = contentString.substr(1);
contentString = "";
}
var type:TriggerType = TriggerType.identifyType(trigger);
var triggerObject:Trigger = new Trigger(trigger, type);
lineContent.push(triggerObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Insertion") {
//Find insertion and determine type.
if (contentString.indexOf("*") != 0 && contentString.indexOf("%2A") != 0) {
ErrorManager.showDevelopmentError("Line parsing - insertion doesn't start with *");
contentString = "";
break;
}
var insertion:String = "";
var indexOfAsterisk:int = contentString.indexOf("*");
var indexOfPercent2A:int = contentString.indexOf("%2A");
var indexOfSecondAsterisk:int = contentString.indexOf("*", 1);
var indexOfSecondPercent2A:int = contentString.indexOf("%2A", 1);
if (Math.max(indexOfSecondAsterisk, indexOfSecondPercent2A) != -1) {
var insertionIndex:int = indexOfAsterisk;
var insertionEndIndex:int = indexOfSecondAsterisk;
var insertionStartLength:uint = 1;
var insertionEndLength:uint = 1;
if (indexOfAsterisk == -1 || (indexOfPercent2A < indexOfAsterisk && indexOfPercent2A != -1)) {
insertionIndex = indexOfPercent2A;
insertionStartLength = 3;
}
if (indexOfSecondAsterisk == -1 || (indexOfSecondPercent2A < indexOfSecondAsterisk && indexOfSecondPercent2A != -1)) {
insertionEndIndex = indexOfSecondPercent2A;
insertionEndLength = 3;
}
insertion = contentString.substr(insertionStartLength, insertionEndIndex - insertionStartLength);
contentString = contentString.substr(insertionEndIndex + insertionEndLength);
} else {
//user error, so ignore it. Act like rest of line is insertion.
insertion = contentString.substr(1);
contentString = "";
}
var insertionObject:LineElement = null;
if (insertion.indexOf("YOU") != -1 || insertion.indexOf("ME") != -1 || insertion.indexOf("MY") != -1 || insertion.indexOf("FINISHES") != -1) { //There's also YOUR, but that's already covered by checking for YOU.
insertionObject = new VariableSubstitution(insertion);
} else {
var variable:Variable = getVariable("\"" + insertion + "\"");
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), "\"" + insertion + "\"");
addVariable(variable);
}
variable.setInsertedInDialogue(true);
insertionObject = new VariableInsertion(variable, insertion);
}
lineContent.push(insertionObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else {
contentString = "";
ErrorManager.showDevelopmentError("Line parsing infinite loop");
}
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Testing!"
//6|Arial
var attributeStart:int = 0;
var hasAttributes:Boolean = false;
if (source.indexOf("{") != -1) {
hasAttributes = true;
attributeStart = source.indexOf("{");
lineExcess[1] = source.substr(0, source.indexOf("{"));
}
//source:
//1|{"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
var attributeString:String = "";
if (hasAttributes) {
var endIndex:Number = Math.max(source.lastIndexOf("{"), source.lastIndexOf("}"));
attributeString = source.substr(attributeStart, endIndex + 1);
source = source.substr(endIndex + 1);
}
//Parse attributeString
lineAttributesString = attributeString;
var attributeParseMode:String = "Start"; //Oh no Pim, more stringly-typed coding! What are you doing?! I'm trying to make things work, that's what I'm doing.
var attributeName:String = "";
var attributeValue:Object; //LineAttributes can be multiple variable references.
var attributeName2:String = "";
var attributeValue2:String = "";
while (attributeString != "") {
//I really should have included an initial_settings line in my examples.
if (attributeParseMode == "Start") {
if (attributeString.indexOf("{") != 0) {
//Not sure who is to blame here. Me or the user?
attributeString = "";
} else {
attributeString = attributeString.substr(1);
attributeParseMode = "NextVar";
}
} else if (attributeParseMode == "NextVar") {
//nextvar, reset.
attributeName = "";
attributeValue = null;
attributeName2 = "";
attributeValue2 = "";
var start:int = attributeString.indexOf("\"");
if (start != -1) {
var end:int = attributeString.indexOf("\"", start + 1);
attributeName = attributeString.substring(start, end + 1);
attributeString = attributeString.substr(end + 1);
attributeParseMode = "NextVal";
} else {
if (attributeString.indexOf("}") == 0) {
attributeString = attributeString.substr(1);
}
//No more variables, so this is the end.
//source = attributeString + source; //<- I had that line of code, but lineAttributesString makes it unnecessary. I think. Gotta test it first.
attributeString = "";
}
} else if (attributeParseMode == "NextVal") {
if (attributeString.indexOf(":") != 0) {
//user error. Now what.
//Decided to add string version of lineAttributes, so I can always detect shit like missing }.
//Same goes for this. whatever.
attributeString = "";
} else {
attributeString = attributeString.substr(1);
if (attributeString.charAt(0) == "\"") {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue = attributeString.substring(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substring(attributeString.indexOf("\"", 1) + 1);
} else {
attributeValue = attributeString;
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable = new Variable(VariableType.getEnum("BOOLEAN"), attributeName);
} else {
variable = new Variable(VariableType.getEnum("STRING"), attributeName);
}
addVariable(variable);
} else if (variable.getType() == VariableType.getEnum("UNKNOWN")) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable.setType(VariableType.getEnum("BOOLEAN"));
} else {
variable.setType(VariableType.getEnum("STRING"));
}
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else if (attributeString.indexOf("{") == 0) {
//Array.
attributeString = attributeString.substr(1);
lineAttributeValueArray = new Array();
attributeParseMode = "NextSubVar";
} else if (attributeString.indexOf(",") != -1 || attributeString.indexOf("}") != -1) {
//Numeric.
var nextcomma:int = attributeString.indexOf(",");
var nextbackaccolade:int = attributeString.indexOf("}");
if (nextcomma != -1) {
if (nextbackaccolade != -1 && nextbackaccolade < nextcomma) { //I don't know either.
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
} else {
attributeValue = attributeString.substr(0, nextcomma);
attributeString = attributeString.substr(nextcomma);
}
} else {
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("NUMERIC"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else {
//Yeaahh... damn users again.
//Unknown type, but lets register the attribute anyway.
attributeValue = attributeString;
attributeString = "";
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
}
}
} else if (attributeParseMode == "NextSubVar") {
//"name":??? (value)
attributeName2 = "";
attributeValue2 = "";
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeString = attributeString.substr(nextSegmentLocation); //I hope that didn't contain anything important.
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
//This segment - NextSubVar name String, correct
attributeName2 = attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
} else if (attributeString.indexOf(":", 1) != -1) {
//This segment - NextSubVar name String, missing end double quote
attributeName2 = attributeString.substr(0, attributeString.indexOf(":", 1));
attributeString = attributeString.substr(attributeString.indexOf(":", 1));
} else {
//fuck you, learn to write dialogues for once.
//I mean, how inept do you have to be to keep making all these mistakes -
//given a line like {"set":{"var":"value","var2":0}}
//Here's where I have to watch out for...
//{"set:{"var":"value","var2":0}}
//{"set"{"var":"value","var2":0}}
//{"set": {"var":"value","var2":0}}
//{"set":{ "var":"value","var2":0}}
//{"set":{"var""value","var2":0}}
//{"set":{"var":value","var2":0}}
//etc. how hard is it to just, yknow, write the line properly?
attributeString = "";
}
}
attributeParseMode = "NextSubVal";
} else if (nextSegmentChar == "}") {
attributeString = attributeString.substr(nextSegmentLocation + 1);
attributeParseMode = "NextVar";
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
}
} else if (attributeParseMode == "NextSubVal") {
//This segment - NextSubVal
//Does it start with "? Find next ", that is value. Else, find next , or }
//Does it start with something else? Find next , or }.
if (attributeString.indexOf(":") == 0) {
attributeString = attributeString.substr(1);
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.push([attributeString.indexOf(","), ","]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeValue2 = attributeString.substr(0, nextSegmentLocation);
attributeString = attributeString.substr(nextSegmentLocation);
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else {
//find next comma or }
var nextCommaIndex:int = attributeString.indexOf(",");
var nextBackAccoladeIndex:int = attributeString.indexOf("}");
if (nextCommaIndex != -1) {
if (nextBackAccoladeIndex != -1 && nextBackAccoladeIndex < nextCommaIndex) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
attributeValue2 += attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
}
} else if (nextBackAccoladeIndex != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//we fucked
attributeValue2 += attributeString;
attributeString = "";
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar"; //safety measure
}
}
} else {
//yeah so now what
attributeString = "";
}
} else if (nextSegmentChar == ",") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else if (nextSegmentChar == "}") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//stop fucking things up, man
attributeString = "";
}
} else {
//I've had it.
var variableReference:VariableReference = new VariableReference(attributeName2, null);
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeString = "";
}
}
}
//source:
//1|
//2|
//3|}
//4|:"true"}
//5|
//6|
//atributeString:
//1|{"style":"Him"}
//2|
//3|
//4|
//5|
//6|
lineExcess[2] = source;
line = new Line(lineNumber, lineName, rawLine, lineContent, lineContentString, lineExcess, lineAttributes, lineAttributesString);
return line;
}
/**
* Parses a single Line of Dialogue from a String.
* Note that since SDT still parses commented lines, the DialogueChecker has to do so as well.
* Certain severe issues don't care that a line is unused, for instance.
* @param lineText the string that should be converted to a Line object.
* @param lineIndex the index of the line in the array - used for determining lineNumber.
* @return a line object if possible, nothing otherwise.
*/
private function parseLine(lineText:String, lineIndex:uint):Line {
var lineNumber:uint = lineIndex + 1;
var lineName:String = "";
var rawLine:String = lineText;
var lineContent:Array = new Array();
var lineExcess:Array = ["", "", ""];
var lineAttribute:LineAttribute = null;
var lineAttributeValueArray:Array = new Array();
var lineAttributes:Array = new Array();
var lineAttributesString:String = "";
var lineContentString:String = "";
var line:Line = null;
//1|intro:"Hi!" {"style":"Him"}
//2|general : "Hello"
//3|help"me"{"next":"pls"}
//4|held:Let go!{"held":"true"}
//5|under_line"Testing!"
//6|font:Arial
var source:String = lineText;
var nameEnd:uint = 0;
if (source.indexOf(":") != -1 || source.indexOf("\"") != -1) {
//valid for all 6 examples.
//Needs : or " to be a line. Otherwise it's not parsable.
if (source.indexOf(":") != -1) {
nameEnd = source.indexOf(":");
} else {
nameEnd = source.indexOf("\"");
}
} else {
return null; //Comment Filter!
}
lineName = source.substr(0, nameEnd);
source = source.substring(nameEnd);
//1|:"Hi!" {"style":"Him"}
//2|: "Hello"
//3|:"pls"}
//4|:Let go!{"held":"true"}
//5|"Testing!"
//6|:Arial
var contentStart:int = 0;
if (source.indexOf(":") == 0) {
source = source.substring(1);
//1|"Hi!" {"style":"Him"}
//2| "Hello"
//3|"pls"}
//4|Let go!{"held":"true"}
//6|Arial
contentStart = source.indexOf("\"");
}
if (contentStart >= 0 && lineName != "initial_settings") {
lineExcess[0] = source.substr(0, contentStart);
source = source.substr(contentStart);
}
//1|"Hi!" {"style":"Him"}
//2|"Hello"
//3|"pls"}
//4|"held":"true"}
//5|"Coming!"
//6|Arial
var contentString:String = "";
if (source.indexOf("\"") == 0 && source.indexOf("\"", 1) != -1 && lineName != "initial_settings") {
contentString = source.substr(0, source.indexOf("\"", 1) + 1);
source = source.substr(source.indexOf("\"", 1) + 1);
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|Arial
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Coming!"
//6|
if (contentString == "" && lineName != "initial_settings") {
contentString = source;
source = "";
}
lineContentString = contentString;
//Parse contentString
//When parsing a contentString, you're treating everything as normal string until...
//Б - change to delayString (new normal string, keep until different character)
//% - change to special char (new normal string, parse next 2 chars, keep that as pattern, then parse until pattern is broken)
//* - change to VariableInsertion/VariableSubstitution (Treat as Insertion until YOU/ME/YOUR/MY/FINISHES is detected)
//[ - change to Trigger
var contentParseMode:String = "Normal"; //Remember kids, Stringly-typed code is bad! What I'm doing here is bad! So don't do it! (Even although it makes things easier sometimes...)
var currentContentSegment:String = "";
while (contentString != "") {
if (contentParseMode == "Normal") {
//The problem: 4 functions give 4 values. Which function gives the lowest positive value?
var checkArray:Array = new Array();
checkArray.push([contentString.indexOf("Б"), "Б"]);
checkArray.push([contentString.indexOf("%"), "%"]);
checkArray.push([contentString.indexOf("*"), "*"]);
checkArray.push([contentString.indexOf("["), "["]);
checkArray.sortOn([0], [Array.NUMERIC]);
var nextIssue:int = -1;
var nextChar:String = "";
for (var i:uint = 0, isize:uint = checkArray.length; i < isize; i++) {
if (checkArray[i][0] != -1) {
nextIssue = checkArray[i][0];
nextChar = checkArray[i][1];
i = isize;
}
}
if (nextChar == "Б" || nextChar == "%" || nextChar == "*" || nextChar == "[") {
if (nextChar == "Б") {
contentParseMode = "Delay";
} else if (nextChar == "*" || (nextChar == "%" && contentString.indexOf("%2A") == nextIssue)) {
contentParseMode = "Insertion";
} else if (nextChar == "%") {
//trace(contentString.indexOf("%2A")); //commented because it was just extra noise for me as dev and I don't know why I had put this in (v2.13)
contentParseMode = "SpecialChar";
} else if (nextChar == "[") {
contentParseMode = "Trigger";
}
currentContentSegment = contentString.substr(0, nextIssue);
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = contentString.substr(nextIssue);
} else {
currentContentSegment = contentString;
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = "";
}
} else if (contentParseMode == "Delay") {
//Loop until next char is not delay char. Add all looped chars to content array, strip from content string. Evaluate next section.
while (contentString.length > 0 && contentString.indexOf("Б") == 0) {
currentContentSegment += "Б";
contentString = contentString.substr(1);
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "SpecialChar") {
//Identify special char type, loop until pattern is not next section of string. Add all looped chars to content array, strip from content string. Evaluate next section.
var specialCharPattern:String = contentString.substr(0, 3);
//check if it's actually a percent encoded value here
var hexString:String = "0123456789ABCDEFabcdef";
if (!(specialCharPattern.length == 3 && hexString.indexOf(specialCharPattern.charAt(1)) != -1 && hexString.indexOf(specialCharPattern.charAt(2)) != -1)) {
//it's not a proper percent encoded value.
//treat the % as %25, and strip only 1 character.
currentContentSegment = specialCharPattern;
contentString = contentString.substring(1); //strip 1 char
} else {
while (contentString.length > 0 && contentString.indexOf(specialCharPattern) == 0) {
currentContentSegment += specialCharPattern;
contentString = contentString.substr(specialCharPattern.length);
}
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Trigger") {
//Find trigger and identify trigger if possible...?
//TODO: Identify variable insertions within triggers
if (contentString.indexOf("[") != 0) {
ErrorManager.showDevelopmentError("Line parsing - trigger doesn't start with [");
contentString = "";
break;
}
var trigger:String = "";
if (contentString.indexOf("]") != -1) {
trigger = contentString.substr(1, contentString.indexOf("]") - 1);
contentString = contentString.substr(contentString.indexOf("]") + 1);
} else {
//user error, so ignore it. Act like rest of line is trigger.
trigger = contentString.substr(1);
contentString = "";
}
var type:TriggerType = TriggerType.identifyType(trigger);
var triggerObject:Trigger = new Trigger(trigger, type);
lineContent.push(triggerObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Insertion") {
//Find insertion and determine type.
if (contentString.indexOf("*") != 0 && contentString.indexOf("%2A") != 0) {
ErrorManager.showDevelopmentError("Line parsing - insertion doesn't start with *");
contentString = "";
break;
}
var insertion:String = "";
var indexOfAsterisk:int = contentString.indexOf("*");
var indexOfPercent2A:int = contentString.indexOf("%2A");
var indexOfSecondAsterisk:int = contentString.indexOf("*", 1);
var indexOfSecondPercent2A:int = contentString.indexOf("%2A", 1);
if (Math.max(indexOfSecondAsterisk, indexOfSecondPercent2A) != -1) {
var insertionIndex:int = indexOfAsterisk;
var insertionEndIndex:int = indexOfSecondAsterisk;
var insertionStartLength:uint = 1;
var insertionEndLength:uint = 1;
if (indexOfAsterisk == -1 || (indexOfPercent2A < indexOfAsterisk && indexOfPercent2A != -1)) {
insertionIndex = indexOfPercent2A;
insertionStartLength = 3;
}
if (indexOfSecondAsterisk == -1 || (indexOfSecondPercent2A < indexOfSecondAsterisk && indexOfSecondPercent2A != -1)) {
insertionEndIndex = indexOfSecondPercent2A;
insertionEndLength = 3;
}
insertion = contentString.substr(insertionStartLength, insertionEndIndex - insertionStartLength);
contentString = contentString.substr(insertionEndIndex + insertionEndLength);
} else {
//user error, so ignore it. Act like rest of line is insertion.
insertion = contentString.substr(1);
contentString = "";
}
var insertionObject:LineElement = null;
if (insertion.indexOf("YOU") != -1 || insertion.indexOf("ME") != -1 || insertion.indexOf("MY") != -1 || insertion.indexOf("FINISHES") != -1) { //There's also YOUR, but that's already covered by checking for YOU.
insertionObject = new VariableSubstitution(insertion);
} else {
var variable:Variable = getVariable("\"" + insertion + "\"");
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), "\"" + insertion + "\"");
addVariable(variable);
}
variable.setInsertedInDialogue(true);
insertionObject = new VariableInsertion(variable, insertion);
}
lineContent.push(insertionObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else {
contentString = "";
ErrorManager.showDevelopmentError("Line parsing infinite loop");
}
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Testing!"
//6|Arial
var attributeStart:int = 0;
var hasAttributes:Boolean = false;
if (source.indexOf("{") != -1) {
hasAttributes = true;
attributeStart = source.indexOf("{");
lineExcess[1] = source.substr(0, source.indexOf("{"));
}
//source:
//1|{"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
var attributeString:String = "";
if (hasAttributes) {
var endIndex:Number = Math.max(source.lastIndexOf("{"), source.lastIndexOf("}"));
attributeString = source.substr(attributeStart, endIndex + 1);
source = source.substr(endIndex + 1);
}
//Parse attributeString
lineAttributesString = attributeString;
var attributeParseMode:String = "Start"; //Oh no Pim, more stringly-typed coding! What are you doing?! I'm trying to make things work, that's what I'm doing.
var attributeName:String = "";
var attributeValue:Object; //LineAttributes can be multiple variable references.
var attributeName2:String = "";
var attributeValue2:String = "";
while (attributeString != "") {
//I really should have included an initial_settings line in my examples.
if (attributeParseMode == "Start") {
if (attributeString.indexOf("{") != 0) {
//Not sure who is to blame here. Me or the user?
attributeString = "";
} else {
attributeString = attributeString.substr(1);
attributeParseMode = "NextVar";
}
} else if (attributeParseMode == "NextVar") {
//nextvar, reset.
attributeName = "";
attributeValue = null;
attributeName2 = "";
attributeValue2 = "";
var start:int = attributeString.indexOf("\"");
if (start != -1) {
var end:int = attributeString.indexOf("\"", start + 1);
attributeName = attributeString.substring(start, end + 1);
attributeString = attributeString.substr(end + 1);
attributeParseMode = "NextVal";
} else {
if (attributeString.indexOf("}") == 0) {
attributeString = attributeString.substr(1);
}
//No more variables, so this is the end.
//source = attributeString + source; //<- I had that line of code, but lineAttributesString makes it unnecessary. I think. Gotta test it first.
attributeString = "";
}
} else if (attributeParseMode == "NextVal") {
if (attributeString.indexOf(":") != 0) {
//user error. Now what.
//Decided to add string version of lineAttributes, so I can always detect shit like missing }.
//Same goes for this. whatever.
attributeString = "";
} else {
attributeString = attributeString.substr(1);
if (attributeString.charAt(0) == "\"") {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue = attributeString.substring(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substring(attributeString.indexOf("\"", 1) + 1);
} else {
attributeValue = attributeString;
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable = new Variable(VariableType.getEnum("BOOLEAN"), attributeName);
} else {
variable = new Variable(VariableType.getEnum("STRING"), attributeName);
}
addVariable(variable);
} else if (variable.getType() == VariableType.getEnum("UNKNOWN")) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable.setType(VariableType.getEnum("BOOLEAN"));
} else {
variable.setType(VariableType.getEnum("STRING"));
}
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else if (attributeString.indexOf("{") == 0) {
//Array.
attributeString = attributeString.substr(1);
lineAttributeValueArray = new Array();
attributeParseMode = "NextSubVar";
} else if (attributeString.indexOf(",") != -1 || attributeString.indexOf("}") != -1) {
//Numeric.
var nextcomma:int = attributeString.indexOf(",");
var nextbackaccolade:int = attributeString.indexOf("}");
if (nextcomma != -1) {
if (nextbackaccolade != -1 && nextbackaccolade < nextcomma) { //I don't know either.
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
} else {
attributeValue = attributeString.substr(0, nextcomma);
attributeString = attributeString.substr(nextcomma);
}
} else {
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("NUMERIC"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else {
//Yeaahh... damn users again.
//Unknown type, but lets register the attribute anyway.
attributeValue = attributeString;
attributeString = "";
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
}
}
} else if (attributeParseMode == "NextSubVar") {
//"name":??? (value)
attributeName2 = "";
attributeValue2 = "";
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeString = attributeString.substr(nextSegmentLocation); //I hope that didn't contain anything important.
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
//This segment - NextSubVar name String, correct
attributeName2 = attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
} else if (attributeString.indexOf(":", 1) != -1) {
//This segment - NextSubVar name String, missing end double quote
attributeName2 = attributeString.substr(0, attributeString.indexOf(":", 1));
attributeString = attributeString.substr(attributeString.indexOf(":", 1));
} else {
//fuck you, learn to write dialogues for once.
//I mean, how inept do you have to be to keep making all these mistakes -
//given a line like {"set":{"var":"value","var2":0}}
//Here's where I have to watch out for...
//{"set:{"var":"value","var2":0}}
//{"set"{"var":"value","var2":0}}
//{"set": {"var":"value","var2":0}}
//{"set":{ "var":"value","var2":0}}
//{"set":{"var""value","var2":0}}
//{"set":{"var":value","var2":0}}
//etc. how hard is it to just, yknow, write the line properly?
attributeString = "";
}
}
attributeParseMode = "NextSubVal";
} else if (nextSegmentChar == "}") {
attributeString = attributeString.substr(nextSegmentLocation + 1);
attributeParseMode = "NextVar";
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
}
} else if (attributeParseMode == "NextSubVal") {
//This segment - NextSubVal
//Does it start with "? Find next ", that is value. Else, find next , or }
//Does it start with something else? Find next , or }.
if (attributeString.indexOf(":") == 0) {
attributeString = attributeString.substr(1);
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.push([attributeString.indexOf(","), ","]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeValue2 = attributeString.substr(0, nextSegmentLocation);
attributeString = attributeString.substr(nextSegmentLocation);
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else {
//find next comma or }
var nextCommaIndex:int = attributeString.indexOf(",");
var nextBackAccoladeIndex:int = attributeString.indexOf("}");
if (nextCommaIndex != -1) {
if (nextBackAccoladeIndex != -1 && nextBackAccoladeIndex < nextCommaIndex) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
attributeValue2 += attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
}
} else if (nextBackAccoladeIndex != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//we fucked
attributeValue2 += attributeString;
attributeString = "";
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar"; //safety measure
}
}
} else {
//yeah so now what
attributeString = "";
}
} else if (nextSegmentChar == ",") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else if (nextSegmentChar == "}") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//stop fucking things up, man
attributeString = "";
}
} else {
//I've had it.
var variableReference:VariableReference = new VariableReference(attributeName2, null);
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeString = "";
}
}
}
//source:
//1|
//2|
//3|}
//4|:"true"}
//5|
//6|
//atributeString:
//1|{"style":"Him"}
//2|
//3|
//4|
//5|
//6|
lineExcess[2] = source;
line = new Line(lineNumber, lineName, rawLine, lineContent, lineContentString, lineExcess, lineAttributes, lineAttributesString);
return line;
}
/**
* Parses a single Line of Dialogue from a String.
* Note that since SDT still parses commented lines, the DialogueChecker has to do so as well.
* Certain severe issues don't care that a line is unused, for instance.
* @param lineText the string that should be converted to a Line object.
* @param lineIndex the index of the line in the array - used for determining lineNumber.
* @return a line object if possible, nothing otherwise.
*/
private function parseLine(lineText:String, lineIndex:uint):Line {
var lineNumber:uint = lineIndex + 1;
var lineName:String = "";
var rawLine:String = lineText;
var lineContent:Array = new Array();
var lineExcess:Array = ["", "", ""];
var lineAttribute:LineAttribute = null;
var lineAttributeValueArray:Array = new Array();
var lineAttributes:Array = new Array();
var lineAttributesString:String = "";
var lineContentString:String = "";
var line:Line = null;
//1|intro:"Hi!" {"style":"Him"}
//2|general : "Hello"
//3|help"me"{"next":"pls"}
//4|held:Let go!{"held":"true"}
//5|under_line"Testing!"
//6|font:Arial
var source:String = lineText;
var nameEnd:uint = 0;
if (source.indexOf(":") != -1 || source.indexOf("\"") != -1) {
//valid for all 6 examples.
//Needs : or " to be a line. Otherwise it's not parsable.
if (source.indexOf(":") != -1) {
nameEnd = source.indexOf(":");
} else {
nameEnd = source.indexOf("\"");
}
} else {
return null; //Comment Filter!
}
lineName = source.substr(0, nameEnd);
source = source.substring(nameEnd);
//1|:"Hi!" {"style":"Him"}
//2|: "Hello"
//3|:"pls"}
//4|:Let go!{"held":"true"}
//5|"Testing!"
//6|:Arial
var contentStart:int = 0;
if (source.indexOf(":") == 0) {
source = source.substring(1);
//1|"Hi!" {"style":"Him"}
//2| "Hello"
//3|"pls"}
//4|Let go!{"held":"true"}
//6|Arial
contentStart = source.indexOf("\"");
}
if (contentStart >= 0 && lineName != "initial_settings") {
lineExcess[0] = source.substr(0, contentStart);
source = source.substr(contentStart);
}
//1|"Hi!" {"style":"Him"}
//2|"Hello"
//3|"pls"}
//4|"held":"true"}
//5|"Testing!"
//6|Arial
var contentString:String = "";
if (source.indexOf("\"") == 0 && source.indexOf("\"", 1) != -1 && lineName != "initial_settings") {
contentString = source.substr(0, source.indexOf("\"", 1) + 1);
source = source.substr(source.indexOf("\"", 1) + 1);
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|Arial
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Testing!"
//6|
if (contentString == "" && lineName != "initial_settings") {
contentString = source;
source = "";
}
lineContentString = contentString;
//Parse contentString
//When parsing a contentString, you're treating everything as normal string until...
//Б - change to delayString (new normal string, keep until different character)
//% - change to special char (new normal string, parse next 2 chars, keep that as pattern, then parse until pattern is broken)
//* - change to VariableInsertion/VariableSubstitution (Treat as Insertion until YOU/ME/YOUR/MY/FINISHES is detected)
//[ - change to Trigger
var contentParseMode:String = "Normal"; //Remember kids, Stringly-typed code is bad! What I'm doing here is bad! So don't do it! (Even although it makes things easier sometimes...)
var currentContentSegment:String = "";
while (contentString != "") {
if (contentParseMode == "Normal") {
//The problem: 4 functions give 4 values. Which function gives the lowest positive value?
var checkArray:Array = new Array();
checkArray.push([contentString.indexOf("Б"), "Б"]);
checkArray.push([contentString.indexOf("%"), "%"]);
checkArray.push([contentString.indexOf("*"), "*"]);
checkArray.push([contentString.indexOf("["), "["]);
checkArray.sortOn([0], [Array.NUMERIC]);
var nextIssue:int = -1;
var nextChar:String = "";
for (var i:uint = 0, isize:uint = checkArray.length; i < isize; i++) {
if (checkArray[i][0] != -1) {
nextIssue = checkArray[i][0];
nextChar = checkArray[i][1];
i = isize;
}
}
if (nextChar == "Б" || nextChar == "%" || nextChar == "*" || nextChar == "[") {
if (nextChar == "Б") {
contentParseMode = "Delay";
} else if (nextChar == "*" || (nextChar == "%" && contentString.indexOf("%2A") == nextIssue)) {
contentParseMode = "Insertion";
} else if (nextChar == "%") {
//trace(contentString.indexOf("%2A")); //commented because it was just extra noise for me as dev and I don't know why I had put this in (v2.13)
contentParseMode = "SpecialChar";
} else if (nextChar == "[") {
contentParseMode = "Trigger";
}
currentContentSegment = contentString.substr(0, nextIssue);
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = contentString.substr(nextIssue);
} else {
currentContentSegment = contentString;
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = "";
}
} else if (contentParseMode == "Delay") {
//Loop until next char is not delay char. Add all looped chars to content array, strip from content string. Evaluate next section.
while (contentString.length > 0 && contentString.indexOf("Б") == 0) {
currentContentSegment += "Б";
contentString = contentString.substr(1);
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "SpecialChar") {
//Identify special char type, loop until pattern is not next section of string. Add all looped chars to content array, strip from content string. Evaluate next section.
var specialCharPattern:String = contentString.substr(0, 3);
//check if it's actually a percent encoded value here
var hexString:String = "0123456789ABCDEFabcdef";
if (!(specialCharPattern.length == 3 && hexString.indexOf(specialCharPattern.charAt(1)) != -1 && hexString.indexOf(specialCharPattern.charAt(2)) != -1)) {
//it's not a proper percent encoded value.
//treat the % as %25, and strip only 1 character.
currentContentSegment = specialCharPattern;
contentString = contentString.substring(1); //strip 1 char
} else {
while (contentString.length > 0 && contentString.indexOf(specialCharPattern) == 0) {
currentContentSegment += specialCharPattern;
contentString = contentString.substr(specialCharPattern.length);
}
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Trigger") {
//Find trigger and identify trigger if possible...?
//TODO: Identify variable insertions within triggers
if (contentString.indexOf("[") != 0) {
ErrorManager.showDevelopmentError("Line parsing - trigger doesn't start with [");
contentString = "";
break;
}
var trigger:String = "";
if (contentString.indexOf("]") != -1) {
trigger = contentString.substr(1, contentString.indexOf("]") - 1);
contentString = contentString.substr(contentString.indexOf("]") + 1);
} else {
//user error, so ignore it. Act like rest of line is trigger.
trigger = contentString.substr(1);
contentString = "";
}
var type:TriggerType = TriggerType.identifyType(trigger);
var triggerObject:Trigger = new Trigger(trigger, type);
lineContent.push(triggerObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Insertion") {
//Find insertion and determine type.
if (contentString.indexOf("*") != 0 && contentString.indexOf("%2A") != 0) {
ErrorManager.showDevelopmentError("Line parsing - insertion doesn't start with *");
contentString = "";
break;
}
var insertion:String = "";
var indexOfAsterisk:int = contentString.indexOf("*");
var indexOfPercent2A:int = contentString.indexOf("%2A");
var indexOfSecondAsterisk:int = contentString.indexOf("*", 1);
var indexOfSecondPercent2A:int = contentString.indexOf("%2A", 1);
if (Math.max(indexOfSecondAsterisk, indexOfSecondPercent2A) != -1) {
var insertionIndex:int = indexOfAsterisk;
var insertionEndIndex:int = indexOfSecondAsterisk;
var insertionStartLength:uint = 1;
var insertionEndLength:uint = 1;
if (indexOfAsterisk == -1 || (indexOfPercent2A < indexOfAsterisk && indexOfPercent2A != -1)) {
insertionIndex = indexOfPercent2A;
insertionStartLength = 3;
}
if (indexOfSecondAsterisk == -1 || (indexOfSecondPercent2A < indexOfSecondAsterisk && indexOfSecondPercent2A != -1)) {
insertionEndIndex = indexOfSecondPercent2A;
insertionEndLength = 3;
}
insertion = contentString.substr(insertionStartLength, insertionEndIndex - insertionStartLength);
contentString = contentString.substr(insertionEndIndex + insertionEndLength);
} else {
//user error, so ignore it. Act like rest of line is insertion.
insertion = contentString.substr(1);
contentString = "";
}
var insertionObject:LineElement = null;
if (insertion.indexOf("YOU") != -1 || insertion.indexOf("ME") != -1 || insertion.indexOf("MY") != -1 || insertion.indexOf("FINISHES") != -1) { //There's also YOUR, but that's already covered by checking for YOU.
insertionObject = new VariableSubstitution(insertion);
} else {
var variable:Variable = getVariable("\"" + insertion + "\"");
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), "\"" + insertion + "\"");
addVariable(variable);
}
variable.setInsertedInDialogue(true);
insertionObject = new VariableInsertion(variable, insertion);
}
lineContent.push(insertionObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else {
contentString = "";
ErrorManager.showDevelopmentError("Line parsing infinite loop");
}
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Testing!"
//6|Arial
var attributeStart:int = 0;
var hasAttributes:Boolean = false;
if (source.indexOf("{") != -1) {
hasAttributes = true;
attributeStart = source.indexOf("{");
lineExcess[1] = source.substr(0, source.indexOf("{"));
}
//source:
//1|{"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
var attributeString:String = "";
if (hasAttributes) {
var endIndex:Number = Math.max(source.lastIndexOf("{"), source.lastIndexOf("}"));
attributeString = source.substr(attributeStart, endIndex + 1);
source = source.substr(endIndex + 1);
}
//Parse attributeString
lineAttributesString = attributeString;
var attributeParseMode:String = "Start"; //Oh no Pim, more stringly-typed coding! What are you doing?! I'm trying to make things work, that's what I'm doing.
var attributeName:String = "";
var attributeValue:Object; //LineAttributes can be multiple variable references.
var attributeName2:String = "";
var attributeValue2:String = "";
while (attributeString != "") {
//I really should have included an initial_settings line in my examples.
if (attributeParseMode == "Start") {
if (attributeString.indexOf("{") != 0) {
//Not sure who is to blame here. Me or the user?
attributeString = "";
} else {
attributeString = attributeString.substr(1);
attributeParseMode = "NextVar";
}
} else if (attributeParseMode == "NextVar") {
//nextvar, reset.
attributeName = "";
attributeValue = null;
attributeName2 = "";
attributeValue2 = "";
var start:int = attributeString.indexOf("\"");
if (start != -1) {
var end:int = attributeString.indexOf("\"", start + 1);
attributeName = attributeString.substring(start, end + 1);
attributeString = attributeString.substr(end + 1);
attributeParseMode = "NextVal";
} else {
if (attributeString.indexOf("}") == 0) {
attributeString = attributeString.substr(1);
}
//No more variables, so this is the end.
//source = attributeString + source; //<- I had that line of code, but lineAttributesString makes it unnecessary. I think. Gotta test it first.
attributeString = "";
}
} else if (attributeParseMode == "NextVal") {
if (attributeString.indexOf(":") != 0) {
//user error. Now what.
//Decided to add string version of lineAttributes, so I can always detect shit like missing }.
//Same goes for this. whatever.
attributeString = "";
} else {
attributeString = attributeString.substr(1);
if (attributeString.charAt(0) == "\"") {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue = attributeString.substring(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substring(attributeString.indexOf("\"", 1) + 1);
} else {
attributeValue = attributeString;
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable = new Variable(VariableType.getEnum("BOOLEAN"), attributeName);
} else {
variable = new Variable(VariableType.getEnum("STRING"), attributeName);
}
addVariable(variable);
} else if (variable.getType() == VariableType.getEnum("UNKNOWN")) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable.setType(VariableType.getEnum("BOOLEAN"));
} else {
variable.setType(VariableType.getEnum("STRING"));
}
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else if (attributeString.indexOf("{") == 0) {
//Array.
attributeString = attributeString.substr(1);
lineAttributeValueArray = new Array();
attributeParseMode = "NextSubVar";
} else if (attributeString.indexOf(",") != -1 || attributeString.indexOf("}") != -1) {
//Numeric.
var nextcomma:int = attributeString.indexOf(",");
var nextbackaccolade:int = attributeString.indexOf("}");
if (nextcomma != -1) {
if (nextbackaccolade != -1 && nextbackaccolade < nextcomma) { //I don't know either.
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
} else {
attributeValue = attributeString.substr(0, nextcomma);
attributeString = attributeString.substr(nextcomma);
}
} else {
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("NUMERIC"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else {
//Yeaahh... damn users again.
//Unknown type, but lets register the attribute anyway.
attributeValue = attributeString;
attributeString = "";
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
}
}
} else if (attributeParseMode == "NextSubVar") {
//"name":??? (value)
attributeName2 = "";
attributeValue2 = "";
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeString = attributeString.substr(nextSegmentLocation); //I hope that didn't contain anything important.
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
//This segment - NextSubVar name String, correct
attributeName2 = attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
} else if (attributeString.indexOf(":", 1) != -1) {
//This segment - NextSubVar name String, missing end double quote
attributeName2 = attributeString.substr(0, attributeString.indexOf(":", 1));
attributeString = attributeString.substr(attributeString.indexOf(":", 1));
} else {
//fuck you, learn to write dialogues for once.
//I mean, how inept do you have to be to keep making all these mistakes -
//given a line like {"set":{"var":"value","var2":0}}
//Here's where I have to watch out for...
//{"set:{"var":"value","var2":0}}
//{"set"{"var":"value","var2":0}}
//{"set": {"var":"value","var2":0}}
//{"set":{ "var":"value","var2":0}}
//{"set":{"var""value","var2":0}}
//{"set":{"var":value","var2":0}}
//etc. how hard is it to just, yknow, write the line properly?
attributeString = "";
}
}
attributeParseMode = "NextSubVal";
} else if (nextSegmentChar == "}") {
attributeString = attributeString.substr(nextSegmentLocation + 1);
attributeParseMode = "NextVar";
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
}
} else if (attributeParseMode == "NextSubVal") {
//This segment - NextSubVal
//Does it start with "? Find next ", that is value. Else, find next , or }
//Does it start with something else? Find next , or }.
if (attributeString.indexOf(":") == 0) {
attributeString = attributeString.substr(1);
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.push([attributeString.indexOf(","), ","]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeValue2 = attributeString.substr(0, nextSegmentLocation);
attributeString = attributeString.substr(nextSegmentLocation);
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else {
//find next comma or }
var nextCommaIndex:int = attributeString.indexOf(",");
var nextBackAccoladeIndex:int = attributeString.indexOf("}");
if (nextCommaIndex != -1) {
if (nextBackAccoladeIndex != -1 && nextBackAccoladeIndex < nextCommaIndex) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
attributeValue2 += attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
}
} else if (nextBackAccoladeIndex != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//we fucked
attributeValue2 += attributeString;
attributeString = "";
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar"; //safety measure
}
}
} else {
//yeah so now what
attributeString = "";
}
} else if (nextSegmentChar == ",") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else if (nextSegmentChar == "}") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//stop fucking things up, man
attributeString = "";
}
} else {
//I've had it.
var variableReference:VariableReference = new VariableReference(attributeName2, null);
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeString = "";
}
}
}
//source:
//1|
//2|
//3|}
//4|:"true"}
//5|
//6|
//atributeString:
//1|{"style":"Him"}
//2|
//3|
//4|
//5|
//6|
lineExcess[2] = source;
line = new Line(lineNumber, lineName, rawLine, lineContent, lineContentString, lineExcess, lineAttributes, lineAttributesString);
return line;
}
Parsing a Dialogue Script - fixing my 620 line mess
Given a Dialogue Script for SDT (NSFW! Google at own risk), parse said dialogue script for validation with checkers. A dialogue script consists of a set of lines.
There's a special line, initial_settings
, formatted like such:
initial_settings:{"variable1":numericvalue,"variable2":"stringvalue"}
The rest of the lines follow this format:
linename:"content[TRIGGER]*insertion*" {"attribute":"value","complexattribute":{"variable":numericvalue,"variable2":"stringvalue"}}
Class variables:
//The lines of the dialogue, stored in order of appearance.
private var lines:Array;
//A dictionary of the lines. Structured like so:
//Indexed by linename. Contents are an array of indexes for the lines array.
private var linesDictionary:Array;
//The entire dialogue in string format, if available.
private var dialogue:String;
//String-indexed.
private var variables:Array;
Parsing a dialogue...
public function parseDialogueFromString(dialogueText:String):void {
var a:Array = dialogueText.split("\r"); //Maybe I should split by \r\n first, then by \n\r, then by \r, then by \n?
if (a.length == 1) {
a = dialogueText.split("\n");
}
//Parse each line individually...
for (var i:uint = 0, isize:uint = a.length; i < isize; i++) {
var line:Line = parseLine(a[i], i);
//Then place them in the dictionary and main array.
if (line != null) {
if (linesDictionary[line.getLineName()] == null) {
linesDictionary[line.getLineName()] = new Array();
}
linesDictionary[line.getLineName()].push(lines.push(line) - 1);
}
}
}
line by line.
/**
* Parses a single Line of Dialogue from a String.
* Note that since SDT still parses commented lines, the DialogueChecker has to do so as well.
* Certain severe issues don't care that a line is unused, for instance.
* @param lineText the string that should be converted to a Line object.
* @param lineIndex the index of the line in the array - used for determining lineNumber.
* @return a line object if possible, nothing otherwise.
*/
private function parseLine(lineText:String, lineIndex:uint):Line {
var lineNumber:uint = lineIndex + 1;
var lineName:String = "";
var rawLine:String = lineText;
var lineContent:Array = new Array();
var lineExcess:Array = ["", "", ""];
var lineAttribute:LineAttribute = null;
var lineAttributeValueArray:Array = new Array();
var lineAttributes:Array = new Array();
var lineAttributesString:String = "";
var lineContentString:String = "";
var line:Line = null;
//1|intro:"Hi!" {"style":"Him"}
//2|general : "Hello"
//3|help"me"{"next":"pls"}
//4|held:Let go!{"held":"true"}
//5|under_line"Testing!"
//6|font:Arial
var source:String = lineText;
var nameEnd:uint = 0;
if (source.indexOf(":") != -1 || source.indexOf("\"") != -1) {
//valid for all 6 examples.
//Needs : or " to be a line. Otherwise it's not parsable.
if (source.indexOf(":") != -1) {
nameEnd = source.indexOf(":");
} else {
nameEnd = source.indexOf("\"");
}
} else {
return null; //Comment Filter!
}
lineName = source.substr(0, nameEnd);
source = source.substring(nameEnd);
//1|:"Hi!" {"style":"Him"}
//2|: "Hello"
//3|:"pls"}
//4|:Let go!{"held":"true"}
//5|"Testing!"
//6|:Arial
var contentStart:int = 0;
if (source.indexOf(":") == 0) {
source = source.substring(1);
//1|"Hi!" {"style":"Him"}
//2| "Hello"
//3|"pls"}
//4|Let go!{"held":"true"}
//6|Arial
contentStart = source.indexOf("\"");
}
if (contentStart >= 0 && lineName != "initial_settings") {
lineExcess[0] = source.substr(0, contentStart);
source = source.substr(contentStart);
}
//1|"Hi!" {"style":"Him"}
//2|"Hello"
//3|"pls"}
//4|"held":"true"}
//5|"Coming!"
//6|Arial
var contentString:String = "";
if (source.indexOf("\"") == 0 && source.indexOf("\"", 1) != -1 && lineName != "initial_settings") {
contentString = source.substr(0, source.indexOf("\"", 1) + 1);
source = source.substr(source.indexOf("\"", 1) + 1);
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|Arial
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Coming!"
//6|
if (contentString == "" && lineName != "initial_settings") {
contentString = source;
source = "";
}
lineContentString = contentString;
//Parse contentString
//When parsing a contentString, you're treating everything as normal string until...
//Б - change to delayString (new normal string, keep until different character)
//% - change to special char (new normal string, parse next 2 chars, keep that as pattern, then parse until pattern is broken)
//* - change to VariableInsertion/VariableSubstitution (Treat as Insertion until YOU/ME/YOUR/MY/FINISHES is detected)
//[ - change to Trigger
var contentParseMode:String = "Normal"; //Remember kids, Stringly-typed code is bad! What I'm doing here is bad! So don't do it! (Even although it makes things easier sometimes...)
var currentContentSegment:String = "";
while (contentString != "") {
if (contentParseMode == "Normal") {
//The problem: 4 functions give 4 values. Which function gives the lowest positive value?
var checkArray:Array = new Array();
checkArray.push([contentString.indexOf("Б"), "Б"]);
checkArray.push([contentString.indexOf("%"), "%"]);
checkArray.push([contentString.indexOf("*"), "*"]);
checkArray.push([contentString.indexOf("["), "["]);
checkArray.sortOn([0], [Array.NUMERIC]);
var nextIssue:int = -1;
var nextChar:String = "";
for (var i:uint = 0, isize:uint = checkArray.length; i < isize; i++) {
if (checkArray[i][0] != -1) {
nextIssue = checkArray[i][0];
nextChar = checkArray[i][1];
i = isize;
}
}
if (nextChar == "Б" || nextChar == "%" || nextChar == "*" || nextChar == "[") {
if (nextChar == "Б") {
contentParseMode = "Delay";
} else if (nextChar == "*" || (nextChar == "%" && contentString.indexOf("%2A") == nextIssue)) {
contentParseMode = "Insertion";
} else if (nextChar == "%") {
//trace(contentString.indexOf("%2A")); //commented because it was just extra noise for me as dev and I don't know why I had put this in (v2.13)
contentParseMode = "SpecialChar";
} else if (nextChar == "[") {
contentParseMode = "Trigger";
}
currentContentSegment = contentString.substr(0, nextIssue);
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = contentString.substr(nextIssue);
} else {
currentContentSegment = contentString;
lineContent.push(currentContentSegment);
currentContentSegment = "";
contentString = "";
}
} else if (contentParseMode == "Delay") {
//Loop until next char is not delay char. Add all looped chars to content array, strip from content string. Evaluate next section.
while (contentString.length > 0 && contentString.indexOf("Б") == 0) {
currentContentSegment += "Б";
contentString = contentString.substr(1);
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "SpecialChar") {
//Identify special char type, loop until pattern is not next section of string. Add all looped chars to content array, strip from content string. Evaluate next section.
var specialCharPattern:String = contentString.substr(0, 3);
//check if it's actually a percent encoded value here
var hexString:String = "0123456789ABCDEFabcdef";
if (!(specialCharPattern.length == 3 && hexString.indexOf(specialCharPattern.charAt(1)) != -1 && hexString.indexOf(specialCharPattern.charAt(2)) != -1)) {
//it's not a proper percent encoded value.
//treat the % as %25, and strip only 1 character.
currentContentSegment = specialCharPattern;
contentString = contentString.substring(1); //strip 1 char
} else {
while (contentString.length > 0 && contentString.indexOf(specialCharPattern) == 0) {
currentContentSegment += specialCharPattern;
contentString = contentString.substr(specialCharPattern.length);
}
}
lineContent.push(currentContentSegment);
currentContentSegment = "";
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Trigger") {
//Find trigger and identify trigger if possible...?
//TODO: Identify variable insertions within triggers
if (contentString.indexOf("[") != 0) {
ErrorManager.showDevelopmentError("Line parsing - trigger doesn't start with [");
contentString = "";
break;
}
var trigger:String = "";
if (contentString.indexOf("]") != -1) {
trigger = contentString.substr(1, contentString.indexOf("]") - 1);
contentString = contentString.substr(contentString.indexOf("]") + 1);
} else {
//user error, so ignore it. Act like rest of line is trigger.
trigger = contentString.substr(1);
contentString = "";
}
var type:TriggerType = TriggerType.identifyType(trigger);
var triggerObject:Trigger = new Trigger(trigger, type);
lineContent.push(triggerObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else if (contentParseMode == "Insertion") {
//Find insertion and determine type.
if (contentString.indexOf("*") != 0 && contentString.indexOf("%2A") != 0) {
ErrorManager.showDevelopmentError("Line parsing - insertion doesn't start with *");
contentString = "";
break;
}
var insertion:String = "";
var indexOfAsterisk:int = contentString.indexOf("*");
var indexOfPercent2A:int = contentString.indexOf("%2A");
var indexOfSecondAsterisk:int = contentString.indexOf("*", 1);
var indexOfSecondPercent2A:int = contentString.indexOf("%2A", 1);
if (Math.max(indexOfSecondAsterisk, indexOfSecondPercent2A) != -1) {
var insertionIndex:int = indexOfAsterisk;
var insertionEndIndex:int = indexOfSecondAsterisk;
var insertionStartLength:uint = 1;
var insertionEndLength:uint = 1;
if (indexOfAsterisk == -1 || (indexOfPercent2A < indexOfAsterisk && indexOfPercent2A != -1)) {
insertionIndex = indexOfPercent2A;
insertionStartLength = 3;
}
if (indexOfSecondAsterisk == -1 || (indexOfSecondPercent2A < indexOfSecondAsterisk && indexOfSecondPercent2A != -1)) {
insertionEndIndex = indexOfSecondPercent2A;
insertionEndLength = 3;
}
insertion = contentString.substr(insertionStartLength, insertionEndIndex - insertionStartLength);
contentString = contentString.substr(insertionEndIndex + insertionEndLength);
} else {
//user error, so ignore it. Act like rest of line is insertion.
insertion = contentString.substr(1);
contentString = "";
}
var insertionObject:LineElement = null;
if (insertion.indexOf("YOU") != -1 || insertion.indexOf("ME") != -1 || insertion.indexOf("MY") != -1 || insertion.indexOf("FINISHES") != -1) { //There's also YOUR, but that's already covered by checking for YOU.
insertionObject = new VariableSubstitution(insertion);
} else {
var variable:Variable = getVariable("\"" + insertion + "\"");
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), "\"" + insertion + "\"");
addVariable(variable);
}
variable.setInsertedInDialogue(true);
insertionObject = new VariableInsertion(variable, insertion);
}
lineContent.push(insertionObject);
if (contentString.charAt(0) == "%" && contentString.indexOf("%2A") != 0) {
contentParseMode = "SpecialChar";
} else if (contentString.charAt(0) == "[") {
contentParseMode = "Trigger";
} else if (contentString.charAt(0) == "*" || contentString.indexOf("%2A") == 0) {
contentParseMode = "Insertion";
} else if (contentString.charAt(0) == "Б") {
contentParseMode = "Delay";
} else {
contentParseMode = "Normal";
}
} else {
contentString = "";
ErrorManager.showDevelopmentError("Line parsing infinite loop");
}
}
//source:
//1| {"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
//contentString:
//1|"Hi!"
//2|"Hello"
//3|"pls"
//4|"held"
//5|"Testing!"
//6|Arial
var attributeStart:int = 0;
var hasAttributes:Boolean = false;
if (source.indexOf("{") != -1) {
hasAttributes = true;
attributeStart = source.indexOf("{");
lineExcess[1] = source.substr(0, source.indexOf("{"));
}
//source:
//1|{"style":"Him"}
//2|
//3|}
//4|:"true"}
//5|
//6|
var attributeString:String = "";
if (hasAttributes) {
var endIndex:Number = Math.max(source.lastIndexOf("{"), source.lastIndexOf("}"));
attributeString = source.substr(attributeStart, endIndex + 1);
source = source.substr(endIndex + 1);
}
//Parse attributeString
lineAttributesString = attributeString;
var attributeParseMode:String = "Start"; //Oh no Pim, more stringly-typed coding! What are you doing?! I'm trying to make things work, that's what I'm doing.
var attributeName:String = "";
var attributeValue:Object; //LineAttributes can be multiple variable references.
var attributeName2:String = "";
var attributeValue2:String = "";
while (attributeString != "") {
//I really should have included an initial_settings line in my examples.
if (attributeParseMode == "Start") {
if (attributeString.indexOf("{") != 0) {
//Not sure who is to blame here. Me or the user?
attributeString = "";
} else {
attributeString = attributeString.substr(1);
attributeParseMode = "NextVar";
}
} else if (attributeParseMode == "NextVar") {
//nextvar, reset.
attributeName = "";
attributeValue = null;
attributeName2 = "";
attributeValue2 = "";
var start:int = attributeString.indexOf("\"");
if (start != -1) {
var end:int = attributeString.indexOf("\"", start + 1);
attributeName = attributeString.substring(start, end + 1);
attributeString = attributeString.substr(end + 1);
attributeParseMode = "NextVal";
} else {
if (attributeString.indexOf("}") == 0) {
attributeString = attributeString.substr(1);
}
//No more variables, so this is the end.
//source = attributeString + source; //<- I had that line of code, but lineAttributesString makes it unnecessary. I think. Gotta test it first.
attributeString = "";
}
} else if (attributeParseMode == "NextVal") {
if (attributeString.indexOf(":") != 0) {
//user error. Now what.
//Decided to add string version of lineAttributes, so I can always detect shit like missing }.
//Same goes for this. whatever.
attributeString = "";
} else {
attributeString = attributeString.substr(1);
if (attributeString.charAt(0) == "\"") {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue = attributeString.substring(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substring(attributeString.indexOf("\"", 1) + 1);
} else {
attributeValue = attributeString;
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable = new Variable(VariableType.getEnum("BOOLEAN"), attributeName);
} else {
variable = new Variable(VariableType.getEnum("STRING"), attributeName);
}
addVariable(variable);
} else if (variable.getType() == VariableType.getEnum("UNKNOWN")) {
if (attributeValue == "\"false\"" || attributeValue == "\"true\"") {
variable.setType(VariableType.getEnum("BOOLEAN"));
} else {
variable.setType(VariableType.getEnum("STRING"));
}
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else if (attributeString.indexOf("{") == 0) {
//Array.
attributeString = attributeString.substr(1);
lineAttributeValueArray = new Array();
attributeParseMode = "NextSubVar";
} else if (attributeString.indexOf(",") != -1 || attributeString.indexOf("}") != -1) {
//Numeric.
var nextcomma:int = attributeString.indexOf(",");
var nextbackaccolade:int = attributeString.indexOf("}");
if (nextcomma != -1) {
if (nextbackaccolade != -1 && nextbackaccolade < nextcomma) { //I don't know either.
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
} else {
attributeValue = attributeString.substr(0, nextcomma);
attributeString = attributeString.substr(nextcomma);
}
} else {
attributeValue = attributeString.substr(0, nextbackaccolade);
attributeString = attributeString.substr(nextbackaccolade);
}
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("NUMERIC"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
} else {
//Yeaahh... damn users again.
//Unknown type, but lets register the attribute anyway.
attributeValue = attributeString;
attributeString = "";
lineAttribute = new LineAttribute(attributeName, attributeValue);
lineAttributes.push(lineAttribute);
if (lineName == "initial_settings") {
var variable:Variable = getVariable(attributeName);
if (variable == null) {
variable = new Variable(VariableType.getEnum("UNKNOWN"), attributeName);
addVariable(variable);
}
variable.setInitialValue(attributeValue);
}
attributeParseMode = "NextVar";
}
}
} else if (attributeParseMode == "NextSubVar") {
//"name":??? (value)
attributeName2 = "";
attributeValue2 = "";
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeString = attributeString.substr(nextSegmentLocation); //I hope that didn't contain anything important.
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
//This segment - NextSubVar name String, correct
attributeName2 = attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
} else if (attributeString.indexOf(":", 1) != -1) {
//This segment - NextSubVar name String, missing end double quote
attributeName2 = attributeString.substr(0, attributeString.indexOf(":", 1));
attributeString = attributeString.substr(attributeString.indexOf(":", 1));
} else {
//fuck you, learn to write dialogues for once.
//I mean, how inept do you have to be to keep making all these mistakes -
//given a line like {"set":{"var":"value","var2":0}}
//Here's where I have to watch out for...
//{"set:{"var":"value","var2":0}}
//{"set"{"var":"value","var2":0}}
//{"set": {"var":"value","var2":0}}
//{"set":{ "var":"value","var2":0}}
//{"set":{"var""value","var2":0}}
//{"set":{"var":value","var2":0}}
//etc. how hard is it to just, yknow, write the line properly?
attributeString = "";
}
}
attributeParseMode = "NextSubVal";
} else if (nextSegmentChar == "}") {
attributeString = attributeString.substr(nextSegmentLocation + 1);
attributeParseMode = "NextVar";
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
}
} else if (attributeParseMode == "NextSubVal") {
//This segment - NextSubVal
//Does it start with "? Find next ", that is value. Else, find next , or }
//Does it start with something else? Find next , or }.
if (attributeString.indexOf(":") == 0) {
attributeString = attributeString.substr(1);
var nextSegmentArray:Array = new Array();
nextSegmentArray.push([attributeString.indexOf("}"), "}"]);
nextSegmentArray.push([attributeString.indexOf("\""), "\""]);
nextSegmentArray.push([attributeString.indexOf(","), ","]);
nextSegmentArray.sortOn([0], [Array.NUMERIC]);
var nextSegmentLocation:int = -1;
var nextSegmentChar:String = "";
for (var i:uint = 0, isize:uint = nextSegmentArray.length; i < isize; i++) {
if (nextSegmentArray[i][0] != -1) {
nextSegmentLocation = nextSegmentArray[i][0];
nextSegmentChar = nextSegmentArray[i][1];
i = isize;
}
}
if (nextSegmentChar == "\"") {
attributeValue2 = attributeString.substr(0, nextSegmentLocation);
attributeString = attributeString.substr(nextSegmentLocation);
if (attributeString.indexOf("\"") == 0) {
if (attributeString.indexOf("\"", 1) != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("\"", 1) + 1);
attributeString = attributeString.substr(attributeString.indexOf("\"", 1) + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else {
//find next comma or }
var nextCommaIndex:int = attributeString.indexOf(",");
var nextBackAccoladeIndex:int = attributeString.indexOf("}");
if (nextCommaIndex != -1) {
if (nextBackAccoladeIndex != -1 && nextBackAccoladeIndex < nextCommaIndex) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
attributeValue2 += attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
}
} else if (nextBackAccoladeIndex != -1) {
attributeValue2 += attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//we fucked
attributeValue2 += attributeString;
attributeString = "";
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar"; //safety measure
}
}
} else {
//yeah so now what
attributeString = "";
}
} else if (nextSegmentChar == ",") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf(","));
attributeString = attributeString.substr(attributeString.indexOf(",") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
attributeParseMode = "NextSubVar";
} else if (nextSegmentChar == "}") {
attributeValue2 = attributeString.substr(0, attributeString.indexOf("}"));
attributeString = attributeString.substr(attributeString.indexOf("}") + 1);
var variableReference:VariableReference = new VariableReference(attributeName2, attributeValue2);
if (attributeName == "\"set\"") {
addSetValueToVariable(attributeName2, attributeValue2);
} else if (attributeName == "\"check\"") {
addCheckedValueToVariable(attributeName2, attributeValue2);
}
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeParseMode = "NextVar";
} else {
//stop fucking things up, man
attributeString = "";
}
} else {
//I've had it.
var variableReference:VariableReference = new VariableReference(attributeName2, null);
lineAttributeValueArray.push(variableReference);
lineAttribute = new LineAttribute(attributeName, lineAttributeValueArray);
lineAttributes.push(lineAttribute);
attributeString = "";
}
}
}
//source:
//1|
//2|
//3|}
//4|:"true"}
//5|
//6|
//atributeString:
//1|{"style":"Him"}
//2|
//3|
//4|
//5|
//6|
lineExcess[2] = source;
line = new Line(lineNumber, lineName, rawLine, lineContent, lineContentString, lineExcess, lineAttributes, lineAttributesString);
return line;
}
I'm looking for a way to split up my MASSIVE parse function into something more manageable. Improvements on a smaller scale are also welcomed.
default