public static KirinIfStatement ParseNodes( KirinIfStatementStart startNode, KirinNode[] nodes, KirinIfStatementEnd endNode, string content) { var statement = new KirinIfStatement(-1, -1); string currentCondition = startNode.RawCondition; KirinNode conditionNode = startNode; List <KirinNode> subStatement = new List <KirinNode>(); foreach (var subnode in nodes) { if (subnode.NodeType != "KirinElseIfStatement") { subStatement.Add(subnode); } else { var conditionStatement = FiMLexer.ParseStatement(subStatement.ToArray(), content); try { statement.AddCondition(currentCondition, conditionStatement); } catch (FiMException ex) { throw new Exception(ex.Message + " at line " + FiMHelper.GetIndexPair(content, conditionNode.Start).Line); } var elseIfNode = subnode as KirinElseIfStatement; currentCondition = elseIfNode.RawCondition; conditionNode = subnode; subStatement.Clear(); } } if (subStatement.Count > 0) { var conditionStatement = FiMLexer.ParseStatement(subStatement.ToArray(), content); try { statement.AddCondition(currentCondition, conditionStatement); } catch (FiMException ex) { throw new Exception(ex.Message + " at line " + FiMHelper.GetIndexPair(content, conditionNode.Start).Line); } } statement.SetComplete(startNode.Start, endNode.Start + endNode.Length); if (statement.Count == 0) { throw new FiMException("If Statement has empty conditions"); } return(statement); }
public virtual object Execute(FiMClass reportClass) { uint localVariables = 0; object result = null; foreach (var node in this.Body) { if (!node.GetType().IsSubclassOf(typeof(KirinExecutableNode))) { if (node.GetType().IsSubclassOf(typeof(KirinNode)) || node.GetType() == typeof(KirinNode)) { var no = (KirinNode)node; throw new FiMException($"Paragraph contains a non-KirinExecutable node at line ${FiMHelper.GetIndexPair(reportClass.Report.ReportString, node.Start).Line}"); } else { throw new FiMException($"Paragraph contains a non-KirinExecutable node ('{node.NodeType}')"); } } var n = (KirinExecutableNode)node; if (n.NodeType == "KirinVariableDeclaration") { localVariables++; } object r; #if HIDE_ERROR r = n.Execute(reportClass); #else try { r = n.Execute(reportClass); } catch (FiMException err) { throw new Exception(err.Message + " at line " + FiMHelper.GetIndexPair(reportClass.Report.ReportString, n.Start).Line); } #endif if (r != null) { reportClass.Variables.Pop(count: localVariables); return(r); } if (n.NodeType == "KirinReturn") { result = ((KirinValue)r).Value; break; } } reportClass.Variables.Pop(count: localVariables); return(result); }
public override object Execute(FiMClass reportClass) { var variable = reportClass.GetVariable(this.LeftOp); if (variable == null) { throw new FiMException("Variable " + this.LeftOp + " does not exist"); } if (!FiMHelper.IsTypeArray(variable.Type) && variable.Type != KirinVariableType.STRING) { throw new FiMException("Variable " + this.LeftOp + " is not an array"); } var kIndex = new KirinValue(this.RawIndex, reportClass); if (kIndex.Type != KirinVariableType.NUMBER) { throw new FiMException("Invalid index " + kIndex.Value); } var iValue = Convert.ToInt32(kIndex.Value); var value = new KirinValue(this.RightOp, reportClass); if (variable.Type == KirinVariableType.STRING) { if (value.Type != KirinVariableType.CHAR) { throw new FiMException("Invalid array modify value"); } var sb = new StringBuilder(variable.Value as string); sb[iValue] = (char)variable.Value; variable.Value = sb.ToString(); } else { if (!FiMHelper.IsTypeOfArray(value.Type, (KirinArrayType)variable.Type)) { throw new FiMException("Invalid array modify value"); } dynamic dict; int index = Convert.ToInt32(kIndex.Value); if (variable.Type == KirinVariableType.STRING_ARRAY) { dict = variable.Value as Dictionary <int, string>; dict[index] = Convert.ToString(value.Value); } else if (variable.Type == KirinVariableType.NUMBER_ARRAY) { dict = variable.Value as Dictionary <int, double>; dict[index] = Convert.ToDouble(value.Value); } else if (variable.Type == KirinVariableType.BOOL_ARRAY) { dict = variable.Value as Dictionary <int, bool>; dict[index] = Convert.ToBoolean(value.Value); } } ; return(null); }
private static string SanitizeValue(string value, JavascriptContainer container, KirinVariableType?expectedType = null) { var eType = FiMHelper.DeclarationType.Determine(" " + value, out string eKeyword, strict: false); if (eType != KirinVariableType.UNKNOWN) { value = value.Substring(eKeyword.Length); expectedType = eType; } // Nothing if ((value == null || value == "nothing") && expectedType != null) { return(DefaultValue((KirinVariableType)expectedType)); } if (KirinLiteral.TryParse(value, out object val)) { if (val.GetType() == typeof(bool)) { return((bool)val == true ? "true" : "false"); } return(value); } // Calling an existing method if (container.report.GetParagraphLazy(value) != null) { string args = ""; string pName = value; if (pName.Contains(KirinFunctionCall.FunctionParam)) { int pIndex = pName.IndexOf(KirinFunctionCall.FunctionParam); pName = pName.Substring(0, pIndex); args = string.Join(", ", value .Substring(pName.Length + KirinFunctionCall.FunctionParam.Length) .Split(new string[] { " and " }, StringSplitOptions.None) .Select(v => SanitizeValue(v, container)) ); } if (container.internalFunctions.ContainsKey(pName)) { return($"{ container.internalFunctions[pName] }({ args })"); } return($"this.{ SanitizeName(pName, container) }({ args })"); } // Array if (expectedType != null && FiMHelper.IsTypeArray((KirinVariableType)expectedType)) { string args = string.Join(", ", value .Split(new string[] { " and " }, StringSplitOptions.None) .Select(v => SanitizeValue(v, container)) ); return($"[, { args }]"); } // Array index if (IsArrayIndex(value)) { var match = GetArrayIndex(value); var index = SanitizeValue(match.RawIndex, container); var variable = SanitizeValue(match.RawVariable, container); return($"{ variable }[ fim_index({ variable }, {index}) ]"); } // Arithmetic if (KirinArithmetic.IsArithmetic(value, out var arithmeticResult)) { return(ParseArithmeticNodes(arithmeticResult, container)); } // Conditional if (KirinConditional.IsConditional(value, out var conditionalResult)) { return(ParseConditionalNodes(conditionalResult, container)); } // Calling an existing variable (hopefully) return(SanitizeName(value, container)); }