Beispiel #1
0
        //var function functionCall ({function})() a=b
        public static JsExpression ParseProgram(List <Token> list)
        {
            JsExpression program = new JsExpression("", null);

            current = program;
            index   = 0;
            for (; index < list.Count; index++)
            {
                var item = list[index];
                switch (item.type)
                {
                case TokenType.VAR:
                    current = ParseVar(list);
                    program.child.Add(current);
                    break;

                case TokenType.FUNCTION:
                    current = ParseFunction(list);
                    program.child.Add(current);
                    break;

                case TokenType.OpenParenthese:
                    current = ParseLambdaCall(list);
                    program.child.Add(current);
                    break;

                case TokenType.IDENTIFY:
                    switch (list[index + 1].type)
                    {
                    case TokenType.BIND:        //=
                        current = ParseAssign(list);
                        break;

                    case TokenType.SemiColon: //identifier
                        current = ParseIdentify(list);
                        index++;              //match ;
                        break;

                    case TokenType.POINT:        //call method or get field or set field or add new field
                    {
                        bool needMatchSemiColon = false;
                        if (LookAhead(list, index, 3, TokenType.OpenParenthese) ||
                            LookAhead(list, index, 3, TokenType.SemiColon))               //if method call
                        {
                            needMatchSemiColon = true;
                        }
                        current = ParsePointExpression(list);
                        // method call and get field need match ;
                        // now only check method call
                        // field get should not appear
                        if (needMatchSemiColon)
                        {
                            index++;            //match ;
                        }
                    }
                    break;

                    case TokenType.EQ:
                    case TokenType.UNEQ:
                    case TokenType.LT:
                    case TokenType.GE:
                    case TokenType.LE:
                    case TokenType.GT:
                    case TokenType.AND:
                    case TokenType.OR:
                        current = ParseBool(list);
                        index++;        //match ;
                        break;

                    default:
                        //func call
                        current = ParseFunctionCall(list);
                        index++;        //match ;
                        break;
                    }
                    program.child.Add(current);
                    break;

                case TokenType.NUMBER:     // num | Math Exp | Bool Exp
                    if (isMathOperation(list[index + 1]))
                    {
                        current = ParseRelation(list);
                    }
                    else if (isBoolOperation(list[index + 1]))
                    {
                        current = ParseBool(list);
                    }
                    else
                    {
                        current = new JsExpression(list[index].name, program);
                    }
                    index++;    //match ;
                    program.child.Add(current);
                    break;

                case TokenType.STRING:
                    current = new JsExpression(item.name, current);
                    index++;    //match ;
                    program.child.Add(current);
                    break;

                default:
                    exceptions.Add(new Exception(current.value + " is an unknow expression"));
                    break;
                }
                current = program;
            }
            return(program);
        }
Beispiel #2
0
        //expList 内所有表达式都需要;
        //有的内部已经match了;
        //funcCall,PointExp没有match
        public static JsExpression ParseExpList(List <Token> list)
        {
            JsExpression expList = new JsExpression("{", current);

            current = expList;
            index++;
            while (list[index].type != TokenType.CloseBrace)
            {
                var item = list[index];
                switch (item.type)
                {
                case TokenType.VAR:    // already matched ;
                    expList.child.Add(ParseVar(list));
                    break;

                case TokenType.FUNCTION:    // already matched ;
                    expList.child.Add(ParseFunction(list));
                    break;

                case TokenType.OpenParenthese:
                    current = ParseLambdaCall(list);
                    expList.child.Add(current);
                    current = expList;
                    index++;    // match ;
                    break;

                case TokenType.IDENTIFY:

                    switch (list[index + 1].type)
                    {
                    case TokenType.BIND:        //=
                        // already matched ;
                        expList.child.Add(ParseAssign(list));
                        break;

                    case TokenType.POINT:        //a.b()| a.b=1 |a.b
                    {
                        bool isMethodCall = false;
                        if (LookAhead(list, index, 3, TokenType.OpenParenthese))            //if method call
                        {
                            isMethodCall = true;
                        }
                        expList.child.Add(ParsePointExpression(list));
                        // method call and get field need match ;
                        // now only check method call
                        // field get should not appear
                        if (isMethodCall)
                        {
                            index++;            //match ;
                        }
                    }
                    break;

                    default:
                        //func call
                        expList.child.Add(ParseFunctionCall(list));
                        index++;        //match ;
                        break;
                    }
                    break;

                case TokenType.IF:    // no need to macth ;
                    expList.child.Add(ParseIf(list));
                    break;

                case TokenType.WHILE:    // no need to macth ;
                    expList.child.Add(ParseWhile(list));
                    break;

                case TokenType.RETURN:    // already matched ;
                    expList.child.Add(ParseReturn(list));
                    break;

                default:
                    exceptions.Add(new Exception("undefine indentifier"));
                    break;
                }
                index++;//match }
            }
            current = expList.parent;
            return(expList);
        }
Beispiel #3
0
        //a=num|function|(|indentify|new identify
        public static JsExpression ParseAssign(List <Token> list)
        {
            JsExpression assignExp = new JsExpression("=", current);

            current = assignExp;
            assignExp.child.Add(ParseIdentify(list));
            index++;
            (list[index].type == TokenType.BIND).OrThrows("expected '='");
            index++;
            switch (list[index].type)
            {
            case TokenType.NUMBER:
                assignExp.child.Add(GetSingleOrMathExpressionItem(list));
                break;

            case TokenType.IDENTIFY:    //var|function call|a.b|bool
                switch (list[index + 1].type)
                {
                case TokenType.OpenParenthese:        //function call
                    assignExp.child.Add(ParseFunctionCall(list));
                    break;

                case TokenType.SemiColon:        //num or var
                    assignExp.child.Add(new JsExpression(list[index].name, current));
                    break;

                case TokenType.POINT:         //PointExp
                    assignExp.child.Add(ParsePointExpression(list));
                    break;

                case TokenType.ADD:        // Math Exp
                case TokenType.SUB:
                case TokenType.MUL:
                case TokenType.DIV:
                    assignExp.child.Add(ParseRelation(list));
                    break;

                case TokenType.AND:
                case TokenType.OR:
                case TokenType.EQ:
                case TokenType.UNEQ:
                case TokenType.LT:
                case TokenType.GE:
                case TokenType.LE:
                case TokenType.GT:        //Bool Exp
                    assignExp.child.Add(ParseBool(list));
                    break;
                }
                break;

            case TokenType.FUNCTION:
                assignExp.child.Add(ParseFunction(list));
                break;

            case TokenType.OpenParenthese:
                index++;    //pass ( ;annoymous function
                assignExp.child.Add(ParseFunction(list));
                break;

            case TokenType.NEW:
                assignExp.child.Add(ParseNewExpression(list));
                break;

            default:
                assignExp.child.Add(new JsExpression(list[index].name, assignExp));
                break;
            }
            index++;//match ;
            (list[index].type == TokenType.SemiColon).OrThrows("expected a semicolon");
            current = assignExp.parent;
            return(assignExp);
        }
Beispiel #4
0
 public JsFunction(string[] args, JsExpression body, Env env)
 {
     this.args = args;
     this.body = body;
     this.env  = env;
 }