Example #1
0
        /** Parses a \c guard definition, which makes a \c value accessible through the a getter and/or a setter.
         *
         *  guard Foo is io .foo:
         *       get:
         *           return .foo
         *       set:
         *           .foo := 2 * value
         */
        private GuardStatement ParseGuardStatement()
        {
            Token start = _matcher.Match(TokenKind.Keyword_Guard);
            _matcher.Match(TokenKind.Space);
            SymbolDefinition name = ParseSymbolDefinition(SymbolKind.Guard);
            #if false
            Token @base = null;
            if (_matcher.This.Kind == TokenKind.Dot)
            {
                _matcher.Match(TokenKind.Dot);
                @base = name;
                @name = _matcher.Match(TokenKind.Name);
            }
            #endif
            _matcher.Match(TokenKind.Space);
            _matcher.Match(TokenKind.Keyword_Is);
            _matcher.Match(TokenKind.Space);
            DirectionKind direction = ParseDirection();
            _matcher.Match(TokenKind.Space);
            #if DONE
            Expression member = ParseInstanceExpression();
            #else
            _matcher.Match(TokenKind.Dot);
            Token token = _matcher.Match(TokenKind.Name);
            SymbolReference reference = new SymbolReference(token.Cursor, PathKind.Instance, token.Text);
            Type type = new NamedType(token.Cursor, reference);
            #endif

            Statement getter = null;
            Statement setter = null;
            if (_matcher.This.Kind == TokenKind.Colon)
            {
                _matcher.Match(TokenKind.Colon);
                _matcher.Match(TokenKind.EndOfLine);
                token = _matcher.Match(TokenKind.Indent);     // NOTE: Update 'token'!
                switch (direction)
                {
                    case DirectionKind.Out:
                        getter = ParseGetRoutine((Type) type.Clone());
                        break;

                    case DirectionKind.In:
                        setter = ParseSetRoutine((Type) type.Clone());
                        break;

                    case DirectionKind.InOut:
                        if (_matcher.This.Kind == TokenKind.Keyword_Get)
                            getter = ParseGetRoutine((Type) type.Clone());
                        if (_matcher.This.Kind == TokenKind.Keyword_Set)
                            setter = ParseSetRoutine((Type) type.Clone());
                        if (getter == null && setter == null)
                            throw new ParserError(token.Cursor, "Getter or setter must be specified after colon");
                        break;

                    default:
                        throw new System.ArgumentException("direction");
                }
                _matcher.Match(TokenKind.Dedent);
            }

            if (getter == null)
            {
                if (direction != DirectionKind.In)
                    getter = CreateDefaultGetter(token.Cursor, token.Text);
                else
                    getter = new NoneStatement(token.Cursor);
            }

            if (setter == null)
            {
                if (direction != DirectionKind.Out)
                    setter = CreateDefaultSetter(token.Cursor, token.Text);
                else
                    setter = new NoneStatement(token.Cursor);
            }

            return new GuardStatement(start.Cursor, name, direction, type, getter, setter);
        }