public override void Parse(string input, int charIndex) { input = input.Trim(); if (string.IsNullOrWhiteSpace(input)) { throw new AST_EmptyInputException("Provided string is empty", charIndex); } if (!input.StartsWith("if") || !input.EndsWith("ends if")) { throw new AST_EmptyInputException("Provided string is not an if code piece", charIndex); } int insideIndexStart = "if".Length; while (AST_Program.separator_ast.IndexOf(input[insideIndexStart]) != -1) { //We are skipping white-spaces ++insideIndexStart; } if (input[insideIndexStart] != '(') { throw new AST_BadFormatException("Failed to find conditional expression inside if", charIndex + insideIndexStart); } Stack <string> brackets = new Stack <string>(); int insideIndexEnd = insideIndexStart + 1; brackets.Push("("); while (brackets.Count > 0) { if (input[insideIndexEnd] == '(') { brackets.Push("("); insideIndexEnd++; } else if (input[insideIndexEnd] == ')') { if (brackets.Peek() == "(") { brackets.Pop(); insideIndexEnd++; } else { throw new AST_BadFormatException("Failed to parse conditional expression inside if", new AST_BadFormatException("Encountered unexpected tokens in bracket stack", charIndex + insideIndexEnd), charIndex + insideIndexEnd); } } else { insideIndexEnd++; } if (input.Length <= insideIndexEnd) { throw new AST_BadFormatException("Reached end of input while parsing if brackets", charIndex + insideIndexEnd); } } //insideIndexEnd points at closing bracket + 1 string conditionalExpression = input.Substring(insideIndexStart + 1, insideIndexEnd - insideIndexStart - 2); inside = new AST_Expression(this, conditionalExpression + " ;", charIndex + insideIndexStart + 1); int localInput = insideIndexEnd; while (AST_Program.separator_ast.IndexOf(input[localInput]) != -1) { localInput++; } if (input.IndexOf("does", localInput) != localInput) { //We failed to find if body throw new AST_BadFormatException("Conditional statement body was not found", charIndex + localInput); } Stack <string> codeSegments = new Stack <string>(); codeSegments.Push("does"); int codeSegmentStart = localInput; localInput++; while (codeSegments.Count > 0) { if (input.IndexOf("does", localInput) == localInput) { codeSegments.Push("does"); } else if (input.IndexOf("ends", localInput) == localInput) { if (codeSegments.Peek() != "does") { throw new AST_BadFormatException("Failed to parse conditional expression inside if", new AST_BadFormatException("Encountered unexpected tokens in bracket stack", charIndex + localInput), charIndex + localInput); } codeSegments.Pop(); } localInput++; if (input.Length <= localInput && codeSegments.Count > 0) { throw new AST_BadFormatException("Reached end of input while parsing if body", charIndex + localInput); } } //localInput points at letter n from "ends" string codeBody = input.Substring(codeSegmentStart + "does".Length, localInput - 1 - "does".Length - codeSegmentStart); int elseIndex = localInput + "ends".Length; while (AST_Program.separator_ast.IndexOf(input[elseIndex]) != -1 && elseIndex < input.Length) { ++elseIndex; } if (input.IndexOf("if", elseIndex) != elseIndex) { if (input.IndexOf("else", elseIndex) != elseIndex) { throw new AST_BadFormatException("Bad formatting of if statement", elseIndex); } else { //We should parse "else" elseIndex += "else".Length; while (AST_Program.separator_ast_nosemicolon.IndexOf(input[elseIndex]) != -1) { elseIndex++; } if (input.IndexOf("does", elseIndex) != elseIndex) { throw new AST_BadFormatException("Couldn\'t find does part of else", elseIndex); } elseIndex += "does".Length; int doesCount = 1, elseEndsIndex = elseIndex; while (doesCount != 0) { if (input.IndexOf("does", elseEndsIndex) == elseEndsIndex) { doesCount++; elseEndsIndex += "does".Length; } else if (input.IndexOf("ends", elseEndsIndex) == elseEndsIndex) { doesCount--; elseEndsIndex += "ends".Length; } else { elseEndsIndex++; } if (input.Length <= elseEndsIndex && doesCount != 0) { throw new AST_BadFormatException("Reached end of input while parsing else body", charIndex + elseEndsIndex); } } string elseBody = input.Substring(elseIndex, elseEndsIndex - "ends".Length - elseIndex); string[] elseExps = AST_Function.Split(elseBody, charIndex + codeSegmentStart + "does".Length); if (elseExps.Length > 0) { else_expressions = new LinkedList <AST_Expression>(); } int elseExLength = elseIndex; foreach (string ex in elseExps) { bool hasActualExpression = false; for (int p = 0; p < ex.Length; ++p) { if (!AST_Program.separator_ast.Contains(ex[p])) { hasActualExpression = true; break; } } if (hasActualExpression) { string nat = ex.Trim(); if (nat.StartsWith("native does") && nat.EndsWith("native ends")) { else_expressions.AddLast(new AST_Native(this, nat, charIndex + elseExLength)); } else if (nat.StartsWith("if") && nat.EndsWith("ends if")) { else_expressions.AddLast(new AST_If(this, nat, charIndex + elseExLength)); } else if (nat.StartsWith("while") && nat.EndsWith("ends while")) { else_expressions.AddLast(new AST_While(this, nat, charIndex + elseExLength)); } else if (nat.StartsWith("for") && nat.EndsWith("ends for")) { else_expressions.AddLast(new AST_For(this, nat, charIndex + elseExLength)); } else { //Try to find local variable bool isVariable = false; string[] pieces = nat.Split(AST_Program.separator_ast.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (pieces.Length == 2) { //We may have a variable declaration isVariable = true; try { //Do a simple parameter check beforehand not to waste time just in case var localType = CodeBlocks.ParameterType.GetParameterType(pieces[0]); AST_LocalVariable localVariable = new AST_LocalVariable(this, nat, charIndex + elseExLength); else_expressions.AddLast(localVariable); } catch (Exception) { //It is not isVariable = false; } } if (!isVariable) { //Parse as an expression else_expressions.AddLast(new AST_Expression(this, ex + ";", charIndex + elseExLength)); } } } elseExLength += ex.Length + 1; } } } string[] exps = AST_Function.Split(codeBody, charIndex + codeSegmentStart + "does".Length); if (exps.Length > 0) { expressions = new LinkedList <AST_Expression>(); } int exLength = codeSegmentStart + "does".Length; foreach (string ex in exps) { bool hasActualExpression = false; for (int p = 0; p < ex.Length; ++p) { if (!AST_Program.separator_ast.Contains(ex[p])) { hasActualExpression = true; break; } } if (hasActualExpression) { string nat = ex.Trim(); if (nat.StartsWith("native does") && nat.EndsWith("native ends")) { expressions.AddLast(new AST_Native(this, nat, charIndex + exLength)); } else if (nat.StartsWith("if") && nat.EndsWith("ends if")) { expressions.AddLast(new AST_If(this, nat, charIndex + exLength)); } else if (nat.StartsWith("while") && nat.EndsWith("ends while")) { expressions.AddLast(new AST_While(this, nat, charIndex + exLength)); } else if (nat.StartsWith("for") && nat.EndsWith("ends for")) { expressions.AddLast(new AST_For(this, nat, charIndex + exLength)); } else { //Try to find local variable bool isVariable = false; string[] pieces = nat.Split(AST_Program.separator_ast.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); if (pieces.Length == 2) { //We may have a variable declaration isVariable = true; try { //Do a simple parameter check beforehand not to waste time just in case var localType = CodeBlocks.ParameterType.GetParameterType(pieces[0]); AST_LocalVariable localVariable = new AST_LocalVariable(this, nat, charIndex + exLength); expressions.AddLast(localVariable); } catch (Exception) { //It is not isVariable = false; } } if (!isVariable) { //Parse as an expression expressions.AddLast(new AST_Expression(this, ex + ";", charIndex + exLength)); } } } exLength += ex.Length + 1; } }
public abstract void Parse(AST_Function input);
public override void Parse(AST_Function input) { functionData.accessLevel = input.accessLevel; functionData.name = input.name; functionData.ending = ""; //TODO - implement locals functionData.locals = new List <Tuple <AST_Variable, bool, string> >(); functionData.left = new Stack <string>(); functionData.right = new Stack <string>(); functionData.ret = new Stack <string>(); if (input.parameters == null) { functionData.parameters = null; } else { functionData.parameters = new List <Tuple <AST_Variable, bool, string> >(); int addr = 4; for (int i = input.parameters.Count - 1; i >= 0; --i) { var p = input.parameters.ElementAt(i); string address = ""; string dataType = p.DataType.GetName(); switch (dataType) { case "bool": addr += 1; address = "byte ptr ebp+" + addr.ToString(CultureInfo.InvariantCulture) + ""; break; case "float32": throw new NotImplementedException("Floats are not supported"); case "int32": addr += 4; address = "ptr ebp+" + addr.ToString(CultureInfo.InvariantCulture) + ""; break; case "int8": addr += 1; address = "byte ptr ebp+" + addr.ToString(CultureInfo.InvariantCulture) + ""; break; case "int16": addr += 2; address = "word ptr ebp+" + addr.ToString(CultureInfo.InvariantCulture) + ""; break; } functionData.parameters.Add(new Tuple <AST_Variable, bool, string>(p, false, address)); } } functionData.returnValue = input.retValue; //if (functionData.returnValue.DataType != DataType.Void) functionData.axUsed = true; functionData.axUsed = false; functionData.bxUsed = false; functionData.cxUsed = false; functionData.dxUsed = false; Result += input.name + ":" + AST_Program.separator_line; //Working with input parameters, if void then skip if (input.parameters.Count > 0 && !(input.parameters.Count == 1 && input.parameters.First.Value.DataType.GetName() == "void")) { Result += "\tpush \tebp" + AST_Program.separator_line; Result += "\tmov \tebp,\tesp" + AST_Program.separator_line; functionData.ending += "\tmov \tesp,\tebp" + AST_Program.separator_line; functionData.ending += "\tpop \tebp" + AST_Program.separator_line; } functionData.ending += "\tret" + AST_Program.separator_line; foreach (var exp in input.expressions) { exp.Accept(this); } //if (input.parameters.Count == 1 && input.parameters.First.Value.DataType == DataType.Void) //{ // Result += functionData.ending; //} }