// 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); } // [ZZ] For whatever reason, the parser is closely tied to the tokenizer, and to the general scripting lumps framework (see scripttype). // For this reason I have to still inherit the old tokenizer while only using the new one. //ReportError("found zscript? :)"); prevstreamposition = -1; tokenizer = new ZScriptTokenizer(datareader); // region-as-category, ZScript ver List <DecorateCategoryInfo> regions = new List <DecorateCategoryInfo>(); while (true) { ZScriptToken token = tokenizer.ExpectToken(ZScriptTokenType.Identifier, // const, enum, class, etc ZScriptTokenType.Whitespace, ZScriptTokenType.Newline, ZScriptTokenType.BlockComment, ZScriptTokenType.LineComment, ZScriptTokenType.Preprocessor); if (token == null) // EOF reached, whatever. { break; } if (!token.IsValid) { ReportError("Expected preprocessor statement, const, enum or class declaraction, got " + token); return(false); } // toplevel tokens allowed are only Preprocessor and Identifier. switch (token.Type) { case ZScriptTokenType.Whitespace: case ZScriptTokenType.Newline: case ZScriptTokenType.BlockComment: break; case ZScriptTokenType.LineComment: { string cmtval = token.Value.TrimStart(); if (cmtval.Length <= 0 || cmtval[0] != '$') { break; } // check for $GZDB_SKIP if (cmtval.Trim().ToLowerInvariant() == "$gzdb_skip") { return(true); } // if we are in a region, read property using function from ZScriptActorStructure if (regions.Count > 0) { ZScriptActorStructure.ParseGZDBComment(regions.Last().Properties, cmtval); } } break; case ZScriptTokenType.Preprocessor: { tokenizer.SkipWhitespace(); ZScriptToken directive = tokenizer.ExpectToken(ZScriptTokenType.Identifier); if (directive == null || !directive.IsValid) { ReportError("Expected preprocessor directive, got " + ((Object)directive ?? "<null>").ToString()); return(false); } string d_value = directive.Value.ToLowerInvariant(); if (d_value == "include") { tokenizer.SkipWhitespace(); ZScriptToken include_name = tokenizer.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.String, ZScriptTokenType.Name); if (include_name == null || !include_name.IsValid) { ReportError("Cannot include: expected a string value, got " + ((Object)include_name ?? "<null>").ToString()); return(false); } if (!ParseInclude(include_name.Value)) { return(false); } } else if (d_value == "region") { // just read everything until newline. string region_name = ""; while (true) { token = tokenizer.ReadToken(); if (token == null || token.Type == ZScriptTokenType.Newline) { break; } region_name += token.Value; } DecorateCategoryInfo region = new DecorateCategoryInfo(); string[] cattitle = region_name.Split(DataManager.CATEGORY_SPLITTER, StringSplitOptions.RemoveEmptyEntries); if (regions.Count > 0) { region.Category.AddRange(regions.Last().Category); region.Properties = new Dictionary <string, List <string> >(regions.Last().Properties, StringComparer.OrdinalIgnoreCase); } region.Category.AddRange(cattitle); regions.Add(region); } else if (d_value == "endregion") { // read everything until newline too? // - only if it causes problems if (regions.Count > 0) { regions.RemoveAt(regions.Count - 1); // remove last region from the list } else { LogWarning("Superfluous #endregion found without corresponding #region"); } } else { ReportError("Unknown preprocessor directive: " + directive.Value); return(false); } break; } case ZScriptTokenType.Identifier: { // identifier can be one of: class, enum, const, struct // the only type that we really care about is class, as it's the one that has all actors. switch (token.Value.ToLowerInvariant()) { case "extend": tokenizer.SkipWhitespace(); token = tokenizer.ExpectToken(ZScriptTokenType.Identifier); if (token == null || !token.IsValid || ((token.Value.ToLowerInvariant() != "class") && (token.Value.ToLowerInvariant() != "struct"))) { ReportError("Expected class or struct, got " + ((Object)token ?? "<null>").ToString()); return(false); } if (!ParseClassOrStruct((token.Value.ToLowerInvariant() == "struct"), true, (regions.Count > 0 ? regions.Last() : null))) { return(false); } break; case "class": // todo parse class if (!ParseClassOrStruct(false, false, (regions.Count > 0 ? regions.Last() : null))) { return(false); } break; case "struct": // todo parse struct if (!ParseClassOrStruct(true, false, null)) { return(false); } break; case "const": if (!ParseConst()) { return(false); } break; case "enum": if (!ParseEnum()) { return(false); } break; case "version": // expect a string. do nothing about it. tokenizer.SkipWhitespace(); token = tokenizer.ExpectToken(ZScriptTokenType.String); if (token == null || !token.IsValid) { ReportError("Expected version string, got " + ((Object)token ?? "<null>").ToString()); return(false); } break; default: ReportError("Expected preprocessor statement, const, enum or class declaraction, got " + token); return(false); } break; } } } return(true); }
internal bool Process() { RestoreStreamData(); bool isactor = false; ZScriptClassStructure _pstruct = this; while (_pstruct != null) { if (_pstruct.ClassName.ToLowerInvariant() == "actor") { isactor = true; break; } if (_pstruct.ParentName != null) { string _pname = _pstruct.ParentName.ToLowerInvariant(); Parser.allclasses.TryGetValue(_pname, out _pstruct); } else { _pstruct = null; } } string log_inherits = ((ParentName != null) ? "inherits " + ParentName : ""); if (ReplacementName != null) { log_inherits += ((log_inherits.Length > 0) ? ", " : "") + "replaces " + ReplacementName; } if (log_inherits.Length > 0) { log_inherits = " (" + log_inherits + ")"; } if (isactor) { Actor = new ZScriptActorStructure(Parser, Region, ClassName, ReplacementName, ParentName); if (Parser.HasError) { Actor = null; return(false); } // check actor replacement. Parser.archivedactors[Actor.ClassName.ToLowerInvariant()] = Actor; Parser.realarchivedactors[Actor.ClassName.ToLowerInvariant()] = Actor; if (Actor.CheckActorSupported()) { Parser.actors[Actor.ClassName.ToLowerInvariant()] = Actor; } // Replace an actor? if (Actor.ReplacesClass != null) { if (Parser.GetArchivedActorByName(Actor.ReplacesClass, false) != null) { Parser.archivedactors[Actor.ReplacesClass.ToLowerInvariant()] = Actor; } else { Parser.LogWarning("Unable to find \"" + Actor.ReplacesClass + "\" class to replace, while parsing \"" + Actor.ClassName + "\""); } if (Actor.CheckActorSupported() && Parser.GetActorByName(Actor.ReplacesClass) != null) { Parser.actors[Actor.ReplacesClass.ToLowerInvariant()] = Actor; } } //mxd. Add to current text resource if (!Parser.scriptresources[TextResourcePath].Entries.Contains(Actor.ClassName)) { Parser.scriptresources[TextResourcePath].Entries.Add(Actor.ClassName); } } //Parser.LogWarning(string.Format("Parsed {0}class {1}{2}", isactor?"actor ":"", ClassName, log_inherits)); return(true); }