public static Assignment ParseAssignment(this IEnumerator <Token> tokenStream, IdentifierToken id) { var valueToken = GetNext(tokenStream); switch (valueToken) { case IntegerToken: break; case FloatToken: break; case BooleanToken: break; case StringToken: break; default: throw ParsingException.CreateError(valueToken, "value"); } ExpectNext <SemicolonToken>(tokenStream); return(new Assignment(id, valueToken)); }
private static List <string> ParseStringList(IEnumerator <Token> tokenStream) { var strings = new List <string>(); tokenStream.ExpectNext <OpenBraceToken>(); while (true) { var token = tokenStream.GetNext(); switch (token) { case CommaToken: break; case StringToken s: strings.Add(s.Value); break; case CloseBraceToken: return(strings); default: throw ParsingException.CreateError(token, "identifier or end of block"); } } }
public static IEnumerable <IExpression> Parse(IEnumerable <Token> tokens) { using var tokenStream = tokens.GetEnumerator(); while (tokenStream.MoveNext()) { if (tokenStream.Current is IdentifierToken i) { switch (tokenStream.GetNext()) { case OpenBraceToken _: yield return(ParseBlock(i, tokenStream)); break; case EqualsToken _: yield return(tokenStream.ParseAssignment(i)); break; default: throw ParsingException.CreateError(tokenStream.Current, "open brace or equals"); } } else { throw ParsingException.CreateError <IdentifierToken>(tokenStream.Current); } } }
private static IExpression ParseBlock(IdentifierToken name, IEnumerator <Token> tokenStream) { var token = tokenStream.GetNext(); return(token switch { CloseBraceToken _ => new Block(name, ImmutableArray <Assignment> .Empty), IdentifierToken i => ParseBlock(name, i, tokenStream), _ => throw ParsingException.CreateError(token, "identifier or end of block"), });
private static Elevator ParseElevator(IEnumerator <Token> tokenStream, IdentifierToken id) { var oldNum = tokenStream .ExpectNext <IntegerToken>() .ValueAsUshort(token => ParsingException.CreateError(token, "UShort value")); tokenStream.ExpectNext <SemicolonToken>(); return(new Elevator(oldNum)); }
private static IExpression ParseBlockOrTupleList(IdentifierToken name, IEnumerator <Token> tokenStream) { var token = tokenStream.GetNext(); return(token switch { OpenBraceToken ob => ParseIntTupleList(name, ob.Location, tokenStream), CloseBraceToken _ => new Block(name, ImmutableArray <Assignment> .Empty), IdentifierToken i => ParseBlock(name, i, tokenStream), _ => throw ParsingException.CreateError(token, "identifier, end of block, or start of tuple"), });
private static TileMappings ParseTileMappings(IEnumerator <Token> tokenStream) { tokenStream.ExpectNext <OpenBraceToken>(); var ambushModzones = new List <AmbushModzone>(); var changeTriggerModzones = new List <ChangeTriggerModzone>(); var tileTemplates = new List <TileTemplate>(); var triggerTemplates = new List <TriggerTemplate>(); var zoneTemplates = new List <ZoneTemplate>(); while (true) { var token = tokenStream.GetNext(); switch (token) { case IdentifierToken id: switch (id.Id.ToLower()) { case "modzone": ParseModzone(tokenStream, id, ambushModzones, changeTriggerModzones); break; case "tile": tileTemplates.Add(ParseTileTemplate(tokenStream, id)); break; case "trigger": triggerTemplates.Add(ParseTriggerTemplate(tokenStream, id)); break; case "zone": zoneTemplates.Add(ParseZone(tokenStream, id)); break; default: throw ParsingException.CreateError(id, "unknown identifier"); } break; case CloseBraceToken: return(new TileMappings( ambushModzones.ToImmutableArray(), changeTriggerModzones.ToImmutableArray(), tileTemplates.ToImmutableArray(), triggerTemplates.ToImmutableArray(), zoneTemplates.ToImmutableArray())); default: throw ParsingException.CreateError(token, "identifier or end of block"); } } }
private static TriggerTemplate ParseTriggerTemplate(IEnumerator <Token> tokenStream, IdentifierToken id) { var oldNum = tokenStream .ExpectNext <IntegerToken>() .ValueAsUshort(token => ParsingException.CreateError(token, "UShort value")); tokenStream.ExpectNext <OpenBraceToken>(); var block = tokenStream.ParseBlock(id); return(ReadTriggerTemplate(oldNum, block)); }
private static ZoneTemplate ParseZone(IEnumerator <Token> tokenStream, IdentifierToken id) { var oldNum = tokenStream .ExpectNext <IntegerToken>() .ValueAsUshort(token => ParsingException.CreateError(token, "UShort value")); tokenStream.ExpectNext <OpenBraceToken>(); var block = tokenStream.ParseBlock(id); var fields = block.GetFieldAssignments(); return(new ZoneTemplate( oldNum, Comment: fields.GetOptionalFieldValue("comment", ""))); }
private static void ParseModzone( IEnumerator <Token> tokenStream, IdentifierToken id, List <AmbushModzone> ambushModzones, List <ChangeTriggerModzone> changeTriggerModzones) { var oldNum = tokenStream .ExpectNext <IntegerToken>() .ValueAsUshort(token => ParsingException.CreateError(token, "UShort value")); bool fillZone = false; var next = tokenStream.ExpectNext <IdentifierToken>(); if (next.Id.ToLower() == "fillzone") { fillZone = true; next = tokenStream.ExpectNext <IdentifierToken>(); } if (next.Id.ToLower() == "ambush") { tokenStream.ExpectNext <SemicolonToken>(); ambushModzones.Add(new AmbushModzone(oldNum, fillZone)); } else if (next.Id.ToLower() == "changetrigger") { var action = tokenStream.ExpectNext <StringToken>().Value; tokenStream.ExpectNext <OpenBraceToken>(); var block = tokenStream.ParseBlock(id); var triggerTemplate = ReadTriggerTemplate(oldNum, block); changeTriggerModzones.Add(new ChangeTriggerModzone(oldNum, action, triggerTemplate, fillZone)); } else { throw ParsingException.CreateError(next, "ambush or changetrigger"); } }
public static Block ParseBlock(this IEnumerator <Token> tokenStream, IdentifierToken name) { var assignments = new List <Assignment>(); while (true) { var token = GetNext(tokenStream); switch (token) { case IdentifierToken i: ExpectNext <EqualsToken>(tokenStream); assignments.Add(tokenStream.ParseAssignment(i)); break; case CloseBraceToken: return(new Block(name, assignments.ToImmutableArray())); default: throw ParsingException.CreateError(token, "identifier or end of block"); } } }
private static IEnumerable <IMapping> ParseThingMappings(IEnumerator <Token> tokenStream) { tokenStream.ExpectNext <OpenBraceToken>(); var thingMappings = new List <IMapping>(); while (true) { var token = tokenStream.GetNext(); switch (token) { case IdentifierToken id: switch (id.Id.ToLower()) { case "elevator": thingMappings.Add(ParseElevator(tokenStream, id)); break; case "trigger": thingMappings.Add(ParseTriggerTemplate(tokenStream, id)); break; default: throw ParsingException.CreateError(id, "unknown identifier"); } break; case OpenBraceToken: thingMappings.Add(ParseThingTemplate(tokenStream)); break; case CloseBraceToken: return(thingMappings); default: throw ParsingException.CreateError(token, "identifier or end of block"); } } }
private static FlatMappings ParseFlatMappings(IEnumerator <Token> tokenStream) { var ceilings = new List <string>(); var floors = new List <string>(); tokenStream.ExpectNext <OpenBraceToken>(); while (true) { var token = tokenStream.GetNext(); switch (token) { case IdentifierToken id: switch (id.Id.ToLower()) { case "ceiling": ceilings.AddRange(ParseStringList(tokenStream)); break; case "floor": floors.AddRange(ParseStringList(tokenStream)); break; default: throw ParsingException.CreateError(id, "unknown identifier"); } break; case CloseBraceToken: return(new FlatMappings( ceilings.ToImmutableArray(), floors.ToImmutableArray())); default: throw ParsingException.CreateError(token, "identifier or end of block"); } } }
private static (string mapLump, string?mapName, bool isMapNameLookup) ParseMapHeader( IdentifierToken context, IEnumerator <Token> tokenStream) { var mapLump = tokenStream.ExpectNext <StringToken>().Value; string?mapName = null; bool isMapNameLookup = false; var next = tokenStream.GetNextSkippingNewlines(); if (next is StringToken nameToken) { mapName = nameToken.Value; tokenStream.ExpectNextSkippingNewlines <OpenBraceToken>(); } else if (next is IdentifierToken lookupToken) { if (lookupToken.Id.ToLower() != "lookup") { throw ParsingException.CreateError(lookupToken, "lookup"); } isMapNameLookup = true; mapName = tokenStream.ExpectNext <StringToken>().Value; tokenStream.ExpectNextSkippingNewlines <OpenBraceToken>(); } else if (next is OpenBraceToken) { // expected, do nothing } else { throw new ParsingException("Messed up map definition: " + context); } return(mapLump, mapName, isMapNameLookup); }
private static IEnumerable <VariableAssignment> ParseBlock(IEnumerator <Token> tokenStream, bool alreadyOpened) { if (!alreadyOpened) { tokenStream.ExpectNextSkippingNewlines <OpenBraceToken>(); } while (true) { var token = tokenStream.GetNextSkippingNewlines(); switch (token) { case IdentifierToken id: var next = tokenStream.GetNext(); var valueBuilder = ImmutableArray.CreateBuilder <Token>(); switch (next) { case NewLineToken: yield return(new VariableAssignment(id, valueBuilder.ToImmutable())); break; case EqualsToken: next = tokenStream.GetNext(); if (next == null || next is NewLineToken) { throw new ParsingException($"Messed up line staring with {id}"); } valueBuilder.Add(next); bool continueLoop = true; while (continueLoop) { next = tokenStream.GetNext(); switch (next) { case NewLineToken: yield return(new VariableAssignment(id, valueBuilder.ToImmutable())); continueLoop = false; break; case null: throw new ParsingException("Unexpected end of file"); default: valueBuilder.Add(next); break; } } break; default: throw new ParsingException($"Messed up line starting with {id}"); } break; case CloseBraceToken: yield break; default: throw ParsingException.CreateError(token, "identifier or close brace"); } } }
private static ThingTemplate ParseThingTemplate(IEnumerator <Token> tokenStream) { var oldNum = tokenStream .ExpectNext <IntegerToken>() .ValueAsUshort(token => ParsingException.CreateError(token, "UShort value")); tokenStream.ExpectNext <CommaToken>(); var actor = tokenStream.ExpectNext <IdentifierToken>().Id.ToString(); tokenStream.ExpectNext <CommaToken>(); var angles = tokenStream.ExpectNext <IntegerToken>().Value; tokenStream.ExpectNext <CommaToken>(); var flags = new HashSet <string>(); var next = tokenStream.GetNext(); if (next is IntegerToken i) { if (i.Value != 0) { throw ParsingException.CreateError(i, "Expected 0 value for flags"); } tokenStream.ExpectNext <CommaToken>(); } else if (next is IdentifierToken flagToken) { flags.Add(flagToken.Id.ToLower()); while (true) { next = tokenStream.GetNext(); if (next is CommaToken) { break; } else if (next is PipeToken) { flags.Add(tokenStream.ExpectNext <IdentifierToken>().Id.ToLower()); } else { throw ParsingException.CreateError(next, "Comma or pipe"); } } } else { throw ParsingException.CreateError(next, "Expected number or flags"); } var minSkill = tokenStream.ExpectNext <IntegerToken>().Value; tokenStream.ExpectNext <CloseBraceToken>(); return(new ThingTemplate( oldNum, actor, angles, Holowall: flags.Contains("holowall"), Pathing: flags.Contains("pathing"), Ambush: flags.Contains("ambush"), Minskill: minSkill)); }