private CommandLineParserResult HandleExcept(CommandLineParserResult result, TokenizedInput tokens, string currentToken) { var index = tokens.IndexOf(currentToken) + 1; if (index >= tokens.Count) { return(null); } var except = new List <Object>(); // process rest of the tokens as objects for (int i = index; i < tokens.Count; i++) { // TODO: handle multiple objects with same name var next = tokens[i]; if (next.IsPreposition() && result.Preposition == null) { result.Preposition = Prepositions.Get(next); continue; } var obj = GetObject(result, next); if (obj == null) { result.Error = Messages.CantSeeObject; return(result); } else if (obj is MultipleObjectsFound) { var input = GetInput(result.Verb); if (input.Error.HasValue()) { return(input); } if (input.Objects.Count > 0) { except.AddRange(input.Objects); } } else { except.Add(obj); } } result.Objects = result.Objects.Where(x => !except.Contains(x)).ToList(); return(null); }
public Grammar(string format) { Format = format; foreach (var token in Tokens) { if (Prepositions.Contains(token)) { Preposition = token; break; } } }
private CommandLineParserResult Parse(Verb verb, TokenizedInput tokens) { var result = new CommandLineParserResult { Verb = verb }; var lastToken = ""; foreach (string token in tokens) { var obj = GetObject(result, token); if (obj is Skip) { continue; } if (result.Objects.Contains(obj)) { // will happen for something like "take the brass lamp" continue; } if (obj != null) { if (obj.InScope) { if (result.Preposition == null || !result.Objects.Any()) { // handles commands like "put on coat", "put down book", etc. result.Ordered.Add(obj); result.Objects.Add(obj); } else { result.Ordered.Add(obj); result.IndirectObject = obj; } } else if (obj is MultipleObjectsFound) { return(ResolveMultipleObjects(verb, (MultipleObjectsFound)obj)); } else { result.Error = Messages.CantSeeObject; return(result); } } // distinguish between prepositions and movement - "go south", "put bottle down", "close up grate" else if ((result.Verb is IDirectionProxy) && token.IsDirection() && !result.Objects.Any()) { var v = token.ToVerb(); result.Ordered.Add(v); result.Verb = v; } else if (token.IsPreposition()) { var p = Prepositions.Get(token); result.Ordered.Add(p); result.Preposition = p; } else if (token == "all" && !result.Objects.Any()) { result.IsAll = true; if (!verb.Multi && !verb.MultiHeld) { result.Error = Messages.MultiNotAllowed; break; } var multi = new List <Object>(); if (verb.Multi) { var objectsInRoom = from o in CurrentRoom.ObjectsInRoom() where !o.Animate select o; multi.AddRange(objectsInRoom); } if (verb.MultiHeld) { multi.AddRange(Inventory.Items); } // if object count is only 1, we don't add it so it can be handled in the verb using implict // messages e.g. (the small bottle) if (multi.Count > 1) { result.Objects.AddRange(multi); } } else if (token == "except" && (verb.Multi || verb.MultiHeld) && lastToken == "all") { var except = HandleExcept(result, tokens, token); if (except != null) { return(except); } break; } else { obj = result.Objects.FirstOrDefault(); if (obj != null && !result.IsAll) { result.Error = Messages.PartialUnderstanding(verb, obj); } else { result.Error = Messages.CantSeeObject; } return(result); } lastToken = token; } return(result); }
public InputResult Parse(string input) { var result = new InputResult(); var tokenizer = new InputTokenizer(); var tokens = tokenizer.Tokenize(input); if (tokens.Count == 0) { result.Action = () => { Context.Parser.Print(L.DoNotUnderstand); return(true); }; return(result); } // there can be more than one match for verbs like "switch" // which has one class that handles "switch on" and another // class that handles "switch off" var possibleVerbs = VerbList.GetVerbsByName(tokens[0]); if (possibleVerbs.Count == 0) { result.Verb = new NullVerb(); result.Action = ErrorAction(L.VerbNotRecognized); return(result); } if (possibleVerbs.Count == 1) { result.Verb = possibleVerbs.First(); } // remove verb token tokens.RemoveAt(0); var grammarTokens = new List <string>(); bool hasPreposition = false; foreach (string token in tokens) { // var objects = Objects.WithName(token); var objects = ( from o in Objects.WithName(token) where L.ObjectsInScope().Contains(o) select o ).ToList(); bool hasObject = result.Objects.Count > 0; if (!hasObject) { var rooms = Rooms.WithName(token); foreach (var room in rooms) { objects.Add(room); } } if (objects.Count == 0) { bool isDirection = possibleVerbs.Count == 1 && Compass.Directions.Contains(token) && result.Objects.Count == 0; bool isPreposition = Prepositions.Contains(token); if (isDirection) { possibleVerbs.Clear(); possibleVerbs.Add(VerbList.GetVerbByName(token)); } else if (isPreposition) { hasPreposition = true; grammarTokens.Add(token); result.Preposition = token; } else if (token == K.ALL) { grammarTokens.Add(token); result.IsAll = true; } else if (token == K.EXCEPT) { if (!result.IsAll && !result.Objects.Any()) { result.Action = ErrorAction(L.CantSeeObject); return(result); } result.IsExcept = true; } else { result.Action = ErrorAction(L.CantSeeObject); return(result); } } else { // need to implement "Which do you mean, the red cape or the black cape?" type behavior here Object obj; var ofInterest = objects.Where(x => x.InScope).ToList(); if (ofInterest.Count > 1) { obj = ofInterest.FirstOrDefault(x => x.InInventory); } else { obj = ofInterest.FirstOrDefault(); } //------------------------------------------------------------------------------------- bool isIndirectObject = hasPreposition && hasObject; if (obj == null) { result.Action = ErrorAction(L.CantSeeObject); return(result); } if (isIndirectObject) { grammarTokens.Add(K.INDIRECT_OBJECT_TOKEN); result.IndirectObject = obj; } else if (result.IsExcept) { result.Exceptions.Add(obj); } else { if (!grammarTokens.Contains(K.OBJECT_TOKEN)) { grammarTokens.Add(K.OBJECT_TOKEN); } if (!result.Objects.Contains(obj)) { result.Objects.Add(obj); } } } } result.Pregrammar = string.Join(" ", grammarTokens.ToArray()); var grammarBuilder = new GrammarBuilder(grammarTokens); var grammars = grammarBuilder.Build(); FindVerb(result, possibleVerbs, grammars); if ((result.IsAll || result.Objects.Count > 1) && !result.Verb.AllowsMulti) { return(DoesNotAllowMulti()); } if (result.Grammar == null) { var incomplete = new IncompleteInput(); incomplete.Handle(result); } if (result.IsAll) { if (result.ObjectsMustBeHeld) { result.Objects = Inventory.Items.Reverse().ToList(); } else { // This is different from Inform 6 which will include scenery and static // objects (resulting in the generation of ridiculous messages like // "well house: that's hardly portable" result.Objects = ( from o in L.ObjectsInScope() where o != L.CurrentLocation && !o.IsScenery && !o.IsStatic && !Inventory.Contains(o) select o ).ToList(); } } if (result.IsExcept) { if (!result.Exceptions.Any()) { return(WhatDoYouWantToDo(result)); } result.Exceptions.ForEach(x => result.Objects.Remove(x)); } return(result); }
public bool Parse(string input) { InputTokenizer tokenizer = new InputTokenizer(); var tokens = tokenizer.Tokenize(input); if (tokens.Count == 0) { Error = L.DoNotUnderstand; return(false); } IList <Verb> possibleVerbs = VerbList.GetVerbsByName(tokens[0]); if (possibleVerbs.Count == 0) { Error = L.VerbNotRecognized; return(false); } // remove verb token tokens.RemoveAt(0); var grammarTokens = new List <string>(); bool hasPreposition = false; bool isException = false; foreach (string token in tokens) { var obj = Adventure.Net.Objects.GetByName(token); if (obj == null) { if (Prepositions.Contains(token)) { hasPreposition = true; grammarTokens.Add(token); } else if (token == "all") { grammarTokens.Add(token); } else if (token == "except") { isException = true; } else { Error = L.DoNotUnderstand; return(false); } } else { if (hasPreposition && Objects.Count > 0) { grammarTokens.Add("y"); IndirectObject = obj; } else if (isException) { Exceptions.Add(obj); } else { if (!grammarTokens.Contains("x")) { grammarTokens.Add("x"); } Objects.Add(obj); } } } Pregrammar = string.Join(" ", grammarTokens.ToArray()); var grammarBuilder = new GrammarBuilder(grammarTokens); var grammars = grammarBuilder.Build(); return(true); }
public InputResult Parse(string input) { var result = new InputResult(); var tokenizer = new InputTokenizer(); var tokens = tokenizer.Tokenize(input); Action removeVerbToken = () => tokens.RemoveAt(0); if (tokens.Count == 0) { result.Action = () => { Context.Parser.Print(L.DoNotUnderstand); return(true); }; return(result); } // there can be more than one match for verbs like "switch" // which has one class that handles "switch on" and another // class that handles "switch off" var possibleVerbs = VerbList.GetVerbsByName(tokens[0]); if (possibleVerbs.Count == 0) { result.Verb = new NullVerb(); result.Action = ErrorAction(L.VerbNotRecognized); return(result); } if (possibleVerbs.Count == 1) { result.Verb = possibleVerbs.First(); } //else { NOT sure what to do about multiple possible verbs here} // remove verb token removeVerbToken(); var grammarTokens = new List <string>(); bool hasPreposition = false; foreach (string token in tokens) { bool hasObject = result.Objects.Count > 0; var objects = Objects.WithName(token); if (!hasObject) { var rooms = Rooms.WithName(token); foreach (var room in rooms) { objects.Add(room); } } if (objects.Count == 0) { bool isDirection = possibleVerbs.Count == 1 && Compass.Directions.Contains(token) && result.Objects.Count == 0; bool isPreposition = Prepositions.Contains(token); if (isDirection) { possibleVerbs.Clear(); possibleVerbs.Add(VerbList.GetVerbByName(token)); } else if (isPreposition) { hasPreposition = true; grammarTokens.Add(token); result.Preposition = token; } else if (token == K.ALL) { // result.Objects.AddRange(L.ObjectsInScope()); grammarTokens.Add(token); result.IsAll = true; } else if (token == K.EXCEPT) { if (!result.IsAll && !result.Objects.Any()) { result.Action = ErrorAction(L.CantSeeObject); return(result); } result.IsExcept = true; } else { if (result.IsPartial) { string partial = String.Format("I only understood you as far as wanting to {0} the {1}.", possibleVerbs[0].Name, result.Objects[0].Name); result.Action = ErrorAction(partial); return(result); } result.Action = ErrorAction(L.CantSeeObject); return(result); } } else { // need to implement "Which do you mean, the red cape or the black cape?" type behavior here Object obj; var ofInterest = objects.Where(x => x.InScope).ToList(); if (ofInterest.Count > 1) { obj = ofInterest.FirstOrDefault(x => x.InInventory); } else { obj = ofInterest.FirstOrDefault(); } //------------------------------------------------------------------------------------- bool isIndirectObject = hasPreposition && hasObject; if (obj == null) { result.Action = ErrorAction(L.CantSeeObject); return(result); } if (isIndirectObject) { grammarTokens.Add(K.INDIRECT_OBJECT_TOKEN); result.IndirectObject = obj; } else if (result.IsExcept) { //result.Objects.Remove(obj); result.Exceptions.Add(obj); } else { if (!grammarTokens.Contains(K.OBJECT_TOKEN)) { grammarTokens.Add(K.OBJECT_TOKEN); } if (!result.Objects.Contains(obj)) { result.Objects.Add(obj); } result.IsPartial = true; } } } result.Pregrammar = string.Join(" ", grammarTokens.ToArray()); var grammarBuilder = new GrammarBuilder(grammarTokens); var grammars = grammarBuilder.Build(); FindVerb(result, possibleVerbs, grammars); if (result.Grammar == null) { var incomplete = new IncompleteInput(); incomplete.Handle(result); } if (result.IsAll) { if (result.ObjectsMustBeHeld) { result.Objects = result.Objects.Where(x => x.InInventory).ToList(); } else { result.Objects = L.ObjectsInScope(); } } if (result.IsExcept) { result.Exceptions.ForEach(x => result.Objects.Remove(x)); } return(result); }
public static bool IsPreposition(this string input) { return(Prepositions.Contains(input)); }