예제 #1
0
        public static bool TryParse(string content, int start, int length, out KirinNode result)
        {
            result = null;
            var match = PreKeywords.FirstOrDefault(k => content.StartsWith(k));

            if (match == null)
            {
                return(false);
            }

            string condition = content.Substring(match.Length);

            if (!KirinConditional.IsConditional(condition, out var cResult))
            {
                throw new FiMException("Expression is not a conditional");
            }

            var node = new KirinWhileLoop(start, length)
            {
                Condition = cResult
            };

            result = node;
            return(true);
        }
예제 #2
0
 private BaseNode CreateNode(string value)
 {
     if (!KirinConditional.IsConditional(value, out var result))
     {
         return new ValueNode()
                {
                    RawValue = value
                }
     }
     ;
     return(CreateNode(result));
 }
예제 #3
0
        public override object Execute(FiMClass reportClass)
        {
            if (!this.Complete)
            {
                throw new FiMException("Executing an incomplete if statement");
            }

            foreach (var cS in Conditions)
            {
                var conditional = new KirinConditional(cS.Condition);
                if (conditional.GetValue(reportClass) == false)
                {
                    continue;
                }
                return(cS.Statement.Execute(reportClass));
            }
            return(null);
        }
예제 #4
0
        public override object Execute(FiMClass reportClass)
        {
            if (this.Statement == null)
            {
                throw new FiMException("While loop has no statement");
            }

            var conditional = new KirinConditional(Condition);

            while (conditional.GetValue(reportClass) == true)
            {
                var value = Statement.Execute(reportClass);
                if (value != null)
                {
                    break;
                }
            }

            return(null);
        }
예제 #5
0
        public void AddCondition(string condition, KirinStatement statement)
        {
            if (this.Complete)
            {
                throw new FiMException("Expected end of if statement");
            }

            if (condition == string.Empty)
            {
                condition     = "correct is correct";
                this.Complete = true;
            }

            if (!KirinConditional.IsConditional(condition, out var result))
            {
                throw new FiMException("Expression is not a conditional");
            }

            Conditions.Add(new KirinConditionStatement()
            {
                Condition = result,
                Statement = statement
            });
        }
예제 #6
0
        /// <summary>
        /// Evaluates raw FiM++ string into a value
        /// </summary>
        public static object Evaluate(
            FiMClass reportClass,
            string evaluatable,
            out KirinVariableType returnedType,
            KirinVariableType?expectedType = null
            )
        {
            returnedType = KirinVariableType.UNKNOWN;

            // Nothing
            if (evaluatable == "nothing" && expectedType != null)
            {
                returnedType = (KirinVariableType)expectedType;
                return(FiMHelper.GetDefaultValue(returnedType));
            }

            // Calling an existing variable
            if (reportClass.GetVariable(evaluatable) != null)
            {
                var variable = reportClass.GetVariable(evaluatable);
                returnedType = variable.Type;
                return(variable.Value);
            }

            // Calling an existing method
            if (reportClass.GetParagraphLazy(evaluatable) != null)
            {
                KirinValue[] args  = null;
                string       pName = evaluatable;

                if (pName.Contains(KirinFunctionCall.FunctionParam))
                {
                    int pIndex = pName.IndexOf(KirinFunctionCall.FunctionParam);
                    pName = pName.Substring(0, pIndex);
                    args  = KirinFunctionCall.ParseCallArguments(
                        evaluatable.Substring(pName.Length + KirinFunctionCall.FunctionParam.Length), reportClass
                        ).ToArray();
                }

                var paragraph = reportClass.GetParagraph(pName);
                if (paragraph == null)
                {
                    throw new FiMException("Paragraph " + pName + " not found");
                }

                if (paragraph.ReturnType == KirinVariableType.UNKNOWN)
                {
                    throw new FiMException("Paragraph returns nothing");
                }
                returnedType = paragraph.ReturnType;
                return(paragraph.Execute(args));
            }

            // Array
            if (expectedType != null && FiMHelper.IsTypeArray((KirinVariableType)expectedType))
            {
                System.Collections.IDictionary dict = null;
                var args = KirinFunctionCall.ParseCallArguments(evaluatable, reportClass);

                if (!FiMHelper.IsTypeOfArray(args[0].Type, (KirinArrayType)expectedType))
                {
                    throw new FiMException("Invalid list value type");
                }
                if (!args.All(a => a.Type == args[0].Type))
                {
                    throw new FiMException("Unidentical list value type");
                }

                int i = 1;
                if (expectedType == KirinVariableType.STRING_ARRAY)
                {
                    dict = new Dictionary <int, string>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToString(kv.Value)));
                }
                else if (expectedType == KirinVariableType.NUMBER_ARRAY)
                {
                    dict = new Dictionary <int, double>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToDouble(kv.Value)));
                }
                else if (expectedType == KirinVariableType.BOOL_ARRAY)
                {
                    dict = new Dictionary <int, bool>();
                    args.ForEach(kv => dict.Add(i++, Convert.ToBoolean(kv.Value)));
                }

                returnedType = (KirinVariableType)expectedType;
                return(dict);
            }

            // Array index
            if (FiMHelper.ArrayIndex.IsArrayIndex(evaluatable, reportClass))
            {
                var match = FiMHelper.ArrayIndex.GetArrayIndex(evaluatable, reportClass);

                var varIndex = new KirinValue(match.RawIndex, reportClass);
                if (varIndex.Type != KirinVariableType.NUMBER)
                {
                    throw new FiMException("Invalid index value");
                }
                int index = Convert.ToInt32(varIndex.Value);

                string strVar = match.RawVariable;
                if (!reportClass.Variables.Has(strVar))
                {
                    throw new FiMException("Variable " + strVar + " does not exist");
                }
                var variable = reportClass.Variables.Get(strVar);
                if (!FiMHelper.IsTypeArray(variable.Type) && variable.Type != KirinVariableType.STRING)
                {
                    throw new FiMException("Cannot index a non-array variable");
                }

                if (variable.Type == KirinVariableType.STRING)
                {
                    returnedType = KirinVariableType.CHAR;
                    return(Convert.ToString(variable.Value)[index - 1]);
                }

                var dict = variable.Value as System.Collections.IDictionary;
                if (variable.Type == KirinVariableType.STRING_ARRAY)
                {
                    returnedType = KirinVariableType.STRING;
                    return(Convert.ToString(dict[index]));
                }
                if (variable.Type == KirinVariableType.BOOL_ARRAY)
                {
                    returnedType = KirinVariableType.BOOL;
                    return(Convert.ToBoolean(dict[index]));
                }
                if (variable.Type == KirinVariableType.NUMBER_ARRAY)
                {
                    returnedType = KirinVariableType.NUMBER;
                    return(Convert.ToDouble(dict[index]));
                }
            }

            // Arithmetic
            if (KirinArithmetic.IsArithmetic(evaluatable, out var arithmeticResult))
            {
                var arithmetic = new KirinArithmetic(arithmeticResult);
                var value      = arithmetic.GetValue(reportClass);
                returnedType = FiMHelper.AsVariableType(value.GetType());
                return(value);
            }

            // Conditional
            if (KirinConditional.IsConditional(evaluatable, out var conditionalResult))
            {
                var conditional = new KirinConditional(conditionalResult);
                returnedType = KirinVariableType.BOOL;
                return(conditional.GetValue(reportClass));
            }

            throw new FiMException("Cannot evaluate " + evaluatable);
        }