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); }
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); }
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); }
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())); } }
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); }
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); }
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); }
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); }
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); }
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)); } }
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); }
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); }
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); }
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)); } }
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); }
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(); }