コード例 #1
0
ファイル: CFGBuilder.cs プロジェクト: woods1060/verisol
 private void AppendControlFlow(ASTNode astNode)
 {
     astNode.Accept(this);
 }
コード例 #2
0
        /// <summary>
        /// Preprocess a string of text
        /// </summary>
        /// <param name="source">source</param>
        /// <returns>preprocessed source</returns>
        public string Process(string source)
        {
            //search for #* macro *#
            List <MacroDefinition> macros = new List <MacroDefinition>();

            using (StringReader sr = new StringReader(source))
            {
                bool isInMacro = false;
                int  pos       = 0;
                int  start     = 0;
                int  end       = 0;
                while (sr.Peek() != -1)
                {
                    char c = (char)sr.Read();
                    pos++;

                    if (c == '#' && sr.Peek() == '*')
                    {
                        start = pos;
                        if (isInMacro)
                        {
                            //throw error
                        }
                        sr.Read();
                        pos++;
                        isInMacro = true;
                    }
                    else if (c == '*' && sr.Peek() == '#')
                    {
                        if (!isInMacro)
                        {
                            //throw error
                        }
                        sr.Read();
                        pos++;
                        end       = pos;
                        isInMacro = false;

                        macros.Add(new MacroDefinition(start, end, source.Substring(start + 1, end - (start + 1) - 2).Trim()));
                    }
                }
            }

            //solve all macro and put it back
            string processedSource             = source;
            Dictionary <string, int> variables = new Dictionary <string, int>();
            Interpreter interpreter            = new Interpreter(variables);

            foreach (MacroDefinition macro in macros)
            {
                Lexer  lexer  = new Lexer(macro.Macro);
                Parser parser = new Parser(lexer);
                try
                {
                    ASTNode result = parser.Parse();
                    result.Accept(interpreter);
                    int output = interpreter.Output;
                    if (result is Assignment)
                    {
                        Assignment asgm = result as Assignment;

                        processedSource = processedSource.Replace(macro.Start - 1, macro.End - macro.Start + 1, "");
                    }
                    else
                    {
                        processedSource = processedSource.Replace(macro.Start - 1, macro.End - macro.Start + 1, output.ToString());
                    }
                }
                catch (Exception e)
                {
                    ErrorMessage = e.Message;
                    IsSuccess    = false;
                }
            }

            return(processedSource);
        }
コード例 #3
0
 public NodeMapper(ASTNode root)
 {
     this.root   = root;
     idToNodeMap = new Dictionary <int, ASTNode>();
     root.Accept(this);
 }
コード例 #4
0
ファイル: Interpreter.cs プロジェクト: Kahdeg-15520487/XSS
        private StackValue Evaluate(ASTNode Expression)
        {
            #region operation
            int IntegerOperation(StackValue operand1, StackValue operand2, TokenType op)
            {
                int i1 = (int)operand1.Value;
                int i2 = (int)operand2.Value;

                switch (op)
                {
                case TokenType.PLUS:
                    return(i1 + i2);

                case TokenType.MINUS:
                    return(i1 - i2);

                case TokenType.MULTIPLY:
                    return(i1 * i2);

                case TokenType.DIVIDE:
                    return(i1 / i2);

                case TokenType.MODULO:
                    return(i1 % i2);
                }

                return(0);
            }

            float FloatOperation(StackValue operand1, StackValue operand2, TokenType op)
            {
                float f1 = operand1.Value is float?(float)operand1.Value : (int)operand1.Value;
                float f2 = operand2.Value is float?(float)operand2.Value : (int)operand2.Value;

                switch (op)
                {
                case TokenType.PLUS:
                    return(f1 + f2);

                case TokenType.MINUS:
                    return(f1 - f2);

                case TokenType.MULTIPLY:
                    return(f1 * f2);

                case TokenType.DIVIDE:
                    return(f1 / f2);

                case TokenType.EXPONENT:
                    return((float)Math.Pow(f1, f2));
                }

                return(0);
            }

            string StringOperation(StackValue operand1, StackValue operand2, TokenType op)
            {
                string s1 = operand1.Value.ToString();
                string s2 = operand2.Value.ToString();

                if (op == TokenType.PLUS)
                {
                    return(s1 + s2);
                }

                return("");
            }

            bool BoolOperation(StackValue operand1, StackValue operand2, TokenType op)
            {
                bool b1 = (bool)operand1.Value;
                bool b2 = op == TokenType.NOT ? true : (bool)operand2.Value;

                switch (op)
                {
                case TokenType.AND:
                    return(b1 && b2);

                case TokenType.OR:
                    return(b1 || b2);

                case TokenType.XOR:
                    return(b1 ^ b2);

                case TokenType.NOT:
                    return(!b1);
                }

                return(false);
            }

            bool IntComparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                int i1 = (int)operand1.Value;
                int i2 = (int)operand2.Value;

                switch (op)
                {
                case TokenType.EQUAL:
                    return(i1 == i2);

                case TokenType.NOTEQUAL:
                    return(i1 != i2);

                case TokenType.LARGER:
                    return(i1 > i2);

                case TokenType.LARGEREQUAL:
                    return(i1 >= i2);

                case TokenType.LESSER:
                    return(i1 < i2);

                case TokenType.LESSEREQUAL:
                    return(i1 <= i2);
                }
                return(false);
            }

            bool FloatComparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                float f1 = (float)operand1.Value;
                float f2 = (float)operand2.Value;

                switch (op)
                {
                case TokenType.EQUAL:
                    return(f1 == f2);

                case TokenType.NOTEQUAL:
                    return(f1 != f2);

                case TokenType.LARGER:
                    return(f1 > f2);

                case TokenType.LARGEREQUAL:
                    return(f1 >= f2);

                case TokenType.LESSER:
                    return(f1 < f2);

                case TokenType.LESSEREQUAL:
                    return(f1 <= f2);
                }
                return(false);
            }

            bool CharComparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                char c1 = (char)operand1.Value;
                char c2 = (char)operand2.Value;

                switch (op)
                {
                case TokenType.EQUAL:
                    return(c1 == c2);

                case TokenType.NOTEQUAL:
                    return(c1 != c2);

                case TokenType.LARGER:
                    return(c1 > c2);

                case TokenType.LARGEREQUAL:
                    return(c1 >= c2);

                case TokenType.LESSER:
                    return(c1 < c2);

                case TokenType.LESSEREQUAL:
                    return(c1 <= c2);
                }
                return(false);
            }

            bool StringComparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                string s1         = (string)operand1.Value;
                string s2         = (string)operand2.Value;
                var    comparison = s1.CompareTo(s2);

                switch (op)
                {
                case TokenType.EQUAL:
                    return(s1.Equals(s2));

                case TokenType.NOTEQUAL:
                    return(!s1.Equals(s2));

                case TokenType.LARGER:
                    return(comparison > 0);

                case TokenType.LARGEREQUAL:
                    return(comparison >= 0);

                case TokenType.LESSER:
                    return(comparison < 0);

                case TokenType.LESSEREQUAL:
                    return(comparison <= 0);
                }
                return(false);
            }

            bool BoolComparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                bool b1 = (bool)operand1.Value;
                bool b2 = (bool)operand2.Value;

                switch (op)
                {
                case TokenType.EQUAL:
                    return(b1 == b2);

                case TokenType.NOTEQUAL:
                    return(b1 != b2);
                }
                return(false);
            }

            bool Comparison(StackValue operand1, StackValue operand2, TokenType op)
            {
                bool result = true;

                switch (operand1.Type)
                {
                case ValType.Integer:
                    int i1 = (int)operand1.Value;
                    if (operand2.Type == ValType.Float)
                    {
                        //do int comparison
                        int i2 = (int)(float)operand2.Value;
                        switch (op)
                        {
                        case TokenType.EQUAL:
                            result = i1 == i2;
                            break;

                        case TokenType.NOTEQUAL:
                            result = i1 != i2;
                            break;

                        case TokenType.LARGER:
                            result = i1 > i2;
                            break;

                        case TokenType.LARGEREQUAL:
                            result = i1 >= i2;
                            break;

                        case TokenType.LESSER:
                            result = i1 < i2;
                            break;

                        case TokenType.LESSEREQUAL:
                            result = i1 <= i2;
                            break;
                        }
                    }
                    else if (operand2.Type == ValType.Char)
                    {
                        //do int comparison
                        int i2 = (int)(char)operand2.Value;
                        switch (op)
                        {
                        case TokenType.EQUAL:
                            result = i1 == i2;
                            break;

                        case TokenType.NOTEQUAL:
                            result = i1 != i2;
                            break;

                        case TokenType.LARGER:
                            result = i1 > i2;
                            break;

                        case TokenType.LARGEREQUAL:
                            result = i1 >= i2;
                            break;

                        case TokenType.LESSER:
                            result = i1 < i2;
                            break;

                        case TokenType.LESSEREQUAL:
                            result = i1 <= i2;
                            break;
                        }
                    }
                    else
                    {
                        BinaryRuntimeError(operand1, operand2, op);
                    }
                    break;

                case ValType.Float:
                    float f1 = (float)operand1.Value;
                    if (operand2.Type == ValType.Integer)
                    {
                        //do flt math
                        float f2 = (float)(int)operand2.Value;
                        switch (op)
                        {
                        case TokenType.EQUAL:
                            result = f1 == f2;
                            break;

                        case TokenType.NOTEQUAL:
                            result = f1 != f2;
                            break;

                        case TokenType.LARGER:
                            result = f1 > f2;
                            break;

                        case TokenType.LARGEREQUAL:
                            result = f1 >= f2;
                            break;

                        case TokenType.LESSER:
                            result = f1 < f2;
                            break;

                        case TokenType.LESSEREQUAL:
                            result = f1 <= f2;
                            break;
                        }
                    }
                    else
                    {
                        BinaryRuntimeError(operand1, operand2, op);
                    }
                    break;

                case ValType.Char:
                    int c1 = (int)(char)operand1.Value;
                    if (operand2.Type == ValType.Integer)
                    {
                        //do int comparison
                        int c2 = (int)(char)operand2.Value;
                        switch (op)
                        {
                        case TokenType.EQUAL:
                            result = c1 == c2;
                            break;

                        case TokenType.NOTEQUAL:
                            result = c1 != c2;
                            break;

                        case TokenType.LARGER:
                            result = c1 > c2;
                            break;

                        case TokenType.LARGEREQUAL:
                            result = c1 >= c2;
                            break;

                        case TokenType.LESSER:
                            result = c1 < c2;
                            break;

                        case TokenType.LESSEREQUAL:
                            result = c1 <= c2;
                            break;
                        }
                    }
                    else
                    {
                        BinaryRuntimeError(operand1, operand2, op);
                    }
                    break;

                case ValType.Bool:
                    //cause there is no boolean comparison operator with mixed type
                    BinaryRuntimeError(operand1, operand2, op);
                    break;

                case ValType.String:
                    //cause there is no string comparison operator with mixed type
                    BinaryRuntimeError(operand1, operand2, op);
                    break;

                case ValType.Null:
                    BinaryRuntimeError(operand1, operand2, op);
                    break;
                }
                return(result);
            }

            bool TypeTesting(StackValue operand1, StackValue operand2, TokenType op)
            {
                ValType type = operand2.CastTo <ValType>();

                switch (op)
                {
                case TokenType.EQUAL:
                case TokenType.NOTEQUAL:
                    if (operand1.Type != ValType.Type)
                    {
                        return(false);
                    }
                    else
                    {
                        var type2 = operand1.CastTo <ValType>();
                        return(op == TokenType.EQUAL ? type == type2 : !(type == type2));
                    }

                case TokenType.IS:
                    // <value> is <Type>
                    return(operand1.Type == type);
                }

                return(false);
            }

            #endregion

            #region evaluate expression
            void EvaluateBinaryOperation(StackValue operand1, StackValue operand2, TokenType op)
            {
                var v1 = ResolveStackValue(operand1);
                var v2 = ResolveStackValue(operand2);

                if (v1.Type == v2.Type)
                {
                    switch (v1.Type)
                    {
                    case ValType.Integer:
                        switch (op)
                        {
                        case TokenType.PLUS:
                        case TokenType.MINUS:
                        case TokenType.MULTIPLY:
                        case TokenType.DIVIDE:
                        case TokenType.MODULO:
                            Push(IntegerOperation(v1, v2, op));
                            break;

                        case TokenType.EXPONENT:
                            Push(FloatOperation(v1, v2, TokenType.EXPONENT));
                            break;

                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                        case TokenType.LARGER:
                        case TokenType.LARGEREQUAL:
                        case TokenType.LESSER:
                        case TokenType.LESSEREQUAL:
                            Push(IntComparison(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.Float:
                        switch (op)
                        {
                        case TokenType.PLUS:
                        case TokenType.MINUS:
                        case TokenType.MULTIPLY:
                        case TokenType.DIVIDE:
                        case TokenType.EXPONENT:
                            Push(FloatOperation(v1, v2, op));
                            break;

                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                        case TokenType.LARGER:
                        case TokenType.LARGEREQUAL:
                        case TokenType.LESSER:
                        case TokenType.LESSEREQUAL:
                            Push(FloatComparison(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.Bool:
                        switch (op)
                        {
                        case TokenType.AND:
                        case TokenType.OR:
                        case TokenType.XOR:
                            Push(BoolOperation(v1, v2, op));
                            break;

                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                            Push(BoolComparison(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.Char:
                        //concat char
                        switch (op)
                        {
                        case TokenType.PLUS:
                            Push(StringOperation(v1, v2, TokenType.PLUS));
                            break;

                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                        case TokenType.LARGER:
                        case TokenType.LARGEREQUAL:
                        case TokenType.LESSER:
                        case TokenType.LESSEREQUAL:
                            Push(CharComparison(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.String:
                        //concat string
                        switch (op)
                        {
                        case TokenType.PLUS:
                            Push(StringOperation(v1, v2, TokenType.PLUS));
                            break;

                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                        case TokenType.LARGER:
                        case TokenType.LARGEREQUAL:
                        case TokenType.LESSER:
                        case TokenType.LESSEREQUAL:
                            Push(StringComparison(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.Null:
                        BinaryRuntimeError(v1, v2, op);
                        break;

                    case ValType.Type:
                        switch (op)
                        {
                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                            Push(TypeTesting(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    default:
                        switch (op)
                        {
                        case TokenType.IS:
                            Push(TypeTesting(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;
                    }
                }
                else
                {
                    switch (v1.Type)
                    {
                    case ValType.Integer:
                        if (v2.Type == ValType.Float)
                        {
                            //do flt math
                            switch (op)
                            {
                            case TokenType.PLUS:
                            case TokenType.MINUS:
                            case TokenType.MULTIPLY:
                            case TokenType.DIVIDE:
                            case TokenType.EXPONENT:
                                Push(FloatOperation(v1, v2, op));
                                break;

                            case TokenType.EQUAL:
                            case TokenType.NOTEQUAL:
                            case TokenType.LARGER:
                            case TokenType.LARGEREQUAL:
                            case TokenType.LESSER:
                            case TokenType.LESSEREQUAL:
                                Push(Comparison(v1, v2, op));
                                break;
                            }
                        }
                        else if (v2.Type == ValType.Char)
                        {
                            //do int math
                            switch (op)
                            {
                            case TokenType.PLUS:
                            case TokenType.MINUS:
                            case TokenType.MULTIPLY:
                            case TokenType.DIVIDE:
                                Push(IntegerOperation(v1, v2, op));
                                break;

                            case TokenType.EXPONENT:
                                Push(FloatOperation(v1, v2, TokenType.EXPONENT));
                                break;

                            case TokenType.EQUAL:
                            case TokenType.NOTEQUAL:
                            case TokenType.LARGER:
                            case TokenType.LARGEREQUAL:
                            case TokenType.LESSER:
                            case TokenType.LESSEREQUAL:
                                Push(Comparison(v1, v2, op));
                                break;
                            }
                        }
                        else if (op == TokenType.IS)
                        {
                            Push(TypeTesting(v1, v2, op));
                        }
                        else
                        {
                            BinaryRuntimeError(v1, v2, op);
                        }
                        break;

                    case ValType.Float:
                        if (v2.Type == ValType.Integer)
                        {
                            //do flt math
                            switch (op)
                            {
                            case TokenType.PLUS:
                            case TokenType.MINUS:
                            case TokenType.MULTIPLY:
                            case TokenType.DIVIDE:
                            case TokenType.EXPONENT:
                                Push(FloatOperation(v1, v2, op));
                                break;

                            case TokenType.EQUAL:
                            case TokenType.NOTEQUAL:
                            case TokenType.LARGER:
                            case TokenType.LARGEREQUAL:
                            case TokenType.LESSER:
                            case TokenType.LESSEREQUAL:
                                Push(Comparison(v1, v2, op));
                                break;
                            }
                        }
                        else if (op == TokenType.IS)
                        {
                            Push(TypeTesting(v1, v2, op));
                        }
                        else
                        {
                            BinaryRuntimeError(v1, v2, op);
                        }
                        break;

                    case ValType.Char:
                        switch (op)
                        {
                        case TokenType.EQUAL:
                        case TokenType.NOTEQUAL:
                        case TokenType.LARGER:
                        case TokenType.LARGEREQUAL:
                        case TokenType.LESSER:
                        case TokenType.LESSEREQUAL:
                            Push(Comparison(v1, v2, op));
                            break;

                        case TokenType.IS:
                            Push(TypeTesting(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;

                    case ValType.Bool:
                        if (op == TokenType.IS)
                        {
                            Push(TypeTesting(v1, v2, op));
                        }
                        else
                        {
                            BinaryRuntimeError(v1, v2, op);
                        }
                        break;

                    case ValType.String:
                        //concat string
                        if (op == TokenType.PLUS)
                        {
                            Push(StringOperation(v1, v2, TokenType.PLUS));
                        }
                        else if (op == TokenType.IS)
                        {
                            Push(TypeTesting(v1, v2, op));
                        }
                        else if (op == TokenType.IS)
                        {
                            Push(TypeTesting(v1, v2, op));
                        }
                        else
                        {
                            BinaryRuntimeError(v1, v2, op);
                        }
                        break;

                    default:
                        switch (op)
                        {
                        case TokenType.IS:
                            Push(TypeTesting(v1, v2, op));
                            break;

                        default:
                            BinaryRuntimeError(v1, v2, op);
                            break;
                        }
                        break;
                    }
                }
            }

            void EvaluateUnaryOperation(StackValue operand, TokenType op)
            {
                var v = ResolveStackValue(operand);

                switch (op)
                {
                case TokenType.MINUS:
                    if (v.Type == ValType.Integer)
                    {
                        int i = v.CastTo <int>();
                        Push(-i);
                    }
                    else if (v.Type == ValType.Float)
                    {
                        float f = v.CastTo <float>();
                        Push(-f);
                    }
                    else
                    {
                        UnaryRuntimeError(operand, op);
                    }
                    break;

                case TokenType.NOT:
                    if (v.Type == ValType.Bool)
                    {
                        bool b = v.CastTo <bool>();
                        Push(!b);
                    }
                    break;

                case TokenType.TYPEOF:
                    Push(v.Type);
                    break;
                }
            }

            #endregion

            #region visit the astnode
            Expression.Accept(this);
            #endregion

            #region process operand
            if (EvaluationStack.Count == 0)
            {
                return(StackValue.Null);
            }

            ReverseStack();
            while (EvaluationStack.Count > 1)
            {
                StackValue operand1 = EvaluationStack.Pop();
                StackValue operand2 = EvaluationStack.Pop();
                TokenType  op;
                if (operand2.Type == ValType.Operator)
                {
                    //unary opearation
                    op = (TokenType)operand2.Value;
                    EvaluateUnaryOperation(operand1, op);
                }
                else
                {
                    var tots = EvaluationStack.Pop();
                    op = (TokenType)tots.Value;

                    if (op == TokenType.ASSIGN)
                    {
                        //do assignment
                        //todo check type
                        var varname = (string)operand2.Value;
                        if (!CurrentScope.Contain(varname))
                        {
                            RuntimeError($"{varname} is not defined");
                        }
                        CurrentScope.Assign(varname, ResolveStackValue(operand1).Value);
                        Push(ResolveStackValue(operand2));
                    }
                    else if (op == TokenType.VAR)
                    {
                        //declare a variable in the environment
                        var varname = operand2.CastTo <string>();
                        if (CurrentScope.Contain(varname))
                        {
                            RuntimeError($"{varname} already defined");
                        }
                        CurrentScope.Define(varname, ResolveStackValue(operand1).Value);
                        Push(ResolveStackValue(operand2));
                    }
                    else
                    {
                        EvaluateBinaryOperation(operand1, operand2, op);
                    }
                }
            }

            return(ResolveStackValue(EvaluationStack.Pop()));

            #endregion
        }