示例#1
0
        // This parses the given decorate stream
        // Returns false on errors
        public override bool Parse(Stream stream, string sourcefilename)
        {
            base.Parse(stream, sourcefilename);

            // Keep local data
            Stream       localstream     = datastream;
            string       localsourcename = sourcename;
            BinaryReader localreader     = datareader;

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                // Read a token
                string objdeclaration = ReadToken();
                if (objdeclaration != null)
                {
                    objdeclaration = objdeclaration.ToLowerInvariant();
                    if (objdeclaration == "actor")
                    {
                        // Read actor structure
                        ActorStructure actor = new ActorStructure(this);
                        if (this.HasError)
                        {
                            break;
                        }

                        // Add the actor
                        archivedactors[actor.ClassName.ToLowerInvariant()] = actor;
                        if (actor.CheckActorSupported())
                        {
                            actors[actor.ClassName.ToLowerInvariant()] = actor;
                        }

                        // Replace an actor?
                        if (actor.ReplacesClass != null)
                        {
                            if (GetArchivedActorByName(actor.ReplacesClass) != null)
                            {
                                archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Unable to find the DECORATE class '" + actor.ReplacesClass + "' to replace, while parsing '" + actor.ClassName + "'");
                            }

                            if (actor.CheckActorSupported())
                            {
                                if (GetActorByName(actor.ReplacesClass) != null)
                                {
                                    actors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                                }
                            }
                        }
                    }
                    else if (objdeclaration == "#include")
                    {
                        // Include a file
                        SkipWhitespace(true);
                        string filename = ReadToken();
                        if (!string.IsNullOrEmpty(filename))
                        {
                            // Strip the quotes
                            filename = filename.Replace("\"", "");

                            // Callback to parse this file now
                            if (OnInclude != null)
                            {
                                OnInclude(this, filename);
                            }

                            // Set our buffers back to continue parsing
                            datastream = localstream;
                            datareader = localreader;
                            sourcename = localsourcename;
                            if (HasError)
                            {
                                break;
                            }
                        }
                        else
                        {
                            ReportError("Expected file name to include");
                            break;
                        }
                    }
                    else if ((objdeclaration == "const") || (objdeclaration == "native"))
                    {
                        // We don't need this, ignore up to the first next ;
                        while (SkipWhitespace(true))
                        {
                            string t = ReadToken();
                            if ((t == ";") || (t == null))
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        // Unknown structure!
                        // Best we can do now is just find the first { and then
                        // follow the scopes until the matching } is found
                        string token2;
                        do
                        {
                            if (!SkipWhitespace(true))
                            {
                                break;
                            }
                            token2 = ReadToken();
                            if (token2 == null)
                            {
                                break;
                            }
                        }while(token2 != "{");
                        int scopelevel = 1;
                        do
                        {
                            if (!SkipWhitespace(true))
                            {
                                break;
                            }
                            token2 = ReadToken();
                            if (token2 == null)
                            {
                                break;
                            }
                            if (token2 == "{")
                            {
                                scopelevel++;
                            }
                            if (token2 == "}")
                            {
                                scopelevel--;
                            }
                        }while(scopelevel > 0);
                    }
                }
            }

            // Return true when no errors occurred
            return(ErrorDescription == null);
        }
        // This parses the given decorate stream
        // Returns false on errors
        public override bool Parse(TextResourceData data, bool clearerrors)
        {
            //mxd. Already parsed?
            if (!base.AddTextResource(data))
            {
                if (clearerrors)
                {
                    ClearError();
                }
                return(true);
            }

            // Cannot process?
            if (!base.Parse(data, clearerrors))
            {
                return(false);
            }

            //mxd. Region-as-category stuff...
            List <DecorateCategoryInfo> regions = new List <DecorateCategoryInfo>();           //mxd

            // Keep local data
            Stream       localstream           = datastream;
            string       localsourcename       = sourcename;
            BinaryReader localreader           = datareader;
            DataLocation locallocation         = datalocation;     //mxd
            string       localtextresourcepath = textresourcepath; //mxd

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                // Read a token
                string objdeclaration = ReadToken();
                if (!string.IsNullOrEmpty(objdeclaration))
                {
                    objdeclaration = objdeclaration.ToLowerInvariant();
                    if (objdeclaration == "$gzdb_skip")
                    {
                        break;
                    }
                    switch (objdeclaration)
                    {
                    case "actor":
                    {
                        // Read actor structure
                        ActorStructure actor = new ActorStructure(this, (regions.Count > 0 ? regions[regions.Count - 1] : null));
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // Add the actor
                        archivedactors[actor.ClassName.ToLowerInvariant()] = actor;
                        if (actor.CheckActorSupported())
                        {
                            actors[actor.ClassName.ToLowerInvariant()] = actor;
                        }

                        // Replace an actor?
                        if (actor.ReplacesClass != null)
                        {
                            if (GetArchivedActorByName(actor.ReplacesClass) != null)
                            {
                                archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                            }
                            else
                            {
                                LogWarning("Unable to find \"" + actor.ReplacesClass + "\" class to replace, while parsing \"" + actor.ClassName + "\"");
                            }

                            if (actor.CheckActorSupported() && GetActorByName(actor.ReplacesClass) != null)
                            {
                                actors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                            }
                        }

                        //mxd. Add to current text resource
                        if (!textresources[textresourcepath].Entries.Contains(actor.ClassName))
                        {
                            textresources[textresourcepath].Entries.Add(actor.ClassName);
                        }
                    }
                    break;

                    case "#include":
                    {
                        //INFO: ZDoom DECORATE include paths can't be relative ("../actor.txt")
                        //or absolute ("d:/project/actor.txt")
                        //or have backward slashes ("info\actor.txt")
                        //include paths are relative to the first parsed entry, not the current one
                        //also include paths may or may not be quoted
                        SkipWhitespace(true);
                        string filename = StripQuotes(ReadToken(false));                                 //mxd. Don't skip newline

                        //mxd. Sanity checks
                        if (string.IsNullOrEmpty(filename))
                        {
                            ReportError("Expected file name to include");
                            return(false);
                        }

                        //mxd. Check invalid path chars
                        if (!CheckInvalidPathChars(filename))
                        {
                            return(false);
                        }

                        //mxd. Absolute paths are not supported...
                        if (Path.IsPathRooted(filename))
                        {
                            ReportError("Absolute include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Relative paths are not supported
                        if (filename.StartsWith(RELATIVE_PATH_MARKER) || filename.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
                            filename.StartsWith(ALT_RELATIVE_PATH_MARKER) || filename.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
                        {
                            ReportError("Relative include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Backward slashes are not supported
                        if (filename.Contains(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture)))
                        {
                            ReportError("Only forward slashes are supported by ZDoom");
                            return(false);
                        }

                        //mxd. Already parsed?
                        if (parsedlumps.Contains(filename))
                        {
                            ReportError("Already parsed \"" + filename + "\". Check your include directives");
                            return(false);
                        }

                        //mxd. Add to collection
                        parsedlumps.Add(filename);

                        // Callback to parse this file now
                        if (OnInclude != null)
                        {
                            OnInclude(this, filename);
                        }

                        //mxd. Bail out on error
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // Set our buffers back to continue parsing
                        datastream       = localstream;
                        datareader       = localreader;
                        sourcename       = localsourcename;
                        datalocation     = locallocation;                             //mxd
                        textresourcepath = localtextresourcepath;                     //mxd
                    }
                    break;

                    case "damagetype":                             //mxd
                        // Get DamageType name
                        SkipWhitespace(true);
                        string damagetype = StripQuotes(ReadToken(false));
                        if (string.IsNullOrEmpty(damagetype))
                        {
                            ReportError("Expected DamageType name");
                            return(false);
                        }

                        // Next should be "{"
                        SkipWhitespace(true);
                        if (!NextTokenIs("{"))
                        {
                            return(false);
                        }

                        // Skip the structure
                        while (SkipWhitespace(true))
                        {
                            string t = ReadToken();
                            if (string.IsNullOrEmpty(t) || t == "}")
                            {
                                break;
                            }
                        }

                        // Add to collection
                        if (!damagetypes.Contains(damagetype))
                        {
                            damagetypes.Add(damagetype);
                        }
                        break;

                    case "enum":
                    case "native":
                    case "const":
                        while (SkipWhitespace(true))
                        {
                            string t = ReadToken();
                            if (string.IsNullOrEmpty(t) || t == ";")
                            {
                                break;
                            }
                        }
                        break;

                    //mxd. Region-as-category handling
                    case "#region":
                        SkipWhitespace(false);
                        string cattitle = ReadLine();
                        if (!string.IsNullOrEmpty(cattitle))
                        {
                            // Make new category info
                            string[] parts = cattitle.Split(DataManager.CATEGORY_SPLITTER, StringSplitOptions.RemoveEmptyEntries);

                            DecorateCategoryInfo info = new DecorateCategoryInfo();
                            if (regions.Count > 0)
                            {
                                // Preserve nesting
                                info.Category.AddRange(regions[regions.Count - 1].Category);
                                info.Properties = new Dictionary <string, List <string> >(regions[regions.Count - 1].Properties);
                            }
                            info.Category.AddRange(parts);

                            // Add to collection
                            regions.Add(info);
                        }
                        break;

                    //mxd. Region-as-category handling
                    case "#endregion":
                        if (regions.Count > 0)
                        {
                            regions.RemoveAt(regions.Count - 1);
                        }
                        else
                        {
                            LogWarning("Unexpected #endregion token");
                        }
                        break;

                    default:
                    {
                        //mxd. In some special cases (like the whole actor commented using "//") our special comments will be detected here...
                        if (objdeclaration.StartsWith("$"))
                        {
                            if (regions.Count > 0)
                            {
                                // Store region property
                                regions[regions.Count - 1].Properties[objdeclaration] = new List <string> {
                                    (SkipWhitespace(false) ? ReadLine() : "")
                                };
                            }
                            else
                            {
                                // Skip the whole line, then carry on
                                ReadLine();
                            }
                            break;
                        }

                        // Unknown structure!
                        // Best we can do now is just find the first { and then
                        // follow the scopes until the matching } is found
                        string token2;
                        do
                        {
                            if (!SkipWhitespace(true))
                            {
                                break;
                            }
                            token2 = ReadToken();
                            if (string.IsNullOrEmpty(token2))
                            {
                                break;
                            }
                        }while(token2 != "{");

                        int scopelevel = 1;
                        do
                        {
                            if (!SkipWhitespace(true))
                            {
                                break;
                            }
                            token2 = ReadToken();
                            if (string.IsNullOrEmpty(token2))
                            {
                                break;
                            }
                            if (token2 == "{")
                            {
                                scopelevel++;
                            }
                            if (token2 == "}")
                            {
                                scopelevel--;
                            }
                        }while(scopelevel > 0);
                    }
                    break;
                    }
                }
            }

            // Return true when no errors occurred
            return(ErrorDescription == null);
        }