-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnlp.py
94 lines (80 loc) · 2.82 KB
/
nlp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""Natural language like arguments parser """
import re
from oodict import OODict
import sys
class NLParser:
"""Parse args by rules, and dispatch them to appropriate method of
given handler
"""
def __init__(self):
self.CHARS = '.*?'
self.VAR = '(.+?)'
self.magic_ending = 'mNaLgP1c'
def set_handler(self, handler):
"""Set default handler"""
self.dispatcher = handler
self.rules = handler.usage_rules
def _parse(self, pattern, sentence):
"""
patterns are like 'create $type on $dev of $host', items must be separated
with space. Words with leading $ are vars. The other literal words in pattern
act as grammar sugar and separators of var.
Return OODict, you can use something like
d = parse(...)
d.type, d.dev, d.host
return values are all stripped.
"""
# We need to know when to stop.
sentence += self.magic_ending
values = OODict()
vars = []
regex = ''
last_is_var = False # If two vars are consecutive, we need to use one space to separate them
for item in pattern.split():
if item[0] == '$':
if last_is_var:
regex += ' '
vars.append(item[1:])
regex += self.VAR
last_is_var = True
else:
if not last_is_var:
regex +='\s*?' # eat spaces of two adjacent literals
regex += item
last_is_var = False
regex += self.magic_ending
#print regex, sentence
r = re.match(regex, sentence)
if not r:
return None
i = 0
for var in vars:
v = r.groups()[i].strip()
#print v
if not v:
print '$%s is empty: %s' % (var, pattern)
return None
values[var] = v
i += 1
return values
def parse(self, sentence):
if not sentence or sentence == 'help':
for k, v in sorted(self.rules.items()):
print k
sys.exit(0)
for pattern, name in self.rules.items():
args = self._parse(pattern, sentence)
if args is None:
continue
# Found
try:
op = getattr(self.dispatcher, name)
except AttributeError:
print 'Operation not supportted', name
sys.exit(-1)
if hasattr(self.dispatcher, '_pre_command'):
self.dispatcher._pre_command(name, args)
op(args)
sys.exit(0)
print 'Can\'t understand', sentence
return -1