コード例 #1
0
        }                                    // set during AST construction

        #region implemented abstract members of Node

        /// <summary>
        /// Resolve type defined by this typeExpression. Type Expression must be given in reversed order.
        /// </summary>
        /// <returns>The resolved type.</returns>
        /// <param name="typeExpr">Enumerator of reversed type expresion enumeration.</param>
        public static TypeNode RecursiveResolveArrayType <TSymbol>(IEnumerator <IParseTree <TSymbol> > typeExpr) where TSymbol : ISymbol <TSymbol>
        {
            bool isMutable = ASTBuilder.EatSymbol("mutable", typeExpr);

            if (ASTBuilder.EatSymbol("]", typeExpr))   // if ] is present then create ArrayType
            {
                var resType = new ArrayTypeNode();
                resType.IsConstant  = !isMutable;
                resType.IsFixedSize = false;             // we initialize all arrays as dynamic size
                if (ASTBuilder.EatSymbol("[", typeExpr)) // opening bracket, no length expression
                {
                    resType.LengthExpression = null;
                }
                else     // length expression present
                {
                    resType.LengthExpression = ExpressionNode.GetExpressionNode(typeExpr.Current);
                    typeExpr.MoveNext();
                    Debug.Assert(ASTBuilder.EatSymbol("[", typeExpr)); // eat opening bracket
                }
                resType.ElementType = RecursiveResolveArrayType(typeExpr);
                return(resType);
            }
            else
            {
                var resType = new NamedTypeNode();
                resType.BuildNode(typeExpr.Current);
                resType.IsConstant = !isMutable;
                return(resType);
            }
        }
コード例 #2
0
        }                                                         // set during AST construction

        #region implemented abstract members of Node

        public override void BuildNode <TSymbol>(IParseTree <TSymbol> parseTree)
        {
            // Block -> "{" (Expression ";")* "}"
            var childs = ASTBuilder.ChildrenEnumerator(parseTree);

            childs.MoveNext();               // go to "{"
            Debug.Assert(childs.MoveNext()); // enter the brackets
            var elems = new List <ExpressionNode>();

            while (!ASTBuilder.EatSymbol("}", childs)) // collect expressions until closing "}"
            {
                elems.Add(ExpressionNode.GetExpressionNode(childs.Current));
                childs.MoveNext();                               // go to the next symbol
                Debug.Assert(ASTBuilder.EatSymbol(";", childs)); // it must be ";"
            }
            Elements = elems;
        }
コード例 #3
0
        /// <summary>
        /// Parse one line expression with ++ -- (postfix), function call, array subscript, slice subscript operators.
        /// Enumerator must be given with reversed ordering of arguments. This corresponds to Operator2Expression from Grammar.
        /// </summary>
        public static ExpressionNode ParseOperator2 <TSymbol>(IEnumerator <IParseTree <TSymbol> > opExpr) where TSymbol : ISymbol <TSymbol>
        {
            // O2 -> O1 (     "++" | "--"
            //           |    "(" (E ",")* E? ")"
            //           |    "[" E "]"
            //           |    "[" E? ".." E? "]"
            //          )*
            if (opExpr.Current.Symbol.IsTerminal)
            {
                string curText = ASTBuilder.EatTerminal(opExpr);
                switch (curText)
                {
                case "++":
                case "--":
                    return(OperatorNode.BuildUnaryOperator(2, curText, ParseOperator2(opExpr)));

                case ")":
                    var args = new LinkedList <ExpressionNode>();
                    while (!ASTBuilder.EatSymbol("(", opExpr))
                    {
                        ASTBuilder.EatSymbol(",", opExpr); // eat ',' before arg - f(x,y,z,) is also possible
                        args.AddFirst(GetExpressionNode(opExpr.Current));
                        opExpr.MoveNext();                 // move to next param with ','
                    }
                    var res = new FunctionCallNode();
                    res.Arguments = new List <ExpressionNode>(args);
                    // TODO: can something return a 'pointer' to function which we can call to execute?
                    res.Name = opExpr.Current.Fragment.GetOriginText();
                    return(res);

                case "]":
                    var  toExpr   = ASTBuilder.EatNonTerminal(opExpr);  // slice to or index
                    bool isSlice  = ASTBuilder.EatSymbol("..", opExpr);
                    var  fromExpr = ASTBuilder.EatNonTerminal(opExpr);
                    Debug.Assert(ASTBuilder.EatSymbol("[", opExpr));
                    if (isSlice)     // slice subscript
                    {
                        return(SliceNode.CreateSliceNode(ParseOperator2(opExpr),
                                                         GetExpressionOrNull(fromExpr), GetExpressionOrNull(toExpr)));
                    }
                    else     // array subscript
                    {
                        return(ElementNode.Create(ParseOperator2(opExpr), GetExpressionNode(toExpr)));
                    }

                default:
                    Debug.Assert(false);
                    break;
                }
            }
            else // non-terminal -> Operator1Expression
            {
                var op1 = opExpr.Current;
                Debug.Assert(!opExpr.MoveNext());      // it must be final symbol in this enumeration
                var node = ASTBuilder.FirstChild(op1); // Operator1Expression -> Operator0Expression
                // Operator0Expression -> AtomicExpression | "(" Expression ")";
                var childs = ASTBuilder.ChildrenEnumerator(node);
                Debug.Assert(childs.MoveNext());
                if (ASTBuilder.EatSymbol("(", childs))
                {
                    return(GetExpressionNode(childs.Current)); // Expression
                }
                else // proceed with AtomicExpression
                {
                    return(ResolveAtomicExpression(childs.Current));
                }
            }
            return(null);
        }