protected override Maybe <IReportNode> Execute(TextParser p) { var month = p.Before(",").AsString(); if (!month) { return(Error(month)); } var year = p.After("Year").SkipWhitespaces().Integer(); if (!year) { return(Error(year)); } return(Ok(ReportNode.Bag( ReportArray.Key("date", ReportNode.Object( ReportNode.Str("month", month), ReportNode.Int("year", year) )) ))); }
protected override Maybe <IReportNode> Execute(TextParser p) { var prefix = p.After("Skills:").SkipWhitespaces(); if (!prefix) { return(Error(prefix)); } List <IReportNode> skills = new List <IReportNode>(); if (!p.Match("none")) { while (!p.EOF) { if (skills.Count > 0) { if (!Mem(p.After(",").SkipWhitespaces())) { return(Error(LastResult)); } } var skill = skillParser.Parse(p); if (!skill) { return(Error(skill)); } skills.Add(skill.Value); } } return(Ok(ReportNode.Bag( ReportNode.Key("skills", ReportNode.Array(skills)) ))); }
protected override Maybe <IReportNode> Execute(TextParser p) { var name = p.Before("[").SkipWhitespacesBackwards().AsString(); if (!name) { return(Error(name)); } var code = p.Between("[", "]").AsString(); if (!code) { return(Error(code)); } p.PushBookmark(); var level = p.SkipWhitespaces().Integer(); var days = Maybe <int> .NA; if (level) { p.RemoveBookmark(); days = p.Try(parser => parser.SkipWhitespaces().Between("(", ")").Integer()); } else { p.PopBookmark(); } return(Ok(ReportNode.Object( ReportNode.Str("name", name), ReportNode.Str("code", code), level ? ReportNode.Int("level", level) : null, days ? ReportNode.Int("days", days) : null ))); }
protected override Maybe <IReportNode> Execute(TextParser p) { var faction = factionName.Parse(p); if (!faction) { return(Error(faction)); } var args = p.After("(").BeforeBackwards(")").List(",", argumentParser); if (!args) { return(Error(args)); } return(Ok(ReportNode.Bag( ReportNode.Key("faction", ReportNode.Object( faction.Value, ReportNode.Key("type", ReportNode.Array(args.Value)) ) ) ))); }
public static Maybe <IReportNode[]> List(this TextParser p, ReadOnlySpan <char> separator, IReportParser itemParser) => List(p, separator, x => itemParser.Parse(x));
public static Maybe <IReportNode> Try(this TextParser parser, IReportParser reportParser) => Try(parser, reportParser.Parse);
protected override Maybe <IReportNode> Execute(TextParser p) { var nameAndNumber = p.After("+").SkipWhitespaces().Before("] : "); // lets hope noone will use this combination in their building names if (!nameAndNumber) { return(Error(nameAndNumber)); } var name = nameAndNumber.BeforeBackwards("[").SkipWhitespacesBackwards().AsString(); if (!name) { return(Error(name)); } var number = nameAndNumber.After("[").Integer(); if (!number) { return(Error(number)); } p.After("] :").SkipWhitespaces(); Queue <TextParser> props = new Queue <TextParser>(); if (!p.EOF) { var props1 = p .Before(";") .RecoverWith(() => p.BeforeBackwards(".")) .List(",", item => item.SkipWhitespaces()); var props2 = p .After(";") .BeforeBackwards(".") .List(";", item => item.SkipWhitespaces()); if (props1) { foreach (var prop in props1.Value) { props.Enqueue(prop); } } if (props2) { foreach (var prop in props2.Value) { props.Enqueue(prop); } } } var type = props.Dequeue().AsString(); var structure = ReportNode.Object( ReportNode.Str("name", name), ReportNode.Int("number", number), ReportNode.Str("type", type) ); if (type.Equals("fleet", StringComparison.OrdinalIgnoreCase)) { var contents = ReportNode.Array(); structure.Add(ReportNode.Key("contents", contents)); while (props.Count > 0) { var item = props.Peek(); item.PushBookmark(); var objCount = item.Integer(); var objType = item.SkipWhitespaces().AsString(); if (!objCount || !objType) { item.PopBookmark(); break; } else { contents.Add(ReportNode.Object( ReportNode.Int("count", objCount), ReportNode.Str("type", objType) )); props.Dequeue(); } } } var flags = ReportNode.Array(); structure.Add(ReportNode.Key("flags", flags)); List <TextParser> unknownProps = new List <TextParser>(); foreach (var prop in props) { var knownProp = prop.OneOf( x => x.After("needs") .SkipWhitespaces() .Integer() .Map(v => ReportNode.Int("needs", v)), x => { var targetProp = x.After("Load:").SkipWhitespaces(); if (!targetProp) { return(targetProp.Convert <IReportNode>()); } var value = targetProp.Before("/").Integer(); if (!value) { return(value.Convert <IReportNode>()); } var max = targetProp.After("/").Integer(); if (!max) { return(max.Convert <IReportNode>()); } return(new Maybe <IReportNode>(ReportNode.Key("load", ReportNode.Object( ReportNode.Int("used", value), ReportNode.Int("max", max) )))); }, x => { var targetProp = x.After("Sailors:").SkipWhitespaces(); if (!targetProp) { return(targetProp.Convert <IReportNode>()); } var value = targetProp.Before("/").Integer(); if (!value) { return(value.Convert <IReportNode>()); } var max = targetProp.After("/").Integer(); if (!max) { return(max.Convert <IReportNode>()); } return(new Maybe <IReportNode>(ReportNode.Key("sailors", ReportNode.Object( ReportNode.Int("current", value), ReportNode.Int("required", max) )))); }, x => x.After("MaxSpeed:") .SkipWhitespaces() .Integer() .Map(v => ReportNode.Int("speed", v)), x => x.After("Sail directions:") .SkipWhitespaces() .List(",", item => item.SkipWhitespaces()) .Map(v => ReportNode.Key("sailDirections", ReportNode.Array( v.Select(sd => ReportNode.Str(sd.AsString())) ))) ); if (knownProp) { structure.Add(knownProp.Value); continue; } var knownFlag = prop.OneOf( x => x.Match("closed to player units"), x => x.Match("contains an inner location"), x => x.Match("engraved with runes of warding") ).AsString(); if (knownFlag) { flags.Add(ReportNode.Str(knownFlag.Value)); continue; } unknownProps.Add(prop); } if (unknownProps.Count > 0) { structure.Add(ReportNode.Str("description", string.Join("; ", unknownProps.Select(x => x.AsString())))); } return(Ok(structure)); }
protected override Maybe <IReportNode> Execute(TextParser p) { var terrain = p.Before("(").SkipWhitespacesBackwards().AsString(); if (!terrain) { return(Error(terrain)); } var coords = coordsParser.Parse(p); if (!coords) { return(Error(coords)); } var province = p.After("in").SkipWhitespaces().OneOf( x => x.Before(","), x => x.Before(".") ).AsString(); if (!province) { return(Error(province)); } var settlement = p.Try(x => { var name = p.After(",").After("contains").SkipWhitespaces().Before("[").SkipWhitespacesBackwards().AsString(); if (!name) { return(name.Convert <(string, string)>()); } var size = p.Between("[", "]").AsString(); if (!size) { return(size.Convert <(string, string)>()); } return(new Maybe <(string, string)>((name.Value, size.Value))); }); var population = p.Try(x => { var amount = p.After(",").SkipWhitespaces().Integer(); if (!amount) { return(amount.Convert <(int, string)>()); } var race = p.Between("(", ")").AsString(); if (!race) { return(race.Convert <(int, string)>()); } return(new Maybe <(int, string)>((amount.Value, race.Value))); }); var tax = p.Try(x => x.After("$").Integer()); return(Ok(ReportNode.Bag( ReportNode.Str("terrain", terrain), ReportNode.Key("coords", coords.Value), ReportNode.Str("province", province), settlement ? ReportNode.Key("settlement", ReportNode.Object( ReportNode.Str("name", settlement.Value.Item1), ReportNode.Str("size", settlement.Value.Item2) )) : null, population ? ReportNode.Key("population", ReportNode.Object( ReportNode.Int("amount", population.Value.Item1), ReportNode.Str("race", population.Value.Item2) )) : null, tax ? ReportNode.Int("tax", tax) : null ))); }
protected override Maybe <IReportNode> Execute(TextParser p) { // don't need dot at the end of line p = p.BeforeBackwards("."); bool own = false; if (p.Match("*")) { own = true; } else if (!Mem(p.Match("-"))) { return(Error(LastResult)); } p = p.SkipWhitespaces(); // unit name // Legatus Legionis Marcus (640) var name = nameParser.Parse(p); if (!name) { return(Error(name)); } // optional on guard flag // , on guard var onGuard = p.Try(parser => parser.After(",").SkipWhitespaces().Match("on guard")); // optional faction name unless this is own unit // , Avalon Empire (15) var faction = p.Try(parser => factionParser.Parse(parser.After(",").SkipWhitespaces())); if (!faction && own) { return(Error(faction)); } // now check for description, it must start with `;` Maybe <string> description = Maybe <string> .NA; p.PushBookmark(); if (p.After(";")) { var descPos = p.Pos - 2; description = new Maybe <string>(p.SkipWhitespaces().SkipWhitespacesBackwards().AsString()); // w/o description p.PopBookmark(); p = p.Slice(descPos - p.Pos + 1); } else { p.RemoveBookmark(); } List <string> flags = new List <string>(); List <IReportNode> items = new List <IReportNode>(); // all element after faction name till first item are flags while (items.Count == 0 && !p.EOF) { // , flag if (!Mem(p.After(",").SkipWhitespaces())) { return(Error(LastResult)); } // there could be no flags var flagOrItem = p.Before(",", ".").RecoverWith(() => p); var item = itemParser.Parse(flagOrItem); if (item) { items.Add(item.Value); } else { flags.Add(flagOrItem.Reset().AsString()); } } var remainingItems = p.Before(".").RecoverWith(() => p).Value; while (!remainingItems.EOF) { var nextItem = remainingItems.After(",").SkipWhitespaces(); if (!nextItem) { break; } var item = itemParser.ParseMaybe(nextItem.Before(",").RecoverWith(() => nextItem)); if (item) { items.Add(item.Value); } } List <IReportNode> props = new List <IReportNode>(); while (!p.EOF) { var nextProp = p.After(".").SkipWhitespaces(); if (!nextProp) { break; } var notSuccess = !nextProp.Success; nextProp = nextProp.Before(".").RecoverWith(() => nextProp); var prop = nextProp.OneOf( weightParser, capacityParser, canStudyParser, skillsParser ); if (prop) { props.Add(prop.Value); } } var result = ReportNode.Object(); result.Add(ReportNode.Bool("own", own)); result.Add(name.Value); result.Add(ReportNode.Key("faction", faction ? ReportNode.Object(faction.Value) : ReportNode.Null())); result.Add(ReportNode.Key("description", description ? ReportNode.Str(description) : ReportNode.Null())); result.Add(ReportNode.Bool("onGuard", onGuard)); result.Add(ReportNode.Key("flags", ReportNode.Array(flags.Select(x => ReportNode.Str(x))))); result.Add(ReportNode.Key("items", ReportNode.Array(items))); result.AddRange(props); return(new Maybe <IReportNode>(result)); }