Last active
August 29, 2015 14:19
-
-
Save 1328/9d7babae7f6e9286dfb2 to your computer and use it in GitHub Desktop.
parser 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from collections import namedtuple | |
| Action = namedtuple('Action', ['verb', 'noun', 'adjective', 'indirect']) | |
| NOUNS = ['sword', 'dog', 'hat'] | |
| VERBS = ['get', 'go', 'eat', 'north', 'east'] | |
| PREPOSITIONS = [ | |
| 'below', 'off', 'toward', 'above', 'beneath', 'on', 'under', | |
| 'across', 'beside', 'from', 'onto', 'underneath', 'between', | |
| 'in', 'out', 'until', 'against', 'beyond', | |
| 'outside', 'along', 'inside', 'over', 'upon', 'among', | |
| 'by', 'past', 'around', 'with', 'at ', 'into', | |
| 'within', 'down', 'through', 'without', 'before', | |
| 'near', 'throughout', 'behind', 'except', 'of', 'to' | |
| ] | |
| CINNAMONS = {'walk':'go', 'consume':'eat', 'n': 'north'} | |
| ELIDE = ['the', 'a'] | |
| def parse(command): | |
| ''' break words into a list, substituing common synonyms, and | |
| return Action ''' | |
| words = [CINNAMONS.get(w, w) for w in command.split() if w not in ELIDE] | |
| return create_action(words) | |
| def parse_preposition(words): | |
| '''parses prepositional phrases | |
| works by finding the last preposition and then cutting off remainder of | |
| words | |
| ''' | |
| last = None | |
| for idx, word in enumerate(words): | |
| if word in PREPOSITIONS: | |
| last = idx | |
| if last is None or last > len(words)-2: | |
| return words, None, None | |
| remaining = [w for idx, w in enumerate(words) if idx < last] | |
| preposition = words[last] | |
| indirect = words[last+1] | |
| return remaining, preposition, indirect | |
| def parse_adjective(words): | |
| '''In a sufficiently long string, treat the word preceding a noun as an | |
| adjective''' | |
| if len(words) == 0: | |
| return [], None, None | |
| found, noun = None, None | |
| remaining = [] | |
| for idx, word in enumerate(words): | |
| if word in NOUNS: | |
| found = idx | |
| noun = word | |
| break | |
| if len(words)<2: | |
| # only one owrd left so no adjective | |
| if noun is not None: | |
| return [], noun, None | |
| return [], words[0], None | |
| if noun is None: | |
| # if we don't match a noun, just make a guess that it is the last word | |
| noun = word[-1] | |
| idx = len(words) - 1 | |
| used = (idx, idx -1) | |
| remaining = [w for idx, w in enumerate(words) if idx not in used] | |
| return remaining, words[idx], words[idx-1] | |
| def parse_verb(words): | |
| remaining = [] | |
| verb = None | |
| for word in words: | |
| if word in VERBS: | |
| verb = word | |
| else: | |
| remaining.append(word) | |
| if verb is None: | |
| # hmm, could not match a verb, so just assume the first word of words is | |
| # a verb and return that | |
| return words[1:], words[0] | |
| return remaining, verb | |
| def create_action(words): | |
| #print('create_action called on {}, kws = {}'.format(words, [(k,v) for k,v in kws.items()])) | |
| words, verb = parse_verb(words) | |
| words, preposition, indirect = parse_preposition(words) | |
| words, noun, adjective = parse_adjective(words) | |
| return Action(verb, noun, adjective, indirect) | |
| check = [ | |
| 'north', | |
| 'n', | |
| 'eat hat', | |
| 'consume hat', | |
| 'consume green hat', | |
| 'get dog from table', | |
| 'get orange dog from table', | |
| 'get orange dog from under', | |
| 'get orange dog from under table', | |
| 'get orange dog from under pink table', # doesn't work too complex | |
| 'get the really, really big sword', | |
| ] | |
| for phrase in check: | |
| print('"{}" => {}'.format(phrase, parse(phrase))) | |
| print('-'*10) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment