Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <syntax>
        /// Объявление-контейнера
        ///         :   [ Спецификатор-контейнера ] unit Имя-контейнера [ FormalGenerics ]
        ///                 { Директива-контейнера }
        ///             is
        ///                 Тело-контейнера
        ///                 [ invariant Список-предикатов ]
        ///             end
        ///
        /// Спецификатор-контейнера
        ///         : ref | val | concurrent | abstract
        ///
        /// Имя-контейнера
        ///         : Составное-имя
        ///
        /// Директива-контейнера
        ///         : Директива-наследования
        ///         | Директива-использования
        ///
        /// Директива-наследования
        ///         : extend Базовый-контейнер { , Базовый-контейнер }
        ///
        /// Базовый-контейнер
        ///         : [ ~ ] UnitTypeName
        ///
        /// Тело-контейнера
        ///         : { Объявление }
        /// </syntax>
        /// <returns></returns>
        public static void parse(bool hidden, bool final, bool abstr, iSCOPE context)
        {
            Debug.Indent();
            Debug.WriteLine("Entering UNIT.parse");

            bool ref_val    = false;  // unit is reference by default
            bool concurrent = false;

            UNIT unit = null;

            Token token = get();
            Token begin = token;

            TokenCode code = TokenCode.Unit;

            switch (token.code)
            {
            case TokenCode.Ref:
                ref_val = true;
                forget();
                code = getUnitKeyword();
                break;

            case TokenCode.Val:
                ref_val = false;
                forget();
                code = getUnitKeyword();
                break;

            case TokenCode.Abstract:
                abstr = true;
                forget();
                code = getUnitKeyword();
                break;

            case TokenCode.Concurrent:
                concurrent = true;
                forget();
                code = getUnitKeyword();
                break;

            case TokenCode.Unit:
                code = TokenCode.Unit;
                forget();
                break;

            case TokenCode.Package:
                code = TokenCode.Package;
                forget();
                break;
            }

            // 1. Unit header

            token = expect(TokenCode.Identifier);
            Token compoundName = IDENTIFIER.parseCompoundName(token);

            if (code == TokenCode.Package)
            {
                if (!ENTITY.options.optConfig)
                {
                    warning(token, "no-config");
                    unit = new UNIT(compoundName.image, ref_val, abstr, concurrent);
                }
                else
                {
                    unit = new PACKAGE(compoundName.image, ref_val, abstr, concurrent);
                }
            }
            else
            {
                unit = new UNIT(compoundName.image, ref_val, abstr, concurrent);
            }

            Debug.WriteLine("======================" + compoundName.image);

            unit.parent = context.self;
            unit.setSpecs(hidden, final);
            Context.enter(unit);

            // 2. Generic parameters

            token = get();
            if (token.code == TokenCode.LBracket)
            {
                forget();
                while (true)
                {
                    var generic = FORMAL_GENERIC.parse(unit);
                    unit.add(generic);

                    token = get();
                    switch (token.code)
                    {
                    case TokenCode.Comma:
                    case TokenCode.Semicolon: forget(); continue;

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

                    default: { /* Syntax error */ break; }
                    }
                }
Finish:
                ;
            }

            // Possible unit alias

            token = get();
            if (token.code == TokenCode.Alias)
            {
                forget();
                token      = expect(TokenCode.Identifier);
                unit.alias = new IDENTIFIER(token);
            }

            // 3. Unit directives: inheritance

            token = get();
            if (token.code == TokenCode.Extend)
            {
                forget();
                while (true)
                {
                    PARENT parent = PARENT.parse(unit);
                    if (parent == null) /* Syntax error */ break {
                        ;
                    }
                    unit.add(parent);

                    token = get();
                    switch (token.code)
                    {
                    case TokenCode.Comma:
                    case TokenCode.Semicolon:
                    case TokenCode.EOL:
                        forget();
                        continue;

                    default:
                        goto Use;
                    }
                }
            }
Пример #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);
        }