void PreprocessCode(string rawCode) { code = rawCode.ToLower(); // Enforce curly braces to be on their own line: code = code.Replace("{", "\n{\n"); code = code.Replace("}", "\n}\n"); // Format lines var unformattedLines = code.Split('\n'); var formattedLines = new List <string>(); foreach (string unformattedLine in unformattedLines) { if (!string.IsNullOrWhiteSpace(unformattedLine)) { string formattedLine = CompilerFormatter.Format(unformattedLine); string[] sections = formattedLine.Split(' '); // Strip comments foreach (string s in sections) { if (s == commentMarker) { formattedLine = formattedLine.Substring(0, formattedLine.IndexOf(commentMarker)); } } if (!string.IsNullOrWhiteSpace(formattedLine)) { // Syntactic sugar if (sections.Length > 1) { sections = formattedLine.Split(' '); if (sections[1] == "+=") { formattedLine = string.Format("{0} = {0} + ( {1} )", sections[0], ArrayToString(sections, 2)); } else if (sections[1] == "-=") { formattedLine = string.Format("{0} = {0} - ( {1} )", sections[0], ArrayToString(sections, 2)); } else if (sections[1] == "*=") { formattedLine = string.Format("{0} = {0} * ( {1} )", sections[0], ArrayToString(sections, 2)); } else if (sections[1] == "/=") { formattedLine = string.Format("{0} = {0} / ( {1} )", sections[0], ArrayToString(sections, 2)); } else if (sections[1] == "++") { formattedLine = string.Format("{0} = {0} + 1", sections[0]); } else if (sections[1] == "--") { formattedLine = string.Format("{0} = {0} - 1", sections[0]); } } formattedLines.Add(formattedLine); processedCode += formattedLine + '\n'; } } } lines = formattedLines.ToArray(); // Create condition block info var conditionBlocks = new List <ConditionBlockInfo>(); int blockDepth = 0; for (int i = 0; i < lines.Length; i++) { string section = lines[i].Split(' ')[0]; var condition = new ConditionBlockInfo() { lineIndex = i, depth = blockDepth }; switch (section) { case "if": condition.type = ConditionBlockInfo.Type.If; conditionBlocks.Add(condition); break; case "elseif": condition.type = ConditionBlockInfo.Type.ElseIf; conditionBlocks.Add(condition); break; case "else": condition.type = ConditionBlockInfo.Type.Else; conditionBlocks.Add(condition); break; case "{": blockDepth++; break; case "}": blockDepth--; break; } } // Create links between chained conditions (if-elseif-else) for (int i = 0; i < conditionBlocks.Count; i++) { var condition = conditionBlocks[i]; conditionByLineIndex.Add(condition.lineIndex, condition); // Try find an elseif/else block attached to this block if (condition.type == ConditionBlockInfo.Type.If || condition.type == ConditionBlockInfo.Type.ElseIf) { for (int j = i + 1; j < conditionBlocks.Count; j++) { var nextCondition = conditionBlocks[j]; // At same depth, so might be continuation of chain if (nextCondition.depth == condition.depth) { // If-statement is start of a new chain, so must be end of current chain if (nextCondition.type == ConditionBlockInfo.Type.If) { break; } condition.nextInChain = nextCondition; nextCondition.previousInChain = condition; break; } // Out of scope, so is end of chain else if (nextCondition.depth < condition.depth) { break; } } } } }
public ValueString(string code, Dictionary <string, float> variables) { values = new List <float> (); elements = new List <ExpressionElement> (); string[] sections = code.Split(' '); for (int i = 0; i < sections.Length; i++) { string section = sections[i]; // Check for built-in functions (sqrt, abs) etc if (VirtualCompiler.ArrayContainsString(VirtualCompiler.builtinFunctions, section)) { switch (section) { case "sqrt": elements.Add(ExpressionElement.SqrtFunc); break; case "abs": elements.Add(ExpressionElement.AbsFunc); break; case "sign": elements.Add(ExpressionElement.SignFunc); break; case "sin": elements.Add(ExpressionElement.SinFunc); break; case "cos": elements.Add(ExpressionElement.CosFunc); break; case "tan": elements.Add(ExpressionElement.TanFunc); break; case "asin": elements.Add(ExpressionElement.AsinFunc); break; case "acos": elements.Add(ExpressionElement.AcosFunc); break; case "atan": elements.Add(ExpressionElement.AtanFunc); break; } } // Check for math operators (+, -) etc else if (VirtualCompiler.ArrayContainsString(VirtualCompiler.mathOperators, section) || section == "(" || section == ")") { switch (section) { case "+": elements.Add(ExpressionElement.Plus); break; case "-": elements.Add(ExpressionElement.Minus); break; case "*": elements.Add(ExpressionElement.Multiply); break; case "/": elements.Add(ExpressionElement.Divide); break; case "(": elements.Add(ExpressionElement.StartGroup); break; case ")": elements.Add(ExpressionElement.EndGroup); break; } } // Try get value from variable name else if (variables.ContainsKey(section)) { values.Add(variables[section]); elements.Add(ExpressionElement.Value); } // Try get value from variable array else if (section.Contains("[") && section.Contains("]")) { string indexString = VirtualCompiler.Substring(section, section.IndexOf("[") + 1, section.IndexOf("]")); var indexValueString = new ValueString(CompilerFormatter.Format(indexString), variables); int index = (int)new NumericalExpression(indexValueString).Evaluate(); string varName = section.Substring(0, section.IndexOf("[")) + VirtualCompiler.arrayIndexSeperator + index; if (variables.ContainsKey(varName)) { elements.Add(ExpressionElement.Value); values.Add(variables[varName]); } } // Try parse value string to float else { float value; if (float.TryParse(section.Replace(".", ","), out value)) { values.Add(value); elements.Add(ExpressionElement.Value); } } } }
static string HighlightLine(string line, SyntaxTheme theme) { var cols = new List <Color>(); var startEndIndices = new List <Vector2Int>(); string[] sections = CompilerFormatter.Format(line).Split(' '); int nonSpaceIndex = 0; bool isComment = false; for (int i = 0; i < sections.Length; i++) { Color colour = Color.clear; string section = sections[i]; if (section == CompilerSymbols.commentMarker || isComment) { colour = theme.comment; isComment = true; } else if (section == CompilerSymbols.usingKeyword) { colour = theme.usingKeyword; } else if (CompilerSymbols.ArrayContainsString(CompilerSymbols.types, section)) { colour = theme.types; } else if (CompilerSymbols.ArrayContainsString(CompilerSymbols.reservedNames, section)) { colour = theme.reservedNames; } else if (CompilerSymbols.allOperators.Contains(section.ToLower())) { colour = theme.allOperators; } else if (CompilerSymbols.ArrayContainsString(CompilerSymbols.builtinFunctions, section)) { colour = theme.builtinFunctions; } else if (CompilerSymbols.brackets.Contains(section.ToLower())) { colour = theme.brackets; } else if (float.TryParse(section.Replace('.', ','), out _)) { colour = theme.value; } else { colour = theme.variable; } if (colour != Color.clear) { cols.Add(colour); int endIndex = nonSpaceIndex + sections[i].Length; startEndIndices.Add(new Vector2Int(nonSpaceIndex, endIndex)); } nonSpaceIndex += sections[i].Length; } if (cols.Count > 0) { nonSpaceIndex = 0; int colIndex = 0; int actualStartIndex = -1; for (int i = 0; i <= line.Length; i++) { if (startEndIndices[colIndex].x == nonSpaceIndex) { actualStartIndex = i; } else if (startEndIndices[colIndex].y == nonSpaceIndex) { //print (colIndex + " replace: " + startEndIndices[colIndex] +" with: " + new Vector2Int (actualStartIndex, i)); startEndIndices[colIndex] = new Vector2Int(actualStartIndex, i); colIndex++; if (colIndex >= cols.Count) { break; } i--; continue; } if (i < line.Length) { char c = line[i]; if (c != ' ') { nonSpaceIndex++; } } } } for (int i = cols.Count - 1; i >= 0; i--) { var col = cols[i]; var startEndIndex = startEndIndices[i]; string colString = ColorUtility.ToHtmlStringRGB(col); line = line.Insert(startEndIndex.y, "</color>"); line = line.Insert(startEndIndex.x, $"<color=#{colString}>"); //print ("insert: " + startEndIndex.x + " " + startEndIndex.y); } return(line); }
static string HighlightLine(string line, SyntaxTheme theme) { var cols = new List <Color> (); var startEndIndices = new List <Vector2Int> (); string[] sections = CompilerFormatter.Format(line).Split(' '); int nonSpaceIndex = 0; bool isComment = false; for (int i = 0; i < sections.Length; i++) { Color colour = Color.clear; string section = sections[i]; if (section == VirtualCompiler.commentMarker || isComment) { colour = theme.comment; isComment = true; } else if (section == "if" || section == "elseif" || section == "else") { colour = theme.conditionKeyword; } else if (section == "loop") { colour = theme.loopKeyword; } else if (VirtualCompiler.ArrayContainsString(VirtualCompiler.mathOperators, section)) { colour = theme.mathOperator; } else if (VirtualCompiler.ArrayContainsString(VirtualCompiler.comparisonOperators, section)) { colour = theme.comparisonOperator; } else if (section == "(" || section == ")") { colour = theme.parentheses; } else if (section == "{" || section == "}") { colour = theme.curlyBrackets; } else if (float.TryParse(section.Replace('.', ','), out _)) { colour = theme.value; } else if (section == "=") { colour = theme.assignment; } else { colour = theme.variable; } if (colour != Color.clear) { cols.Add(colour); int endIndex = nonSpaceIndex + sections[i].Length; startEndIndices.Add(new Vector2Int(nonSpaceIndex, endIndex)); } nonSpaceIndex += sections[i].Length; } if (cols.Count > 0) { nonSpaceIndex = 0; int colIndex = 0; int actualStartIndex = -1; for (int i = 0; i <= line.Length; i++) { if (startEndIndices[colIndex].x == nonSpaceIndex) { actualStartIndex = i; } else if (startEndIndices[colIndex].y == nonSpaceIndex) { //print (colIndex + " replace: " + startEndIndices[colIndex] +" with: " + new Vector2Int (actualStartIndex, i)); startEndIndices[colIndex] = new Vector2Int(actualStartIndex, i); colIndex++; if (colIndex >= cols.Count) { break; } i--; continue; } if (i < line.Length) { char c = line[i]; if (c != ' ') { nonSpaceIndex++; } } } } for (int i = cols.Count - 1; i >= 0; i--) { var col = cols[i]; var startEndIndex = startEndIndices[i]; string colString = ColorUtility.ToHtmlStringRGB(col); line = line.Insert(startEndIndex.y, "</color>"); line = line.Insert(startEndIndex.x, $"<color=#{colString}>"); //print ("insert: " + startEndIndex.x + " " + startEndIndex.y); } return(line); }