bool whileCheck(SymbolTable symbolTable) { (string, object)ret = children[0].Evaluate(symbolTable); God.VerifyType("boolean", ret); return((bool)ret.Item2); }
override public (string, object) Evaluate(SymbolTable symbolTable) { if (value.ToString() == "=") { (string, object)val = children[1].Evaluate(symbolTable); symbolTable.Set((string)children[0].value, val.Item2, val.Item1); return("none", null); } (string, object)ret1 = children[0].Evaluate(symbolTable); (string, object)ret2 = children[1].Evaluate(symbolTable); switch (value.ToString()) { case "+": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("integer", ((int)ret1.Item2 + (int)ret2.Item2)); case "-": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("integer", ((int)ret1.Item2 - (int)ret2.Item2)); case "*": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("integer", ((int)ret1.Item2 * (int)ret2.Item2)); case "/": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("integer", ((int)ret1.Item2 / (int)ret2.Item2)); case ">": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("boolean", ((int)ret1.Item2 > (int)ret2.Item2)); case "<": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); return("boolean", ((int)ret1.Item2 < (int)ret2.Item2)); case "&": God.VerifyType("boolean", ret1); God.VerifyType("boolean", ret2); return("boolean", ((bool)ret1.Item2 && (bool)ret2.Item2)); case "|": God.VerifyType("boolean", ret1); God.VerifyType("boolean", ret2); return("boolean", ((bool)ret1.Item2 || (bool)ret2.Item2)); case "==": if (ret1.Item1 != ret2.Item1) { throw new SystemException($"Invalid relative operation == between variables of types {ret1.Item1} and {ret2.Item1}."); } switch (ret1.Item1) { case "boolean": return("boolean", (bool)ret1.Item2 == (bool)ret2.Item2); case "integer": return("boolean", (int)ret1.Item2 == (int)ret2.Item2); default: throw new SystemException($"Invalid variable type for == operation. {ret1.Item1}."); } case "vardec": //get value of type node and interact with ident node to sabe the var type //string type = (string)children[1].value; string key = (string)children[0].value; symbolTable.Set(key, null, "none"); return("none", null); default: throw new SystemException($"Invalid Binary Operator ( {value} was received at node on integer operation )"); } }
public static Node ParseFactor() { //Console.WriteLine("Parsing Factor"); //Factor rules //1st -> num //1st -> + //1st -> - //1st -> not //1st -> ( //+ -> factor //- -> factor //not -> factor //( -> expression //expression -> ) //identifier acts as num //True | False acts as num Node root; switch (tokens.actual.type) { case "INT": root = new IntVal(); root.value = tokens.actual.value; tokens.SelectNext(); return(root); case "IDENTIFIER": root = new Identifier((string)tokens.actual.value); root.value = tokens.actual.value; tokens.SelectNext(); return(root); /* * //check if this is a function * if(tokens.actual.type == "POPEN"){ * FuncCall call = new FuncCall(); * call.value = root.value; * tokens.SelectNext(); * * if(tokens.actual.type != "PCLOSE"){ * do{ * if(tokens.actual.type == "COMMA"){ * tokens.SelectNext(); * } * call.Add(ParseRelExpression()); * } while(tokens.actual.type == "COMMA"); * } * Expect("PCLOSE",true); * return call; * } */ case "TRUE": case "FALSE": root = new UnOp(); root.value = tokens.actual.type == "TRUE" ? "true": "false"; tokens.SelectNext(); return(root); /* * case "PLUS": * case "MINUS": * root = new UnOp(); * root.value = tokens.actual.type == "PLUS" ? '+': '-'; * tokens.SelectNext(); * root.children[0] = ParseFactor(); * return root; */ case "NOT": root = new UnOp(); root.value = "not"; tokens.SelectNext(); root.children[0] = ParseFactor(); return(root); //way to call func in assigns case "GET": tokens.SelectNext(); Expect("IDENTIFIER", false); FuncCall call = new FuncCall(); call.value = (string)tokens.actual.value; tokens.SelectNext(); if (tokens.actual.type == "WITH") { tokens.SelectNext(); do { if (tokens.actual.type == "COMMA") { tokens.SelectNext(); } call.Add(ParseRelExpression()); }while (tokens.actual.type == "COMMA"); } return(call); /* * case "POPEN": * tokens.SelectNext(); * root = ParseRelExpression(); * if(tokens.actual.type != "PCLOSE"){ * throw new SystemException ($"Missing closing parentesis (position {tokens.position}) [Line: {CurrentLine}]"); * } * tokens.SelectNext(); * return root; */ case "INPUT": root = new UnOp(); root.value = "input"; tokens.SelectNext(); return(root); } //End of term reached, but exiting was not allowed God.Error($"Invalid expression format. Expression end was unexpected."); return(null); }
override public (string, object) Evaluate(SymbolTable symbolTable) { if (value.ToString() == "=") { (string, object)assign = children[1].Evaluate(symbolTable); Writer.assign(children[0].value.ToString()); return("none", null); } if (value.ToString() == "vardec") { // get value of type node and interact with ident node to sabe the var type string type = (string)children[1].value; string key = (string)children[0].value; symbolTable.Set(key, null, type); Writer.declare(key); return("none", null); } (string, object)ret1 = children[0].Evaluate(symbolTable); Writer.write("PUSH EBX"); (string, object)ret2 = children[1].Evaluate(symbolTable); Writer.write("POP EAX"); switch (value.ToString()) { case "+": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("ADD EAX, EBX"); Writer.write("MOV EBX, EAX"); return("integer", null); case "-": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("SUB EAX, EBX"); Writer.write("MOV EBX, EAX"); return("integer", null); case "*": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("IMUL EBX"); Writer.write("MOV EBX, EAX"); return("integer", null); case "/": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("IDIV EBX"); Writer.write("MOV EBX, EAX"); return("integer", null); case ">": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("CMP EAX, EBX"); Writer.write("CALL binop_jg"); return("boolean", null); case "<": God.VerifyType("integer", ret1); God.VerifyType("integer", ret2); Writer.write("CMP EAX, EBX"); Writer.write("CALL binop_jl"); return("boolean", null); case "&": God.VerifyType("boolean", ret1); God.VerifyType("boolean", ret2); Writer.write("AND EAX, EBX"); return("boolean", null); case "|": God.VerifyType("boolean", ret1); God.VerifyType("boolean", ret2); Writer.write("OR EAX, EBX"); return("boolean", null); case "==": if (ret1.Item1 != ret2.Item1) { throw new SystemException($"Invalid relative operation == between variables of types {ret1.Item1} and {ret2.Item1}."); } Writer.write("CMP EAX, EBX"); Writer.write("CALL binop_je"); switch (ret1.Item1) { case "boolean": return("boolean", null); case "integer": return("boolean", null); default: throw new SystemException($"Invalid variable type for == operation. {ret1.Item1}."); } default: throw new SystemException($"Invalid Binary Operator ( {value} was received at node on integer operation )"); } }
public Token SelectNext() { //Console.WriteLine("next token"); Token ret = new Token(); string tokenizable = ""; while (true) { //If origin got to the end or comment starter (') detected //TODO rethink this!!! if (position >= origin.Length) { if (tokenizable.Length > 0) { God.Error("Unexpected EOF."); } ret.type = "EOF"; actual = ret; return(ret); } //end TODO if (discard == 0) { if (origin[position] == '/') { if (origin[++position] == '/') { discard = 1; } else if (origin[position] == '*') { discard = 2; } } else if (origin[position] == '\n') { God.line++; God.posDelta = position; } position++; continue; } if (pcomment) { if (origin[position] == ')') { pcomment = false; } position++; continue; } //is it starting a comment with () if (origin[position] == '(') { pcomment = true; position++; continue; } //C comment escaped? if (origin[position] == '\n') { if (discard == 1) { discard = 0; } God.line++; God.posDelta = position; position++; continue; } if (origin[position] == '*') { if (origin[++position] == '/') { if (discard == 2) { discard = 0; } else { God.Error("Unexpected token *."); } } continue; } //Handle sign case if ("(),.".Contains(origin[position])) { if (tokenizable.Length == 0) //token is a sign or simbol { switch (origin[position]) { case '(': ret.type = "POPEN"; break; case ')': ret.type = "PCLOSE"; break; case ',': ret.type = "COMMA"; break; case '.': ret.type = "PERIOD"; break; } position++; actual = ret; return(ret); } //token was a number or ident and ended in a sign (so the sign is not included and the token ended) if (ret.type == "IDENTIFIER") { //same as identifier ending in space string upToken = tokenizable.ToUpper(); if (reservedWords.Contains(upToken)) { ret.type = upToken; actual = ret; return(ret); } ret.type = "IDENTIFIER"; ret.value = tokenizable; actual = ret; return(ret); } else { int value; if (int.TryParse(tokenizable, out value)) { ret.type = "INT"; ret.value = value; actual = ret; return(actual); } else { God.Error("Unexpected not parseble integer found."); } } } //char is part of a number if (int.TryParse(origin[position].ToString(), out int dummy)) //not +|- and is a number; { tokenizable += origin[position]; position++; } //char is a letter (can be identifier, space or a invalid char token) else { if (origin[position] == ' ' || origin[position] == '\t') //is a space? { if (tokenizable.Length == 0) //ignore space { position++; } else //handle end of ident or number token //v2.1: Bug where a number is considered a identifier if there is a space after it. doublechecking it here { if (int.TryParse(tokenizable, out int value)) { ret.type = "INT"; ret.value = value; actual = ret; return(actual); } string upToken = tokenizable.ToUpper(); if (reservedWords.Contains(upToken)) { ret.type = upToken; actual = ret; return(ret); } //check if word is reserved ret.type = "IDENTIFIER"; ret.value = tokenizable; actual = ret; return(ret); } } else if (tokenizable.Length == 0) //start with letter or '_' { if (Char.IsLetter(origin[position]) || origin[position] == '_') { ret.type = "IDENTIFIER"; tokenizable += origin[position]; position++; } else { God.Error("Unexpected token found, identifiers should start with '_' or a letter."); } } else //token exist, found found chars after letter or '_' { if (ret.type == "IDENTIFIER") { tokenizable += origin[position]; position++; } else { God.Error("Unexpected token found, unknow char at position."); } } } /* (V1.1.1) (Changed to last two if statements. Now throws an error if invalid char to showcase comment feature better) * else { //if this branch runs, this char is not in my alphabet, so it will be ignored; * position++; * } */ } }