IsArrayKeyword() public static method

Returns true if the symbol is a pair of square brackets with zero or more commas inside, e.g. "[,]", which in EC# represents an array type of a specific number of dimensions.
public static IsArrayKeyword ( Symbol s ) : bool
s Symbol
return bool
Exemplo n.º 1
0
        private void PrintTypeWithArraySizes(LNode cons)
        {
            LNode type = cons.Target;

            // Called by AutoPrintNewOperator; type is already validated.
            Debug.Assert(type.Calls(S.Of, 2) && S.IsArrayKeyword(type.Args[0].Name));
            // We have to deal with the "constructor arguments" specially.
            // First of all, the constructor arguments appear inside the
            // square brackets, which is unusual: int[x + y]. But there's
            // something much more strange in case of arrays of arrays: the
            // order of the square brackets must be reversed. If the
            // constructor argument is 10, an array of two-dimensional
            // arrays of int is written int[10][,], rather than int[,][10]
            // which would be easier to handle.
            int   dims = cons.ArgCount, innerDims;
            LNode elemType = type.Args[1];
            var   dimStack = InternalList <int> .Empty;

            while ((innerDims = CountDimensionsIfArrayType(elemType)) != 0)
            {
                dimStack.Add(innerDims);
                elemType = elemType.Args[1];
            }

            PrintType(elemType, EP.Primary.LeftContext(ContinueExpr));

            _out.Write('[', true);
            bool first = true;

            foreach (var arg in cons.Args)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    WriteThenSpace(',', SpaceOpt.AfterComma);
                }
                PrintExpr(arg, StartExpr, 0);
            }
            _out.Write(']', true);

            // Write the brackets for the inner array types
            for (int i = dimStack.Count - 1; i >= 0; i--)
            {
                _out.Write(S.GetArrayKeyword(dimStack[i]).Name, true);
            }
        }
Exemplo n.º 2
0
        static Symbol SpecialTypeKind(LNode n, Ambiguity flags, Precedence context)
        {
            // detects when notation for special types applies: Foo[], Foo*, Foo?
            // assumes IsComplexIdentifier() is already known to be true
            LNode first;

            if (n.Calls(S.Of, 2) && (first = n.Args[0]).IsId && (flags & Ambiguity.TypeContext) != 0)
            {
                var kind = first.Name;
                if (S.IsArrayKeyword(kind) || kind == S.QuestionMark)
                {
                    return(kind);
                }
                if (kind == S._Pointer && ((flags & Ambiguity.AllowPointer) != 0 || context.Left == StartStmt.Left))
                {
                    return(kind);
                }
            }
            return(null);
        }
Exemplo n.º 3
0
        public bool AutoPrintComplexIdentOperator(Precedence precedence, Precedence context, Ambiguity flags)
        {
            // Handles #of and @`.`, including array types
            int    argCount = _n.ArgCount;
            Symbol name     = _n.Name;

            Debug.Assert((name == S.Of || name == S.Dot) && _n.IsCall);

            var first = _n.Args[0, null];

            if (first == null)
            {
                return(false);                // no args
            }
            bool needParens, needSpecialOfNotation = false;

            if (!CanAppearIn(precedence, context, out needParens) || needParens)
            {
                return(false);                // this only happens inside $ operator, e.g. $(a.b)
            }
            if (name == S.Dot)
            {
                // The trouble with the dot is its high precedence; because of
                // this, arguments after a dot cannot use prefix notation as a
                // fallback. For example "@.(a, b(c))" cannot be printed "a.b(c)"
                // since that means @.(a, b)(c)". The first argument to non-
                // unary "." can use prefix notation safely though, e.g.
                // "@.(b(c), a)" can (and must) be printed "b(c).a".
                if (argCount > 2)
                {
                    return(false);
                }
                if (HasPAttrs(first))
                {
                    return(false);
                }
                LNode afterDot = _n.Args.Last;
                // Unary dot is no problem: .(a) is parsed the same as .a, i.e.
                // the parenthesis are ignored, so we can print an expr like
                // @`.`(a+b) as .(a+b), but the parser counts parens on binary
                // dot, so in that case the argument after the dot must not be any
                // kind of call (except substitution) and must not have attributes,
                // unless it is in parens.
                if (argCount == 2 && !afterDot.IsParenthesizedExpr())
                {
                    if (HasPAttrs(afterDot))
                    {
                        return(false);
                    }
                    if (afterDot.IsCall && afterDot.Name != S.Substitute)
                    {
                        return(false);
                    }
                }
                else if ((flags & Ambiguity.CastRhs) != 0)
                {
                    return(false);                    // cannot print (Foo) @`.`(x) as (Foo) .x
                }
            }
            else if (name == S.Of)
            {
                var ici = ICI.Default | ICI.AllowAttrs;
                if ((flags & Ambiguity.InDefinitionName) != 0)
                {
                    ici |= ICI.NameDefinition;
                }
                if (!IsComplexIdentifier(_n, ici))
                {
                    if (IsComplexIdentifier(_n, ici | ICI.AllowAnyExprInOf))
                    {
                        needSpecialOfNotation = true;
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            if (name == S.Dot)
            {
                if (argCount == 1)
                {
                    _out.Write('.', true);
                    PrintExpr(first, EP.Substitute);
                }
                else
                {
                    PrintExpr(first, precedence.LeftContext(context), flags & Ambiguity.TypeContext);
                    _out.Write('.', true);
                    PrintExpr(_n.Args[1], precedence.RightContext(context));
                }
            }
            else if (_n.Name == S.Of)
            {
                // Check for special type names such as Foo? or Foo[]
                Symbol stk = SpecialTypeKind(_n, flags, context);
                if (stk != null)
                {
                    if (S.IsArrayKeyword(stk))
                    {
                        // We do something very strange in case of arrays of arrays:
                        // the order of the square brackets must be reversed when
                        // arrays are nested. For example, an array of two-dimensional
                        // arrays of int is written int[][,], rather than int[,][]
                        // which would be much easier to handle.
                        var stack     = InternalList <Symbol> .Empty;
                        var innerType = _n;
                        do
                        {
                            stack.Add(stk);
                            innerType = innerType.Args[1];
                        } while (S.IsArrayKeyword(stk = SpecialTypeKind(innerType, flags, context) ?? GSymbol.Empty));

                        PrintType(innerType, EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer));

                        for (int i = 0; i < stack.Count; i++)
                        {
                            _out.Write(stack[i].Name, true);                             // e.g. [] or [,]
                        }
                    }
                    else
                    {
                        PrintType(_n.Args[1], EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer));
                        _out.Write(stk == S._Pointer ? '*' : '?', true);
                    }
                    return(true);
                }

                PrintExpr(first, precedence.LeftContext(context));

                _out.Write(needSpecialOfNotation ? "!(" : "<", true);
                for (int i = 1; i < argCount; i++)
                {
                    if (i > 1)
                    {
                        WriteThenSpace(',', SpaceOpt.AfterCommaInOf);
                    }
                    PrintType(_n.Args[i], StartExpr, Ambiguity.InOf | Ambiguity.AllowPointer | (flags & Ambiguity.InDefinitionName));
                }
                _out.Write(needSpecialOfNotation ? ')' : '>', true);
            }
            else
            {
                Debug.Assert(_n.Name == S.Substitute);
                G.Verify(AutoPrintOperator(ContinueExpr, 0));
            }
            return(true);
        }