コード例 #1
0
        private EcmaStatment GetFor(EcmaTokenizer token)
        {
            token.Next().Excepect(TokenType.Punctor, "(");
            ExpresionData first = new ExpresionData(ExpresionType.Null);

            if (token.Next().IsNot(TokenType.Punctor, ";"))
            {
                if (token.Current().Is(TokenType.Keyword, "var"))
                {
                    token.Next();
                    first = VariableDeclarationList(token);
                }
                else
                {
                    first = Expresion(token);
                }
            }
            EcmaStatment current = null;

            if (token.Current().Is(TokenType.Keyword, "in"))
            {
                token.Next();
                current           = new EcmaStatment(EcmaStatmentType.ForIn);
                current.Expresion = first;
                current.Second    = Expresion(token);
            }
            else
            {
                token.Current().Excepect(TokenType.Punctor, ";");
                token.Next();
                current           = new EcmaStatment(EcmaStatmentType.For);
                current.Expresion = first;
                if (token.Current().IsNot(TokenType.Punctor, ";"))
                {
                    current.Second = Expresion(token);
                    token.Current().Excepect(TokenType.Punctor, ";");
                }
                else
                {
                    current.Second = new ExpresionData(ExpresionType.Null);
                }

                if (token.Next().IsNot(TokenType.Punctor, ")"))
                {
                    current.Tree = Expresion(token);
                }
                else
                {
                    current.Tree = new ExpresionData(ExpresionType.Null);
                }
            }

            token.Current().Excepect(TokenType.Punctor, ")");
            token.Next();
            current.Statment = GetStatment(token);
            return(current);
        }
コード例 #2
0
        private ExpresionData NewExpression(EcmaTokenizer token)
        {
            ExpresionData exp = new ExpresionData(ExpresionType.New);

            token.Next();
            exp.Left = PrimaryExpresion(token);
            token.Current().Excepect(TokenType.Punctor, "(");
            exp.Arg = Arguments(token);
            return(exp);
        }
コード例 #3
0
        private ExpresionData PrimaryExpresion(EcmaTokenizer token)
        {
            TokenBuffer buf = token.Current();

            token.Next();

            if (buf.Is(TokenType.Keyword, "this"))
            {
                return(new ExpresionData(ExpresionType.This));
            }

            if (buf.Is(TokenType.Number))
            {
                ExpresionData n = new ExpresionData(ExpresionType.Number);
                n.Sign = buf.Context;
                return(n);
            }

            if (buf.Is(TokenType.Null))
            {
                return(new ExpresionData(ExpresionType.Null));
            }

            if (buf.Is(TokenType.Bool))
            {
                ExpresionData b = new ExpresionData(ExpresionType.Bool);
                b.Sign = buf.Context;
                return(b);
            }

            if (buf.Is(TokenType.Identify))
            {
                ExpresionData identify = new ExpresionData(ExpresionType.Identify);
                identify.Name = buf.Context;
                return(identify);
            }

            if (buf.Is(TokenType.String))
            {
                ExpresionData str = new ExpresionData(ExpresionType.String);
                str.Sign = buf.Context;
                return(str);
            }

            if (buf.Is(TokenType.Punctor, "("))
            {
                ExpresionData p = Expresion(token);
                token.Current().Excepect(TokenType.Punctor, ")");
                token.Next();
                return(p);
            }

            throw new EcmaRuntimeException("Unknown token detected " + buf.Context + "(" + buf.Type.ToString() + ") on line " + buf.LineStart);
        }
コード例 #4
0
        private ExpresionData UnaryExpression(EcmaTokenizer token)
        {
            if (token.Current().Is(TokenType.Keyword, new string[] { "delete", "void", "typeof" }) || token.Current().Is(TokenType.Punctor, new string[] { "++", "--", "+", "-", "~", "!" }))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Unary);
                buf.Sign = token.Current().Context;
                token.Next();
                buf.Left = UnaryExpression(token);
                return(buf);
            }

            return(PostfixExpression(token));
        }
コード例 #5
0
        private ExpresionData PostfixExpression(EcmaTokenizer token)
        {
            ExpresionData exp = LeftHandSideExpression(token);

            if (token.Current().Is(TokenType.Punctor, new string[] { "--", "++" }))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Unary);
                buf.Sign = token.Current().Context;
                buf.Left = exp;
                token.Next();
                return(buf);
            }
            return(exp);
        }
コード例 #6
0
        private ExpresionData BitwiseANDExpression(EcmaTokenizer token)
        {
            ExpresionData exp = EqualityExpression(token);

            if (token.Current().Is(TokenType.Punctor, "&"))
            {
                token.Next();
                ExpresionData buf = new ExpresionData(ExpresionType.BAND);
                buf.Left  = exp;
                buf.Right = BitwiseANDExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #7
0
        private ExpresionData LogicalORExpression(EcmaTokenizer token)
        {
            ExpresionData exp = LogicalANDExpression(token);

            if (token.Current().Is(TokenType.Punctor, "||"))
            {
                token.Next();
                ExpresionData buf = new ExpresionData(ExpresionType.Or);
                buf.Left  = exp;
                buf.Right = LogicalORExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #8
0
        private ExpresionData MultiplicativeExpression(EcmaTokenizer token)
        {
            ExpresionData exp = UnaryExpression(token);

            if (token.Current().Is(TokenType.Punctor, new string[] { "*", "/", "%" }))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Multiplicative);
                buf.Sign = token.Current().Context;
                token.Next();
                buf.Left  = exp;
                buf.Right = MultiplicativeExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #9
0
        private ExpresionData RelationalExpression(EcmaTokenizer token)
        {
            ExpresionData exp = ShiftExpression(token);

            if (token.Current().Is(TokenType.Punctor, RelationalOperator))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Relational);
                buf.Left = exp;
                buf.Sign = token.Current().Context;
                token.Next();
                buf.Right = ShiftExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #10
0
        private ExpresionData EqualityExpression(EcmaTokenizer token)
        {
            ExpresionData exp = RelationalExpression(token);

            if (token.Current().Is(TokenType.Punctor, new string[] { "==", "!=" }))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Equlity);
                buf.Left = exp;
                buf.Sign = token.Current().Context;
                token.Next();
                buf.Right = RelationalExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #11
0
        private ExpresionData AssignmentExpression(EcmaTokenizer token)
        {
            ExpresionData exp = ConditionalExpression(token);

            if (token.Current().Is(TokenType.Punctor, AssignOperator))
            {
                ExpresionData buf = new ExpresionData(ExpresionType.Assign);
                buf.Left = exp;
                buf.Sign = token.Current().Context;
                token.Next();
                buf.Right = AssignmentExpression(token);
                return(buf);
            }

            return(exp);
        }
コード例 #12
0
        private ExpresionData VariableDeclarationList(EcmaTokenizer token)
        {
            List <ExpresionData> list = new List <ExpresionData>();
            ExpresionData        exp;

            token.Current().Excepect(TokenType.Identify);
            exp = new ExpresionData(ExpresionType.Assign);
            ExpresionData identify = new ExpresionData(ExpresionType.Identify);

            identify.Name = token.Current().Context;
            exp.Left      = identify;
            exp.Sign      = "=";
            if (token.Next().Is(TokenType.Punctor, "="))
            {
                token.Next();
                exp.Right = AssignmentExpression(token);
            }
            else
            {
                exp.Right = new ExpresionData(ExpresionType.Null);
            }
            list.Add(exp);
            while (token.Current().Is(TokenType.Punctor, ","))
            {
                exp = new ExpresionData(ExpresionType.Assign);
                token.Next().Excepect(TokenType.Identify);
                identify      = new ExpresionData(ExpresionType.Identify);
                identify.Name = token.Current().Context;
                exp.Left      = identify;
                exp.Sign      = "=";
                if (token.Next().Is(TokenType.Punctor, "="))
                {
                    token.Next();
                    exp.Right = AssignmentExpression(token);
                }
                else
                {
                    exp.Right = new ExpresionData(ExpresionType.Null);
                }
                list.Add(exp);
            }

            ExpresionData varList = new ExpresionData(ExpresionType.VarList);

            varList.Multi = list;
            return(varList);
        }
コード例 #13
0
        private ExpresionData ConditionalExpression(EcmaTokenizer token)
        {
            ExpresionData exp = LogicalORExpression(token);

            if (token.Current().Is(TokenType.Punctor, "?"))
            {
                token.Next();
                ExpresionData buf = new ExpresionData(ExpresionType.Conditional);
                buf.Test = exp;
                buf.Left = AssignmentExpression(token);
                token.Current().Excepect(TokenType.Punctor, ":");
                token.Next();
                buf.Right = AssignmentExpression(token);
                return(buf);
            }
            return(exp);
        }
コード例 #14
0
        private ExpresionData Expresion(EcmaTokenizer token)
        {
            ExpresionData expresion = AssignmentExpression(token);

            if (token.Current().Is(TokenType.Punctor, ","))
            {
                ExpresionData buffer = new ExpresionData(ExpresionType.MultiExpresion);
                buffer.Multi = new List <ExpresionData>();
                buffer.Multi.Add(expresion);
                while (token.Current().Is(TokenType.Punctor, ","))
                {
                    token.Next();
                    buffer.Multi.Add(AssignmentExpression(token));
                }
                return(buffer);
            }

            return(expresion);
        }
コード例 #15
0
        private ExpresionData LeftHandSideExpression(EcmaTokenizer token)
        {
            if (token.Current().Is(TokenType.Keyword, "new"))
            {
                return(NewExpression(token));
            }

            ExpresionData exp = PrimaryExpresion(token);
            ExpresionData buf = null;

            while (token.Current().Is(TokenType.Punctor, new string[] { ".", "(", "[" }))
            {
                switch (token.Current().Context)
                {
                case ".":
                    token.Next().Excepect(TokenType.Identify);
                    buf      = new ExpresionData(ExpresionType.ObjGet);
                    buf.Left = exp;
                    buf.Sign = token.Current().Context;
                    token.Next();
                    exp = buf;
                    break;

                case "[":
                    token.Next();
                    buf       = new ExpresionData(ExpresionType.ItemGet);
                    buf.Left  = exp;
                    buf.Right = Expresion(token);
                    token.Current().Excepect(TokenType.Punctor, "]");
                    token.Next();
                    break;

                case "(":
                    buf      = new ExpresionData(ExpresionType.Call);
                    buf.Left = exp;
                    buf.Arg  = Arguments(token);
                    break;
                }
                exp = buf;
            }
            return(exp);
        }
コード例 #16
0
        private static EcmaValue EvulateExpresion(EcmaState state, ExpresionData expresion)
        {
            EcmaValue      value = null;
            EcmaHeadObject obj;

            switch (expresion.Type)
            {
            case ExpresionType.MultiExpresion:
                for (int i = 0; i < expresion.Multi.Count; i++)
                {
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Multi[i]));
                }
                return(value);

            case ExpresionType.Assign:
                if (expresion.Sign == "=")
                {
                    EcmaValue ai = EvulateExpresion(state, expresion.Left);
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Right));
                    Reference.PutValue(ai, value, state.GlobalObject);
                    return(value);
                }
                else
                {
                    EcmaValue sa = EvulateExpresion(state, expresion.Left);
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Right));
                    value = EcmaMath.Math(state, Reference.GetValue(sa), expresion.Sign.Substring(0, 1), value);
                    Reference.PutValue(sa, value, state.GlobalObject);
                    return(value);
                }

            case ExpresionType.Conditional:
                return(Reference.GetValue(EvulateExpresion(state, expresion.Test)).ToBoolean(state) ? Reference.GetValue(EvulateExpresion(state, expresion.Left)) : Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.Or:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (value.ToBoolean(state))
                {
                    return(value);
                }
                return(Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.AND:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (!value.ToBoolean(state))
                {
                    return(value);
                }
                return(Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.BOR:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "|", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.XOR:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "^", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.BAND:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "&", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Equlity:
                bool er = EcmaEquel.IsEquel(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                return(EcmaValue.Boolean(expresion.Sign == "==" ? er : !er));

            case ExpresionType.Relational:
                if (expresion.Sign == "<")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                    if (value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(value);
                }
                else if (expresion.Sign == ">")
                {
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Right)), value);
                    if (value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(value);
                }
                else if (expresion.Sign == "<=")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Right)), Reference.GetValue(EvulateExpresion(state, expresion.Left)));
                    if (value.IsBoolean() && value.ToBoolean(state) || value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(EcmaValue.Boolean(true));
                }
                else if (expresion.Sign == ">=")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                    if (value.IsBoolean() && value.ToBoolean(state) || value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(EcmaValue.Boolean(true));
                }
                return(EcmaValue.Boolean(false));

            case ExpresionType.Shift:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Additive:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Multiplicative:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Unary:
                value = EvulateExpresion(state, expresion.Left);
                switch (expresion.Sign)
                {
                case "delete":
                    return(EcmaValue.Boolean(Reference.GetBase(value).Delete(Reference.GetPropertyName(value))));

                case "void":
                    Reference.GetValue(value);
                    return(EcmaValue.Undefined());

                case "typeof":
                    if (value.IsRefrence() && Reference.GetBase(value) == null)
                    {
                        return(EcmaValue.String("undefined"));
                    }

                    value = Reference.GetValue(value);

                    if (value.IsObject())
                    {
                        obj = value.ToObject(state);
                        if (obj is ICallable)
                        {
                            return(EcmaValue.String("function"));
                        }
                    }

                    return(EcmaValue.String(value.Type().ToString().ToLower()));

                case "++":
                    double ul = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToNumber(state);
                    Reference.PutValue(value, EcmaValue.Number(ul + 1), state.GlobalObject);
                    return(EcmaValue.Number(ul + 1));

                case "--":
                    double nul = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToNumber(state);
                    Reference.PutValue(value, EcmaValue.Number(nul + 1), state.GlobalObject);
                    return(EcmaValue.Number(nul + 1));

                case "+":
                    return(EcmaValue.Number(+Reference.GetValue(value).ToNumber(state)));

                case "-":
                    return(EcmaValue.Number(-Reference.GetValue(value).ToNumber(state)));

                case "~":
                    return(EcmaValue.Number(~Reference.GetValue(value).ToInt32(state)));

                case "!":
                    return(EcmaValue.Boolean(!Reference.GetValue(value).ToBoolean(state)));

                default:
                    throw new EcmaRuntimeException("Unary evulation out of sync. Unknown sign: " + expresion.Sign);
                }

            case ExpresionType.ItemGet:
                obj = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToObject(state);
                return(EcmaValue.Reference(new Reference(
                                               Reference.GetValue(EvulateExpresion(state, expresion.Right)).ToString(state),
                                               obj
                                               )));

            case ExpresionType.ObjGet:
                return(EcmaValue.Reference(new Reference(
                                               expresion.Sign,
                                               Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToObject(state)
                                               )));

            case ExpresionType.New:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (!value.IsObject())
                {
                    throw new EcmaRuntimeException("After 'new' keyword there must be a object");
                }
                obj = value.ToObject(state);

                if (!(obj is IConstruct))
                {
                    throw new EcmaRuntimeException("Object dont implements Constructor");
                }

                value = (obj as IConstruct).Construct(GetArguments(state, obj, expresion.Arg));

                if (!value.IsObject())
                {
                    throw new EcmaRuntimeException("The constructor dont return a object");
                }

                return(value);

            case ExpresionType.Call:
                EcmaValue func = EvulateExpresion(state, expresion.Left);
                value = Reference.GetValue(func);
                obj   = value.ToObject(state);
                if (!(obj is ICallable))
                {
                    throw new EcmaRuntimeException("The object dont implements Call");
                }

                EcmaHeadObject self;

                if (func.IsRefrence())
                {
                    self = Reference.GetBase(func);
                }
                else
                {
                    self = null;
                }

                return((obj as ICallable).Call(self, GetArguments(state, obj, expresion.Arg)));

            case ExpresionType.This:
                return(EcmaValue.Object(state.GetThis()));

            case ExpresionType.Identify:
                return(EcmaValue.Reference(state.GetIdentify(expresion.Name)));

            case ExpresionType.Number:
                return(EcmaValue.Number(Double.Parse(expresion.Sign)));

            case ExpresionType.Null:
                return(EcmaValue.Undefined());

            case ExpresionType.Bool:
                return(EcmaValue.Boolean(expresion.Sign == "true"));

            case ExpresionType.String:
                return(EcmaValue.String(expresion.Sign));

            case ExpresionType.VarList:
                for (int i = 0; i < expresion.Multi.Count; i++)
                {
                    value = EvulateExpresion(state, expresion.Multi[i]);
                }
                return(value);

            default:
                throw new EcmaRuntimeException("Evulator expresion out of sync. Unknown expresion type: " + expresion.Type);
            }
        }