Exemplo n.º 1
0
 public static void GenerateNodes(JSContext context, TextWriter textWriter, AstNodeList nodes)
 {
     foreach (AstNode node in nodes)
     {
         GenerateNode(context, textWriter, node);
     }
 }
Exemplo n.º 2
0
 public StatementListNode(NodeArgs args, AstNodeList statements)
     : base(args)
 {
     ChildNodes.Clear();
       foreach (AstNode stmt in statements)
     AddChild(null, stmt);
 }
Exemplo n.º 3
0
        //Node traversal
        public IEnumerable <AstNode> GetAll()
        {
            AstNodeList result = new AstNodeList();

            AddAll(result);
            return(result);
        }
Exemplo n.º 4
0
 static void RotateOpeator(BinaryExpression node, AstNodeList rightSide)
 {
     if (rightSide.Count == 0)
     {
         // the list is empty -- remove the node altogether
         node.Parent.ReplaceChild(node, null);
     }
     else if (rightSide.Count == 1)
     {
         // the list has only one item -- replace the node with the one item
         node.Parent.ReplaceChild(node, rightSide[0]);
     }
     else if (rightSide.Count == 2)
     {
         // there are only two items -- rotate the first to the left-hand side
         // and replace the right-hand side with the second item
         node.Operand1 = rightSide[0];
         node.Operand2 = rightSide[1];
     }
     else
     {
         // there will still be more than one left in the list after we peel off the
         // first one. rotate the first item to the left-hand side
         var temp = rightSide[0];
         rightSide.RemoveAt(0);
         node.Operand1 = temp;
     }
 }
        protected Procedure(AstNode definition)
        {
            if (definition.GetNodeType() == NodeType.Method)//Chapus medio alto. Mucho codigo copiado y pegado, deberia de existir alguno nodo que sea padre de MethodNode y FuncionNode para arreglar esto
            {
                ParamCount = ((MethodNode)definition).ParamList.Count;
                ParamNames = new string[ParamCount];
                var i = 0;
                foreach (var param in ((MethodNode)definition).ParamList)
                {
                    ParamNames[i] = ((IdentifierNode)param).Value;
                    i++;
                }
                Stmts = new AstNodeList(((MethodNode)definition).Stmts);
            }
            else if (definition.GetNodeType() == NodeType.Function)
            {
                ParamCount = ((FunctionNode)definition).ParamList.Count;
                ParamNames = new string[ParamCount];
                var i = 0;
                foreach (var param in ((FunctionNode)definition).ParamList)
                {
                    ParamNames[i] = ((IdentifierNode)param).Value;
                    i++;
                }
                Stmts = new AstNodeList(((FunctionNode)definition).Stmts);
            }
            else
            {
                throw new Exception("No se puede instanciar Function con un nodo tipo: " + (definition == null ? "null" : definition.GetNodeType().ToString()));
            }
            var name = ((IdentifierNode)definition.ChildNodes[0]).Value.ToLowerInvariant();

            Name = name;
        }
Exemplo n.º 6
0
        private static void RecurseParameters(AstNodeList parameterList, AstNode node)
        {
            if (node != null)
            {
                // if this is a comma operator, then we need to
                var binOp = node as BinaryOperator;
                if (binOp != null && binOp.OperatorToken == JSToken.Comma)
                {
                    // there are two or more parameters - recurse the list so we get them added left to right,
                    // converting each one to a binding object
                    RecurseParameters(parameterList, binOp.Operand1);

                    // comma operators can flatten lots of commas to an element on the left, and subsequent
                    // elements in a list on the right.
                    var rightList = binOp.Operand2 as AstNodeList;
                    if (rightList != null)
                    {
                        foreach (var listItem in rightList.Children)
                        {
                            parameterList.Append(ConvertToParameter(listItem, parameterList.Count));
                        }
                    }
                    else
                    {
                        // nope, just a single item
                        parameterList.Append(ConvertToParameter(binOp.Operand2, parameterList.Count));
                    }
                }
                else
                {
                    // nope; single operand to convert to a parameter
                    parameterList.Append(ConvertToParameter(node, 0));
                }
            }
        }
        private Expression GetExpressionFrom(AstNodeList astNodeList)
        {
            if (astNodeList.Count == 1)
            {
                return GetExpression((Token) astNodeList[0]);
            }

            Expression firstExpression, secondExpression;

            var operationToken = (Token) astNodeList[1].ChildNodes[0];

            if (astNodeList[0].ChildNodes != null && astNodeList[0].ChildNodes.Count != 1)
            {
                firstExpression = GetExpressionFrom(astNodeList[0].ChildNodes);
            }
            else
            {
                firstExpression = GetExpression(((Token) astNodeList[0].ChildNodes[0]));
                //firstExpression = Expression.Constant(decimal.Parse(((Token) astNodeList[0].ChildNodes[0]).Text),
                //                                      typeof (decimal?));
            }


            if (astNodeList[2].ChildNodes != null && astNodeList[2].ChildNodes.Count != 1)
            {
                secondExpression = GetExpressionFrom(astNodeList[2].ChildNodes);
            }
            else
            {
                secondExpression = GetExpression(((Token)astNodeList[2].ChildNodes[0]));
                //secondExpression = Expression.Constant(decimal.Parse(((Token) astNodeList[2].ChildNodes[0]).Text),
                //                                       typeof (decimal?));
            }
            return DoOperation(operationToken, firstExpression, secondExpression);
        }
Exemplo n.º 8
0
 public AstNodeArgs(BnfTerm term, CompilerContext context, SourceSpan span, AstNodeList childNodes)
 {
     Context = context;
       Term = term;
       Span = span;
       ChildNodes = childNodes;
 }
Exemplo n.º 9
0
 public AstNodeArgs(BnfTerm term, CompilerContext context, SourceSpan span, AstNodeList childNodes)
 {
     Context    = context;
     Term       = term;
     Span       = span;
     ChildNodes = childNodes;
 }
Exemplo n.º 10
0
 public static void GenerateNodes(JSContext context, TextWriter textWriter, AstNodeList nodes)
 {
     foreach (AstNode node in nodes)
     {
         GenerateNode(context, textWriter, node);
     }
 }
Exemplo n.º 11
0
 public virtual void Visit(AstNodeList node)
 {
     if (node != null)
     {
          AcceptChildren(node);
     }
 }
Exemplo n.º 12
0
        private Expression GetExpressionFrom(AstNodeList astNodeList)
        {
            if (astNodeList.Count == 1)
            {
                return(GetExpression((Token)astNodeList[0]));
            }

            Expression firstExpression, secondExpression;

            var operationToken = (Token)astNodeList[1].ChildNodes[0];

            if (astNodeList[0].ChildNodes != null && astNodeList[0].ChildNodes.Count != 1)
            {
                firstExpression = GetExpressionFrom(astNodeList[0].ChildNodes);
            }
            else
            {
                firstExpression = GetExpression(((Token)astNodeList[0].ChildNodes[0]));
                //firstExpression = Expression.Constant(decimal.Parse(((Token) astNodeList[0].ChildNodes[0]).Text),
                //                                      typeof (decimal?));
            }


            if (astNodeList[2].ChildNodes != null && astNodeList[2].ChildNodes.Count != 1)
            {
                secondExpression = GetExpressionFrom(astNodeList[2].ChildNodes);
            }
            else
            {
                secondExpression = GetExpression(((Token)astNodeList[2].ChildNodes[0]));
                //secondExpression = Expression.Constant(decimal.Parse(((Token) astNodeList[2].ChildNodes[0]).Text),
                //                                       typeof (decimal?));
            }
            return(DoOperation(operationToken, firstExpression, secondExpression));
        }
Exemplo n.º 13
0
        public void ResetForPrecompilation()
        {
            GraphNodeUID      = 0;
            CodeBlockIndex    = 0;
            RuntimeTableIndex = 0;

            //Initialize the dynamic string table and dynamic function table
            DynamicVariableTable = new DynamicVariableTable();
            DynamicFunctionTable = new DynamicFunctionTable();

            if (Options.SuppressBuildOutput)
            {
                //  don't log any of the build related messages
                //  just accumulate them in relevant containers with
                //  BuildStatus object
                //
                BuildStatus = new BuildStatus(this, false, false, false);
            }
            else
            {
                BuildStatus = new BuildStatus(this, Options.BuildOptWarningAsError);
            }

            if (AstNodeList != null)
            {
                AstNodeList.Clear();
            }

            ExpressionUID     = 0;
            ForLoopBlockIndex = Constants.kInvalidIndex;
        }
Exemplo n.º 14
0
 public void Visit(AstNodeList node)
 {
     if (node != null)
     {
         DoesRequire = true;
     }
 }
Exemplo n.º 15
0
 public AstNode()
 {
     ChildNodes = new AstNodeList();
     Evaluate   = DoEvaluate;
     SetValue   = DoSetValue;
     NodeType   = AstNodeType.Unknown;
 }
Exemplo n.º 16
0
 private void AddAll(AstNodeList list)
 {
     list.Add(this);
     foreach (AstNode child in this.ChildNodes)
     {
         child.AddAll(list);
     }
 }
Exemplo n.º 17
0
 public StatementListNode(NodeArgs args, AstNodeList statements) : base(args)
 {
     ChildNodes.Clear();
     foreach (AstNode stmt in statements)
     {
         AddChild(null, stmt);
     }
 }
Exemplo n.º 18
0
 public void ReplaceChildNodes(AstNodeList nodeList)
 {
     ChildNodes.Clear();
     foreach (AstNode node in nodeList)
     {
         AddChild(node);
     }
 }
        public static Expression CompileStatementList(AstNodeList childNode)
        {
            Expression lastExpressionNode = null;
            var block = new List<Expression>();

            //they all statement but, inside the statement held the tpe
            foreach (var statement in childNode)
            {
                 if (statement.ChildNodes[0] is VariableDeclarationNode)
                 {
                     //var xx; // var is ChildNodes[0] , xx  is ChildNodes[1]
                     var declaration = (VariableDeclarationNode)statement.ChildNodes[0];
                     VariableList.Add((ParameterExpression)declaration.GenerateExpression(statement.ChildNodes[0].ChildNodes[1]));
                }
                else if (statement.ChildNodes[0] is VariableAssignmentNode)
                {
                    //xx=2+3; // xx os a variable token , = is a symbol token , expression 
                    var assignment = (VariableAssignmentNode)statement.ChildNodes[0];
                    var expressionNode = (ExpressionNode) statement.ChildNodes[0].ChildNodes[2];
                    var variableToken = (Token)statement.ChildNodes[0].ChildNodes[0];
                    var expression1 = expressionNode.GenerateExpression(null);
                    var expression2 = VariableList.Get(variableToken.Text);

                    block.Add(assignment.GenerateExpression(new TwoExpressionsDto
                        {
                            Expression1 = expression1,
                            Expression2 = expression2
                        }));
                }
                else if (statement.ChildNodes[0] is ExpressionNode)
                {
                    var expressionNode = (ExpressionNode) statement.ChildNodes[0];
                    lastExpressionNode = expressionNode.GenerateExpression(null);
                }
                 else if (statement.ChildNodes[0] is IfStatementNode)
                 {
                     var expressionNode = (IfStatementNode)statement.ChildNodes[0];
                     block.Add(expressionNode.GenerateExpression(null));
                 }
                 else
                 {
                     Debug.WriteLine("Whaaaaaaaat how? it seems like you changed the grammer without changing the code");
                 }
            }

            if (lastExpressionNode != null)
            {
                block.Add(lastExpressionNode);
                return Expression.Block(block);
            }

            if (block.Any())
            {
                return Expression.Block(block);
            }
            return null;
        }
Exemplo n.º 20
0
 public FunctionCallNode(NodeArgs args, VarRefNode name, AstNodeList arguments) : base(args) {
   ChildNodes.Clear();
   NameRef = name;
   NameRef.Flags |= AstNodeFlags.SuppressNotDefined;
   AddChild("Name", NameRef);
   Arguments = arguments;
   foreach (AstNode arg in Arguments) 
     AddChild("Arg", arg);
 }//constructor
Exemplo n.º 21
0
        public static Expression CompileStatementList(AstNodeList childNode)
        {
            Expression lastExpressionNode = null;
            var        block = new List <Expression>();

            //they all statement but, inside the statement held the tpe
            foreach (var statement in childNode)
            {
                if (statement.ChildNodes[0] is VariableDeclarationNode)
                {
                    //var xx; // var is ChildNodes[0] , xx  is ChildNodes[1]
                    var declaration = (VariableDeclarationNode)statement.ChildNodes[0];
                    VariableList.Add((ParameterExpression)declaration.GenerateExpression(statement.ChildNodes[0].ChildNodes[1]));
                }
                else if (statement.ChildNodes[0] is VariableAssignmentNode)
                {
                    //xx=2+3; // xx os a variable token , = is a symbol token , expression
                    var assignment     = (VariableAssignmentNode)statement.ChildNodes[0];
                    var expressionNode = (ExpressionNode)statement.ChildNodes[0].ChildNodes[2];
                    var variableToken  = (Token)statement.ChildNodes[0].ChildNodes[0];
                    var expression1    = expressionNode.GenerateExpression(null);
                    var expression2    = VariableList.Get(variableToken.Text);

                    block.Add(assignment.GenerateExpression(new TwoExpressionsDto
                    {
                        Expression1 = expression1,
                        Expression2 = expression2
                    }));
                }
                else if (statement.ChildNodes[0] is ExpressionNode)
                {
                    var expressionNode = (ExpressionNode)statement.ChildNodes[0];
                    lastExpressionNode = expressionNode.GenerateExpression(null);
                }
                else if (statement.ChildNodes[0] is IfStatementNode)
                {
                    var expressionNode = (IfStatementNode)statement.ChildNodes[0];
                    block.Add(expressionNode.GenerateExpression(null));
                }
                else
                {
                    Debug.WriteLine("Whaaaaaaaat how? it seems like you changed the grammer without changing the code");
                }
            }

            if (lastExpressionNode != null)
            {
                block.Add(lastExpressionNode);
                return(Expression.Block(block));
            }

            if (block.Any())
            {
                return(Expression.Block(block));
            }
            return(null);
        }
Exemplo n.º 22
0
 public virtual void Visit(AstNodeList node)
 {
     if (node != null)
     {
         foreach (var childNode in node.Children)
         {
             childNode.Accept(this);
         }
     }
 }
Exemplo n.º 23
0
 public virtual void Visit(AstNodeList node)
 {
     if (node != null)
     {
         foreach (var childNode in node.Children)
         {
             childNode.Accept(this);
         }
     }
 }
Exemplo n.º 24
0
 public override void Visit(AstNodeList node)
 {
     if (node != null && node.Count > 0)
     {
         // this is really only ever not-ed when it's the right-hand operand
         // of a comma operator, which we flattened to decrease stack recursion.
         // so to logical-not this element, we only need to not the last item
         // in the list (because all the others are comma-separated)
         node[node.Count - 1].Accept(this);
     }
 }
Exemplo n.º 25
0
 public override void Visit(AstNodeList node)
 {
     if (node != null && node.Count > 0)
     {
         // this is really only ever not-ed when it's the right-hand operand
         // of a comma operator, which we flattened to decrease stack recursion.
         // so to logical-not this element, we only need to not the last item
         // in the list (because all the others are comma-separated)
         node[node.Count - 1].Accept(this);
     }
 }
Exemplo n.º 26
0
 public FunctionCallNode(NodeArgs args, VarRefNode name, AstNodeList arguments) : base(args)
 {
     ChildNodes.Clear();
     NameRef        = name;
     NameRef.Flags |= AstNodeFlags.SuppressNotDefined;
     AddChild("Name", NameRef);
     Arguments = arguments;
     foreach (AstNode arg in Arguments)
     {
         AddChild("Arg", arg);
     }
 }//constructor
Exemplo n.º 27
0
 public virtual AstNode FoldConstants()
 {
     var childrenCopy = new AstNodeList();
     foreach (var child in ChildNodes)
     {
         var nChild = (child as CompilableNode).FoldConstants();
         if (nChild != null) childrenCopy.Add(nChild);
     }
     ChildNodes.Clear();
     ChildNodes.AddRange(childrenCopy);
     return this;
 }
Exemplo n.º 28
0
        private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
        {
            IGrammarTerm nonTeminal = reduceAction.NonTerminal;
            AstNode      result;

            AstNodeArgs args = new AstNodeArgs(nonTeminal, sourceSpan, childNodes);

            Type ntNodeType = nonTeminal.NodeType ?? typeof(AstNode);

            bool isList = nonTeminal.IsSet(TermOptions.IsList);

            if (isList && childNodes.Count > 1 && childNodes[0].Term == nonTeminal)
            {
                result = childNodes[0];
                AstNode newChild = childNodes[childNodes.Count - 1];
                newChild.Parent = result;
                result.ChildNodes.Add(newChild);
                return(result);
            }

            if (nonTeminal.IsSet(TermOptions.IsStarList) && childNodes.Count == 1)
            {
                childNodes = childNodes[0].ChildNodes;
            }

            if (!isList && !nonTeminal.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1)
            {
                Type childNodeType = childNodes[0].Term.NodeType ?? typeof(AstNode);
                if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
                {
                    return(childNodes[0]);
                }
            }

            result = null;
            if (ntNodeType == typeof(AstNode))
            {
                result = new AstNode(args);
            }
            else
            {
                ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
                if (ctor == null)
                {
                    throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");
                }

                result = (AstNode)ctor.Invoke(new object[] { args });
            }

            return(result);
        }
Exemplo n.º 29
0
 public virtual void Visit(AstNodeList node)
 {
     if (node != null)
     {
         foreach (var element in node.Children)
         {
             if (element != null)
             {
                 element.Accept(this);
             }
         }
     }
 }
Exemplo n.º 30
0
 public CondFormNode(NodeArgs args, AstNodeList clauses, AstNode elseClause) : base(args) {
   ChildNodes.Clear();
   Clauses = clauses;
   foreach (AstNode clause in clauses) {
     clause.Role = "Arg";
     ChildNodes.Add(clause);
   }
   ElseClause = elseClause;
   if (ElseClause != null) {
     ElseClause.Role = "else";
     ChildNodes.Add(ElseClause);
   }
 }
Exemplo n.º 31
0
        private void ExecuteReduceAction(ActionRecord action)
        {
            ParserState oldState = _currentState;
            int         popCnt   = action.PopCount;

            //Get new node's child nodes - these are nodes being popped from the stack
            AstNodeList childNodes = new AstNodeList();

            for (int i = 0; i < action.PopCount; i++)
            {
                AstNode child = Stack[Stack.Count - popCnt + i].Node;
                if (!child.Term.IsSet(TermOptions.IsPunctuation))
                {
                    childNodes.Add(child);
                }
            }
            //recover state, location and pop the stack
            SourceSpan newNodeSpan;

            if (popCnt == 0)
            {
                newNodeSpan = new SourceSpan(_currentToken.Location, 0);
            }
            else
            {
                SourceLocation firstPopLoc   = Stack[Stack.Count - popCnt].Node.Location;
                int            lastPopEndPos = Stack[Stack.Count - 1].Node.Span.EndPos;
                newNodeSpan   = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
                _currentState = Stack[Stack.Count - popCnt].State;
                Stack.Pop(popCnt);
            }
            //Create new node
            AstNode node = CreateNode(action, newNodeSpan, childNodes);

            // Push node/current state into the stack
            Stack.Push(node, _currentState);
            //switch to new state
            ActionRecord gotoAction;

            if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction))
            {
                _currentState = gotoAction.NewState;
            }
            else
            {
                //should never happen
                throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
                                                          action.NonTerminal, oldState, _currentState));
            }
        }//method
Exemplo n.º 32
0
        private static bool NotJustPrimitives(AstNodeList nodeList)
        {
            // if any node in the list isn't a constant wrapper (boolean, number, string)
            // or a unary (presumably a negative number), then we've got something other than
            // a primitive in the list (array or object)
            foreach (var child in nodeList)
            {
                if (!(child is ConstantWrapper) && !(child is UnaryExpression))
                {
                    return(true);
                }
            }

            // if we get here, then everything is a primitive
            return(false);
        }
Exemplo n.º 33
0
 public CondFormNode(NodeArgs args, AstNodeList clauses, AstNode elseClause) : base(args)
 {
     ChildNodes.Clear();
     Clauses = clauses;
     foreach (AstNode clause in clauses)
     {
         clause.Role = "Arg";
         ChildNodes.Add(clause);
     }
     ElseClause = elseClause;
     if (ElseClause != null)
     {
         ElseClause.Role = "else";
         ChildNodes.Add(ElseClause);
     }
 }
Exemplo n.º 34
0
        public GlobalFunctionExpr(AstNodeArgs args)
            : base(args)
        {
            this.FunctionName = (Token)args.ChildNodes[0].DepthFirstTraversal().OfType <Token>().Single();
            AstNodeList funcArgs = args.ChildNodes[2].ChildNodes;

            this.InputParameter1 = (ExpressionNode)funcArgs[0];
            if (funcArgs.Count > 1)
            {
                this.InputParameter2 = (ExpressionNode)funcArgs[1];
            }
            if (funcArgs.Count > 2)
            {
                this.InputParameter3 = (ExpressionNode)funcArgs[2];
            }
        }
Exemplo n.º 35
0
        private void ExecuteReduceAction(ActionRecord action)
        {
            ParserState oldState = _currentState;
            int         popCnt   = action.PopCount;

            AstNodeList childNodes = new AstNodeList();

            for (int i = 0; i < action.PopCount; i++)
            {
                AstNode child = _stack[_stack.Count - popCnt + i].Node;
                if (!child.Term.IsSet(TermOptions.IsPunctuation))
                {
                    childNodes.Add(child);
                }
            }

            SourceSpan newNodeSpan;

            if (popCnt == 0)
            {
                newNodeSpan = new SourceSpan(_currentToken.Location, 0);
            }
            else
            {
                SourceLocation firstPopLoc   = _stack[_stack.Count - popCnt].Node.Location;
                int            lastPopEndPos = _stack[_stack.Count - 1].Node.Span.EndPos;
                newNodeSpan   = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
                _currentState = _stack[_stack.Count - popCnt].State;
                _stack.Pop(popCnt);
            }

            AstNode node = CreateNode(action, newNodeSpan, childNodes);

            _stack.Push(node, _currentState);

            ActionRecord gotoAction;

            if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction))
            {
                _currentState = gotoAction.NewState;
            }
            else
            {
                throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
                                                          action.NonTerminal, oldState, _currentState));
            }
        }
Exemplo n.º 36
0
        public static AstNodeList ToParameters(AstNode node)
        {
            AstNodeList parameterList = null;

            if (node != null)
            {
                parameterList = new AstNodeList(node.Context);

                // ignore any parentheses around the parameter(s)
                var groupingOperator = node as GroupingOperator;
                RecurseParameters(
                    parameterList,
                    groupingOperator != null ? groupingOperator.Operand : node);
            }

            return(parameterList);
        }
Exemplo n.º 37
0
        public virtual void Visit(AstNodeList node)
        {
            if (node != null)
            {
                var count = node.Count;

                for (var i = 0; i < count; i++)
                {
                    var element = node[i];

                    if (element != null)
                    {
                        element.Accept(this);
                    }
                }
            }
        }
Exemplo n.º 38
0
        public void Visit(AstNodeList node)
        {
            if (node != null)
            {
                for (var ndx = 0; ndx < node.Count; ++ndx)
                {
                    if (ndx > 0)
                    {
                        m_writer.Write(',');
                    }

                    if (node[ndx] != null)
                    {
                        node[ndx].Accept(this);
                    }
                }
            }
        }
Exemplo n.º 39
0
 public void Visit(AstNodeList node)
 {
     // add the names for each item in the list
     // this assumes that the items are name declarations!
     // (like parameter lists)
     if (node != null)
     {
         var count = node.Count;
         for (var i = 0; i < count; i++)
         {
             var itemNode = node[i];
             if (itemNode != null)
             {
                 itemNode.Accept(this);
             }
         }
     }
 }
Exemplo n.º 40
0
        public void Visit(AstNodeList node)
        {
            if (node != null)
            {
                for (var ndx = 0; ndx < node.Count; ++ndx)
                {
                    if (ndx > 0)
                    {
                        m_writer.Write(',');
                        if (m_settings.OutputMode == OutputMode.MultipleLines)
                        {
                            m_writer.Write(' ');
                        }
                    }

                    if (node[ndx] != null)
                    {
                        node[ndx].Accept(this);
                    }
                }
            }
        }
Exemplo n.º 41
0
 public ScriptExprList(AstNodeArgs args)
     : base(args)
 {
   exprList = (ChildNodes[0] is ScriptExpr) ? ChildNodes : ChildNodes[0].ChildNodes;
 }
Exemplo n.º 42
0
        private void ExecuteReduceAction(ActionRecord action)
        {
            ParserState oldState = _currentState;
              int popCnt = action.PopCount;

              //Get new node's child nodes - these are nodes being popped from the stack
              AstNodeList childNodes = new AstNodeList();
              for (int i = 0; i < action.PopCount; i++) {
            AstNode child = Stack[Stack.Count - popCnt + i].Node;
            if (!child.Term.IsSet(TermOptions.IsPunctuation))
              childNodes.Add(child);
              }
              //recover state, location and pop the stack
              SourceSpan newNodeSpan;
              if (popCnt == 0) {
            newNodeSpan = new SourceSpan(_currentToken.Location, 0);
              } else {
            SourceLocation firstPopLoc = Stack[Stack.Count - popCnt].Node.Location;
            int lastPopEndPos = Stack[Stack.Count - 1].Node.Span.EndPos;
            newNodeSpan = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
            _currentState = Stack[Stack.Count - popCnt].State;
            Stack.Pop(popCnt);
              }
              //Create new node
              AstNode node = CreateNode(action, newNodeSpan, childNodes);
              // Push node/current state into the stack
              Stack.Push(node, _currentState);
              //switch to new state
              ActionRecord gotoAction;
              if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction)) {
            _currentState = gotoAction.NewState;
              } else
            //should never happen
            throw new CompilerException( string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
              action.NonTerminal, oldState, _currentState));
        }
Exemplo n.º 43
0
        //---------------------------------------------------------------------------------------
        // MemberExpression
        //
        // Accessor :
        //  <empty> |
        //  Arguments Accessor
        //  '[' Expression ']' Accessor |
        //  '.' Identifier Accessor |
        //
        //  Don't have this function throwing an exception without checking all the calling sites.
        //  There is state in instance variable that is saved on the calling stack in some function
        //  (i.e ParseFunction and ParseClass) and you don't want to blow up the stack
        //---------------------------------------------------------------------------------------
        private AstNode MemberExpression(AstNode expression, List<Context> newContexts)
        {
            for (; ; )
            {
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_MemberExprNoSkipTokenSet);
                try
                {
                    switch (m_currentToken.Token)
                    {
                        case JSToken.LeftParenthesis:
                            AstNodeList args = null;
                            RecoveryTokenException callError = null;
                            m_noSkipTokenSet.Add(NoSkipTokenSet.s_ParenToken);
                            try
                            {
                                args = ParseExpressionList(JSToken.RightParenthesis);
                            }
                            catch (RecoveryTokenException exc)
                            {
                                args = (AstNodeList)exc._partiallyComputedNode;
                                if (IndexOfToken(NoSkipTokenSet.s_ParenToken, exc) == -1)
                                    callError = exc; // thrown later on
                            }
                            finally
                            {
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ParenToken);
                            }

                            expression = new CallNode(expression.Context.CombineWith(args.Context), this)
                                {
                                    Function = expression,
                                    Arguments = args,
                                    InBrackets = false
                                };

                            if (null != newContexts && newContexts.Count > 0)
                            {
                                (newContexts[newContexts.Count - 1]).UpdateWith(expression.Context);
                                if (!(expression is CallNode))
                                {
                                    expression = new CallNode(newContexts[newContexts.Count - 1], this)
                                        {
                                            Function = expression,
                                            Arguments = new AstNodeList(CurrentPositionContext(), this)
                                        };
                                }
                                else
                                {
                                    expression.Context = newContexts[newContexts.Count - 1];
                                }

                                ((CallNode)expression).IsConstructor = true;
                                newContexts.RemoveAt(newContexts.Count - 1);
                            }

                            if (callError != null)
                            {
                                callError._partiallyComputedNode = expression;
                                throw callError;
                            }

                            GetNextToken();
                            break;

                        case JSToken.LeftBracket:
                            m_noSkipTokenSet.Add(NoSkipTokenSet.s_BracketToken);
                            try
                            {
                                //
                                // ROTOR parses a[b,c] as a call to a, passing in the arguments b and c.
                                // the correct parse is a member lookup on a of c -- the "b,c" should be
                                // a single expression with a comma operator that evaluates b but only
                                // returns c.
                                // So we'll change the default behavior from parsing an expression list to
                                // parsing a single expression, but returning a single-item list (or an empty
                                // list if there is no expression) so the rest of the code will work.
                                //
                                //args = ParseExpressionList(JSToken.RightBracket);
                                GetNextToken();
                                args = new AstNodeList(CurrentPositionContext(), this);

                                AstNode accessor = ParseExpression();
                                if (accessor != null)
                                {
                                    args.Append(accessor);
                                }
                            }
                            catch (RecoveryTokenException exc)
                            {
                                if (IndexOfToken(NoSkipTokenSet.s_BracketToken, exc) == -1)
                                {
                                    if (exc._partiallyComputedNode != null)
                                    {
                                        exc._partiallyComputedNode =
                                           new CallNode(expression.Context.CombineWith(m_currentToken.Clone()), this)
                                            {
                                                Function = expression,
                                                Arguments = (AstNodeList)exc._partiallyComputedNode,
                                                InBrackets = true
                                            };
                                    }
                                    else
                                    {
                                        exc._partiallyComputedNode = expression;
                                    }
                                    throw;
                                }
                                else
                                    args = (AstNodeList)exc._partiallyComputedNode;
                            }
                            finally
                            {
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BracketToken);
                            }
                            expression = new CallNode(expression.Context.CombineWith(m_currentToken.Clone()), this)
                                {
                                    Function = expression,
                                    Arguments = args,
                                    InBrackets = true
                                };

                            // there originally was code here in the ROTOR sources that checked the new context list and
                            // changed this member call to a constructor call, effectively combining the two. I believe they
                            // need to remain separate.

                            // remove the close bracket token
                            GetNextToken();
                            break;

                        case JSToken.AccessField:
                            ConstantWrapper id = null;
                            Context nameContext = m_currentToken.Clone();
                            GetNextToken();
                            if (JSToken.Identifier != m_currentToken.Token)
                            {
                                string identifier = JSKeyword.CanBeIdentifier(m_currentToken.Token);
                                if (null != identifier)
                                {
                                    // don't report an error here -- it's actually okay to have a property name
                                    // that is a keyword which is okay to be an identifier. For instance,
                                    // jQuery has a commonly-used method named "get" to make an ajax request
                                    //ForceReportInfo(JSError.KeywordUsedAsIdentifier);
                                    id = new ConstantWrapper(identifier, PrimitiveType.String, m_currentToken.Clone(), this);
                                }
                                else if (JSScanner.IsValidIdentifier(m_currentToken.Code))
                                {
                                    // it must be a keyword, because it can't technically be an identifier,
                                    // but it IS a valid identifier format. Throw a warning but still
                                    // create the constant wrapper so we can output it as-is
                                    ReportError(JSError.KeywordUsedAsIdentifier, m_currentToken.Clone(), true);
                                    id = new ConstantWrapper(m_currentToken.Code, PrimitiveType.String, m_currentToken.Clone(), this);
                                }
                                else
                                {
                                    ReportError(JSError.NoIdentifier);
                                    SkipTokensAndThrow(expression);
                                }
                            }
                            else
                            {
                                id = new ConstantWrapper(m_scanner.Identifier, PrimitiveType.String, m_currentToken.Clone(), this);
                            }
                            GetNextToken();
                            expression = new Member(expression.Context.CombineWith(id.Context), this)
                                {
                                    Root = expression,
                                    Name = id.Context.Code,
                                    NameContext = nameContext.CombineWith(id.Context)
                                };
                            break;
                        default:
                            if (null != newContexts)
                            {
                                while (newContexts.Count > 0)
                                {
                                    (newContexts[newContexts.Count - 1]).UpdateWith(expression.Context);
                                    expression = new CallNode(newContexts[newContexts.Count - 1], this)
                                        {
                                            Function = expression,
                                            Arguments = new AstNodeList(CurrentPositionContext(), this)
                                        };
                                    ((CallNode)expression).IsConstructor = true;
                                    newContexts.RemoveAt(newContexts.Count - 1);
                                }
                            }
                            return expression;
                    }
                }
                catch (RecoveryTokenException exc)
                {
                    if (IndexOfToken(NoSkipTokenSet.s_MemberExprNoSkipTokenSet, exc) != -1)
                        expression = exc._partiallyComputedNode;
                    else
                    {
                        Debug.Assert(exc._partiallyComputedNode == expression);
                        throw;
                    }
                }
                finally
                {
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_MemberExprNoSkipTokenSet);
                }
            }
        }
Exemplo n.º 44
0
        private FunctionObject ParseFunction(FunctionType functionType, Context fncCtx)
        {
            Lookup name = null;
            AstNodeList formalParameters = null;
            Block body = null;
            bool inExpression = (functionType == FunctionType.Expression);
            Context paramsContext = null;

            GetNextToken();

            // get the function name or make an anonymous function if in expression "position"
            if (JSToken.Identifier == m_currentToken.Token)
            {
                name = new Lookup(m_currentToken.Clone(), this)
                    {
                        Name = m_scanner.Identifier
                    };
                GetNextToken();
            }
            else
            {
                string identifier = JSKeyword.CanBeIdentifier(m_currentToken.Token);
                if (null != identifier)
                {
                    name = new Lookup(m_currentToken.Clone(), this)
                        {
                            Name = identifier
                        };
                    GetNextToken();
                }
                else
                {
                    if (!inExpression)
                    {
                        // if this isn't a function expression, then we need to throw an error because
                        // function DECLARATIONS always need a valid identifier name
                        ReportError(JSError.NoIdentifier, m_currentToken.Clone(), true);

                        // BUT if the current token is a left paren, we don't want to use it as the name.
                        // (fix for issue #14152)
                        if (m_currentToken.Token != JSToken.LeftParenthesis
                            && m_currentToken.Token != JSToken.LeftCurly)
                        {
                            identifier = m_currentToken.Code;
                            name = new Lookup(CurrentPositionContext(), this)
                                {
                                    Name = identifier
                                };
                            GetNextToken();
                        }
                    }
                }
            }

            // make a new state and save the old one
            List<BlockType> blockType = m_blockType;
            m_blockType = new List<BlockType>(16);
            Dictionary<string, LabelInfo> labelTable = m_labelTable;
            m_labelTable = new Dictionary<string, LabelInfo>();

            try
            {
                // get the formal parameters
                if (JSToken.LeftParenthesis != m_currentToken.Token)
                {
                    // we expect a left paren at this point for standard cross-browser support.
                    // BUT -- some versions of IE allow an object property expression to be a function name, like window.onclick. 
                    // we still want to throw the error, because it syntax errors on most browsers, but we still want to
                    // be able to parse it and return the intended results. 
                    // Skip to the open paren and use whatever is in-between as the function name. Doesn't matter that it's 
                    // an invalid identifier; it won't be accessible as a valid field anyway.
                    bool expandedIndentifier = false;
                    while (m_currentToken.Token != JSToken.LeftParenthesis
                        && m_currentToken.Token != JSToken.LeftCurly
                        && m_currentToken.Token != JSToken.Semicolon
                        && m_currentToken.Token != JSToken.EndOfFile)
                    {
                        name.Context.UpdateWith(m_currentToken);
                        GetNextToken();
                        expandedIndentifier = true;
                    }

                    // if we actually expanded the identifier context, then we want to report that
                    // the function name needs to be an identifier. Otherwise we didn't expand the 
                    // name, so just report that we expected an open paren at this point.
                    if (expandedIndentifier)
                    {
                        name.Name = name.Context.Code;
                        name.Context.HandleError(JSError.FunctionNameMustBeIdentifier, false);
                    }
                    else
                    {
                        ReportError(JSError.NoLeftParenthesis, true);
                    }
                }

                if (m_currentToken.Token == JSToken.LeftParenthesis)
                {
                    // create the parameter list
                    formalParameters = new AstNodeList(m_currentToken.Clone(), this);
                    paramsContext = m_currentToken.Clone();

                    // skip the open paren
                    GetNextToken();

                    // create the list of arguments and update the context
                    while (JSToken.RightParenthesis != m_currentToken.Token)
                    {
                        String id = null;
                        m_noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet);
                        try
                        {
                            ParameterDeclaration paramDecl = null;
                            if (JSToken.Identifier != m_currentToken.Token && (id = JSKeyword.CanBeIdentifier(m_currentToken.Token)) == null)
                            {
                                if (JSToken.LeftCurly == m_currentToken.Token)
                                {
                                    ReportError(JSError.NoRightParenthesis);
                                    break;
                                }
                                else if (JSToken.Comma == m_currentToken.Token)
                                {
                                    // We're missing an argument (or previous argument was malformed and
                                    // we skipped to the comma.)  Keep trying to parse the argument list --
                                    // we will skip the comma below.
                                    ReportError(JSError.SyntaxError, true);
                                }
                                else
                                {
                                    ReportError(JSError.SyntaxError, true);
                                    SkipTokensAndThrow();
                                }
                            }
                            else
                            {
                                if (null == id)
                                {
                                    id = m_scanner.Identifier;
                                }

                                paramDecl = new ParameterDeclaration(m_currentToken.Clone(), this)
                                    {
                                        Name = id,
                                        Position = formalParameters.Count
                                    };
                                formalParameters.Append(paramDecl);
                                GetNextToken();
                            }

                            // got an arg, it should be either a ',' or ')'
                            if (JSToken.RightParenthesis == m_currentToken.Token)
                            {
                                break;
                            }
                            else if (JSToken.Comma == m_currentToken.Token)
                            {
                                // append the comma context as the terminator for the parameter
                                paramDecl.IfNotNull(p => p.TerminatingContext = m_currentToken.Clone());
                            }
                            else
                            {
                                // deal with error in some "intelligent" way
                                if (JSToken.LeftCurly == m_currentToken.Token)
                                {
                                    ReportError(JSError.NoRightParenthesis);
                                    break;
                                }
                                else
                                {
                                    if (JSToken.Identifier == m_currentToken.Token)
                                    {
                                        // it's possible that the guy was writing the type in C/C++ style (i.e. int x)
                                        ReportError(JSError.NoCommaOrTypeDefinitionError);
                                    }
                                    else
                                        ReportError(JSError.NoComma);
                                }
                            }

                            GetNextToken();
                        }
                        catch (RecoveryTokenException exc)
                        {
                            if (IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exc) == -1)
                                throw;
                        }
                        finally
                        {
                            m_noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet);
                        }
                    }

                    fncCtx.UpdateWith(m_currentToken);
                    GetNextToken();
                }

                // read the function body of non-abstract functions.
                if (JSToken.LeftCurly != m_currentToken.Token)
                    ReportError(JSError.NoLeftCurly, true);

                m_blockType.Add(BlockType.Block);
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                try
                {
                    // parse the block locally to get the exact end of function
                    body = new Block(m_currentToken.Clone(), this);
                    body.BraceOnNewLine = m_foundEndOfLine;
                    GetNextToken();

                    var possibleDirectivePrologue = true;
                    while (JSToken.RightCurly != m_currentToken.Token)
                    {
                        try
                        {
                            // function body's are SourceElements (Statements + FunctionDeclarations)
                            var statement = ParseStatement(true);
                            if (possibleDirectivePrologue)
                            {
                                var constantWrapper = statement as ConstantWrapper;
                                if (constantWrapper != null && constantWrapper.PrimitiveType == PrimitiveType.String)
                                {
                                    // if it's already a directive prologues, we're good to go
                                    if (!(constantWrapper is DirectivePrologue))
                                    {
                                        // make the statement a directive prologue instead of a constant wrapper
                                        statement = new DirectivePrologue(constantWrapper.Value.ToString(), constantWrapper.Context, constantWrapper.Parser)
                                            {
                                                MayHaveIssues = constantWrapper.MayHaveIssues
                                            };
                                    }
                                }
                                else if (!m_newModule)
                                {
                                    // no longer considering constant wrappers
                                    possibleDirectivePrologue = false;
                                }
                            }
                            else if (m_newModule)
                            {
                                // we scanned into a new module -- we might find directive prologues again
                                possibleDirectivePrologue = true;
                            }

                            // add it to the body
                            body.Append(statement);
                        }
                        catch (RecoveryTokenException exc)
                        {
                            if (exc._partiallyComputedNode != null)
                            {
                                body.Append(exc._partiallyComputedNode);
                            }
                            if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1)
                                throw;
                        }
                    }

                    // make sure any important comments before the closing brace are kept
                    if (m_importantComments.Count > 0
                        && m_settings.PreserveImportantComments
                        && m_settings.IsModificationAllowed(TreeModifications.PreserveImportantComments))
                    {
                        // we have important comments before the EOF. Add the comment(s) to the program.
                        foreach (var importantComment in m_importantComments)
                        {
                            body.Append(new ImportantComment(importantComment, this));
                        }

                        m_importantComments.Clear();
                    }

                    body.Context.UpdateWith(m_currentToken);
                    fncCtx.UpdateWith(m_currentToken);
                }
                catch (EndOfFileException)
                {
                    // if we get an EOF here, we never had a chance to find the closing curly-brace
                    fncCtx.HandleError(JSError.UnclosedFunction, true);
                }
                catch (RecoveryTokenException exc)
                {
                    if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1)
                    {
                        exc._partiallyComputedNode = new FunctionObject(fncCtx, this)
                            {
                                FunctionType = (inExpression ? FunctionType.Expression : FunctionType.Declaration),
                                IdContext = name.IfNotNull(n => n.Context),
                                Name = name.IfNotNull(n => n.Name),
                                ParameterDeclarations = formalParameters,
                                ParametersContext = paramsContext,
                                Body = body
                            };
                        throw;
                    }
                }
                finally
                {
                    m_blockType.RemoveAt(m_blockType.Count - 1);
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
                }

                GetNextToken();
            }
            finally
            {
                // restore state
                m_blockType = blockType;
                m_labelTable = labelTable;
            }

            return new FunctionObject(fncCtx, this)
                {
                    FunctionType = functionType,
                    IdContext = name.IfNotNull(n => n.Context),
                    Name = name.IfNotNull(n => n.Name),
                    ParameterDeclarations = formalParameters,
                    ParametersContext = paramsContext,
                    Body = body
                };
        }
Exemplo n.º 45
0
        private AstNode ParseSwitchStatement()
        {
            Context switchCtx = m_currentToken.Clone();
            AstNode expr = null;
            AstNodeList cases = null;
            var braceOnNewLine = false;
            Context braceContext = null;
            m_blockType.Add(BlockType.Switch);
            try
            {
                // read switch(expr)
                GetNextToken();
                if (JSToken.LeftParenthesis != m_currentToken.Token)
                    ReportError(JSError.NoLeftParenthesis);
                GetNextToken();
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                try
                {
                    expr = ParseExpression();

                    if (JSToken.RightParenthesis != m_currentToken.Token)
                    {
                        ReportError(JSError.NoRightParenthesis);
                    }

                    GetNextToken();
                    if (JSToken.LeftCurly != m_currentToken.Token)
                    {
                        ReportError(JSError.NoLeftCurly);
                    }

                    braceOnNewLine = m_foundEndOfLine;
                    braceContext = m_currentToken.Clone();
                    GetNextToken();

                }
                catch (RecoveryTokenException exc)
                {
                    if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1
                          && IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1)
                    {
                        // give up
                        exc._partiallyComputedNode = null;
                        throw;
                    }
                    else
                    {
                        if (exc._partiallyComputedNode == null)
                            expr = new ConstantWrapper(true, PrimitiveType.Boolean, CurrentPositionContext(), this);
                        else
                            expr = exc._partiallyComputedNode;

                        if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) != -1)
                        {
                            if (exc._token == JSToken.RightParenthesis)
                                GetNextToken();

                            if (JSToken.LeftCurly != m_currentToken.Token)
                            {
                                ReportError(JSError.NoLeftCurly);
                            }
                            braceOnNewLine = m_foundEndOfLine;
                            braceContext = m_currentToken.Clone();
                            GetNextToken();
                        }

                    }
                }
                finally
                {
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                }

                // parse the switch body
                cases = new AstNodeList(CurrentPositionContext(), this);
                bool defaultStatement = false;
                m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
                try
                {
                    while (JSToken.RightCurly != m_currentToken.Token)
                    {
                        SwitchCase caseClause = null;
                        AstNode caseValue = null;
                        var caseCtx = m_currentToken.Clone();
                        Context colonContext = null;
                        m_noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet);
                        try
                        {
                            if (JSToken.Case == m_currentToken.Token)
                            {
                                // get the case
                                GetNextToken();
                                caseValue = ParseExpression();
                            }
                            else if (JSToken.Default == m_currentToken.Token)
                            {
                                // get the default
                                if (defaultStatement)
                                {
                                    // we report an error but we still accept the default
                                    ReportError(JSError.DupDefault, true);
                                }
                                else
                                {
                                    defaultStatement = true;
                                }
                                GetNextToken();
                            }
                            else
                            {
                                // This is an error, there is no case or default. Assume a default was missing and keep going
                                defaultStatement = true;
                                ReportError(JSError.BadSwitch);
                            }

                            if (JSToken.Colon != m_currentToken.Token)
                            {
                                ReportError(JSError.NoColon);
                            }
                            else
                            {
                                colonContext = m_currentToken.Clone();
                            }

                            // read the statements inside the case or default
                            GetNextToken();
                        }
                        catch (RecoveryTokenException exc)
                        {
                            // right now we can only get here for the 'case' statement
                            if (IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exc) == -1)
                            {
                                // ignore the current case or default
                                exc._partiallyComputedNode = null;
                                throw;
                            }
                            else
                            {
                                caseValue = exc._partiallyComputedNode;

                                if (exc._token == JSToken.Colon)
                                {
                                    GetNextToken();
                                }
                            }
                        }
                        finally
                        {
                            m_noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet);
                        }

                        m_blockType.Add(BlockType.Block);
                        try
                        {
                            var statements = new Block(m_currentToken.Clone(), this);
                            m_noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                            m_noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                            try
                            {
                                while (JSToken.RightCurly != m_currentToken.Token && JSToken.Case != m_currentToken.Token && JSToken.Default != m_currentToken.Token)
                                {
                                    try
                                    {
                                        // parse a Statement, not a SourceElement
                                        statements.Append(ParseStatement(false));
                                    }
                                    catch (RecoveryTokenException exc)
                                    {
                                        if (exc._partiallyComputedNode != null)
                                        {
                                            statements.Append(exc._partiallyComputedNode);
                                            exc._partiallyComputedNode = null;
                                        }

                                        if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1)
                                        {
                                            throw;
                                        }
                                    }
                                }
                            }
                            catch (RecoveryTokenException exc)
                            {
                                if (IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1)
                                {
                                    caseClause = new SwitchCase(caseCtx, this)
                                        {
                                            CaseValue = caseValue,
                                            ColonContext = colonContext,
                                            Statements = statements
                                        };
                                    cases.Append(caseClause);
                                    throw;
                                }
                            }
                            finally
                            {
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                            }

                            caseCtx.UpdateWith(statements.Context);
                            caseClause = new SwitchCase(caseCtx, this)
                                {
                                    CaseValue = caseValue,
                                    ColonContext = colonContext,
                                    Statements = statements
                                };
                            cases.Append(caseClause);
                        }
                        finally
                        {
                            m_blockType.RemoveAt(m_blockType.Count - 1);
                        }
                    }
                }
                catch (RecoveryTokenException exc)
                {
                    if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1)
                    {
                        //save what you can a rethrow
                        switchCtx.UpdateWith(CurrentPositionContext());
                        exc._partiallyComputedNode = new Switch(switchCtx, this)
                            {
                                Expression = expr,
                                BraceContext = braceContext,
                                Cases = cases,
                                BraceOnNewLine = braceOnNewLine
                            };
                        throw;
                    }
                }
                finally
                {
                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
                }
                switchCtx.UpdateWith(m_currentToken);
                GetNextToken();
            }
            finally
            {
                m_blockType.RemoveAt(m_blockType.Count - 1);
            }

            return new Switch(switchCtx, this)
                {
                    Expression = expr,
                    BraceContext = braceContext,
                    Cases = cases,
                    BraceOnNewLine = braceOnNewLine
                };
        }
Exemplo n.º 46
0
        private AstNode ParseLeftHandSideExpression(bool isMinus)
        {
            AstNode ast = null;
            bool skipToken = true;
            List<Context> newContexts = null;

            TryItAgain:

            // new expression
            while (JSToken.New == m_currentToken.Token)
            {
                if (null == newContexts)
                    newContexts = new List<Context>(4);
                newContexts.Add(m_currentToken.Clone());
                GetNextToken();
            }
            JSToken token = m_currentToken.Token;
            switch (token)
            {
                // primary expression
                case JSToken.Identifier:
                    ast = new Lookup(m_currentToken.Clone(), this)
                        {
                            Name = m_scanner.Identifier
                        };
                    break;

                case JSToken.ConditionalCommentStart:
                    // skip past the start to the next token
                    GetNextToken();
                    if (m_currentToken.Token == JSToken.ConditionalCompilationVariable)
                    {
                        // we have /*@id
                        ast = new ConstantWrapperPP(m_currentToken.Clone(), this)
                            {
                                VarName = m_currentToken.Code,
                                ForceComments = true
                            };

                        GetNextToken();

                        if (m_currentToken.Token == JSToken.ConditionalCommentEnd)
                        {
                            // skip past the closing comment
                            GetNextToken();
                        }
                        else
                        {
                            // we ONLY support /*@id@*/ in expressions right now. If there's not
                            // a closing comment after the ID, then we don't support it.
                            // throw an error, skip to the end of the comment, then ignore it and start
                            // looking for the next token.
                            CCTooComplicated(null);
                            goto TryItAgain;
                        }
                    }
                    else if (m_currentToken.Token == JSToken.ConditionalCommentEnd)
                    {
                        // empty conditional comment! Ignore.
                        GetNextToken();
                        goto TryItAgain;
                    }
                    else
                    {
                        // we DON'T have "/*@IDENT". We only support "/*@IDENT @*/", so since this isn't
                        // and id, throw the error, skip to the end of the comment, and ignore it
                        // by looping back and looking for the NEXT token.
                        m_currentToken.HandleError(JSError.ConditionalCompilationTooComplex);

                        // skip to end of conditional comment
                        while (m_currentToken.Token != JSToken.EndOfFile && m_currentToken.Token != JSToken.ConditionalCommentEnd)
                        {
                            GetNextToken();
                        }
                        GetNextToken();
                        goto TryItAgain;
                    }
                    break;

                case JSToken.This:
                    ast = new ThisLiteral(m_currentToken.Clone(), this);
                    break;

                case JSToken.StringLiteral:
                    ast = new ConstantWrapper(m_scanner.StringLiteralValue, PrimitiveType.String, m_currentToken.Clone(), this)
                        {
                            MayHaveIssues = m_scanner.LiteralHasIssues
                        };
                    break;

                case JSToken.IntegerLiteral:
                case JSToken.NumericLiteral:
                    {
                        Context numericContext = m_currentToken.Clone();
                        double doubleValue;
                        if (ConvertNumericLiteralToDouble(m_currentToken.Code, (token == JSToken.IntegerLiteral), out doubleValue))
                        {
                            // conversion worked fine
                            // check for some boundary conditions
                            var mayHaveIssues = m_scanner.LiteralHasIssues;
                            if (doubleValue == double.MaxValue)
                            {
                                ReportError(JSError.NumericMaximum, numericContext, true);
                            }
                            else if (isMinus && -doubleValue == double.MinValue)
                            {
                                ReportError(JSError.NumericMinimum, numericContext, true);
                            }

                            // create the constant wrapper from the value
                            ast = new ConstantWrapper(doubleValue, PrimitiveType.Number, numericContext, this)
                                {
                                    MayHaveIssues = mayHaveIssues
                                };
                        }
                        else
                        {
                            // check to see if we went overflow
                            if (double.IsInfinity(doubleValue))
                            {
                                ReportError(JSError.NumericOverflow, numericContext, true);
                            }

                            // regardless, we're going to create a special constant wrapper
                            // that simply echos the input as-is
                            ast = new ConstantWrapper(m_currentToken.Code, PrimitiveType.Other, numericContext, this)
                            {
                                MayHaveIssues = true
                            };
                        }
                        break;
                    }

                case JSToken.True:
                    ast = new ConstantWrapper(true, PrimitiveType.Boolean, m_currentToken.Clone(), this);
                    break;

                case JSToken.False:
                    ast = new ConstantWrapper(false, PrimitiveType.Boolean, m_currentToken.Clone(), this);
                    break;

                case JSToken.Null:
                    ast = new ConstantWrapper(null, PrimitiveType.Null, m_currentToken.Clone(), this);
                    break;

                case JSToken.ConditionalCompilationVariable:
                    ast = new ConstantWrapperPP(m_currentToken.Clone(), this)
                        {
                            VarName = m_currentToken.Code,
                            ForceComments = false
                        };
                    break;

                case JSToken.DivideAssign:
                // normally this token is not allowed on the left-hand side of an expression.
                // BUT, this might be the start of a regular expression that begins with an equals sign!
                // we need to test to see if we can parse a regular expression, and if not, THEN
                // we can fail the parse.

                case JSToken.Divide:
                    // could it be a regexp?
                    String source = m_scanner.ScanRegExp();
                    if (source != null)
                    {
                        // parse the flags (if any)
                        String flags = m_scanner.ScanRegExpFlags();
                        // create the literal
                        ast = new RegExpLiteral(m_currentToken.Clone(), this)
                            {
                                Pattern = source,
                                PatternSwitches = flags
                            };
                        break;
                    }
                    goto default;

                // expression
                case JSToken.LeftParenthesis:
                    {
                        var groupingOp = new GroupingOperator(m_currentToken.Clone(), this);
                        ast = groupingOp;
                        GetNextToken();
                        m_noSkipTokenSet.Add(NoSkipTokenSet.s_ParenExpressionNoSkipToken);
                        try
                        {
                            // parse an expression
                            groupingOp.Operand = ParseExpression();
                            if (JSToken.RightParenthesis != m_currentToken.Token)
                            {
                                ReportError(JSError.NoRightParenthesis);
                            }
                            else
                            {
                                // add the closing paren to the expression context
                                ast.Context.UpdateWith(m_currentToken);
                            }
                        }
                        catch (RecoveryTokenException exc)
                        {
                            if (IndexOfToken(NoSkipTokenSet.s_ParenExpressionNoSkipToken, exc) == -1)
                                throw;
                            else
                                groupingOp.Operand = exc._partiallyComputedNode;
                        }
                        finally
                        {
                            m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ParenExpressionNoSkipToken);
                        }
                    }
                    break;

                // array initializer
                case JSToken.LeftBracket:
                    Context listCtx = m_currentToken.Clone();
                    GetNextToken();
                    AstNodeList list = new AstNodeList(CurrentPositionContext(), this);
                    while (JSToken.RightBracket != m_currentToken.Token)
                    {
                        if (JSToken.Comma != m_currentToken.Token)
                        {
                            m_noSkipTokenSet.Add(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet);
                            try
                            {
                                var expression = ParseExpression(true);
                                list.Append(expression);
                                if (JSToken.Comma != m_currentToken.Token)
                                {
                                    if (JSToken.RightBracket != m_currentToken.Token)
                                    {
                                        ReportError(JSError.NoRightBracket);
                                    }

                                    break;
                                }
                                else
                                {
                                    // we have a comma -- skip it after adding it as a terminator
                                    // on the previous expression
                                    expression.IfNotNull(e => e.TerminatingContext = m_currentToken.Clone());
                                    GetNextToken();

                                    // if the next token is the closing brackets, then we need to
                                    // add a missing value to the array because we end in a comma and
                                    // we need to keep it for cross-platform compat.
                                    // TECHNICALLY, that puts an extra item into the array for most modern browsers, but not ALL.
                                    if (m_currentToken.Token == JSToken.RightBracket)
                                    {
                                        list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this));
                                    }
                                }
                            }
                            catch (RecoveryTokenException exc)
                            {
                                if (exc._partiallyComputedNode != null)
                                    list.Append(exc._partiallyComputedNode);
                                if (IndexOfToken(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet, exc) == -1)
                                {
                                    listCtx.UpdateWith(CurrentPositionContext());
                                    exc._partiallyComputedNode = new ArrayLiteral(listCtx, this)
                                        {
                                            Elements = list
                                        };
                                    throw;
                                }
                                else
                                {
                                    if (JSToken.RightBracket == m_currentToken.Token)
                                        break;
                                }
                            }
                            finally
                            {
                                m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet);
                            }
                        }
                        else
                        {
                            // comma -- missing array item in the list
                            list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this)
                                {
                                    TerminatingContext = m_currentToken.Clone()
                                });

                            // skip over the comma
                            GetNextToken();

                            // if the next token is the closing brace, then we end with a comma -- and we need to
                            // add ANOTHER missing value to make sure this last comma doesn't get left off.
                            // TECHNICALLY, that puts an extra item into the array for most modern browsers, but not ALL.
                            if (m_currentToken.Token == JSToken.RightBracket)
                            {
                                list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this));
                            }
                        }
                    }
                    listCtx.UpdateWith(m_currentToken);
                    ast = new ArrayLiteral(listCtx, this)
                        {
                            Elements = list
                        };
                    break;

                // object initializer
                case JSToken.LeftCurly:
                    Context objCtx = m_currentToken.Clone();
                    GetNextToken();

                    var propertyList = new AstNodeList(CurrentPositionContext(), this);

                    if (JSToken.RightCurly != m_currentToken.Token)
                    {
                        for (; ; )
                        {
                            ObjectLiteralField field = null;
                            AstNode value = null;
                            bool getterSetter = false;
                            string ident;

                            switch (m_currentToken.Token)
                            {
                                case JSToken.Identifier:
                                    field = new ObjectLiteralField(m_scanner.Identifier, PrimitiveType.String, m_currentToken.Clone(), this);
                                    break;

                                case JSToken.StringLiteral:
                                    field = new ObjectLiteralField(m_scanner.StringLiteralValue, PrimitiveType.String, m_currentToken.Clone(), this)
                                        {
                                            MayHaveIssues = m_scanner.LiteralHasIssues
                                        };
                                    break;

                                case JSToken.IntegerLiteral:
                                case JSToken.NumericLiteral:
                                    {
                                        double doubleValue;
                                        if (ConvertNumericLiteralToDouble(m_currentToken.Code, (m_currentToken.Token == JSToken.IntegerLiteral), out doubleValue))
                                        {
                                            // conversion worked fine
                                            field = new ObjectLiteralField(
                                              doubleValue,
                                              PrimitiveType.Number,
                                              m_currentToken.Clone(),
                                              this
                                              );
                                        }
                                        else
                                        {
                                            // something went wrong and we're not sure the string representation in the source is 
                                            // going to convert to a numeric value well
                                            if (double.IsInfinity(doubleValue))
                                            {
                                                ReportError(JSError.NumericOverflow, m_currentToken.Clone(), true);
                                            }

                                            // use the source as the field name, not the numeric value
                                            field = new ObjectLiteralField(
                                                m_currentToken.Code,
                                                PrimitiveType.Other,
                                                m_currentToken.Clone(),
                                                this);
                                        }
                                        break;
                                    }

                                case JSToken.Get:
                                case JSToken.Set:
                                    if (PeekToken() == JSToken.Colon)
                                    {
                                        // the field is either "get" or "set" and isn't the special Mozilla getter/setter
                                        field = new ObjectLiteralField(m_currentToken.Code, PrimitiveType.String, m_currentToken.Clone(), this);
                                    }
                                    else
                                    {
                                        // ecma-script get/set property construct
                                        getterSetter = true;
                                        bool isGet = (m_currentToken.Token == JSToken.Get);
                                        value = ParseFunction(
                                          (JSToken.Get == m_currentToken.Token ? FunctionType.Getter : FunctionType.Setter),
                                          m_currentToken.Clone()
                                          );
                                        FunctionObject funcExpr = value as FunctionObject;
                                        if (funcExpr != null)
                                        {
                                            // getter/setter is just the literal name with a get/set flag
                                            field = new GetterSetter(
                                              funcExpr.Name,
                                              isGet,
                                              funcExpr.IdContext.Clone(),
                                              this
                                              );
                                        }
                                        else
                                        {
                                            ReportError(JSError.FunctionExpressionExpected);
                                        }
                                    }
                                    break;

                                default:
                                    // NOT: identifier token, string, number, or getter/setter.
                                    // see if it's a token that COULD be an identifierName.
                                    ident = m_scanner.Identifier;
                                    if (JSScanner.IsValidIdentifier(ident))
                                    {
                                        // BY THE SPEC, if it's a valid identifierName -- which includes reserved words -- then it's
                                        // okay for object literal syntax. However, reserved words here won't work in all browsers,
                                        // so if it is a reserved word, let's throw a low-sev cross-browser warning on the code.
                                        if (JSKeyword.CanBeIdentifier(m_currentToken.Token) == null)
                                        {
                                            ReportError(JSError.ObjectLiteralKeyword, m_currentToken.Clone(), true);
                                        }

                                        field = new ObjectLiteralField(ident, PrimitiveType.String, m_currentToken.Clone(), this);
                                    }
                                    else
                                    {
                                        // throw an error but use it anyway, since that's what the developer has going on
                                        ReportError(JSError.NoMemberIdentifier, m_currentToken.Clone(), true);
                                        field = new ObjectLiteralField(m_currentToken.Code, PrimitiveType.String, m_currentToken.Clone(), this);
                                    }
                                    break;
                            }

                            if (field != null)
                            {
                                if (!getterSetter)
                                {
                                    GetNextToken();
                                }

                                m_noSkipTokenSet.Add(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet);
                                try
                                {
                                    if (!getterSetter)
                                    {
                                        // get the value
                                        if (JSToken.Colon != m_currentToken.Token)
                                        {
                                            ReportError(JSError.NoColon, true);
                                            value = ParseExpression(true);
                                        }
                                        else
                                        {
                                            field.ColonContext = m_currentToken.Clone();
                                            GetNextToken();
                                            value = ParseExpression(true);
                                        }
                                    }

                                    // put the pair into the list of fields
                                    var propCtx = field.Context.Clone().CombineWith(value.IfNotNull(v => v.Context));
                                    var property = new ObjectLiteralProperty(propCtx, this)
                                        {
                                            Name = field,
                                            Value = value
                                        };

                                    propertyList.Append(property);

                                    if (JSToken.RightCurly == m_currentToken.Token)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        if (JSToken.Comma == m_currentToken.Token)
                                        {
                                            // skip the comma after adding it to the property as a terminating context
                                            property.IfNotNull(p => p.TerminatingContext = m_currentToken.Clone());
                                            GetNextToken();

                                            // if the next token is the right-curly brace, then we ended 
                                            // the list with a comma, which is perfectly fine
                                            if (m_currentToken.Token == JSToken.RightCurly)
                                            {
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            if (m_foundEndOfLine)
                                            {
                                                ReportError(JSError.NoRightCurly);
                                            }
                                            else
                                                ReportError(JSError.NoComma, true);
                                            SkipTokensAndThrow();
                                        }
                                    }
                                }
                                catch (RecoveryTokenException exc)
                                {
                                    if (exc._partiallyComputedNode != null)
                                    {
                                        // the problem was in ParseExpression trying to determine value
                                        value = exc._partiallyComputedNode;

                                        var propCtx = field.Context.Clone().CombineWith(value.IfNotNull(v => v.Context));
                                        var property = new ObjectLiteralProperty(propCtx, this)
                                        {
                                            Name = field,
                                            Value = value
                                        };

                                        propertyList.Append(property);
                                    }

                                    if (IndexOfToken(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet, exc) == -1)
                                    {
                                        exc._partiallyComputedNode = new ObjectLiteral(objCtx, this)
                                            {
                                                Properties = propertyList
                                            };
                                        throw;
                                    }
                                    else
                                    {
                                        if (JSToken.Comma == m_currentToken.Token)
                                            GetNextToken();
                                        if (JSToken.RightCurly == m_currentToken.Token)
                                            break;
                                    }
                                }
                                finally
                                {
                                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet);
                                }
                            }
                        }
                    }
                    objCtx.UpdateWith(m_currentToken);
                    ast = new ObjectLiteral(objCtx, this)
                        {
                            Properties = propertyList
                        };
                    break;

                // function expression
                case JSToken.Function:
                    ast = ParseFunction(FunctionType.Expression, m_currentToken.Clone());
                    skipToken = false;
                    break;

                case JSToken.AspNetBlock:
                    ast = new AspNetBlockNode(m_currentToken.Clone(), this)
                        {
                            AspNetBlockText = m_currentToken.Code
                        };
                    break;

                default:
                    string identifier = JSKeyword.CanBeIdentifier(m_currentToken.Token);
                    if (null != identifier)
                    {
                        ast = new Lookup(m_currentToken.Clone(), this)
                            {
                                Name = identifier
                            };
                    }
                    else
                    {
                        ReportError(JSError.ExpressionExpected);
                        SkipTokensAndThrow();
                    }
                    break;
            }

            // can be a CallExpression, that is, followed by '.' or '(' or '['
            if (skipToken)
                GetNextToken();

            return MemberExpression(ast, newContexts);
        }
Exemplo n.º 47
0
        //
        // expression elements we shouldn't get to
        //

        public void Visit(AstNodeList node)
        {
            Debug.Fail("shouldn't get here");
        }
Exemplo n.º 48
0
 public void Visit(AstNodeList node)
 {
     if (node != null)
     {
         // don't bother setting the order of the list itself, just the items
         for (var ndx = 0; ndx < node.Count; ++ndx)
         {
             var item = node[ndx];
             if (item != null)
             {
                 item.Accept(this);
             }
         }
     }
 }
 public void Visit(AstNodeList node)
 {
     // not applicable; terminate
 }
Exemplo n.º 50
0
    private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
    {
      IGrammarTerm nonTeminal = reduceAction.NonTerminal;
      AstNode result;

      AstNodeArgs args = new AstNodeArgs(nonTeminal, sourceSpan, childNodes);
 
      Type ntNodeType = nonTeminal.NodeType ?? typeof(AstNode);

      bool isList = nonTeminal.IsSet(TermOptions.IsList);
      if (isList && childNodes.Count > 1 && childNodes[0].Term == nonTeminal)
      {
        result = childNodes[0];
        AstNode newChild = childNodes[childNodes.Count - 1];
        newChild.Parent = result;
        result.ChildNodes.Add(newChild);
        return result;
      }

      if (nonTeminal.IsSet(TermOptions.IsStarList) && childNodes.Count == 1)
      {
        childNodes = childNodes[0].ChildNodes;
      }

      if (!isList && !nonTeminal.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1)
      {
        Type childNodeType = childNodes[0].Term.NodeType ?? typeof(AstNode);
        if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
          return childNodes[0];
      }

      result = null;
      if (ntNodeType == typeof(AstNode))
      {
        result = new AstNode(args);
      }
      else
      {
        ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
        if (ctor == null)
          throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");

        result = (AstNode)ctor.Invoke(new object[] { args });
      }

      return result;
    }
Exemplo n.º 51
0
        /// <summary>
        /// Parse the source code using the given settings, getting back an abstract syntax tree Block node as the root
        /// representing the list of statements in the source code.
        /// </summary>
        /// <param name="settings">code settings to use to process the source code</param>
        /// <returns>root Block node representing the top-level statements</returns>
        public Block Parse(CodeSettings settings)
        {
            // initialize the scanner with our settings
            // make sure the RawTokens setting is OFF or we won't be able to create our AST
            InitializeScanner(settings);

            // make sure we initialize the global scope's strict mode to our flag, whether or not it
            // is true. This means if the setting is false, we will RESET the flag to false if we are 
            // reusing the scope and a previous Parse call had code that set it to strict with a 
            // program directive. 
            GlobalScope.UseStrict = m_settings.StrictMode;

            // make sure the global scope knows about our known global names
            GlobalScope.SetAssumedGlobals(m_settings);

            // start of a new module
            m_newModule = true;

            Block scriptBlock;
            Block returnBlock;
            switch (m_settings.SourceMode)
            {
                case JavaScriptSourceMode.Program:
                    // simply parse a block of statements
                    returnBlock = scriptBlock = ParseStatements();
                    break;
                    
                case JavaScriptSourceMode.Expression:
                    // create a block, get the first token, add in the parse of a single expression, 
                    // and we'll go fron there.
                    returnBlock = scriptBlock = new Block(CurrentPositionContext(), this);
                    GetNextToken();
                    try
                    {
                        var expr = ParseExpression();
                        if (expr != null)
                        {
                            scriptBlock.Append(expr);
                            scriptBlock.UpdateWith(expr.Context);
                        }
                    }
                    catch (EndOfFileException)
                    {
                        Debug.WriteLine("EOF");
                    }
                    break;

                case JavaScriptSourceMode.EventHandler:
                    // we're going to create the global block, add in a function expression with a single
                    // parameter named "event", and then we're going to parse the input as the body of that
                    // function expression. We're going to resolve the global block, but only return the body
                    // of the function.
                    scriptBlock = new Block(null, this);

                    var parameters = new AstNodeList(null, this);
                    parameters.Append(new ParameterDeclaration(null, this)
                        {
                            Name = "event",
                            RenameNotAllowed = true
                        });

                    var funcExpression = new FunctionObject(null, this)
                        {
                            FunctionType = FunctionType.Expression, 
                            ParameterDeclarations = parameters
                        };
                    scriptBlock.Append(funcExpression);

                    returnBlock = ParseStatements();
                    funcExpression.Body = returnBlock;
                    break;

                default:
                    Debug.Fail("Unexpected source mode enumeration");
                    return null;
            }

            // resolve everything
            ResolutionVisitor.Apply(scriptBlock, GlobalScope, m_settings);

            if (scriptBlock != null && Settings.MinifyCode)
            {
                // this visitor doesn't just reorder scopes. It also combines the adjacent var variables,
                // unnests blocks, identifies prologue directives, and sets the strict mode on scopes. 
                ReorderScopeVisitor.Apply(scriptBlock, this);

                // analyze the entire node tree (needed for hypercrunch)
                // root to leaf (top down)
                var analyzeVisitor = new AnalyzeNodeVisitor(this);
                scriptBlock.Accept(analyzeVisitor);

                // analyze the scope chain (also needed for hypercrunch)
                // root to leaf (top down)
                m_globalScope.AnalyzeScope();

                // if we want to crunch any names....
                if (m_settings.LocalRenaming != LocalRenaming.KeepAll
                    && m_settings.IsModificationAllowed(TreeModifications.LocalRenaming))
                {
                    // then do a top-down traversal of the scope tree. For each field that had not
                    // already been crunched (globals and outers will already be crunched), crunch
                    // the name with a crunch iterator that does not use any names in the verboten set.
                    m_globalScope.AutoRenameFields();
                }

                // if we want to evaluate literal expressions, do so now
                if (m_settings.EvalLiteralExpressions)
                {
                    var visitor = new EvaluateLiteralVisitor(this);
                    scriptBlock.Accept(visitor);
                }

                // if any of the conditions we check for in the final pass are available, then
                // make the final pass
                if (m_settings.IsModificationAllowed(TreeModifications.BooleanLiteralsToNotOperators))
                {
                    var visitor = new FinalPassVisitor(this);
                    scriptBlock.Accept(visitor);
                }

                // we want to walk all the scopes to make sure that any generated
                // variables that haven't been crunched have been assigned valid
                // variable names that don't collide with any existing variables.
                m_globalScope.ValidateGeneratedNames();
            }

            if (returnBlock.Parent != null)
            {
                returnBlock.Parent = null;
            }

            return returnBlock;
        }
Exemplo n.º 52
0
        //
        // expression elements we shouldn't get to
        //

        public void Visit(AstNodeList node)
        {
            Debug.Fail("shouldn't get here");
        }
Exemplo n.º 53
0
 internal AstNodeArgs(IGrammarTerm term, SourceSpan span, AstNodeList childNodes)
 {
   Term = term;
   Span = span;
   ChildNodes = childNodes;
 }
Exemplo n.º 54
0
 // Override this method in language grammar if you want a custom node creation mechanism.
 public virtual AstNode CreateNode(CompilerContext context, ActionRecord reduceAction, 
                               SourceSpan sourceSpan, AstNodeList childNodes)
 {
     return null;
 }
Exemplo n.º 55
0
 public void Visit(AstNodeList node)
 {
     // not applicable; terminate
 }
Exemplo n.º 56
0
        //---------------------------------------------------------------------------------------
        // ParseExpressionList
        //
        //  Given a starting this.currentToken '(' or '[', parse a list of expression separated by
        //  ',' until matching ')' or ']'
        //---------------------------------------------------------------------------------------
        private AstNodeList ParseExpressionList(JSToken terminator)
        {
            Context listCtx = m_currentToken.Clone();
            GetNextToken();
            AstNodeList list = new AstNodeList(listCtx, this);
            if (terminator != m_currentToken.Token)
            {
                for (; ; )
                {
                    m_noSkipTokenSet.Add(NoSkipTokenSet.s_ExpressionListNoSkipTokenSet);
                    try
                    {
                        AstNode item;
                        if (JSToken.Comma == m_currentToken.Token)
                        {
                            item = new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this);
                            list.Append(item);
                        }
                        else if (terminator == m_currentToken.Token)
                        {
                            break;
                        }
                        else
                        {
                            item = ParseExpression(true);
                            list.Append(item);
                        }

                        if (terminator == m_currentToken.Token)
                        {
                            break;
                        }
                        else
                        {
                            if (JSToken.Comma == m_currentToken.Token)
                            {
                                item.IfNotNull(n => n.TerminatingContext = m_currentToken.Clone());
                            }
                            else
                            {
                                if (terminator == JSToken.RightParenthesis)
                                {
                                    //  in ASP+ it's easy to write a semicolon at the end of an expression
                                    //  not realizing it is going to go inside a function call
                                    //  (ie. Response.Write()), so make a special check here
                                    if (JSToken.Semicolon == m_currentToken.Token)
                                    {
                                        if (JSToken.RightParenthesis == PeekToken())
                                        {
                                            ReportError(JSError.UnexpectedSemicolon, true);
                                            GetNextToken();
                                            break;
                                        }
                                    }

                                    ReportError(JSError.NoRightParenthesisOrComma);
                                }
                                else
                                {
                                    ReportError(JSError.NoRightBracketOrComma);
                                }

                                SkipTokensAndThrow();
                            }
                        }
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (exc._partiallyComputedNode != null)
                            list.Append(exc._partiallyComputedNode);
                        if (IndexOfToken(NoSkipTokenSet.s_ExpressionListNoSkipTokenSet, exc) == -1)
                        {
                            exc._partiallyComputedNode = list;
                            throw;
                        }
                    }
                    finally
                    {
                        m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ExpressionListNoSkipTokenSet);
                    }
                    GetNextToken();
                }
            }
            listCtx.UpdateWith(m_currentToken);
            return list;
        }
Exemplo n.º 57
0
    }//method

    private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes) {
      NonTerminal nt = reduceAction.NonTerminal;
      AstNode result;
      NodeArgs nodeArgs = new NodeArgs(_context, nt, sourceSpan, childNodes);

      if (nt.NodeCreator != null) {
        result = nt.NodeCreator(nodeArgs);
        if (result != null)  return result;
      }

      Type defaultNodeType = _context.Compiler.Grammar.DefaultNodeType;
      Type ntNodeType = nt.NodeType ?? defaultNodeType ?? typeof(AstNode);

      // Check if NonTerminal is a list
      // List nodes are produced by .Plus() or .Star() methods of BnfElement
      // In this case, we have a left-recursive list formation production:   
      //     ntList -> ntList + delim? + ntElem
      //  We check if we have already created the list node for ntList (in the first child); 
      //  if yes, we use this child as a result directly, without creating new list node. 
      //  The other incoming child - the last one - is a new list member; 
      // we simply add it to child list of the result ntList node. Optional "delim" node is simply thrown away.
      bool isList = nt.IsSet(TermOptions.IsList);
      if (isList && childNodes.Count > 1 && childNodes[0].Term == nt) {
        result = childNodes[0];
        AstNode newChild = childNodes[childNodes.Count - 1];
        newChild.Parent = result; 
        result.ChildNodes.Add(newChild);
        return result;
      }
      //Check for StarList produced by MakeStarRule; in this case the production is:  ntList -> Empty | Elem+
      // where Elem+ is non-empty list of elements. The child list we are actually interested in is one-level lower
      if (nt.IsSet(TermOptions.IsStarList) && childNodes.Count == 1) {
        childNodes = childNodes[0].ChildNodes;
      }
      // Check for "node-bubbling" case. For identity productions like 
      //   A -> B
      // the child node B is usually a subclass of node A, 
      // so child node B can be used directly in place of the A. So we simply return child node as a result. 
      // TODO: probably need a grammar option to enable/disable this behavior explicitly
      bool canBubble = (Data.Grammar.FlagIsSet(LanguageFlags.BubbleNodes)) && 
        !isList && !nt.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1 && (childNodes[0].Term is NonTerminal);
      if (canBubble) {
        NonTerminal childNT = childNodes[0].Term as NonTerminal;
        Type childNodeType = childNT.NodeType ?? defaultNodeType ?? typeof(AstNode);
        if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
          return childNodes[0];
      }
      // Try using Grammar's CreateNode method
      result = Data.Grammar.CreateNode(_context, reduceAction, sourceSpan, childNodes);
      if (result != null) 
        return result; 

      //Finally create node directly. For perf reasons we try using "new" for AstNode type (faster), and
      // activator for all custom types (slower)
      if (ntNodeType == typeof(AstNode))
        return new AstNode(nodeArgs);

     // if (ntNodeType.GetConstructor(new Type[] {typeof(AstNodeList)}) != null) 
       // return (AstNode)Activator.CreateInstance(ntNodeType, childNodes);
      if (ntNodeType.GetConstructor(new Type[] {typeof(NodeArgs)}) != null) 
        return (AstNode) Activator.CreateInstance(ntNodeType, nodeArgs);
      //The following should never happen - we check that constructor exists when we validate grammar.
      string msg = string.Format(
@"AST Node class {0} does not have a constructor for automatic node creation. 
Provide a constructor with a single NodeArgs parameter, or use NodeCreator delegate property in NonTerminal.", ntNodeType);
      throw new GrammarErrorException(msg);
    }
Exemplo n.º 58
0
        private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
        {
            NonTerminal nt = reduceAction.NonTerminal;
              AstNode result;

              AstNodeArgs args = new AstNodeArgs(nt, _context, sourceSpan, childNodes);
              result = nt.InvokeNodeCreator(args);
              if (result != null) return result;

              Type defaultNodeType = _context.Compiler.Grammar.DefaultNodeType;
              Type ntNodeType = nt.NodeType ?? defaultNodeType ?? typeof(AstNode);

              // Check if NonTerminal is a list
              // List nodes are produced by .Plus() or .Star() methods of BnfElement
              // In this case, we have a left-recursive list formation production:
              //     ntList -> ntList + delim? + ntElem
              //  We check if we have already created the list node for ntList (in the first child);
              //  if yes, we use this child as a result directly, without creating new list node.
              //  The other incoming child - the last one - is a new list member;
              // we simply add it to child list of the result ntList node. Optional "delim" node is simply thrown away.
              bool isList = nt.IsSet(TermOptions.IsList);
              if (isList && childNodes.Count > 1 && childNodes[0].Term == nt) {
            result = childNodes[0];
            AstNode newChild = childNodes[childNodes.Count - 1];
            newChild.Parent = result;
            result.ChildNodes.Add(newChild);
            return result;
              }
              //Check for StarList produced by MakeStarList; in this case the production is:  ntList -> Empty | Elem+
              // where Elem+ is non-empty list of elements. The child list we are actually interested in is one-level lower
              if (nt.IsSet(TermOptions.IsStarList) && childNodes.Count == 1) {
            childNodes = childNodes[0].ChildNodes;
              }
              // Check for "node-bubbling" case. For identity productions like
              //   A -> B
              // the child node B is usually a subclass of node A,
              // so child node B can be used directly in place of the A. So we simply return child node as a result.
              // TODO: probably need a grammar option to enable/disable this behavior explicitly
              if (!isList && !nt.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1) {
            Type childNodeType = childNodes[0].Term.NodeType ?? defaultNodeType ?? typeof(AstNode);
            if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
              return childNodes[0];
              }
              // Try using Grammar's CreateNode method
              result = Data.Grammar.CreateNode(_context, reduceAction, sourceSpan, childNodes);
              if (result == null) {
            //Finally create node directly. For perf reasons we try using "new" for AstNode type (faster), and
            // activator for all custom types (slower)
            if (ntNodeType == typeof(AstNode))
              result = new AstNode(args);
            else
            #if PocketPC || SILVERLIGHT
            {
              ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
              if (ctor == null)
            throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");
              result = (AstNode)ctor.Invoke(new object[] { args });
            }
            #else
            {
              result = (AstNode)Activator.CreateInstance(ntNodeType, args);
            }
            #endif
              }
              if (result != null)
            nt.OnNodeCreated(result);
              return result;
        }
        //
        // IVisitor implementations
        //

        public override void Visit(AstNodeList node)
        {
            if (node != null)
            {
                var commaOperator = node.Parent as CommaOperator;
                AstNodeList list;
                if (commaOperator != null
                    && (list = commaOperator.Operand2 as AstNodeList) != null)
                {
                    // this list is part of a comma-operator, which is a collection of contiguous
                    // expression statements that we combined together. What we want to do is
                    // delete all constant elements from the list.
                    // if the parent is a block, then this was just a collection of statements and
                    // we can delete ALL constant expressions. But if the parent is not a block, then
                    // we will want to keep the last one as-is because it is the return value of the
                    // overall expression.
                    for (var ndx = list.Count - (node.Parent is Block ? 1 : 2); ndx >= 0; --ndx)
                    {
                        if (list[ndx] is ConstantWrapper)
                        {
                            list.RemoveAt(ndx);
                        }
                    }

                }

                // then normally recurse whatever is left over
                base.Visit(node);
            }
        }
Exemplo n.º 60
0
    private void ExecuteReduceAction(ActionRecord action)
    {
      ParserState oldState = _currentState;
      int popCnt = action.PopCount;

      AstNodeList childNodes = new AstNodeList();
      for (int i = 0; i < action.PopCount; i++)
      {
        AstNode child = _stack[_stack.Count - popCnt + i].Node;
        if (!child.Term.IsSet(TermOptions.IsPunctuation))
          childNodes.Add(child);
      }

      SourceSpan newNodeSpan;
      if (popCnt == 0)
      {
        newNodeSpan = new SourceSpan(_currentToken.Location, 0);
      }
      else
      {
        SourceLocation firstPopLoc = _stack[_stack.Count - popCnt].Node.Location;
        int lastPopEndPos = _stack[_stack.Count - 1].Node.Span.EndPos;
        newNodeSpan = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position);
        _currentState = _stack[_stack.Count - popCnt].State;
        _stack.Pop(popCnt);
      }
      
      AstNode node = CreateNode(action, newNodeSpan, childNodes);
      _stack.Push(node, _currentState);

      ActionRecord gotoAction;
      if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction))
      {
        _currentState = gotoAction.NewState;
      }
      else
        throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}",
              action.NonTerminal, oldState, _currentState));
    }