2 # -*- coding: utf-8 -*-
4 ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
5 The original copyright is below
6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 The OpenCV C/C++/Python/Java/... language domain.
10 :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
11 :license: BSD, see LICENSE for details.
15 from copy import deepcopy
17 from docutils import nodes
18 from docutils.parsers.rst import directives
20 from sphinx import addnodes
21 from sphinx.roles import XRefRole
22 from sphinx.locale import l_, _
23 from sphinx.domains import Domain, ObjType
24 from sphinx.directives import ObjectDescription
25 from sphinx.util.nodes import make_refnode
26 from sphinx.util.compat import Directive
27 from sphinx.util.docfields import Field, GroupedField, TypedField
29 ########################### Python Part ###########################
31 # REs for Python signatures
32 py_sig_re = re.compile(
33 r'''^ ([\w.]*\.)? # class name(s)
34 (\w+) \s* # thing name
35 (?: \((.*)\) # optional: arguments
36 (?:\s* -> \s* (.*))? # return annotation
37 )? $ # and nothing more
41 def _pseudo_parse_arglist(signode, arglist):
42 """"Parse" a list of arguments separated by commas.
44 Arguments can have "optional" annotations given by enclosing them in
45 brackets. Currently, this will split at any comma, even if it's inside a
46 string literal (e.g. default argument value).
48 paramlist = addnodes.desc_parameterlist()
51 for argument in arglist.split(','):
52 argument = argument.strip()
53 ends_open = ends_close = 0
54 while argument.startswith('['):
55 stack.append(addnodes.desc_optional())
56 stack[-2] += stack[-1]
57 argument = argument[1:].strip()
58 while argument.startswith(']'):
60 argument = argument[1:].strip()
61 while argument.endswith(']'):
63 argument = argument[:-1].strip()
64 while argument.endswith('['):
66 argument = argument[:-1].strip()
68 stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
70 stack.append(addnodes.desc_optional())
71 stack[-2] += stack[-1]
79 # if there are too few or too many elements on the stack, just give up
80 # and treat the whole argument list as one argument, discarding the
81 # already partially populated paramlist node
82 signode += addnodes.desc_parameterlist()
83 signode[-1] += addnodes.desc_parameter(arglist, arglist)
88 class OCVPyObject(ObjectDescription):
90 Description of a general Python object.
93 'noindex': directives.flag,
94 'module': directives.unchanged,
98 TypedField('parameter', label=l_('Parameters'),
99 names=('param', 'parameter', 'arg', 'argument',
100 'keyword', 'kwarg', 'kwparam'),
101 typerolename='obj', typenames=('paramtype', 'type'),
103 TypedField('variable', label=l_('Variables'), rolename='obj',
104 names=('var', 'ivar', 'cvar'),
105 typerolename='obj', typenames=('vartype',),
107 GroupedField('exceptions', label=l_('Raises'), rolename='exc',
108 names=('raises', 'raise', 'exception', 'except'),
110 Field('returnvalue', label=l_('Returns'), has_arg=False,
111 names=('returns', 'return')),
112 Field('returntype', label=l_('Return type'), has_arg=False,
116 def get_signature_prefix(self, sig):
118 May return a prefix to put before the object name in the signature.
122 def needs_arglist(self):
124 May return true if an empty argument list is to be generated even if
125 the document contains none.
129 def handle_signature(self, sig, signode):
131 Transform a Python signature into RST nodes.
132 Returns (fully qualified name of the thing, classname if any).
134 If inside a class, the current class name is handled intelligently:
135 * it is stripped from the displayed name if present
136 * it is added to the full name (return value) if not present
138 signode += nodes.strong("Python:", "Python:")
139 signode += addnodes.desc_name(" ", " ")
140 m = py_sig_re.match(sig)
143 name_prefix, name, arglist, retann = m.groups()
145 # determine module and class name (if applicable), as well as full name
146 modname = self.options.get(
147 'module', self.env.temp_data.get('py:module'))
148 classname = self.env.temp_data.get('py:class')
151 if name_prefix and name_prefix.startswith(classname):
152 fullname = name_prefix + name
153 # class name is given again in the signature
154 name_prefix = name_prefix[len(classname):].lstrip('.')
156 # class name is given in the signature, but different
158 fullname = classname + '.' + name_prefix + name
160 # class name is not given in the signature
161 fullname = classname + '.' + name
165 classname = name_prefix.rstrip('.')
166 fullname = name_prefix + name
171 signode['module'] = modname
172 signode['class'] = classname
173 signode['fullname'] = fullname
175 sig_prefix = self.get_signature_prefix(sig)
177 signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
180 signode += addnodes.desc_addname(name_prefix, name_prefix)
181 # exceptions are a special case, since they are documented in the
182 # 'exceptions' module.
183 elif add_module and self.env.config.add_module_names:
184 modname = self.options.get(
185 'module', self.env.temp_data.get('py:module'))
186 if modname and modname != 'exceptions':
187 nodetext = modname + '.'
188 signode += addnodes.desc_addname(nodetext, nodetext)
190 signode += addnodes.desc_name(name, name)
192 if self.needs_arglist():
193 # for callables, add an empty parameter list
194 signode += addnodes.desc_parameterlist()
196 signode += addnodes.desc_returns(retann, retann)
197 return fullname, name_prefix
198 _pseudo_parse_arglist(signode, arglist)
200 signode += addnodes.desc_returns(retann, retann)
201 return fullname, name_prefix
203 def get_index_text(self, modname, name):
205 Return the text for the index entry of the object.
207 raise NotImplementedError('must be implemented in subclasses')
209 def add_target_and_index(self, name_cls, sig, signode):
210 modname = self.options.get(
211 'module', self.env.temp_data.get('py:module'))
212 fullname = (modname and modname + '.' or '') + name_cls[0]
214 if fullname not in self.state.document.ids:
215 signode['names'].append(fullname)
216 signode['ids'].append(fullname)
217 signode['first'] = (not self.names)
218 self.state.document.note_explicit_target(signode)
219 objects = self.env.domaindata['ocv']['objects']
220 if fullname in objects:
223 'duplicate object description of %s, ' % fullname +
224 'other instance in ' +
225 self.env.doc2path(objects[fullname][0]) +
226 ', use :noindex: for one of them',
228 objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
230 indextext = self.get_index_text(modname, name_cls)
232 self.indexnode['entries'].append(('single', indextext,
235 def before_content(self):
236 # needed for automatic qualification of members (reset in subclasses)
237 self.clsname_set = False
239 def after_content(self):
241 self.env.temp_data['py:class'] = None
243 class OCVPyModulelevel(OCVPyObject):
245 Description of an object on module level (functions, data).
247 directive_prefix = 'py'
249 def needs_arglist(self):
250 return self.objtype == self.__class__.directive_prefix + 'function'
252 def get_index_text(self, modname, name_cls):
253 if self.objtype == self.__class__.directive_prefix + 'function':
256 if not fname.startswith("cv") and not fname.startswith("cv2"):
257 return _('%s() (Python function)') % fname
258 pos = fname.find(".")
259 modname = fname[:pos]
260 fname = fname[pos+1:]
261 return _('%s() (Python function in %s)') % (fname, modname)
262 return _('%s() (Python function in %s)') % (name_cls[0], modname)
263 elif self.objtype == 'pydata':
265 return _('%s (Python variable)') % name_cls[0]
266 return _('%s (in module %s)') % (name_cls[0], modname)
270 class OCVPyOldModulelevel(OCVPyModulelevel):
271 directive_prefix = 'pyold'
274 class OCVPyXRefRole(XRefRole):
275 def process_link(self, env, refnode, has_explicit_title, title, target):
276 refnode['ocv:module'] = env.temp_data.get('ocv:module')
277 refnode['ocv:class'] = env.temp_data.get('ocv:class')
278 if not has_explicit_title:
279 title = title.lstrip('.') # only has a meaning for the target
280 target = target.lstrip('~') # only has a meaning for the title
281 # if the first character is a tilde, don't display the module/class
282 # parts of the contents
283 if title[0:1] == '~':
285 dot = title.rfind('.')
287 title = title[dot+1:]
288 # if the first character is a dot, search more specific namespaces first
289 # else search builtins first
290 if target[0:1] == '.':
292 refnode['refspecific'] = True
296 ########################### C/C++/Java Part ###########################
298 _identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b)')
299 _argument_name_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b(?:\[\d*\])?|\.\.\.)')
300 _whitespace_re = re.compile(r'\s+(?u)')
301 _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
302 r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
303 _visibility_re = re.compile(r'\b(public|private|protected)\b')
304 _operator_re = re.compile(r'''(?x)
317 'unsigned char': 'C',
323 'unsigned long': 'L',
327 'std::ostream': 'os',
328 'std::istream': 'is',
329 'std::iostream': 'ios',
332 'operator[]': 'subscript-operator',
333 'operator()': 'call-operator',
334 'operator!': 'not-operator',
335 'operator<': 'lt-operator',
336 'operator<=': 'lte-operator',
337 'operator>': 'gt-operator',
338 'operator>=': 'gte-operator',
339 'operator=': 'assign-operator',
340 'operator/': 'div-operator',
341 'operator*': 'mul-operator',
342 'operator%': 'mod-operator',
343 'operator+': 'add-operator',
344 'operator-': 'sub-operator',
345 'operator|': 'or-operator',
346 'operator&': 'and-operator',
347 'operator^': 'xor-operator',
348 'operator&&': 'sand-operator',
349 'operator||': 'sor-operator',
350 'operator==': 'eq-operator',
351 'operator!=': 'neq-operator',
352 'operator<<': 'lshift-operator',
353 'operator>>': 'rshift-operator',
354 'operator-=': 'sub-assign-operator',
355 'operator+=': 'add-assign-operator',
356 'operator*-': 'mul-assign-operator',
357 'operator/=': 'div-assign-operator',
358 'operator%=': 'mod-assign-operator',
359 'operator&=': 'and-assign-operator',
360 'operator|=': 'or-assign-operator',
361 'operator<<=': 'lshift-assign-operator',
362 'operator>>=': 'rshift-assign-operator',
363 'operator^=': 'xor-assign-operator',
364 'operator,': 'comma-operator',
365 'operator->': 'pointer-operator',
366 'operator->*': 'pointer-by-pointer-operator',
367 'operator~': 'inv-operator',
368 'operator++': 'inc-operator',
369 'operator--': 'dec-operator',
370 'operator new': 'new-operator',
371 'operator new[]': 'new-array-operator',
372 'operator delete': 'delete-operator',
373 'operator delete[]': 'delete-array-operator'
377 class DefinitionError(Exception):
379 def __init__(self, description):
380 self.description = description
382 def __unicode__(self):
383 return self.description
386 return unicode(self.encode('utf-8'))
389 class DefExpr(object):
391 def __unicode__(self):
392 raise NotImplementedError()
394 def __eq__(self, other):
395 if type(self) is not type(other):
398 for key, value in self.__dict__.iteritems():
399 if value != getattr(other, value):
401 except AttributeError:
405 def __ne__(self, other):
406 return not self.__eq__(other)
409 """Close a definition expression node"""
410 return deepcopy(self)
413 """Returns the id for the node"""
417 """Returns the name. Returns either `None` or a node with
418 a name you might call :meth:`split_owner` on.
422 def split_owner(self):
423 """Nodes returned by :meth:`get_name` can split off their
424 owning parent. This function returns the owner and the
425 name as a tuple of two items. If a node does not support
426 it, it returns None as owner and self as name.
430 def prefix(self, prefix):
431 """Prefixes a name node (a node returned by :meth:`get_name`)."""
432 raise NotImplementedError()
435 return unicode(self).encode('utf-8')
438 return '<%s %s>' % (self.__class__.__name__, self)
441 class PrimaryDefExpr(DefExpr):
446 def prefix(self, prefix):
447 if isinstance(prefix, PathDefExpr):
448 prefix = prefix.clone()
449 prefix.path.append(self)
451 return PathDefExpr([prefix, self])
454 class NameDefExpr(PrimaryDefExpr):
456 def __init__(self, name):
460 name = _id_shortwords.get(self.name)
463 return self.name.replace(u' ', u'-')
465 def __unicode__(self):
466 return unicode(self.name)
469 class PathDefExpr(PrimaryDefExpr):
471 def __init__(self, parts):
475 rv = u'::'.join(x.get_id() for x in self.path)
476 return _id_shortwords.get(rv, rv)
478 def split_owner(self):
479 if len(self.path) > 1:
480 return PathDefExpr(self.path[:-1]), self.path[-1]
483 def prefix(self, prefix):
484 if isinstance(prefix, PathDefExpr):
485 prefix = prefix.clone()
486 prefix.path.extend(self.path)
488 return PathDefExpr([prefix] + self.path)
490 def __unicode__(self):
491 return u'::'.join(map(unicode, self.path))
494 class TemplateDefExpr(PrimaryDefExpr):
496 def __init__(self, typename, args):
497 self.typename = typename
500 def split_owner(self):
501 owner, typename = self.typename.split_owner()
502 return owner, TemplateDefExpr(typename, self.args)
505 return u'%s:%s:' % (self.typename.get_id(),
506 u'.'.join(x.get_id() for x in self.args))
508 def __unicode__(self):
509 return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
512 class WrappingDefExpr(DefExpr):
514 def __init__(self, typename):
515 self.typename = typename
518 return self.typename.get_name()
521 class ModifierDefExpr(WrappingDefExpr):
523 def __init__(self, typename, modifiers):
524 WrappingDefExpr.__init__(self, typename)
525 self.modifiers = modifiers
528 pieces = [_id_shortwords.get(unicode(x), unicode(x))
529 for x in self.modifiers]
530 pieces.append(self.typename.get_id())
531 return u'-'.join(pieces)
533 def __unicode__(self):
534 return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
537 class PtrDefExpr(WrappingDefExpr):
540 return self.typename.get_id() + u'P'
542 def __unicode__(self):
543 return u'%s*' % self.typename
546 class RefDefExpr(WrappingDefExpr):
549 return self.typename.get_id() + u'R'
551 def __unicode__(self):
552 return u'%s&' % self.typename
555 class ConstDefExpr(WrappingDefExpr):
557 def __init__(self, typename, prefix=False):
558 WrappingDefExpr.__init__(self, typename)
562 return self.typename.get_id() + u'C'
564 def __unicode__(self):
565 return (self.prefix and u'const %s' or u'%s const') % self.typename
567 class ConstTemplateDefExpr(WrappingDefExpr):
569 def __init__(self, typename, prefix=False):
570 WrappingDefExpr.__init__(self, typename)
574 return self.typename.get_id() + u'C'
576 def __unicode__(self):
577 return (self.prefix and u'const %s' or u'%s const') % self.typename
580 class CastOpDefExpr(PrimaryDefExpr):
582 def __init__(self, typename):
583 self.typename = typename
586 return u'castto-%s-operator' % self.typename.get_id()
588 def __unicode__(self):
589 return u'operator %s' % self.typename
592 class ArgumentDefExpr(DefExpr):
594 def __init__(self, type, name, default=None):
597 self.default = default
600 return self.name.get_name()
603 if self.type is None:
605 return self.type.get_id()
607 def __unicode__(self):
608 return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
609 (self.default is not None and u'=%s' % self.default or u'')
612 class NamedDefExpr(DefExpr):
614 def __init__(self, name, visibility, static):
616 self.visibility = visibility
620 return self.name.get_name()
622 def get_modifiers(self):
624 if self.visibility != 'public':
625 rv.append(self.visibility)
631 class TypeObjDefExpr(NamedDefExpr):
633 def __init__(self, name, visibility, static, typename):
634 NamedDefExpr.__init__(self, name, visibility, static)
635 self.typename = typename
638 if self.typename is None:
639 return self.name.get_id()
640 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
642 def __unicode__(self):
643 buf = self.get_modifiers()
644 if self.typename is None:
645 buf.append(unicode(self.name))
647 buf.extend(map(unicode, (self.typename, self.name)))
648 return u' '.join(buf)
651 class MemberObjDefExpr(NamedDefExpr):
653 def __init__(self, name, visibility, static, typename, value):
654 NamedDefExpr.__init__(self, name, visibility, static)
655 self.typename = typename
659 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
661 def __unicode__(self):
662 buf = self.get_modifiers()
663 buf.append(u'%s %s' % (self.typename, self.name))
664 if self.value is not None:
665 buf.append(u'= %s' % self.value)
666 return u' '.join(buf)
669 class FuncDefExpr(NamedDefExpr):
671 def __init__(self, name, visibility, static, explicit, rv,
672 signature, const, pure_virtual, virtual):
673 NamedDefExpr.__init__(self, name, visibility, static)
675 self.signature = signature
676 self.explicit = explicit
678 self.pure_virtual = pure_virtual
679 self.virtual = virtual
684 self.signature and u'__' +
685 u'.'.join(x.get_id() for x in self.signature) or u'',
686 self.const and u'C' or u''
689 def __unicode__(self):
690 buf = self.get_modifiers()
692 buf.append(u'explicit')
694 buf.append(u'virtual')
695 if self.rv is not None:
696 buf.append(unicode(self.rv))
697 buf.append(u'%s(%s)' % (self.name, u', '.join(
698 map(unicode, self.signature))))
701 if self.pure_virtual:
703 return u' '.join(buf)
706 class ClassDefExpr(NamedDefExpr):
708 def __init__(self, name, visibility, static, parents = None):
709 NamedDefExpr.__init__(self, name, visibility, static)
710 self.parents = parents
713 return self.name.get_id()
715 def __unicode__(self):
716 buf = self.get_modifiers()
717 buf.append(unicode(self.name))
718 return u' '.join(buf)
721 class DefinitionParser(object):
723 # mapping of valid type modifiers. if the set is None it means
724 # the modifier can prefix all types, otherwise only the types
725 # (actually more keywords) in the set. Also check
726 # _guess_typename when changing this.
733 'unsigned': set(('char', 'short', 'int', 'long')),
734 'signed': set(('char', 'short', 'int', 'long')),
735 'short': set(('int',)),
736 'long': set(('int', 'long', 'double'))
739 def __init__(self, definition):
740 self.definition = definition.strip()
742 self.end = len(self.definition)
743 self.last_match = None
744 self._previous_state = (0, None)
747 raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
748 (msg, self.pos, self.definition))
750 def match(self, regex):
751 match = regex.match(self.definition, self.pos)
752 if match is not None:
753 self._previous_state = (self.pos, self.last_match)
754 self.pos = match.end()
755 self.last_match = match
760 self.pos, self.last_match = self._previous_state
762 def skip_string(self, string):
764 if self.definition[self.pos:self.pos + strlen] == string:
769 def skip_word(self, word):
770 return self.match(re.compile(r'\b%s\b' % re.escape(word)))
773 return self.match(_whitespace_re)
777 return self.pos >= self.end
780 def current_char(self):
782 return self.definition[self.pos]
787 def matched_text(self):
788 if self.last_match is not None:
789 return self.last_match.group()
791 def _parse_operator(self):
793 # thank god, a regular operator definition
794 if self.match(_operator_re):
795 return NameDefExpr('operator' +
796 _whitespace_re.sub('', self.matched_text))
797 # new/delete operator?
798 for allocop in 'new', 'delete':
799 if not self.skip_word(allocop):
802 if self.skip_string('['):
804 if not self.skip_string(']'):
805 self.fail('expected "]" for ' + allocop)
807 return NameDefExpr('operator ' + allocop)
809 # oh well, looks like a cast operator definition.
810 # In that case, eat another type.
811 type = self._parse_type()
812 return CastOpDefExpr(type)
814 def _parse_name(self):
815 if not self.match(_argument_name_re):
816 self.fail('expected name')
817 identifier = self.matched_text
819 # strictly speaking, operators are not regular identifiers
820 # but because operator is a keyword, it might not be used
821 # for variable names anyways, so we can safely parse the
822 # operator here as identifier
823 if identifier == 'operator':
824 return self._parse_operator()
826 return NameDefExpr(identifier)
828 def _guess_typename(self, path):
831 # for the long type, we don't want the int in there
833 path = [x for x in path if x != 'int']
837 if path[-1] in ('int', 'char'):
838 return path[:-1], path[-1]
841 def _attach_crefptr(self, expr, is_const=False):
843 expr = ConstDefExpr(expr, prefix=True)
846 if self.skip_word('const'):
847 expr = ConstDefExpr(expr)
848 elif self.skip_string('*'):
849 expr = PtrDefExpr(expr)
850 elif self.skip_string('&'):
851 expr = RefDefExpr(expr)
855 def _peek_const(self, path):
862 def _parse_builtin(self, modifier):
864 following = self._modifiers[modifier]
867 if not self.match(_identifier_re):
869 identifier = self.matched_text
870 if identifier in following:
871 path.append(identifier)
872 following = self._modifiers[modifier]
878 is_const = self._peek_const(path)
879 modifiers, typename = self._guess_typename(path)
880 rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
881 return self._attach_crefptr(rv, is_const)
883 def _parse_type_expr(self):
884 typename = self._parse_name()
885 if typename and self.skip_string('['):
887 if self.match(re.compile(r'\d*')):
888 typename.name += self.last_match.group(0)
890 if not self.skip_string(']'):
891 self.fail('expected type')
893 if not self.skip_string('<'):
899 if self.skip_string('>'):
902 if not self.skip_string(','):
903 self.fail('"," or ">" in template expected')
905 args.append(self._parse_type(True))
906 return TemplateDefExpr(typename, args)
908 def _parse_type(self, in_template=False):
913 if self.match(re.compile(r'template\w*<([^>]*)>')):
914 args = self.last_match.group(1).split(',')
915 args = [a.strip() for a in args]
916 modifiers.append(TemplateDefExpr('template', args))
918 # if there is a leading :: or not, we don't care because we
919 # treat them exactly the same. Buf *if* there is one, we
920 # don't have to check for type modifiers
921 if not self.skip_string('::'):
923 while self.match(_identifier_re):
924 modifier = self.matched_text
925 if modifier in self._modifiers:
926 following = self._modifiers[modifier]
927 # if the set is not none, there is a limited set
928 # of types that might follow. It is technically
929 # impossible for a template to follow, so what
930 # we do is go to a different function that just
932 if following is not None:
933 return self._parse_builtin(modifier)
934 modifiers.append(modifier)
941 if (in_template and self.current_char in ',>') or \
942 (result and not self.skip_string('::')) or \
945 result.append(self._parse_type_expr())
948 self.fail('expected type')
952 rv = PathDefExpr(result)
953 is_const = self._peek_const(modifiers)
955 rv = ConstDefExpr(rv, prefix=True)
957 rv = ModifierDefExpr(rv, modifiers)
958 return self._attach_crefptr(rv, False)
960 def _parse_default_expr(self):
962 if self.match(_string_re):
963 return self.matched_text
964 paren_stack_depth = 0
965 max_pos = len(self.definition)
968 idx0 = self.definition.find('(', self.pos)
969 idx1 = self.definition.find(',', self.pos)
970 idx2 = self.definition.find(')', self.pos)
977 idx = min(idx0, idx1, idx2)
979 self.fail('unexpected end in default expression')
981 paren_stack_depth += 1
983 paren_stack_depth -= 1
984 if paren_stack_depth < 0:
986 elif paren_stack_depth == 0:
990 rv = self.definition[rv_start:idx]
994 def _parse_signature(self):
995 if r'CvStatModel::train' in self.definition:
996 # hack to skip parsing of problematic definition
998 return [ArgumentDefExpr("const Mat&", "train_data", None), ArgumentDefExpr(None, self.definition[self.definition.find("["):-1], None)], False, True
1001 if not self.skip_string('('):
1002 self.fail('expected parentheses for function')
1008 self.fail('missing closing parentheses')
1009 if self.skip_string(')'):
1012 if not self.skip_string(','):
1013 self.fail('expected comma between arguments')
1016 argtype = self._parse_type()
1018 if unicode(argtype) == u"...":
1019 if not self.skip_string(')'):
1020 self.fail("var arg must be the last argument")
1021 args.append(ArgumentDefExpr(None, argtype, None))
1023 argname = default = None
1024 if self.skip_string('='):
1026 default = self._parse_default_expr()
1027 elif self.current_char not in ',)':
1028 argname = self._parse_name()
1030 if self.skip_string('='):
1031 default = self._parse_default_expr()
1033 args.append(ArgumentDefExpr(argtype, argname, default))
1035 const = self.skip_word('const')
1038 if self.skip_string('='):
1040 if not (self.skip_string('0') or \
1041 self.skip_word('NULL') or \
1042 self.skip_word('nullptr')):
1043 self.fail('pure virtual functions must be defined with '
1044 'either 0, NULL or nullptr, other macros are '
1048 pure_virtual = False
1049 return args, const, pure_virtual
1051 def _parse_visibility_static(self):
1052 visibility = 'public'
1053 if self.match(_visibility_re):
1054 visibility = self.matched_text
1055 static = self.skip_word('static')
1056 return visibility, static
1058 def parse_type(self):
1059 return self._parse_type()
1061 def parse_type_object(self):
1062 visibility, static = self._parse_visibility_static()
1063 typename = self._parse_type()
1066 name = self._parse_type()
1070 return TypeObjDefExpr(name, visibility, static, typename)
1072 def parse_member_object(self):
1073 visibility, static = self._parse_visibility_static()
1074 typename = self._parse_type()
1075 name = self._parse_type()
1077 if self.skip_string('='):
1078 value = self.read_rest().strip()
1081 return MemberObjDefExpr(name, visibility, static, typename, value)
1083 def parse_enum_member_object(self):
1084 visibility, static = self._parse_visibility_static()
1086 name = self._parse_type()
1088 if self.skip_string('='):
1089 value = self.read_rest().strip()
1092 return MemberObjDefExpr(name, visibility, static, typename, value)
1094 def parse_function(self):
1095 visibility, static = self._parse_visibility_static()
1096 if self.skip_word('explicit'):
1101 if self.skip_word('virtual'):
1106 rv = self._parse_type()
1108 # some things just don't have return values
1109 if self.current_char == '(':
1113 name = self._parse_type()
1114 return FuncDefExpr(name, visibility, static, explicit, rv,
1115 *self._parse_signature(), virtual = virtual)
1117 def parse_class(self):
1118 visibility, static = self._parse_visibility_static()
1119 typename = self._parse_type()
1123 if self.skip_string(':'):
1126 classname_pos = self.pos
1127 pvisibility, pstatic = self._parse_visibility_static()
1129 self.fail('unsepected static keyword, got %r' %
1130 self.definition[self.classname_pos:])
1131 parents.append(ClassDefExpr(self._parse_type(), pvisibility, pstatic))
1132 if not self.skip_string(','):
1134 return ClassDefExpr(typename, visibility, static, parents)
1136 def read_rest(self):
1137 rv = self.definition[self.pos:]
1141 def assert_end(self):
1144 self.fail('expected end of definition, got %r' %
1145 self.definition[self.pos:])
1148 class OCVObject(ObjectDescription):
1149 """Description of a C++ language object."""
1155 TypedField('parameter', label=l_('Parameters'),
1156 names=('param', 'parameter', 'arg', 'argument'),
1157 typerolename='type', typenames=('type',)),
1158 Field('returnvalue', label=l_('Returns'), has_arg=False,
1159 names=('returns', 'return')),
1160 Field('returntype', label=l_('Return type'), has_arg=False,
1164 def attach_name(self, node, name):
1165 owner, name = name.split_owner()
1166 varname = unicode(name)
1167 if owner is not None:
1168 owner = unicode(owner) + '::'
1169 node += addnodes.desc_addname(owner, owner)
1170 node += addnodes.desc_name(varname, varname)
1172 def attach_type(self, node, type):
1174 text = unicode(type)
1175 pnode = addnodes.pending_xref(
1176 '', refdomain='ocv', reftype='type',
1177 reftarget=text, modname=None, classname=None)
1178 pnode['ocv:parent'] = self.env.temp_data.get('ocv:parent')
1179 pnode += nodes.Text(text)
1182 def attach_modifiers(self, node, obj):
1183 if not self.__class__.ismember:
1184 lname = self.__class__.langname
1185 node += nodes.strong(lname + ":", lname + ":")
1186 node += addnodes.desc_name(" ", " ")
1188 if obj.visibility != 'public':
1189 node += addnodes.desc_annotation(obj.visibility,
1191 node += nodes.Text(' ')
1193 node += addnodes.desc_annotation('static', 'static')
1194 node += nodes.Text(' ')
1196 def add_target_and_index(self, sigobj, sig, signode):
1197 theid = sig#obj.get_id()
1198 theid = re.sub(r" +", " ", theid)
1199 if self.objtype == 'emember':
1200 theid = re.sub(r" ?=.*", "", theid)
1201 theid = re.sub(r"=[^,()]+\([^)]*?\)[^,)]*(,|\))", "\\1", theid)
1202 theid = re.sub(r"=\w*[^,)(]+(,|\))", "\\1", theid)
1203 theid = theid.replace("( ", "(").replace(" )", ")")
1204 name = unicode(sigobj.name)
1205 if theid not in self.state.document.ids:
1206 signode['names'].append(theid)
1207 signode['ids'].append(theid)
1208 signode['first'] = (not self.names)
1209 self.state.document.note_explicit_target(signode)
1211 #self.env.domaindata['ocv']['objects'].setdefault(name,
1212 #(self.env.docname, self.objtype, theid))
1213 self.env.domaindata['ocv']['objects'].setdefault(theid,
1214 (self.env.docname, self.objtype, theid))
1215 self.env.domaindata['ocv']['objects2'].setdefault(name,
1216 (self.env.docname, self.objtype, theid))
1218 indextext = self.get_index_text(name)
1220 self.indexnode['entries'].append(('single', indextext, theid, name))
1222 def before_content(self):
1223 lastname = self.names and self.names[-1]
1224 if lastname and not self.env.temp_data.get('ocv:parent'):
1225 assert isinstance(lastname, NamedDefExpr)
1226 self.env.temp_data['ocv:parent'] = lastname.name
1227 self.parentname_set = True
1229 self.parentname_set = False
1231 def after_content(self):
1232 if self.parentname_set:
1233 self.env.temp_data['ocv:parent'] = None
1235 def parse_definition(self, parser):
1236 raise NotImplementedError()
1238 def describe_signature(self, signode, arg):
1239 raise NotImplementedError()
1241 def handle_signature(self, sig, signode):
1242 parser = DefinitionParser(sig)
1244 rv = self.parse_definition(parser)
1246 except DefinitionError, e:
1247 self.env.warn(self.env.docname,
1248 e.description, self.lineno)
1250 self.describe_signature(signode, rv)
1252 parent = self.env.temp_data.get('ocv:parent')
1253 if parent is not None:
1255 rv.name = rv.name.prefix(parent)
1259 class OCVClassObject(OCVObject):
1260 object_annotation = "class "
1261 object_long_name = "class"
1263 def attach_modifiers(self, node, obj, skip_visibility = 'public'):
1264 if obj.visibility != skip_visibility:
1265 node += addnodes.desc_annotation(obj.visibility,
1267 node += nodes.Text(' ')
1269 node += addnodes.desc_annotation('static', 'static')
1270 node += nodes.Text(' ')
1272 def get_index_text(self, name):
1273 return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
1275 def parse_definition(self, parser):
1276 return parser.parse_class()
1278 def describe_signature(self, signode, cls):
1279 self.attach_modifiers(signode, cls)
1280 signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
1281 self.attach_name(signode, cls.name)
1283 for p in cls.parents:
1285 signode += nodes.Text(' : ')
1286 first_parent = False
1288 signode += nodes.Text(', ')
1289 self.attach_modifiers(signode, p, None)
1290 self.attach_name(signode, p.name)
1292 class OCVStructObject(OCVClassObject):
1293 object_annotation = "struct "
1294 object_long_name = "structure"
1296 class OCVTypeObject(OCVObject):
1298 def get_index_text(self, name):
1299 if self.objtype == 'type':
1300 return _('%s (C++ type)') % name
1303 def parse_definition(self, parser):
1304 return parser.parse_type_object()
1306 def describe_signature(self, signode, obj):
1307 self.attach_modifiers(signode, obj)
1308 signode += addnodes.desc_annotation('type ', 'type ')
1309 if obj.typename is not None:
1310 self.attach_type(signode, obj.typename)
1311 signode += nodes.Text(' ')
1312 self.attach_name(signode, obj.name)
1314 class OCVEnumObject(OCVObject):
1316 def get_index_text(self, name):
1317 if self.objtype == 'enum':
1318 return _('%s (enum)') % name
1321 def parse_definition(self, parser):
1322 return parser.parse_type_object()
1324 def describe_signature(self, signode, obj):
1325 self.attach_modifiers(signode, obj)
1326 signode += addnodes.desc_annotation('enum ', 'enum ')
1327 if obj.typename is not None:
1328 self.attach_type(signode, obj.typename)
1329 signode += nodes.Text(' ')
1330 self.attach_name(signode, obj.name)
1333 class OCVMemberObject(OCVObject):
1336 def get_index_text(self, name):
1337 if self.objtype == 'member':
1338 return _('%s (C++ member)') % name
1341 def parse_definition(self, parser):
1342 parent_class = self.env.temp_data.get('ocv:parent')
1343 if parent_class is None:
1344 parser.fail("missing parent structure/class")
1345 return parser.parse_member_object()
1347 def describe_signature(self, signode, obj):
1348 self.attach_modifiers(signode, obj)
1350 self.attach_type(signode, obj.typename)
1351 signode += nodes.Text(' ')
1352 self.attach_name(signode, obj.name)
1353 if obj.value is not None:
1354 signode += nodes.Text(u' = ' + obj.value)
1356 class OCVEnumMemberObject(OCVMemberObject):
1357 def parse_definition(self, parser):
1358 # parent_class = self.env.temp_data.get('ocv:parent')
1359 # if parent_class is None:
1360 # parser.fail("missing parent structure/class")
1361 return parser.parse_enum_member_object()
1363 class OCVFunctionObject(OCVObject):
1365 def attach_function(self, node, func):
1366 owner, name = func.name.split_owner()
1367 if owner is not None:
1368 owner = unicode(owner) + '::'
1369 node += addnodes.desc_addname(owner, owner)
1371 # cast operator is special. in this case the return value
1373 if isinstance(name, CastOpDefExpr):
1374 node += addnodes.desc_name('operator', 'operator')
1375 node += nodes.Text(u' ')
1376 self.attach_type(node, name.typename)
1378 funcname = unicode(name)
1379 node += addnodes.desc_name(funcname, funcname)
1381 paramlist = addnodes.desc_parameterlist()
1382 for arg in func.signature:
1383 param = addnodes.desc_parameter('', '', noemph=True)
1384 if arg.type is not None:
1385 self.attach_type(param, arg.type)
1386 param += nodes.Text(u' ')
1387 #param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
1388 sbrIdx = unicode(arg.name).find("[")
1390 param += nodes.strong(unicode(arg.name), unicode(arg.name))
1392 param += nodes.strong(unicode(arg.name)[:sbrIdx], unicode(arg.name)[:sbrIdx])
1393 param += nodes.Text(unicode(arg.name)[sbrIdx:])
1394 if arg.default is not None:
1395 def_ = u'=' + unicode(arg.default)
1396 #param += nodes.emphasis(def_, def_)
1397 param += nodes.Text(def_)
1402 node += addnodes.desc_addname(' const', ' const')
1403 if func.pure_virtual:
1404 node += addnodes.desc_addname(' = 0', ' = 0')
1406 def get_index_text(self, name):
1407 lname = self.__class__.langname
1408 if lname == "C" and name.startswith("cv"):
1410 return _('%s (%s function)') % (name, lname)
1412 def parse_definition(self, parser):
1413 return parser.parse_function()
1415 def describe_signature(self, signode, func):
1416 self.attach_modifiers(signode, func)
1418 signode += addnodes.desc_annotation('explicit', 'explicit')
1419 signode += nodes.Text(' ')
1421 signode += addnodes.desc_annotation('virtual', 'virtual')
1422 signode += nodes.Text(' ')
1423 # return value is None for things with a reverse return value
1424 # such as casting operator definitions or constructors
1426 if func.rv is not None:
1427 self.attach_type(signode, func.rv)
1428 signode += nodes.Text(u' ')
1429 self.attach_function(signode, func)
1432 class OCVCurrentNamespace(Directive):
1433 """This directive is just to tell Sphinx that we're documenting
1434 stuff in namespace foo.
1438 required_arguments = 1
1439 optional_arguments = 0
1440 final_argument_whitespace = True
1444 env = self.state.document.settings.env
1445 if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
1446 env.temp_data['ocv:prefix'] = None
1448 parser = DefinitionParser(self.arguments[0])
1450 prefix = parser.parse_type()
1452 except DefinitionError, e:
1453 self.env.warn(self.env.docname,
1454 e.description, self.lineno)
1456 env.temp_data['ocv:prefix'] = prefix
1460 class OCVXRefRole(XRefRole):
1462 def process_link(self, env, refnode, has_explicit_title, title, target):
1463 refnode['ocv:parent'] = env.temp_data.get('ocv:parent')
1464 if not has_explicit_title:
1465 target = target.lstrip('~') # only has a meaning for the title
1466 # if the first character is a tilde, don't display the module/class
1467 # parts of the contents
1468 if title[:1] == '~':
1470 dcolon = title.rfind('::')
1472 title = title[dcolon + 2:]
1473 return title, target
1476 class OCVCFunctionObject(OCVFunctionObject):
1479 class OCVJavaFunctionObject(OCVFunctionObject):
1483 class OCVDomain(Domain):
1484 """OpenCV C++ language domain."""
1488 'class': ObjType(l_('class'), 'class'),
1489 'struct': ObjType(l_('struct'), 'struct'),
1490 'function': ObjType(l_('function'), 'func', 'funcx'),
1491 'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'),
1492 'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'),
1493 'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'),
1494 'pyoldfunction': ObjType(l_('pyoldfunction'), 'pyoldfunc'),
1495 'member': ObjType(l_('member'), 'member'),
1496 'emember': ObjType(l_('emember'), 'emember'),
1497 'type': ObjType(l_('type'), 'type'),
1498 'enum': ObjType(l_('enum'), 'enum')
1502 'class': OCVClassObject,
1503 'struct': OCVStructObject,
1504 'function': OCVFunctionObject,
1505 'cfunction': OCVCFunctionObject,
1506 'jfunction': OCVJavaFunctionObject,
1507 'pyfunction': OCVPyModulelevel,
1508 'pyoldfunction': OCVPyOldModulelevel,
1509 'member': OCVMemberObject,
1510 'emember': OCVEnumMemberObject,
1511 'type': OCVTypeObject,
1512 'enum': OCVEnumObject,
1513 'namespace': OCVCurrentNamespace
1516 'class': OCVXRefRole(),
1517 'struct': OCVXRefRole(),
1518 'func' : OCVXRefRole(fix_parens=True),
1519 'funcx' : OCVXRefRole(),
1520 'cfunc' : OCVXRefRole(fix_parens=True),
1521 'cfuncx' : OCVXRefRole(),
1522 'jfunc' : OCVXRefRole(fix_parens=True),
1523 'jfuncx' : OCVXRefRole(),
1524 'pyfunc' : OCVPyXRefRole(),
1525 'pyoldfunc' : OCVPyXRefRole(),
1526 'member': OCVXRefRole(),
1527 'emember': OCVXRefRole(),
1528 'type': OCVXRefRole(),
1529 'enum': OCVXRefRole()
1532 'objects': {}, # fullname -> docname, objtype
1535 def __init__(self, env):
1536 Domain.__init__(self, env)
1537 self.data['objects2'] = {}
1539 def clear_doc(self, docname):
1540 for fullname, (fn, _, _) in self.data['objects'].items():
1542 del self.data['objects'][fullname]
1544 def resolve_xref(self, env, fromdocname, builder,
1545 typ, target, node, contnode):
1546 def _create_refnode(expr):
1547 name = unicode(expr)
1548 if "type" in self.objtypes_for_role(typ):
1550 if "cfunction" in self.objtypes_for_role(typ):
1551 if not name.startswith(u'cv'):
1553 dict = self.data['objects']
1554 if name not in dict:
1555 dict = self.data['objects2']
1556 if name not in dict:
1557 refdoc = node.get('refdoc', fromdocname)
1558 env.warn(refdoc, 'unresolved reference: %r - %r' % (target, typ), node.line)
1561 if obj[1] not in self.objtypes_for_role(typ):
1564 if "class" in self.objtypes_for_role(typ):
1565 title = u"class " + title
1566 elif "struct" in self.objtypes_for_role(typ):
1567 title = u"struct " + title
1568 return make_refnode(builder, fromdocname, obj[0], obj[2],
1571 parser = DefinitionParser(target)
1573 expr = parser.parse_type().get_name()
1575 if not parser.eof or expr is None:
1576 raise DefinitionError('')
1577 except DefinitionError:
1578 refdoc = node.get('refdoc', fromdocname)
1579 env.warn(refdoc, 'unparseable C++ definition: %r' % target,
1583 parent = node['ocv:parent']
1585 rv = _create_refnode(expr)
1586 if rv is not None or parent is None:
1588 parent = parent.get_name()
1590 rv = _create_refnode(expr.prefix(parent))
1594 parent, name = parent.split_owner()
1595 return _create_refnode(expr.prefix(parent))
1597 def get_objects(self):
1598 for refname, (docname, type, theid) in self.data['objects'].iteritems():
1599 yield (refname, refname, type, docname, refname, 1)
1601 def get_type_name(self, type, primary=False):
1603 Return full name for given ObjType.
1609 'class': _('C++ class'),
1610 'struct': _('C/C++ struct'),
1611 'function': _('C++ function'),
1612 'cfunction': _('C function'),
1613 'jfunction': _('Java method'),
1614 'pyfunction': _('Python function'),
1615 'pyoldfunction': _('Legacy Python function'),
1616 'member': _('C++ member'),
1617 'emember': _('enum member'),
1618 'type': _('C/C++ type'),
1619 'enum': _('C/C++ enum'),
1620 'namespace': _('C++ namespace'),
1621 }.get(type.lname, _('%s %s') % (self.label, type.lname))
1624 app.add_domain(OCVDomain)