class LightGrammar(Grammar): action = Set(['change', 'flash', 'set', 'blink']) light = Set(['top', 'middle', 'bottom']) color = Regex(r'(red|yellow|blue|orange|purple|...)') times = Set(['once', 'twice', 'three times']) | Regex(r'\d+ times') one_parse = action + light + Optional(times) + color GOAL = OneOrMore(one_parse) @staticmethod def test(): parser = RobustParser((LightGrammar())) sents = [ "set my top light to red", "set my top light to red and change middle light to yellow", "set my top light to red and change middle light to yellow and " "flash bottom light twice in blue" ] for sent in sents: tree, result = parser.parse(sent) assert result.one_parse[0].color == 'red' print '"%s"' % sent print "parse tree:" print tree print "parse result:" print result print
class LightAdvancedGrammar(Grammar): action = Set(['change', 'flash', 'set', 'blink']) light = Set(['top', 'middle', 'bottom']) color = Regex(r'(red|yellow|blue|orange|purple|...)').\ set_result_action(color2rgb) times = Set(['once', 'twice', 'three times']).\ set_result_action(times2int) | \ Regex(r'\d+ times').set_result_action(regex2int) one_parse = action + light + Optional(times) + color GOAL = OneOrMore(one_parse) @staticmethod def test(): parser = RobustParser((LightAdvancedGrammar())) tree, result = parser.parse("flash my top light twice in red and " "blink middle light 20 times in yellow") print tree print result assert result.one_parse[0].color == (255, 0, 0) assert result.one_parse[0].times == 2 assert result.one_parse[1].color == (255, 255, 0) assert result.one_parse[1].times == 20 print
class TransportGrammar(Grammar): article = Set(['a', 'an', 'the', 'any', 'some']) personLeft = Set(['person left']) personRight = Set(['person right']) beneficiary = personLeft | personRight item = get_items() to = Set(['to']) color = Set(['black','blue','brown','cyan','green','magenta','orange','pink','purple','red','teal','yellow','white']) itemCol = Optional(color) + item itemArt = Optional(article) + itemCol # | it destination = to + beneficiary command = Optional(itemArt) + Optional(destination) GOAL = OneOrMore(command)
def get_items(): query = "all_obj_names(N)." solutions = prolog.all_solutions(query) names = [] for name in solutions[0]['N']: names.append(name.__str__()[1:-1]) return Set(names)
class TimesGrammar(Grammar): special_maps = [ ('once', 1), ('twice', 2), ('thrice', 3), ] special = Or([replaced_string(s, v) for s, v in special_maps]) numbers = NumbersGrammar.GOAL GOAL = special | \ (numbers + Set('times time').ignore()) sents = [ ('zero time', 0), ('once', 1), ('1 time', 1), ('5 times', 5), ('five times', 5), ('sixty seven times', 67), ('five hundred ten times', 510), ('a million times', int(1e6)), ] @staticmethod def test(): g = TimesGrammar() parser = RobustParser(g) for sent, expect in TimesGrammar.sents: _, r = parser.parse(sent) print(r) assert r.get() == expect, "%s <- %s" % (str(r.get()), sent)
class ColorsGrammar(Grammar): GOAL = Set(color2rgb.keys()).set_result_action(add_rgb_to_result) @staticmethod def test(): parser = RobustParser(ColorsGrammar()) for name, rgb in color2rgb.items(): t, r = parser.parse(name)
class QuestionGrammar(Grammar): search = Set([ "revenue numbers", "revenues", "revenue", "sales", "sales numbers", "same store sales" ]) direction = Set(["increase", "decrease", "change"]) company = Set(["Amazon", "LinkedIn", "Microsoft", "Apple"]) duration = Set([ "last quarter", "this quarter", "from last quarter to this quarter", "from last to this quarter", "from last quarter" ]) parse_rule_0 = search + company parse_rule_1 = search + company + duration parse_rule_2 = search + direction + company + duration parser_rule_3 = search + direction + duration + company GOAL = OneOrMore(parse_rule_0 | parse_rule_1 | parse_rule_2 | parser_rule_3) @staticmethod def test(): parser = RobustParser((QuestionGrammar())) sents = [ "what was the revenue for Amazon last quarter?", "did revenue numbers change for Amazon from last quarter to this quarter?", "how much did same store sales increase for Apple last quarter?" ] for sent in sents: tree, result = parser.parse(sent) assert result.one_parse[0].color == 'red' print '"%s"' % sent print "parse tree:" print tree print "parse result:" print result print
class ColoredLightGrammar(Grammar): # On or off on = Set(['turn on', 'on', 'hit']) off = Set(['turn off', 'off', 'kill']) on_off = on | off # light names general_name = Set(["lights", "light", "lamp", "bulb", "lightbulb"]) specific_name = Set([ "top", "bottom", "middle", "kitchen", "living room", "bedroom", "bedside" ]) light_quantifiers = Set(["both", "all"]) light_name = Optional(light_quantifiers) + \ ZeroOrMore(specific_name) + \ Optional(general_name) # actions action_blink = Optional(Set(["blink", "flash"])) # brightness brightness_more = Set( ["bright", "brighter", "strong", "stronger", "too dark"]) brightness_less = Set( ["less bright", "soft", "softer", "dim", "dimmer", "too bright"]) brightness = brightness_more | brightness_less # saturation saturation_more = Set(["deeper", "darker", "warmer", "too cold"]) saturation_less = Set(["lighter", "shallower", "colder", "too warm"]) saturation = saturation_less | saturation_more color = ColorsGrammar.GOAL times = TimesGrammar.GOAL theme = Set([ "christmas", "xmas", "halloween", "romantic", "valentine", "valentine's", "reading", "beach", "sunrise", "sunset" ]) one_parse = (on_off | light_name + on_off | on_off + light_name | light_name + Optional(color) + Optional(times) | light_name + Optional(times) + Optional(color) | light_name + color | light_name + brightness | brightness + light_name | light_name + saturation | saturation + light_name | theme) GOAL = (OneOrMore(one_parse) | action_blink + OneOrMore(one_parse)) sents = [(True, "blink top lights"), (True, "flash both top and bottom light with red color and " "middle light with green and bottom with purple"), (True, "flash both top and bottom light with red color and " "middle light with green"), (True, "flash both "), (True, "blink top lights twice"), (True, "I want to blink top lights"), (True, "on top"), (True, "have top red"), (True, "change top to red and bottom to yellow"), (True, "lights please on"), (True, "flash middle and top light "), (True, "change my top light to red and middle to yellow then " "bottom blue"), (True, "turn on lights please"), (True, "I want to turn off the top light please"), (True, "I want to turn off the lights please"), (True, "change top lights to red"), (True, "kill top lights for me"), (True, "turn lights on"), (True, "blink top"), (True, "blink top lights twice"), (True, "flash middle light twice with red and top once"), (True, "flash middle light twice red top once"), (True, "give me something romantic"), (True, "my top light is too dark"), (True, "my top and bottom lights can be warmer"), (False, "I want to turn ")] @staticmethod def test(): import time parser = RobustParser(ColoredLightGrammar()) sents = ColoredLightGrammar.sents s = time.time() for expect, sent in sents: s1 = time.time() assert expect == parser.print_parse(sent), sent s2 = time.time() print("parse time: %.2f ms" % ((s2 - s1) * 1000)) print() e = time.time() elapsed = e - s print("total time: %.2f s" % (elapsed)) print("per parse: %.2f ms" % (elapsed * 1000 / len(sents)))