private NovelExpression UnfoldArguments(NovelExpression expression, ref List <NovelInstruction> instructions) { //Get the term var term = expression.Term; for (int i = 0; i < term.Count; i++) { int functionEndIndex = -1; int functionElements = 2; //Look for function start operator if (term[i] is NovelFunctionStartOperator && term[i - 1] is NovelExpressionFunctionCall) { //Check if inside function are only comma characters bool onlyCommas = true; for (int j = i + 1; j < term.Count; j++) { var test = term[j]; functionElements++; //Read until novel function end if (term[j] is NovelFunctionEndOperator) { functionEndIndex = j; break; } //If its an operator if (term[j] is NovelExpressionOperator) { //If its different than comma if (!(term[j] is NovelCommaOperator)) { onlyCommas = false; break; } } } if (onlyCommas) { //Fill function with arguments var function = term[i - 1] as NovelExpressionFunctionCall; for (int j = i; j < functionEndIndex; j++) { if (term[j] is NovelExpressionOperand) { function.Arguments.Add(term[j] as NovelExpressionOperand); } } //TODO //here i have number of arguments in function //so i can check if its the right number int newIndex = ParsedScript.DelegateFunctionList. ContainsFunction(function.Name, function.Arguments.Count); //If found new delegated function if (newIndex > -1) { function.Offset = newIndex; } else { throw new NovelException("Could not find delegated method " + function.Name + " with " + function.Arguments.Count() + " arguments.", "", 0); } //Now create new expression var lastStackOperator = Variables.GetStackVariables(); var temporaryVariable = new NovelExpressionVariable("temp_" + lastStackOperator, lastStackOperator); Variables.AddVaraible(temporaryVariable.Name); //instructions.Add(new NovelExpandStack(1)); var newExpression = new NovelExpression(); //newExpression.Term.Add(temporaryVariable); newExpression.Term.Add(function); //newExpression.Term.Add(new NovelAssignOperator()); instructions.Add(newExpression); //Remove from expression for (int j = 0; j < functionElements; j++) { expression.Term.RemoveAt(i - 1); } if (expression.Term.Count > 0) { expression.Term.Insert(i - 1, temporaryVariable); } i -= 1; } } } return(expression); }
public List <NovelInstruction> ParseExpression(string text) { //Trim the expression text = text.Trim(); //Create empty expression object NovelExpression novelExpression = new NovelExpression(); //Declare instructions List <NovelInstruction> instructions = new List <NovelInstruction>(); //For RPN algorithm purpose string output = ""; string buffer = ""; for (int i = 0; i < text.Length; i++) { //Check if the i is pointing at operator name var operatorIndex = IsOperator(text, i); //operatorIndex = -1 means that its regular character if (operatorIndex >= 0) { //Build expression here based on whats in buffer if (!buffer.Equals("")) { if (IsDeclaredVariable(buffer)) { buffer = buffer.Substring(3); if (!Variables.ContainsVariable(buffer)) { instructions.Add(new NovelExpandStack(1)); Variables.AddVaraible(buffer); } //TODO functions name else { throw new NovelException("Variable or function name " + buffer + " already exists.", ParsedFile, ParsedLine); } } //Handle the operands novelExpression = HandleOperand(novelExpression, buffer); //Push variable to the output output += buffer; buffer = ""; } //Get the new operator var op = Operators[operatorIndex]; //Parentheses close operator if (op is NovelCloseCurvedParenthesesOperator) { //Pop all operators till ( while (OperatorStack.Count() > 0) { var opFromStack = OperatorStack.Pop(); if (opFromStack is NovelOpenCurvedParenthesesOperator) { var parentheses = parenthesesType.Pop(); if (parentheses == ParenthesesType.Function) { novelExpression.Term.Add(new NovelFunctionEndOperator()); } break; } else { if (!(opFromStack is NovelOpenCurvedParenthesesOperator || opFromStack is NovelCloseCurvedParenthesesOperator)) { novelExpression.Term.Add(opFromStack); } } } } //If every other operator else { //Iteratore over OperatorStack while (OperatorStack.Count() > 0) { //If priority of new operator is lower or equal pop stack operators // if (op.GetPriority() <= OperatorStack.First().GetPriority() && !(op is NovelOpenCurvedParenthesesOperator)) { var opFromStack = OperatorStack.Pop(); if (!(opFromStack is NovelOpenCurvedParenthesesOperator || opFromStack is NovelCloseCurvedParenthesesOperator)) { novelExpression.Term.Add(opFromStack); } } else { break; } } } //Now put the operator on the stack if not close curved if (!(op is NovelCloseCurvedParenthesesOperator)) { //If previous term part was function call if (novelExpression.Term.Count >= 1 && op is NovelOpenCurvedParenthesesOperator && novelExpression.Term[novelExpression.Term.Count - 1] is NovelExpressionFunctionCall) { parenthesesType.Push(ParenthesesType.Function); novelExpression.Term.Add(new NovelFunctionStartOperator()); } //If normal paretheses else if (op is NovelOpenCurvedParenthesesOperator) { parenthesesType.Push(ParenthesesType.Normal); } OperatorStack.Push(op); } //Move pointer by a length of operator i += op.GetName().Length - 1; } //If its not an operator else { if (text[i].Equals(' ')) { continue; } else if (text[i].Equals('\t')) { continue; } else if (text[i].Equals('\r')) { continue; } else if (text[i].Equals('\n')) { continue; } //If its a quote if (text[i].Equals('\"')) { int len = text.IndexOf('\"', i + 1) - i + 1; buffer += text.Substring(i, len); i += len - 1; } //If its not add single character else { buffer += text[i]; } } } //Empty buffer first if (!buffer.Equals("")) { novelExpression = HandleOperand(novelExpression, buffer); } //Empty operator stack while (OperatorStack.Count() > 0) { var opFromStack = OperatorStack.Pop(); if (!(opFromStack is NovelOpenCurvedParenthesesOperator || opFromStack is NovelCloseCurvedParenthesesOperator)) { novelExpression.Term.Add(opFromStack); } } Variables.AddScope(); int reservedVariables = Variables.GetStackVariables(); while (novelExpression.Term.Count > 0) { novelExpression = UnfoldOperations(novelExpression, ref instructions); novelExpression = UnfoldArguments(novelExpression, ref instructions); //For single variables or literals if (novelExpression.Term.Count == 1) { var newExpression = new NovelExpression(); newExpression.Term.Add(novelExpression.Term[0]); instructions.Add(newExpression); novelExpression.Term.Clear(); } } //How many of temporary variables expression has reservedVariables = Variables.GetStackVariables() - reservedVariables; //Shrink stack to remove them if (reservedVariables > 0) { instructions.Add(new NovelExpandStack(-reservedVariables)); } Variables.RemoveScope(); foreach (var instruction in instructions) { string buff = ""; buff += " " + instruction; Console.WriteLine(buff); } Console.WriteLine(""); return(instructions); }
private NovelExpression UnfoldOperations(NovelExpression expression, ref List <NovelInstruction> instructions) { //Get the term var term = expression.Term; //Look for for (int i = 0; i < term.Count; i++) { var part = term[i]; //Look for operator different //comma //fnc start //fnc end //fnc call if (part is NovelExpressionOperator) { if (!(part is NovelExpressionFunctionCall) && !(part is NovelCommaOperator) && !(part is NovelFunctionStartOperator) && !(part is NovelFunctionEndOperator)) { //If its one argument operator if (part is NovelNegationOperator && term[i - 1] is NovelExpressionOperand) { var operand = term[i - 1] as NovelExpressionOperand; var lastStackOperator = Variables.GetStackVariables(); var temporaryVariable = new NovelExpressionVariable("temp_" + lastStackOperator, lastStackOperator); Variables.AddVaraible(temporaryVariable.Name); instructions.Add(new NovelExpandStack(1)); var newExpression = new NovelExpression(); newExpression.Term.Add(temporaryVariable); newExpression.Term.Add(operand); newExpression.Term.Add(part); newExpression.Term.Add(new NovelAssignOperator()); instructions.Add(newExpression); //Replace last operation with temporary variable expression.Term.RemoveAt(i - 1); expression.Term.RemoveAt(i - 1); //Don't put temporary variable to expression if its empty if (expression.Term.Count > 0) { expression.Term.Insert(i - 1, temporaryVariable); } i -= 1; } //Get the two operands if its not negation else { //If its the end of expression if (part is NovelAssignOperator && expression.Term.Count == 3 && term[i - 1] is NovelExpressionOperand && term[i - 2] is NovelExpressionOperand) { var newExpression = new NovelExpression(); newExpression.Term.Add(term[i - 2]); newExpression.Term.Add(term[i - 1]); newExpression.Term.Add(part); instructions.Add(newExpression); expression.Term.Clear(); } //If both previous parts in term are operands else if ( term[i - 1] is NovelExpressionOperand && term[i - 2] is NovelExpressionOperand) { var operandLeft = term[i - 2] as NovelExpressionOperand; var operandRight = term[i - 1] as NovelExpressionOperand; var lastStackOperator = Variables.GetStackVariables(); var temporaryVariable = new NovelExpressionVariable("temp_" + lastStackOperator, lastStackOperator); Variables.AddVaraible(temporaryVariable.Name); instructions.Add(new NovelExpandStack(1)); //Create new operation of two operands //and assign the result to temporary variable var newExpression = new NovelExpression(); newExpression.Term.Add(temporaryVariable); newExpression.Term.Add(operandLeft); newExpression.Term.Add(operandRight); newExpression.Term.Add(part); newExpression.Term.Add(new NovelAssignOperator()); instructions.Add(newExpression); //Replace last operation with temporary variable expression.Term.RemoveAt(i - 2); expression.Term.RemoveAt(i - 2); expression.Term.RemoveAt(i - 2); if (expression.Term.Count > 0) { expression.Term.Insert(i - 2, temporaryVariable); } i -= 2; } } } } } return(expression); }