| Home | Trees | Indices | Help |
|---|
|
|
1
2 # The contents of this file are subject to the Mozilla Public License
3 # (MPL) Version 1.1 (the "License"); you may not use this file except
4 # in compliance with the License. You may obtain a copy of the License
5 # at http://www.mozilla.org/MPL/
6 #
7 # Software distributed under the License is distributed on an "AS IS"
8 # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 # the License for the specific language governing rights and
10 # limitations under the License.
11 #
12 # The Original Code is LEPL (http://www.acooke.org/lepl)
13 # The Initial Developer of the Original Code is Andrew Cooke.
14 # Portions created by the Initial Developer are Copyright (C) 2009-2010
15 # Andrew Cooke (andrew@acooke.org). All Rights Reserved.
16 #
17 # Alternatively, the contents of this file may be used under the terms
18 # of the LGPL license (the GNU Lesser General Public License,
19 # http://www.gnu.org/licenses/lgpl.html), in which case the provisions
20 # of the LGPL License are applicable instead of those above.
21 #
22 # If you wish to allow use of your version of this file only under the
23 # terms of the LGPL License and not to allow others to use your version
24 # of this file under the MPL, indicate your decision by deleting the
25 # provisions above and replace them with the notice and other provisions
26 # required by the LGPL License. If you do not delete the provisions
27 # above, a recipient may use your version of this file under either the
28 # MPL or the LGPL License.
29
30 '''
31 Base class for matchers.
32 '''
33
34
35 from abc import ABCMeta
36 from types import FunctionType
37
38 from lepl.support.lib import fmt, singleton, identity
39
40 # pylint: disable-msg=C0103, W0105
41 # Python 2.6
42 #class Matcher(metaclass=ABCMeta):
43 _Matcher = ABCMeta('_Matcher', (object, ), {})
44 '''
45 ABC used to identify matchers.
46
47 Note that graph traversal assumes subclasses are hashable and iterable.
48 '''
49
51
54
55 # @abstractmethod
57 '''
58 This is the core method called during recursive decent. It must
59 yield (stream, results) pairs until the matcher has exhausted all
60 possible matches.
61
62 To evaluate a sub-matcher it should yield the result of calling
63 this method on the sub-matcher:
64
65 generator = sub_matcher._match(stream_in)
66 try:
67 while True:
68 # evaluate the sub-matcher
69 (stream_out, result) = yield generator
70 ....
71 # return the result from this matcher
72 yield (stream_out, result)
73 except StopIteration:
74 ...
75
76 The implementation should be decorated with @tagged in almost all
77 cases.
78 '''
79
80 # @abstractmethod
85
86
87 # Python 2.6
88 #class FactoryMatcher(metaclass=ABCMeta):
89 _FactoryMatcher = ABCMeta('_FactoryMatcher', (object, ), {})
90 '''
91 ABC used to identify factory matchers (have a property factory that
92 identifies the matcher they generate).
93 '''
94
95
100
101
106
108 raise MatcherTypeException(msg)
109
110
112 if isinstance(matcher, FunctionType) and hasattr(matcher, 'factory'):
113 return if_factory(matcher.factory)
114 elif issubclass(matcher, Matcher):
115 return if_matcher(matcher)
116 else:
117 raise MatcherTypeException(
118 fmt('{0!s} ({1}) does not appear to be a matcher type',
119 matcher, type(matcher)))
120
121
123 from lepl.matchers.support import FactoryMatcher
124 try:
125 if isinstance(matcher, FactoryMatcher):
126 return if_wrapper(matcher.factory)
127 except TypeError:
128 pass # bug in python impl
129 # may already be unpacked
130 if isinstance(matcher, FunctionType):
131 return if_wrapper(matcher)
132 if isinstance(matcher, Matcher):
133 return if_matcher(matcher)
134 else:
135 raise MatcherTypeException(
136 fmt('{0!s} ({1}) does not appear to be a matcher',
137 matcher, type(matcher)))
138
139
141 '''
142 Given a "constructor" (either a real constructor, or an annotated
143 function), generate something that uniquely identifies that (the class
144 for real constructors, and the embedded function for the output from
145 the factories).
146 '''
147 return case_type(matcher, identity, identity)
148
150 '''
151 '''
152 try:
153 return case_instance(matcher, identity, type)
154 except MatcherTypeException as e:
155 if fail:
156 raise e
157 else:
158 return False
159
161 '''
162 Rewrite a map whose keys are matchers to use canonical_matcher_type.
163 '''
164 return dict((canonical_matcher_type(key), map_[key]) for key in map_)
165
168
169
171 '''
172 Some kind of parent/child management for wrapped classes that I no longer
173 understand, but which appears to be used and working (it doesn't look
174 like rocket science, but until it breaks I don't care enough to know
175 more...)
176 '''
177
181
183 return case_type(child,
184 lambda m: self.factories.add(m),
185 lambda m: self.base.register(m))
186
188 return case_instance(child,
189 lambda m: m is self.base or m in self.factories,
190 lambda m: isinstance(self.base, type)
191 and isinstance(m, self.base))
192
193
195 # if base is a factory then we want the related type
196 try:
197 base = canonical_matcher_type(base)
198 except MatcherTypeException:
199 pass
200 table = singleton(Relations, dict)
201 if base not in table:
202 table[base] = Relations(base)
203 return table[base]
204
205
207 try:
208 return relations(base).child_of(child)
209 except MatcherTypeException as e:
210 if fail:
211 raise e
212 else:
213 return False
214
217
221
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Sat Jun 9 21:51:00 2012 | http://epydoc.sourceforge.net |