コード例 #1
0
        public static Assign CreateAssign(CodeElement elem, Scope scope)
        {
            // assign      = identifier '=' exp ';';
            var         cmd    = new Assign();
            CodeElement idElem = elem.Codes(WordIdentifier).First();

            cmd.VariableName = idElem.Value;
            cmd.VariableType = scope.ExistsVariable(cmd.VariableName, idElem);

            CodeElement expCode = elem.Codes().Last();

            cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

            if (cmd.VariableType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
            }
            if (cmd.VariableType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
            }
            if (cmd.VariableType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
            {
                throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
            }

            return(cmd);
        }
コード例 #2
0
        public static Declare CreateDeclare(CodeElement elem, bool isVariable)
        {
            CodeElement defType    = elem.Codes().FirstOrDefault();
            CodeElement identifier = elem.Codes("identifier").FirstOrDefault();

            Declare dec = new Declare()
            {
                TheName = identifier.Value
            };

            switch (defType.Name)
            {
            case WordTypeInt: dec.TheType = DefType.Int; break;

            case WordTypeStr: dec.TheType = DefType.String; break;

            case WordTypeReal: dec.TheType = DefType.Float; break;

            case WordTypeBool: dec.TheType = DefType.Bool; break;

            case WordTypeVoid:
                if (isVariable)
                {
                    throw new Exception(string.Format("Only functions can be 'void'. {0}", defType.GetLineAndColumn()));
                }
                dec.TheType = DefType.Void;
                break;

            default: throw new Exception(string.Format("The type '{0}' is not defined. {1}", defType.Value, defType.GetLineAndColumn()));
            }

            return(dec);
        }
コード例 #3
0
        public static VariableDef CreateVariableDef(CodeElement elem, Scope scope)
        {
            // variableDef = typeAndId '=' exp ';';
            var def = CreateDeclare(elem.Codes(WordDeclare).First(), true);
            var cmd = new VariableDef()
            {
                Name = def.TheName, VariableType = def.TheType
            };

            if (elem.Codes().Count() == 2)
            {
                CodeElement expCode = elem.Codes().Last();
                cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

                if (cmd.VariableType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
                }
                if (cmd.VariableType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
                }
                if (cmd.VariableType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
                }
            }
            if (scope.ExistsFunction(cmd.Name))
            {
                throw new Exception(string.Format("A Function called '{0}', {1}, is declared", cmd.Name, elem.GetLineAndColumn()));
            }

            scope.Vars.BuildVariable(cmd.VariableType, cmd.Name, elem);
            return(cmd);
        }
コード例 #4
0
        public static void CreateFunctionInnerScope(CodeElement elem, Scope scope)
        {
            // functionDef = typeAndId '(' [typeAndId {',' typeAndId}] ')' '{' scope '}';
            CodeElement defElem = elem.Codes(WordDeclare).First();
            var         def2    = CreateDeclare(defElem, false);
            Function    funcDef;

            scope.Functions.TryGetValue(def2.TheName, out funcDef);

            Variables innerVariables = new Variables(null, null);

            foreach (CodeElement item in elem.Codes(WordDeclare).Where(e => e != defElem))
            {
                var parm = CreateDeclare(item, true);
                innerVariables.BuildVariable(parm.TheType, parm.TheName, item);
            }

            CodeElement scopeElem = elem.Codes(WordScope).First();

            bool alwaysReturns;

            funcDef.FunctionScope = CreateScope(scopeElem, innerVariables, scope, funcDef.FuncType, out alwaysReturns);

            if (funcDef.FuncType != DefType.Void && !alwaysReturns)
            {
                throw new Exception(string.Format("The function '{0}' must return a value, {1}", funcDef.Name, elem.GetLineAndColumn()));
            }
        }
コード例 #5
0
        public static While CreateWhile(CodeElement elem, Scope scope, DefType resultType)
        {
            // loop        = 'while' '(' exp ')' body;
            ExpBase expbase = ExpressionBuilder.CreateExpression(elem.Codes().First(), scope);
            var     cmd     = new While();

            cmd.Expression = expbase as ExpTyped <bool>;
            if (cmd.Expression == null)
            {
                throw new Exception(string.Format("The expression type must be a boolean, {0}", elem.GetLineAndColumn()));
            }

            cmd.Body = CreateBody(elem.Codes(WordBody).First(), scope, resultType, out bool ret);
            return(cmd);
        }
コード例 #6
0
        public static Return CreateReturn(CodeElement elem, Scope scope, DefType resultType)
        {
            // return      = 'return' [exp] ';';

            var cmd = new Return();

            CodeElement expCode = elem.Codes().FirstOrDefault();

            if (expCode != null)
            {
                cmd.Expression = ExpressionBuilder.CreateExpression(expCode, scope);

                if (resultType == DefType.Bool && !ExpBase.IsBool(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a bool'. {0}", expCode.GetLineAndColumn()));
                }
                if (resultType == DefType.Int && !ExpBase.IsInt(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be an integer'. {0}", expCode.GetLineAndColumn()));
                }
                if (resultType == DefType.Float && !ExpBase.IsNumber(cmd.Expression))
                {
                    throw new Exception(string.Format("The expression must be a number'. {0}", expCode.GetLineAndColumn()));
                }
            }
            else
            if (resultType != DefType.Void)
            {
                throw new Exception(string.Format("This function must return a value. {0}", elem.GetLineAndColumn()));
            }

            return(cmd);
        }
コード例 #7
0
        public BenchmarkResult(CodeElement result)
        {
            TestCode = result.Codes().First(c => c.Name == "TestCode").Value;
            Tag      = result.Codes().First(c => c.Name == "tag").Value;

            TestDate  = result.Codes().First(c => c.Name == "date").Value;
            InputSize = int.Parse(result.Codes().First(c => c.Name == "size").Value);
            Combi     = int.Parse(result.Codes().First(c => c.Name == "combi").Value);
            TestRuns  = int.Parse(result.Codes().First(c => c.Name == "runs").Value);

            TimeParse = int.Parse(result.Codes().First(c => c.Name == "avg").Value);
            TimeQuery = int.Parse(result.Codes().First(c => c.Name == "max").Value);
            MemParse  = int.Parse(result.Codes().First(c => c.Name == "min").Value);
        }
コード例 #8
0
        public static FuncCall CreateFuncCall(CodeElement elem, Scope scope)
        {
            // funcCall    = identifier '(' [exp {',' exp}] ')';

            CodeElement idElem = elem.Codes("identifier").First();
            string      name   = idElem.Value;

            Function theFunc = scope.GetFunction(name);

            var parameters = new List <ExpBase>();
            int i          = -1;

            foreach (CodeElement item in elem.Codes().Where(e => e != idElem))
            {
                var parm = CreateExpression(item, scope);
                if (++i == theFunc.Parameters.Count)
                {
                    throw new Exception(string.Format("Too many parameters for function '{0}', {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Int && !ExpBase.IsInt(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be an integer, {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsBool(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be a boolean, {1}", name, item.GetLineAndColumn()));
                }
                if (theFunc.Parameters[i].TheType == DefType.Bool && !ExpBase.IsNumber(parm))
                {
                    throw new Exception(string.Format("The parameter for function '{0}' must be a number, {1}", name, item.GetLineAndColumn()));
                }

                parameters.Add(parm);
            }
            if (i + 1 != theFunc.Parameters.Count)
            {
                throw new Exception(string.Format("Too few parameters for function '{0}', {1}", name, elem.GetLineAndColumn()));
            }

            var call = new FuncCall(theFunc, parameters);

            return(call);
        }
コード例 #9
0
        public static If CreateIf(CodeElement elem, Scope scope, DefType resultType, out bool alwaysReturnValue)
        {
            // if          = 'if' '(' exp ')' body ['else' body];
            ExpBase expbase = ExpressionBuilder.CreateExpression(elem.Codes().First(), scope);
            var     cmd     = new If();

            cmd.Expression = expbase as ExpTyped <bool>;
            if (cmd.Expression == null)
            {
                throw new Exception(string.Format("The expression type must be a boolean, {0}", elem.GetLineAndColumn()));
            }

            bool trueReturn;

            cmd.TrueStatement = CreateBody(elem.Codes(WordBody).First(), scope, resultType, out trueReturn);
            bool elseReturn;

            cmd.ElseStatement = CreateBody(elem.Codes(WordBody).Last(), scope, resultType, out elseReturn);
            alwaysReturnValue = trueReturn && elseReturn;
            return(cmd);
        }
コード例 #10
0
        public static ExpressionBase BuildExp(CodeElement elem)
        {
            if (elem == null)
            {
                throw new Exception("Missing expression element");
            }

            switch (elem.Name)
            {
            case "power":
                return(new Power(elem));

            case "mul":
                return(new Multiply(elem));

            case "div":
                return(new Divide(elem));

            case "sum":
                return(new Sum(elem));

            case "sub":
                return(new Minus(elem));

            case "number":
            case "int":
                return(new Number(elem));

            case "exp":
                return(BuildExp(elem.Codes().FirstOrDefault()));

            case "par":
                return(BuildExp(elem.Codes().FirstOrDefault()));

            default:
                throw new Exception(string.Format("Unknown expression element: '{0}'", elem.Name));
            }
        }
コード例 #11
0
        public static Scope CreateScope(CodeElement elem, Variables innerVariables, Scope parentScope, DefType resultType, out bool alwaysReturnValue) //, bool mustReturn
        {
            // scope       = {functionDef | variableDef | operation};
            alwaysReturnValue = false;

            var scope = new Scope(parentScope, innerVariables);

            //Create all function declarations before funtion-scopes.
            foreach (CodeElement item in elem.Codes(WordFunctionDef))
            {
                CreateFunctionDef(item, scope);
            }

            // Create function-scopes (that may make calls to other functions in same scope)
            foreach (CodeElement item in elem.Codes(WordFunctionDef))
            {
                CreateFunctionInnerScope(item, scope);
            }

            List <OperationBase> operations = new List <OperationBase>();

            foreach (CodeElement item in elem.Codes(c => c.Name != WordFunctionDef))
            {
                if (alwaysReturnValue)
                {
                    throw new Exception(string.Format("The statement can not be reached, {0}, {1}", item.Name, item.GetLineAndColumn()));
                }
                else
                {
                    operations.Add(CreateVariableOrOperation(item, scope, resultType, out alwaysReturnValue));
                }
            }

            scope.Operations = operations;

            return(scope);
        }
コード例 #12
0
        public static void CreateFunctionDef(CodeElement elem, Scope scope)
        {
            // functionDef = typeAndId '(' [typeAndId {',' typeAndId}] ')' '{' scope '}';
            CodeElement defElem = elem.Codes(WordDeclare).First();
            var         def2    = CreateDeclare(defElem, false);
            Function    funcDef = new Function()
            {
                FuncType = def2.TheType, Name = def2.TheName
            };

            if (scope.Functions.ContainsKey(funcDef.Name))
            {
                throw new Exception(string.Format("A function called '{0}', {1}, is allready declared", funcDef.Name, elem.GetLineAndColumn()));
            }

            funcDef.Parameters = new List <Declare>();
            foreach (CodeElement item in elem.Codes(WordDeclare).Where(e => e != defElem))
            {
                var parm = CreateDeclare(item, true);
                funcDef.Parameters.Add(parm);
            }

            scope.Functions.Add(funcDef.Name, funcDef);
        }
コード例 #13
0
        public static OperationBase CreateBody(CodeElement elem, Scope scope, DefType resultType, out bool alwaysReturnValue)
        {
            CodeElement   innerCode = elem.Codes().First();
            OperationBase cmd;

            if (innerCode.Name == WordScope)
            {
                cmd = CreateScope(innerCode, null, scope, resultType, out alwaysReturnValue);
            }
            else
            {
                cmd = CreateVariableOrOperation(innerCode, scope, resultType, out alwaysReturnValue);
            }

            return(cmd);
        }
コード例 #14
0
        public static ExpBase CreateExpression(CodeElement elem, Scope scope)
        {
            if (elem == null)
            {
                throw new Exception("Missing expression element");
            }

            // First non operator values
            switch (elem.Name)
            {
            case WordInt:
                return(new ExpInt(elem));

            case WordString:
                return(new ExpString(elem));

            case WordReal:
                return(new ExpFloat(elem));

            case WordBool:
                return(new ExpBool(elem));

            case WordExp:
                return(CreateExpression(elem.Codes().FirstOrDefault(), scope));

            case WordPar:
                return(CreateExpression(elem.Codes().FirstOrDefault(), scope));

            case "identifier":
                return(CreateExpVariable(elem, scope));

            case WordFuncCall:
                return(CreateExpFuncCall(elem, scope));
            }

            // Then binary operator values. All binary operators has two operants.
            CodeElement first = elem.Codes().FirstOrDefault();
            CodeElement next  = elem.Codes().FirstOrDefault(c => c != first);
            ExpBase     op1   = CreateExpression(first, scope);
            ExpBase     op2   = CreateExpression(next, scope);

            // For multiplication, division, subtraction, greaterThan and lowerThan the operants must be numbers.
            if (elem.Name == WordMul || elem.Name == WordDiv || elem.Name == WordSub || elem.Name == WordGt || elem.Name == WordLt)
            {
                // check type
                if (!ExpBase.IsNumber(op1))
                {
                    throw new Exception(string.Format("The left operant of '{0}', {1}, is not a number", elem.Name, elem.GetLineAndColumn()));
                }
                if (!ExpBase.IsNumber(op2))
                {
                    throw new Exception(string.Format("The right operant of '{0}', {1}, is not a number", elem.Name, elem.GetLineAndColumn()));
                }
            }

            // For 'equals' the operants must both be numbers or both be strings.
            if (elem.Name == WordEq)
            {
                if (!(ExpBase.IsNumber(op1, op2) || ExpBase.IsString(op1, op2)))
                {
                    throw new Exception(string.Format("Operants must both be numbers or both be strings: '{0}', {1}", elem.Name, elem.GetLineAndColumn()));
                }
            }

            switch (elem.Name)
            {
            case WordGt: return(new ExpGt(op1, op2));

            case WordLt: return(new ExpLt(op1, op2));

            case WordEq: return(new ExpEquals(op1, op2));

            case WordDiv: return(new ExpDivide(op1, op2));

            case WordMul:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpMultiplyInt(op1, op2));
                }
                else
                {
                    return(new ExpMultiplyFloat(op1, op2));
                }

            case WordSub:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpMinusInt(op1, op2));
                }
                else
                {
                    return(new ExpMinusFloat(op1, op2));
                }

            case WordSum:
                if (ExpBase.IsInt(op1, op2))
                {
                    return(new ExpSumInt(op1, op2));
                }
                else if (ExpBase.IsNumber(op1, op2))
                {
                    return(new ExpSumFloat(op1, op2));
                }
                else
                {
                    return(new ExpSumString(op1, op2));
                }

            default:
                throw new Exception(string.Format("Unknown expression element: '{0}'", elem.Name));
            }
        }
コード例 #15
0
        public override bool Load(List <TextElement> outElements, int level)
        {
            int from = TextBuffer.PointerNextChar;

            // Read a value first
            if (!LoadValue(outElements, level, true))
            {
                // if the expression does'nt start with a value; the intire expression fails.
                return(SetPointerBack(from));
            }

            TextBuffer.Status.ThisIsUnambiguous(this, outElements[outElements.Count - 1]);

            // Read following operations as alternately binary operators and values.
            var operations = new List <TextElement>();

            from = TextBuffer.PointerNextChar;
            while (LoadBinaryOperator(operations, level) && LoadValue(operations, level, false))
            {
                TextBuffer.Status.ThisIsUnambiguous(this, operations[operations.Count - 1]);
                from = TextBuffer.PointerNextChar;
            }

            // Set pointer back
            TextBuffer.PointerNextChar = from;

            // If only one value the return that.
            if (operations.Count == 0)
            {
                return(true);
            }

            // Order elements in a tree according to precedence and association rules.
            // set first value under a dummy parent
            CodeElement parent = new CodeElement(this, null);

            parent.Add(outElements[0]);

            var comments       = new List <TextElement>();
            int nextValueIndex = 0;

            while (nextValueIndex < operations.Count - 1 && operations[nextValueIndex] is CommentElement)
            {
                comments.Add(operations[nextValueIndex++]);
            }

            while (nextValueIndex < operations.Count - 1)
            {
                int opIndex = nextValueIndex++;

                while (nextValueIndex < operations.Count - 1 && operations[nextValueIndex] is CommentElement)
                {
                    comments.Add(operations[nextValueIndex++]);
                }

                int expIndex = nextValueIndex++;

                while (nextValueIndex < operations.Count && operations[nextValueIndex] is CommentElement)
                {
                    comments.Add(operations[nextValueIndex++]);
                }

                AddOperationToTree(parent.Codes().First(), (CodeElement)operations[opIndex], (CodeElement)operations[expIndex], comments);
                comments.Clear();
            }

            _completeOperations.Insert(0, (CodeElement)parent.ChildNodes[0]);

            outElements[0] = parent.ChildNodes[0];
            return(true);
        }
コード例 #16
0
        private void RunTestParse()
        {
            // Function for calculating new average
            Func <float, float, double, int> newAvg = (i, old, nw) => (int)(i == 0 ? nw : old * i / (i + 1) + nw / (i + 1));

            if (_parserTest == null)
            {
                Result += "Parser not set. Enter levels first\r\n";
            }
            if (string.IsNullOrEmpty(_generatedInputFull))
            {
                Result += "No input. Prepare test first\r\n";
            }
            if (_parserTest == null || string.IsNullOrEmpty(_generatedInputFull))
            {
                return;
            }

            Result = "running";

            // Prepare query test
            string letters             = "bcdefg";
            var    levels              = Benchmark.GetLevelListFromCode();
            List <List <string> > sets = GetIdSets(levels);
            long sum = 0;

            Random rnd = new Random();

            // Local function to add integer to sum.
            void AddAllCombinations2(int level, int number, TextElement elem)
            {
                if (level < sets.Count() - 1)
                {
                    string find = sets[level][rnd.Next(levels[level])];
                    AddAllCombinations2(level + 1, number,
                                        elem.Codes().First(e => e.Name == letters.Substring(level, 1) &&
                                                           e.Codes().First().Value == find));
                }
                else
                {
                    CodeElement el = elem.Codes().First(e => e.Name == letters.Substring(level, 1) &&
                                                        e.Codes().First().Value == sets[level][number]);
                    sum += int.Parse(el.Codes().First(e => e.Name == "int").Value);
                }
            }

            Action parse = () =>
            {
                // ---------- MEMORY ---------------
                Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
                long    memoryUsage1   = currentProcess.WorkingSet64;

                // ---------- PARSING ---------------
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
                CodeDocument doc = CodeDocument.Load(_parserTest, _generatedInputFull);
                stopWatch.Stop();

                // ---------- MEMORY RESULT ---------------
                currentProcess = System.Diagnostics.Process.GetCurrentProcess();
                long memoryUsage2 = (currentProcess.WorkingSet64 - memoryUsage1) / 1024;
                if (memoryUsage2 > int.MaxValue)
                {
                    Result += "Memory use too large.\r\n";
                }
                else
                {
                    Benchmark.MemParse = newAvg(Benchmark.TestRuns, Benchmark.TimeParse, memoryUsage2);
                }

                if (stopWatch.Elapsed.TotalMilliseconds > int.MaxValue)
                {
                    Result += "Parse time too long.\r\n";
                }
                else
                {
                    Benchmark.TimeParse = newAvg(Benchmark.TestRuns, Benchmark.TimeParse, stopWatch.Elapsed.TotalMilliseconds);
                }

                // ---------- QUERYING ---------------
                int number    = -1;
                int lastLevel = levels.Last();
                stopWatch = new Stopwatch();
                stopWatch.Start();

                for (long l = 0; l < Benchmark.Combi; l++)
                {
                    if (++number == lastLevel)
                    {
                        number = 0;
                    }
                    AddAllCombinations2(0, number, doc);
                }
                stopWatch.Stop();

                long expected = ((lastLevel - 1) * lastLevel) / 2;
                for (int i = 0; i < levels.Count - 1; i++)
                {
                    expected *= levels[i];
                }

                if (expected != sum)
                {
                    throw new Exception("test sum is off");
                }

                if (stopWatch.Elapsed.TotalMilliseconds > int.MaxValue)
                {
                    Result += "Query time too long.\r\n";
                }
                else
                {
                    Benchmark.TimeQuery = newAvg(Benchmark.TestRuns, Benchmark.TimeQuery, stopWatch.Elapsed.TotalMilliseconds);
                }

                // ---------- OUTPUT ---------------
                Benchmark.TestRuns++;
                Result = "run " + Benchmark.TestRuns;
                if (BenchmarkCompare != null)
                {
                    Result += "\r\n" + Benchmark.Compare(BenchmarkCompare);
                }
            };

            Thread thread = new Thread(new ThreadStart(parse));

            thread.Start();
        }