Пример #1
0
        /// <summary>
        ///
        /// <syntax><code>
        /// Объявление-переменных
        ///         : Список-идентификаторов [ : Спецификатор-типа ] is Выражение
        ///         | Список-идентификаторов : Спецификатор-типа
        ///
        /// Спецификатор-типа
        ///         : [ ? | ref | val | concurrent ] Тип
        ///         | as Составное-имя
        /// </code></syntax>
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static void parse(bool hidden, bool ffinal, bool isConst, bool isOverride, Token id, Token afterId, iSCOPE context)
        {
            Debug.Indent();
            Debug.WriteLine("Entering VARIABLE.parse");

            TYPE       type        = null;
            EXPRESSION initializer = null;

            bool RefVal  = false; // 'val' by default
            bool Conc    = false;
            bool Abstr   = false;
            bool Foreign = false;

            Token token = id;
            Span  final = null;

            // If id==null, then we just start processing the declaration.
            // In this case, always afterId==null.
            //
            // If id != null then it contains an identifier.
            // In this case, afterId contains ':', ',' or 'is' - three
            // options starting a declaration.

            List <Token> identifiers = new List <Token>();

            if (token == null)
            {
                // We just start parsing variable declaration
                token = get(); forget();
                identifiers.Add(token);

                // Parsing the rest of identifiers in the list (if any)
                while (true)
                {
                    token = get();
                    if (token.code != TokenCode.Comma)
                    {
                        break;
                    }
                    forget();
                    token = expect(TokenCode.Identifier);
                    identifiers.Add(token);
                }
            }
            else
            {
                if (afterId.code == TokenCode.Is)
                {
                    // id is ...
                    identifiers.Add(id);
                    token = afterId;
                }
                else if (afterId.code == TokenCode.Colon)
                {
                    // 'token' contains an identifier.
                    // Check what's after this identifier?
                    //
                    //  id : ...
                    //       ^
                    identifiers.Add(id);
                    token = afterId;
                }
                else if (afterId.code == TokenCode.Comma)
                {
                    // 'token' contains an identifier,
                    // and comma goes after it (comma was parsed already).
                    //
                    //  id, ...
                    //      ^
                    identifiers.Add(id);

                    // Parsing the rest of the list of identifiers.
                    while (true)
                    {
                        token = expect(TokenCode.Identifier);
                        identifiers.Add(token);
                        if (token.code != TokenCode.Comma)
                        {
                            break;
                        }
                        forget();
                    }
                }
                else
                {
                    // Syntax error
                    error(afterId, "syntax-error", "declaration");
                }
            }
            // Here, we have parsed the list of identifiers.
            // 'token' contains the token after the list.
            // Only two valid options are ':' or 'is'.

            if (token.code == TokenCode.Colon)
            {
                // Type is expected.
                if (afterId == null)
                {
                    forget();
                }
                type  = parseTypeSpecifier(context, out RefVal, out Conc, out final);
                token = get();
            }
            if (token.code == TokenCode.Is)
            {
                forget(); token = get();
                if (token.code == TokenCode.Abstract)
                {
                    forget();
                    Abstr = true;
                    final = token.span;
                }
                else if (token.code == TokenCode.Foreign)
                {
                    forget();
                    Foreign = true;
                    final   = token.span;
                }
                else
                {
                    forget();
                    initializer = EXPRESSION.parse(token, context);
                    if (type == null)
                    {
                        // Type inference
                        // initializer.calculateType();
                        type = initializer.type;
                    }
                    final = initializer.span;
                }
            }

            // Here, we have the list of identifiers, their type,
            // and perhaps the initializer.
            // Create the final node(s) for variable declaration(s)
            // out of identifier(s), type and initializer.

            foreach (Token ident in identifiers)
            {
                VARIABLE varDecl = new VARIABLE(new IDENTIFIER(ident), type, initializer);
                varDecl.setSpecs(hidden, ffinal);
                varDecl.setVarSpecs(isConst, isOverride, RefVal, Conc, Abstr, Foreign);
                varDecl.setSpan(ident.span, final != null ? final : ident.span);
                context.add(varDecl);

                varDecl.parent = context.self;

                if (type != null)
                {
                    type.parent = varDecl;
                }
                if (initializer != null)
                {
                    initializer.parent = varDecl;
                }
            }

            Debug.WriteLine("Exiting VARIABLE.parse");
            Debug.Unindent();
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <syntax>
        /// UnitTypeName         : CompoundName [ GenericInstantiation ]
        ///
        /// GenericInstantiation : "[" (Type|Expression) { "," (Type|Expression) } "]"
        /// </syntax>
        /// <returns></returns>
        public static UNIT_REF parse(Token id, bool opt, iSCOPE context)
        {
            Debug.Indent();
            Debug.WriteLine("Entering UNIT_REF.parse");

            Token token = null;

            // We assume that 'id' is 'identifier'.
            if (id == null)
            {
                token = get(); forget();
            }
            else
            {
                token = id;
            }

            token = IDENTIFIER.parseCompoundName(token);
            if (token == null) /* an error was detected earlier */ return {
                (null);
            }
            Token start = token;

            UNIT_REF unit_ref = new UNIT_REF(token.image);

            unit_ref.opt     = opt;
            unit_ref.as_sign = true;
            DECLARATION unit = Context.find(token);

            if (unit != null && (unit is UNIT || unit is FORMAL_TYPE))
            {
                unit_ref.unit_ref = unit;
            }

            token = get();
            if (token.code == TokenCode.LBracket)
            {
                forget();
                while (true)
                {
                    TYPE type = null;
                    token = get();
                    if (token.code == TokenCode.LParen)
                    {
                        type = TUPLE_TYPE.parse(context);
                        unit_ref.add(type);
                        goto Delimiter;
                    }
                    EXPRESSION expr = EXPRESSION.parse(null, context);
                    if (expr is REFERENCE || expr is UNRESOLVED)
                    {
                        string name = null;
                        if (expr is REFERENCE)
                        {
                            if ((expr as REFERENCE).declaration is UNIT)
                            {
                                name = (expr as REFERENCE).declaration.name.identifier;
                            }
                            else
                            {
                                goto NonType;
                            }
                        }
                        else // UNRESOLVED
                        {
                            name = (expr as UNRESOLVED).name.identifier;
                        }

                        id   = new Token(expr.span, TokenCode.Identifier, name, new Category(CategoryCode.identifier));
                        type = UNIT_REF.parse(id, false, context); // Recursive call

                        unit_ref.add(type);
                        type.parent = unit_ref;
                        goto Delimiter;
                    }
                    // else -- expr is perhaps a non-type argument
NonType:
                    token = get();
                    if (token.code == TokenCode.DotDot)
                    {
                        // This is actually a range _type_
                        forget();
                        EXPRESSION right = EXPRESSION.parse(null, context);
                        RANGE_TYPE range = new RANGE_TYPE(expr, right);
                        range.setSpan(expr.span, right.span);
                        unit_ref.add(range);
                        range.parent = unit_ref;
                    }
                    else // Definitely a non-type argument
                    {
                        unit_ref.add(expr);
                        expr.parent = unit_ref;
                    }
Delimiter:
                    token = get();
                    switch (token.code)
                    {
                    case TokenCode.Comma:    forget(); continue;

                    case TokenCode.RBracket: forget(); goto Finish;

                    default: { /* Syntax error in generic actuals */ break; }
                    }
                }
Finish:
                unit_ref.setSpan(start.span, token.span);
            }
            else
            {
                unit_ref.setSpan(start);
            }

            Debug.WriteLine("Exiting UNIT_REF.parse");
            Debug.Unindent();

            return(unit_ref);
        }
Пример #3
0
 public VARIABLE(IDENTIFIER n = null, TYPE t = null, EXPRESSION i = null) : base(n)
 {
     type        = t;
     initializer = i;
 }