示例#1
0
        private void ParseAt(DataStructures.GameData.GameData gd, IEnumerator<LexObject> iterator)
        {
            iterator.MoveNext();
            var type = iterator.Current.Value;
            if (type.Equals("include", StringComparison.InvariantCultureIgnoreCase))
            {
                Expect(iterator, LexType.String);
                if (CurrentFile != null)
                {
                    var filename = iterator.Current.GetValue();
                    var path = Path.GetDirectoryName(CurrentFile) ?? "";
                    var incfile = Path.Combine(path, filename);

                    var current = CurrentFile;
                    var incgd = GetGameDataFromFile(incfile);
                    CurrentFile = current;

                    if (!gd.Includes.Any(x => String.Equals(x, filename, StringComparison.InvariantCultureIgnoreCase))) gd.Includes.Add(filename);

                    // Merge the included gamedata into the current one
                    gd.MapSizeHigh = Math.Max(incgd.MapSizeHigh, gd.MapSizeHigh);
                    gd.MapSizeLow = Math.Min(incgd.MapSizeLow, gd.MapSizeLow);
                    gd.Includes.AddRange(incgd.Includes.Where(x => !gd.Includes.Contains(x)));
                    gd.Classes.AddRange(incgd.Classes.Where(x => !gd.Classes.Any(y => String.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase))));
                    gd.AutoVisgroups.AddRange(incgd.AutoVisgroups.Where(x => !gd.AutoVisgroups.Any(y => String.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase))));
                    gd.MaterialExclusions.AddRange(incgd.MaterialExclusions.Where(x => !gd.MaterialExclusions.Any(y => String.Equals(x, y, StringComparison.InvariantCultureIgnoreCase))));
                }
                else
                {
                    throw new ProviderException("Unable to include a file when not reading from a file.");
                }
            }
            else if (type.Equals("mapsize", StringComparison.InvariantCultureIgnoreCase))
            {
                Expect(iterator, LexType.So);
                Expect(iterator, LexType.Value);
                gd.MapSizeLow = Int32.Parse(iterator.Current.Value);
                Expect(iterator, LexType.Comma);
                Expect(iterator, LexType.Value);
                gd.MapSizeHigh = Int32.Parse(iterator.Current.Value);
                Expect(iterator, LexType.Already);
            }
            else if (type.Equals("materialexclusion", StringComparison.InvariantCultureIgnoreCase))
            {
                Expect(iterator, LexType.Open);
                iterator.MoveNext();
                while (iterator.Current.Type != LexType.Close)
                {
                    Assert(iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + ".");
                    var exclusion = iterator.Current.GetValue();
                    gd.MaterialExclusions.Add(exclusion);
                    iterator.MoveNext();
                }
            }
            else if (type.Equals("autovisgroup", StringComparison.InvariantCultureIgnoreCase))
            {
                Expect(iterator, LexType.Equals);

                iterator.MoveNext();
                Assert(iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + ".");
                var sectionName = iterator.Current.GetValue();
                var sect = new AutoVisgroupSection {Name = sectionName};

                Expect(iterator, LexType.Open);
                iterator.MoveNext();
                while (iterator.Current.Type != LexType.Close)
                {
                    Assert(iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + ".");
                    var groupName = iterator.Current.GetValue();
                    var grp = new AutoVisgroup {Name = groupName};

                    Expect(iterator, LexType.Open);
                    iterator.MoveNext();
                    while (iterator.Current.Type != LexType.Close)
                    {
                        Assert(iterator.Current.IsValueOrString(), "Expected value type, got " + iterator.Current.Type + ".");
                        var entity = iterator.Current.GetValue();
                        grp.EntityNames.Add(entity);
                        iterator.MoveNext();
                    }

                    sect.Groups.Add(grp);
                }

                gd.AutoVisgroups.Add(sect);
            }
            else
            {
                // Parsing:
                // @TypeClass name(param, param) name()
                var ct = ParseClassType(type);
                var gdo = new GameDataObject("", "", ct);
                iterator.MoveNext();
                while (iterator.Current.Type == LexType.Value)
                {
                    // Parsing:
                    // @TypeClass {name(param, param) name()}
                    var name = iterator.Current.Value;
                    var bh = new Behaviour(name);
                    iterator.MoveNext();
                    if (iterator.Current.Type == LexType.Value)
                    {
                        // Allow for the following (first seen in hl2 base):
                        // @PointClass {halfgridsnap} base(Targetname)
                        continue;
                    }
                    Assert(iterator.Current.Type == LexType.So, "Unexpected " + iterator.Current.Type);
                    iterator.MoveNext();
                    while (iterator.Current.Type != LexType.Already)
                    {
                        // Parsing:
                        // name({param, param})
                        if (iterator.Current.Type != LexType.Comma)
                        {
                            Assert(iterator.Current.Type == LexType.Value || iterator.Current.Type == LexType.String,
                                "Unexpected " + iterator.Current.Type + ".");
                            var value = iterator.Current.Value;
                            if (iterator.Current.Type == LexType.String) value = value.Trim('"');
                            bh.Values.Add(value);
                        }
                        iterator.MoveNext();
                    }
                    Assert(iterator.Current.Type == LexType.Already, "Unexpected " + iterator.Current.Type);
                    // Treat base behaviour as a special case
                    if (bh.Name == "base")
                    {
                        gdo.BaseClasses.AddRange(bh.Values);
                    }
                    else
                    {
                        gdo.Behaviours.Add(bh);
                    }
                    iterator.MoveNext();
                }
                // = class_name : "Descr" + "iption" [
                Assert(iterator.Current.Type == LexType.Equals, "Expected equals, got " + iterator.Current.Type);
                Expect(iterator, LexType.Value);
                gdo.Name = iterator.Current.Value;
                iterator.MoveNext();
                if (iterator.Current.Type == LexType.Colon)
                {
                    // Parsing:
                    // : {"Descr" + "iption"} [
                    iterator.MoveNext();
                    gdo.Description = ParsePlusString(iterator);
                }
                Assert(iterator.Current.Type == LexType.Open, "Unexpected " + iterator.Current.Type);

                // Parsing:
                // name(type) : "Desc" : "Default" : "Long Desc" = [ ... ]
                // input name(type) : "Description"
                // output name(type) : "Description"
                iterator.MoveNext();
                while (iterator.Current.Type != LexType.Close)
                {
                    Assert(iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type);
                    var pt = iterator.Current.Value;
                    if (pt == "input" || pt == "output") // IO
                    {
                        // input name(type) : "Description"
                        var io = new IO();
                        Expect(iterator, LexType.Value);
                        io.IOType = (IOType) Enum.Parse(typeof (IOType), pt, true);
                        io.Name = iterator.Current.Value;
                        Expect(iterator, LexType.So);
                        Expect(iterator, LexType.Value);
                        io.VariableType = ParseVariableType(iterator.Current.Value);
                        Expect(iterator, LexType.Already);
                        iterator.MoveNext(); // if not colon, this will be the value of the next io/property, or close
                        if (iterator.Current.Type == LexType.Colon)
                        {
                            iterator.MoveNext();
                            io.Description = ParsePlusString(iterator);
                        }
                        gdo.InOuts.Add(io);
                    }
                    else // Property
                    {
                        Expect(iterator, LexType.So);
                        Expect(iterator, LexType.Value);
                        var vartype = ParseVariableType(iterator.Current.Value);
                        Expect(iterator, LexType.Already);
                        var prop = new Property(pt, vartype);
                        iterator.MoveNext();
                            // if not colon or equals, this will be the value of the next io/property, or close
                        if (iterator.Current.Type == LexType.Value)
                        {
                            // Check for additional flags on the property
                            // e.g.: name(type) readonly : "This is a read only value"
                            //       name(type) report   : "This value will show in the entity report"
                            switch (iterator.Current.Value)
                            {
                                case "readonly":
                                    prop.ReadOnly = true;
                                    iterator.MoveNext();
                                    break;
                                case "report":
                                    prop.ShowInEntityReport = true;
                                    iterator.MoveNext();
                                    break;
                            }
                        }
                        do // Using do/while(false) so I can break out - reduces nesting.
                        {
                            // Short description
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            prop.ShortDescription = ParsePlusString(iterator);

                            // Default value
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            if (iterator.Current.Type != LexType.Colon) // Allow for ': :' structure (no default)
                            {
                                if (iterator.Current.Type == LexType.String)
                                {
                                    prop.DefaultValue = iterator.Current.Value.Trim('"');
                                }
                                else
                                {
                                    Assert(iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type);
                                    prop.DefaultValue = iterator.Current.Value;
                                }
                                iterator.MoveNext();
                            }

                            // Long description
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            prop.Description = ParsePlusString(iterator);
                        } while (false);
                        if (iterator.Current.Type == LexType.Equals)
                        {
                            Expect(iterator, LexType.Open);
                            // Parsing property options:
                            // value : description
                            // value : description : 0
                            iterator.MoveNext();
                            while (iterator.Current.IsValueOrString())
                            {
                                var opt = new Option
                                {
                                    Key = iterator.Current.GetValue()
                                };
                                Expect(iterator, LexType.Colon);

                                // Some FGDs use values for property descriptions instead of strings
                                iterator.MoveNext();
                                Assert(iterator.Current.IsValueOrString(), "Choices value must be value or string type.");
                                if (iterator.Current.Type == LexType.String)
                                {
                                    opt.Description = ParsePlusString(iterator);
                                }
                                else
                                {
                                    opt.Description = iterator.Current.GetValue();
                                    iterator.MoveNext();
                                        // ParsePlusString moves next once it's complete, need to do the same here
                                }

                                prop.Options.Add(opt);
                                if (iterator.Current.Type != LexType.Colon)
                                {
                                    continue;
                                }
                                Expect(iterator, LexType.Value);
                                opt.On = iterator.Current.Value == "1";
                                iterator.MoveNext();
                            }
                            Assert(iterator.Current.Type == LexType.Close, "Unexpected " + iterator.Current.Type);
                            iterator.MoveNext();
                        }
                        gdo.Properties.Add(prop);
                    }
                }
                Assert(iterator.Current.Type == LexType.Close, "Unexpected " + iterator.Current.Type);
                gd.Classes.Add(gdo);
            }
        }
示例#2
0
        private void ParseAt(DataStructures.GameData.GameData gd, IEnumerator<LexObject> iterator)
        {
            iterator.MoveNext();
            var type = iterator.Current.Value;
            if (type == "include")
            {
                Expect(iterator, LexType.String);
                if (CurrentFile != null)
                {
                    var filename = iterator.Current.GetValue();
                    var path = Path.GetDirectoryName(CurrentFile) ?? "";
                    var incfile = Path.Combine(path, filename);
                    var incgd = GetGameDataFromFile(incfile);
                    gd.MapSizeHigh = incgd.MapSizeHigh;
                    gd.MapSizeLow = incgd.MapSizeLow;
                    gd.Includes.Add(filename);
                    gd.Classes.AddRange(incgd.Classes);
                }
                else
                {
                    throw new ProviderException("Unable to include a file when not reading from a file.");
                }
            }
            else if (type == "mapsize")
            {
                Expect(iterator, LexType.So);
                Expect(iterator, LexType.Value);
                gd.MapSizeLow = Int32.Parse(iterator.Current.Value);
                Expect(iterator, LexType.Comma);
                Expect(iterator, LexType.Value);
                gd.MapSizeHigh = Int32.Parse(iterator.Current.Value);
                Expect(iterator, LexType.Already);
            }
            else
            {
                // Parsing:
                // @TypeClass name(param, param) name()
                var ct = ParseClassType(type);
                var gdo = new GameDataObject("", "", ct);
                iterator.MoveNext();
                while (iterator.Current.Type == LexType.Value)
                {
                    // Parsing:
                    // @TypeClass {name(param, param) name()}
                    var name = iterator.Current.Value;
                    var bh = new Behaviour(name);
                    iterator.MoveNext();
                    if (iterator.Current.Type == LexType.Value)
                    {
                        // Allow for the following (first seen in hl2 base):
                        // @PointClass {halfgridsnap} base(Targetname)
                        continue;
                    }
                    Assert(iterator.Current.Type == LexType.So, "Unexpected " + iterator.Current.Type);
                    iterator.MoveNext();
                    while (iterator.Current.Type != LexType.Already)
                    {
                        // Parsing:
                        // name({param, param})
                        if (iterator.Current.Type != LexType.Comma)
                        {
                            Assert(iterator.Current.Type == LexType.Value || iterator.Current.Type == LexType.String,
                                   "Unexpected " + iterator.Current.Type + ".");
                            var value = iterator.Current.Value;
                            if (iterator.Current.Type == LexType.String) value = value.Trim('"');
                            bh.Values.Add(value);
                        }
                        iterator.MoveNext();
                    }
                    Assert(iterator.Current.Type == LexType.Already, "Unexpected " + iterator.Current.Type);
                    // Treat base behaviour as a special case
                    if (bh.Name == "base")
                    {
                        gdo.BaseClasses.AddRange(bh.Values);
                    }
                    else
                    {
                        gdo.Behaviours.Add(bh);
                    }
                    iterator.MoveNext();
                }
                // = class_name : "Descr" + "iption" [
                Assert(iterator.Current.Type == LexType.Equals, "Expected equals, got " + iterator.Current.Type);
                Expect(iterator, LexType.Value);
                gdo.Name = iterator.Current.Value;
                iterator.MoveNext();
                if (iterator.Current.Type == LexType.Colon)
                {
                    // Parsing:
                    // : {"Descr" + "iption"} [
                    iterator.MoveNext();
                    gdo.Description = ParsePlusString(iterator);
                }
                Assert(iterator.Current.Type == LexType.Open, "Unexpected " + iterator.Current.Type);

                // Parsing:
                // name(type) : "Desc" : "Default" : "Long Desc" = [ ... ]
                // input name(type) : "Description"
                // output name(type) : "Description"
                iterator.MoveNext();
                while (iterator.Current.Type != LexType.Close)
                {
                    Assert(iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type);
                    var pt = iterator.Current.Value;
                    if (pt == "input" || pt == "output") // IO
                    {
                        // input name(type) : "Description"
                        var io = new IO();
                        Expect(iterator, LexType.Value);
                        io.IOType = (IOType) Enum.Parse(typeof (IOType), pt, true);
                        io.Name = iterator.Current.Value;
                        Expect(iterator, LexType.So);
                        Expect(iterator, LexType.Value);
                        io.VariableType = ParseVariableType(iterator.Current.Value);
                        Expect(iterator, LexType.Already);
                        iterator.MoveNext(); // if not colon, this will be the value of the next io/property, or close
                        if (iterator.Current.Type == LexType.Colon)
                        {
                            iterator.MoveNext();
                            io.Description = ParsePlusString(iterator);
                        }
                        gdo.InOuts.Add(io);
                    }
                    else // Property
                    {
                        Expect(iterator, LexType.So);
                        Expect(iterator, LexType.Value);
                        var vartype = ParseVariableType(iterator.Current.Value);
                        Expect(iterator, LexType.Already);
                        var prop = new Property(pt, vartype);
                        iterator.MoveNext(); // if not colon or equals, this will be the value of the next io/property, or close
                        if (iterator.Current.Type == LexType.Value && iterator.Current.Value == "readonly")
                        {
                            // Readonly properties require a special case:
                            // name(type) readonly : "Description"
                            prop.ReadOnly = true;
                            iterator.MoveNext();
                        }
                        do // Using do/while(false) so I can break out - reduces nesting.
                        {
                            // Short description
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            prop.ShortDescription = ParsePlusString(iterator);

                            // Default value
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            if (iterator.Current.Type != LexType.Colon) // Allow for ': :' structure (no default)
                            {
                                if (iterator.Current.Type == LexType.String)
                                {
                                    prop.DefaultValue = iterator.Current.Value.Trim('"');
                                }
                                else
                                {
                                    Assert(iterator.Current.Type == LexType.Value, "Unexpected " + iterator.Current.Type);
                                    prop.DefaultValue = iterator.Current.Value;
                                }
                                iterator.MoveNext();
                            }

                            // Long description
                            if (iterator.Current.Type != LexType.Colon) break;
                            iterator.MoveNext();
                            prop.Description = ParsePlusString(iterator);
                        } while (false);
                        if (iterator.Current.Type == LexType.Equals)
                        {
                            Expect(iterator, LexType.Open);
                            // Parsing property options:
                            // value : description
                            // value : description : 0
                            iterator.MoveNext();
                            while (iterator.Current.IsValueOrString())
                            {
                                var opt = new Option
                                {
                                    Key = iterator.Current.GetValue()
                                };
                                Expect(iterator, LexType.Colon);

                                // Some FGDs use values for property descriptions instead of strings
                                iterator.MoveNext();
                                Assert(iterator.Current.IsValueOrString(), "Choices value must be value or string type.");
                                if (iterator.Current.Type == LexType.String)
                                {
                                    opt.Description = ParsePlusString(iterator);
                                }
                                else
                                {
                                    opt.Description = iterator.Current.GetValue();
                                    iterator.MoveNext(); // ParsePlusString moves next once it's complete, need to do the same here
                                }

                                prop.Options.Add(opt);
                                if (iterator.Current.Type != LexType.Colon)
                                {
                                    continue;
                                }
                                Expect(iterator, LexType.Value);
                                opt.On = iterator.Current.Value == "1";
                                iterator.MoveNext();
                            }
                            Assert(iterator.Current.Type == LexType.Close, "Unexpected " + iterator.Current.Type);
                            iterator.MoveNext();
                        }
                        gdo.Properties.Add(prop);
                    }
                }
                Assert(iterator.Current.Type == LexType.Close, "Unexpected " + iterator.Current.Type);
                gd.Classes.Add(gdo);
            }
        }