Ejemplo n.º 1
0
        public bool Match(SourceStream source, out MemberType result)
        {
            result = null;

            if (!source.IsValid())
            {
                return(false);
            }

            var kind  = MemberKind.unknown;
            var slice = source.GetSlice();

            if (slice.MatchString(KeywordMemberList))
            {
                kind |= MemberKind.List;
            }
            else if (!slice.MatchString(KeywordMemberType))
            {
                return(false);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.ReadWord(out string type_name))
            {
                throw new ParseError("expected type name.", slice);
            }

            kind |= MemberType.ResolveKind(type_name);

            SkipCommentsAndWhitespace(slice);

            if (!slice.ReadWord(out string name))
            {
                throw new ParseError("expected to read field name.", slice);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.MatchString(TokenMemberAssignment))
            {
                throw new ParseError($"expected '{TokenMemberAssignment}'.", slice);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.ReadWord(out string ordstr))
            {
                throw new ParseError("expected to read member ordinal.", slice);
            }

            if (!ordstr.TryParse(out int ordinal))
            {
                slice.MoveBy(-ordstr.Length);
                throw new ParseError($"'{ordstr}' is not a valid oridinal.", slice);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.MatchString(TokenMemberTerminator))
            {
                throw new ParseError($"expected '{TokenMemberTerminator}'.", slice);
            }

            var span = source.Join(slice);

            result = new MemberType(name, type_name, ordinal, kind, span);

            return(true);
        }
Ejemplo n.º 2
0
        public bool Match(SourceStream source, out NamespaceType result)
        {
            result = null;

            if (!source.IsValid())
            {
                return(false);
            }

            var slice = source.GetSlice();

            SkipCommentsAndWhitespace(slice);

            if (!slice.MatchString(KeywordNamespace))
            {
                return(false);
            }

            SkipCommentsAndWhitespace(slice);

            string namespace_name = string.Empty;

name_match:

            if (!slice.ReadWord(out string name))
            {
                throw new ParseError($"expected namespace 'name'.", slice);
            }

            if (!name.IsNameLegal())
            {
                slice.MoveBy(-name.Length);
                throw new ParseError($"'{name}' is not a legal namespace.", slice);
            }

            namespace_name += name;

            SkipCommentsAndWhitespace(slice);

            if (slice.MatchString(TokenNameExtension))
            {
                namespace_name += TokenNameExtension;
                goto name_match;
            }

            if (!slice.MatchString(TokenNamespaceFirst))
            {
                throw new ParseError($"expected '{TokenNamespaceFirst}'.", slice);
            }

            var types   = new TypeList();
            var parsers = new GrammarParserDelegate[]
            {
                MatchStruct,
                match_enum,
                MatchNamespace,
            };

            while (slice.IsValid())
            {
                SkipCommentsAndWhitespace(slice);

                if (slice.MatchString(TokenNamespaceFinal))
                {
                    break;
                }

                if (!MatchAny(slice, parsers, out BaseType type))
                {
                    throw new ParseError("cannot parse", slice);
                }

                types.Add(type);
            }

            var span = source.Join(slice);

            result = new NamespaceType(namespace_name, types, span);

            return(true);
        }
Ejemplo n.º 3
0
        public bool Match(SourceStream source, out EnumType result)
        {
            result = null;

            if (!source.IsValid())
            {
                return(false);
            }

            var slice = source.GetSlice();

            if (!slice.MatchString(KeywordEnum))
            {
                return(false);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.ReadWord(out string name))
            {
                throw new ParseError("expected to read enum name.", slice);
            }

            if (!name.IsNameLegal())
            {
                slice.MoveBy(-name.Length);
                throw new ParseError($"'{name}' is not a legal enum name.", slice);
            }

            SkipCommentsAndWhitespace(slice);

            if (!slice.MatchString(TokenEnumFirst))
            {
                throw new ParseError($"expected to find '{TokenEnumFirst}'.", slice);
            }

            SkipCommentsAndWhitespace(slice);

            List <(string name, byte ordinal)> values = new List <(string, byte)>();

            while (slice.IsValid())
            {
                SkipCommentsAndWhitespace(slice);

                if (slice.MatchString(TokenEnumFinal))
                {
                    break;
                }

                if (!slice.ReadWord(out string member_name))
                {
                    throw new ParseError("expected to read member name.", slice);
                }

                if (!member_name.IsNameLegal())
                {
                    slice.MoveBy(-member_name.Length);
                    throw new ParseError($"'{member_name}' is not a legal member name.", slice);
                }

                SkipCommentsAndWhitespace(slice);

                if (!slice.MatchString(TokenEnumAssignment))
                {
                    throw new ParseError($"expected '{TokenEnumAssignment}'.", slice);
                }

                SkipCommentsAndWhitespace(slice);

                if (!slice.ReadWord(out string ordstr))
                {
                    throw new ParseError("unable to read enum value.", slice);
                }

                if (!ordstr.TryParse(out byte ordinal))
                {
                    slice.MoveBy(-ordstr.Length);
                    throw new ParseError($"'{ordstr}' is not a valid oridinal.", slice);
                }

                values.Add((member_name, ordinal));

                SkipCommentsAndWhitespace(slice);

                if (!slice.MatchString(TokenEnumSeparator))
                {
                    if (slice.MatchString(TokenEnumFinal))
                    {
                        break;
                    }

                    throw new ParseError($"expected '{TokenEnumSeparator}' or '{TokenEnumFinal}'.", slice);
                }

                SkipCommentsAndWhitespace(slice);
            }

            var span = source.Join(slice);

            result = new EnumType(name, values.ToArray(), span);

            return(true);
        }