public Exp_Node_New(List <string> input, int charInd) { this.input = input; if (input.Count == 1) { if (isConstant(input[0])) { exp_Type = Exp_Type.Constant; exp_Data = input[0]; left = null; right = null; } else if (isVariable(input[0])) { exp_Type = Exp_Type.Variable; exp_Data = input[0]; left = null; right = null; } else if (isEmptyOperation(input[0], out AST_Operator @operator)) { exp_Type = Exp_Type.Operator; exp_Data = input[0]; exp_Operator = @operator; left = null; right = null; } else { throw new AST_BadFormatException(input[0] + " can\'t be parsed", charInd); } return; } int i = 0; List <Exp_Piece> pieces = new List <Exp_Piece>(); for (i = 0; i < input.Count; ++i) { pieces.Add( new Exp_Piece { inStrg = input[i], indexStart = i, indexEnd = i, inNode = null, isString = true } ); } Exp_Node_New result = new Exp_Node_New(pieces, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; }
public Exp_Node_New(Exp_Node_New left, Exp_Node_New right, List <string> input, string exp_Data, Exp_Type exp_Type, AST_Operator exp_Operator) { this.left = left; this.right = right; this.input = input; this.exp_Data = exp_Data; this.exp_Type = exp_Type; this.exp_Operator = exp_Operator; }
private Exp_Node_New(List <Exp_Piece> input, int charInd) { //TODO - fix charInd references and broken List<string> input passes this.input = null; if (input.Count == 1) { if (input[0].isString) { if (isConstant(input[0].inStrg)) { exp_Type = Exp_Type.Constant; exp_Data = input[0].inStrg; left = null; right = null; } else if (isVariable(input[0].inStrg)) { exp_Type = Exp_Type.Variable; exp_Data = input[0].inStrg; left = null; right = null; } else if (isEmptyOperation(input[0].inStrg, out AST_Operator @operator)) { exp_Type = Exp_Type.Operator; exp_Data = input[0].inStrg; exp_Operator = @operator; left = null; right = null; } else { throw new AST_BadFormatException(input[0].inStrg + " can\'t be parsed", charInd); } } else { exp_Type = input[0].inNode.exp_Type; exp_Data = input[0].inNode.exp_Data; exp_Operator = input[0].inNode.exp_Operator; left = input[0].inNode.left; right = input[0].inNode.right; this.input = input[0].inNode.input; } return; } int i = 0; bool found = false; int maxLayer = AST_Expression.operators_ast.Max(a => a.layer); for (int layer = 0; layer <= maxLayer; ++layer) { if (found) { break; } List <AST_Operator> ops = AST_Expression.operators_ast.Where(a => a.layer == layer).ToList(); if (ops.Count == 0) { continue; } int[] opIndexesLeft = new int[ops.Count]; int[] opIndexesRight = new int[ops.Count]; int[] opIndexes = new int[ops.Count]; for (int j = 0; j < ops.Count; ++j) { opIndexesLeft[j] = -1; opIndexesRight[j] = -1; opIndexes[j] = -1; } int op = 0, opLeft = 0, opRight = 0; bool opLeftFilled = false, opRightFilled = false; for (int opInd = 0; opInd < ops.Count; ++opInd) { string operation = ""; string[] opPieces = ops[opInd].oper.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); operation = opPieces[0]; //TODO - DONE - find RightToLeft operators separately and compare their distance to the last element opIndexesLeft[opInd] = input.FindIndex(a => a.isString && a.inStrg == operation); opIndexesRight[opInd] = input.FindLastIndex(a => a.isString && a.inStrg == operation); if ((opIndexesLeft[opLeft] == -1 || opIndexesLeft[opInd] < opIndexesLeft[opLeft] || !opLeftFilled || (opIndexesLeft[opInd] == opIndexesLeft[opLeft] && ops[opInd].oper.Length > ops[opLeft].oper.Length) ) && opIndexesLeft[opInd] != -1 && ops[opInd].isLeftToRight) { //Operator exists and is closer to the start of input opLeft = opInd; opLeftFilled = true; } if ((opIndexesRight[opRight] == -1 || opIndexesRight[opInd] > opIndexesRight[opRight] || !opRightFilled || (opIndexesRight[opInd] == opIndexesRight[opRight] && ops[opInd].oper.Length > ops[opRight].oper.Length) ) && opIndexesRight[opInd] != -1 && !ops[opInd].isLeftToRight) { opRight = opInd; opRightFilled = true; } } if (!opRightFilled && !opLeftFilled) { continue; } if (input.Count - opIndexesRight[opRight] - 1 < (opIndexesLeft[opLeft] == -1 ? input.Count : opIndexesLeft[opLeft]) && (opRightFilled || !opLeftFilled)) { op = opRight; opIndexes[op] = opIndexesRight[op]; } else { op = opLeft; opIndexes[op] = opIndexesLeft[op]; } if (opIndexes[op] == -1) { continue; } //We found an operation. Now we need to check if it is valid if (ops[op].isPaired) { //This operation is a brackets operation if (ops[op].operandCount != 1) { throw new AST_BadFormatException( "Compiler error - a paired operation with not one operand exists", charInd + opIndexes[op]); } //TODO - move this code somewhere so it is executed once List <Tuple <string, string> > brackets = AST_Expression.operators_ast .Where(a => a.isPaired && a.operandCount == 1) .Select(a => { string[] bracketParts = a.oper.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (bracketParts.Length != 2) { throw new AST_BadFormatException( "Compiler error - a paired operation" + a.oper + " with not two pieces exists", charInd); } return(new Tuple <string, string>(bracketParts[0], bracketParts[1])); }) .ToList(); Stack <string> bracketStack = new Stack <string>(); i = opIndexes[op]; bracketStack.Push(input[i].inStrg); ++i; while (i < input.Count) { int bracketIndexStart = brackets.FindIndex(a => a.Item1 == input[i].inStrg); int bracketIndexStop = brackets.FindIndex(a => a.Item2 == input[i].inStrg); if (bracketIndexStop != -1) { if (bracketStack.Peek() == brackets[bracketIndexStop].Item1) { bracketStack.Pop(); } else { throw new AST_BadFormatException( "Bracket sequence of the expression is incorrect", charInd + i); } } else if (bracketIndexStart != -1) { bracketStack.Push(input[i].inStrg); } ++i; if (bracketStack.Count == 0) { break; } } if (bracketStack.Count == 0) { //Closing bracket is at position i-1 found = true; if (i - 2 == opIndexes[op]) { //Brackets are empty //TODO - call parameter-less functions with brackets if (i - 3 >= 0 && input[i - 3].isString && isVariable(input[i - 3].inStrg)) { //We have a parameter-less function input.RemoveRange(opIndexes[op], 2); Exp_Node_New functionNode = new Exp_Node_New( null, null, null, input[opIndexes[op] - 1].inStrg, Exp_Type.Function, new AST_Operator()); input.RemoveRange(opIndexes[op] - 1, 1); Exp_Piece bracketsPiece = new Exp_Piece { indexStart = opIndexes[op] - 1, indexEnd = i - 1, inNode = functionNode, inStrg = null, isString = false }; input.Insert(opIndexes[op] - 1, bracketsPiece); } else { //TODO - initialize arrays with empty brackets throw new AST_BadFormatException( "Empty brackets " + input[opIndexes[op]], charInd + i); } } else { //Create the content array List <Exp_Piece> content = new List <Exp_Piece>(i - 2 - opIndexes[op]); for (int j = 0; j < content.Capacity; ++j) { content.Add(input[opIndexes[op] + 1 + j]); } input.RemoveRange(opIndexes[op], i - opIndexes[op]); Exp_Node_New bracketsNode = new Exp_Node_New(content, opIndexes[op] + 1) /*{ exp_Operator = ops[op] }*/; Exp_Piece bracketsPiece; if (opIndexes[op] - 1 >= 0 && input[opIndexes[op] - 1].isString && isVariable(input[opIndexes[op] - 1].inStrg)) { //We have a function Exp_Node_New functionNode = new Exp_Node_New( null, bracketsNode, null, input[opIndexes[op] - 1].inStrg, Exp_Type.Function, new AST_Operator()); input.RemoveRange(opIndexes[op] - 1, 1); bracketsPiece = new Exp_Piece { indexStart = opIndexes[op] - 1, indexEnd = i - 1, inNode = functionNode, inStrg = null, isString = false }; input.Insert(opIndexes[op] - 1, bracketsPiece); } else { bracketsPiece = new Exp_Piece { indexStart = opIndexes[op], indexEnd = i - 1, inNode = bracketsNode, inStrg = null, isString = false }; input.Insert(opIndexes[op], bracketsPiece); } } Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } else { throw new AST_BadFormatException( "No closing bracket found for " + bracketStack.Peek(), charInd + i); } } else { if (ops[op].isPrefix == true) { if (opIndexes[op] == input.Count - 1) { //Prefix at the end - false match continue; } if (opIndexes[op] >= 1 && !((input[opIndexes[op] - 1].isString && isOperation(input[opIndexes[op] - 1].inStrg)) /* || * (!input[opIndexes[op] - 1].isString && isOperation(input[opIndexes[op] - 1].inNode))*/)) { //It is not actually prefix continue; } //We have a prefix operation if (ops[op].operandCount == 0) { throw new AST_BadFormatException( "Compiler error - Found a 0-operand operator in a non-0-operand input", charInd + opIndexes[op]); } if (ops[op].toEnd) { List <Exp_Piece> content = new List <Exp_Piece>(input.Count - opIndexes[op] - 1); for (int j = 0; j < content.Capacity; ++j) { content.Add(input[opIndexes[op] + 1 + j]); } Exp_Node_New rightNode = new Exp_Node_New(content, opIndexes[op] + 1); input.RemoveRange(opIndexes[op], input.Count - opIndexes[op]); Exp_Node_New rightResult = new Exp_Node_New( null, rightNode, new List <string>(ToListString(content)), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece rightResultPiece = new Exp_Piece { indexStart = opIndexes[op], indexEnd = opIndexes[op], inStrg = null, inNode = rightResult, isString = false }; input.Insert(opIndexes[op], rightResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } else { //TODO - leave only similar code List <Exp_Piece> content = new List <Exp_Piece>(1); content.Add(input[opIndexes[op] + 1]); Exp_Node_New rightNode = new Exp_Node_New(content, opIndexes[op] + 1); input.RemoveRange(opIndexes[op], 2); Exp_Node_New rightResult = new Exp_Node_New( null, rightNode, new List <string>(ToListString(content)), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece rightResultPiece = new Exp_Piece { indexStart = opIndexes[op], indexEnd = opIndexes[op], inStrg = null, inNode = rightResult, isString = false }; input.Insert(opIndexes[op], rightResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } } else if (ops[op].isPrefix == false) { if (opIndexes[op] == 0) { //Suffix at the start - false match continue; } if (opIndexes[op] < input.Count - 1 && !((input[opIndexes[op] + 1].isString && isOperation(input[opIndexes[op] + 1].inStrg)) /* || * (!input[opIndexes[op] + 1].isString && isOperation(input[opIndexes[op] + 1].inNode))*/)) { //It is not actually prefix continue; } //We have a suffix operation if (ops[op].operandCount == 0) { throw new AST_BadFormatException( "Compiler error - Found a 0-operand operator in a non-0-operand input", charInd + opIndexes[op]); } if (ops[op].toEnd) { List <Exp_Piece> content = new List <Exp_Piece>(opIndexes[op]); for (int j = 0; j < content.Capacity; ++j) { content.Add(input[j]); } Exp_Node_New leftNode = new Exp_Node_New(content, charInd); input.RemoveRange(0, opIndexes[op] + 1); Exp_Node_New leftResult = new Exp_Node_New( leftNode, null, new List <string>(ToListString(content)), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece leftResultPiece = new Exp_Piece { indexStart = 0, indexEnd = 0, inStrg = null, inNode = leftResult, isString = false }; input.Insert(0, leftResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } else { List <Exp_Piece> content = new List <Exp_Piece>(1); content.Add(input[opIndexes[op] - 1]); Exp_Node_New leftNode = new Exp_Node_New(content, charInd + opIndexes[op] - 1); input.RemoveRange(opIndexes[op] - 1, 2); Exp_Node_New leftResult = new Exp_Node_New( leftNode, null, new List <string>(ToListString(content)), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece leftResultPiece = new Exp_Piece { indexStart = opIndexes[op] - 1, indexEnd = opIndexes[op] - 1, inStrg = null, inNode = leftResult, isString = false }; input.Insert(opIndexes[op] - 1, leftResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } } else { if (opIndexes[op] == 0 || opIndexes[op] == input.Count - 1) { //We have a false match continue; } //We have a standard two-operand operator if (ops[op].operandCount != 2) { throw new AST_BadFormatException( "Compiler error - Found a non-2-operand infix operator", charInd + opIndexes[op]); } if (ops[op].toEnd) { List <Exp_Piece> contentLeft = new List <Exp_Piece>(opIndexes[op]); for (int j = 0; j < contentLeft.Capacity; ++j) { contentLeft.Add(input[j]); } Exp_Node_New leftNode = new Exp_Node_New(contentLeft, charInd); input.RemoveRange(0, opIndexes[op] + 1); List <Exp_Piece> contentRight = new List <Exp_Piece>(input.Count); for (int j = 0; j < contentRight.Capacity; ++j) { contentRight.Add(input[j]); } Exp_Node_New rightNode = new Exp_Node_New(contentRight, charInd + 1); input.RemoveRange(0, input.Count); Exp_Node_New infixResult = new Exp_Node_New( leftNode, rightNode, new List <string>(ToListString(contentLeft)). Union(new List <string>(ToListString(contentRight))).ToList(), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece infixResultPiece = new Exp_Piece { indexStart = 0, indexEnd = 0, inStrg = null, inNode = infixResult, isString = false }; input.Insert(0, infixResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } else { List <Exp_Piece> contentLeft = new List <Exp_Piece>(1); contentLeft.Add(input[opIndexes[op] - 1]); Exp_Node_New leftNode = new Exp_Node_New(contentLeft, charInd + opIndexes[op] - 1); input.RemoveRange(opIndexes[op] - 1, 2); List <Exp_Piece> contentRight = new List <Exp_Piece>(1); contentRight.Add(input[opIndexes[op] - 1]); Exp_Node_New rightNode = new Exp_Node_New(contentRight, charInd + opIndexes[op]); input.RemoveRange(opIndexes[op] - 1, 1); Exp_Node_New infixResult = new Exp_Node_New( leftNode, rightNode, new List <string>(ToListString(contentLeft)). Union(new List <string>(ToListString(contentRight))).ToList(), ops[op].oper, Exp_Type.Operator, ops[op]) { exp_Operator = ops[op] }; Exp_Piece infixResultPiece = new Exp_Piece { indexStart = opIndexes[op] - 1, indexEnd = opIndexes[op] - 1, inStrg = null, inNode = infixResult, isString = false }; input.Insert(opIndexes[op] - 1, infixResultPiece); Exp_Node_New result = new Exp_Node_New(input, charInd); this.input = result.input; this.exp_Type = result.exp_Type; this.exp_Data = result.exp_Data; this.exp_Operator = result.exp_Operator; this.left = result.left; this.right = result.right; found = true; return; } } } } if (!found) { throw new AST_BadFormatException( "No operator or operand found in input", charInd + input.Count - 1); } }