Пример #1
0
 bool whileCheck(SymbolTable symbolTable)
 {
     (string, object)ret = children[0].Evaluate(symbolTable);
     God.VerifyType("boolean", ret);
     return((bool)ret.Item2);
 }
Пример #2
0
        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 )");
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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 )");
            }
        }
Пример #5
0
        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++;
                 * }
                 */
            }
        }