mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-09-03 20:52:55 -05:00
C++, change parsing context to explicit arguments, fixes some casting operators.
This commit is contained in:
+181
-160
@@ -120,6 +120,7 @@
|
||||
"""
|
||||
|
||||
import re
|
||||
import traceback
|
||||
from copy import deepcopy
|
||||
|
||||
from six import iteritems, text_type
|
||||
@@ -266,12 +267,8 @@ class ASTBase(UnicodeMixin):
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %s>' % (self.__class__.__name__, self)
|
||||
|
||||
def _verify_parsing_context(context):
|
||||
if not context in {'typeObject', 'functionObject', 'memberObject', 'classObject', 'namespaceObject', 'xrefObject', 'abstractDecl', 'functionObjectArgument', 'baseClass'}:
|
||||
raise Exception("Parsing context '%s' is invalid." % context)
|
||||
|
||||
def _verify_description_mod(mode):
|
||||
def _verify_description_mode(mode):
|
||||
if not mode in {'lastIsName', 'noneIsName', 'markType', 'param'}:
|
||||
raise Exception("Description mode '%s' is invalid." % mode)
|
||||
|
||||
@@ -287,7 +284,7 @@ class ASTOperatorBuildIn(ASTBase):
|
||||
return text_type(self)
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
identifier = text_type(self)
|
||||
if mode == 'lastIsName':
|
||||
signode += addnodes.desc_name(identifier, identifier)
|
||||
@@ -302,8 +299,11 @@ class ASTOperatorType(ASTBase):
|
||||
def __unicode__(self):
|
||||
return u''.join(['operator ', text_type(self.type)])
|
||||
|
||||
def get_name_no_template(self):
|
||||
return text_type(self)
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
identifier = text_type(self)
|
||||
if mode == 'lastIsName':
|
||||
signode += addnodes.desc_name(identifier, identifier)
|
||||
@@ -319,7 +319,7 @@ class ASTTemplateArgConstant(ASTBase):
|
||||
return text_type(self.value)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
signode += nodes.Text(text_type(self))
|
||||
|
||||
class ASTNestedNameElement(ASTBase):
|
||||
@@ -345,7 +345,7 @@ class ASTNestedNameElement(ASTBase):
|
||||
return text_type(self.identifier)
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
if mode == 'markType':
|
||||
targetText = prefix + text_type(self)
|
||||
pnode = addnodes.pending_xref(
|
||||
@@ -397,7 +397,7 @@ class ASTNestedName(ASTBase):
|
||||
return u'::'.join([text_type(n) for n in self.names])
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
if mode == 'lastIsName':
|
||||
addname = u'::'.join([text_type(n) for n in self.names[:-1]])
|
||||
if len(self.names) > 1: addname += u'::'
|
||||
@@ -476,7 +476,7 @@ class ASTFunctinoParameter(ASTBase):
|
||||
else: return text_type(self.arg)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
if self.ellipsis: signode += nodes.Text('...')
|
||||
else: self.arg.describe_signature(signode, mode, env)
|
||||
|
||||
@@ -530,7 +530,7 @@ class ASTParametersQualifiers(ASTBase):
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
paramlist = addnodes.desc_parameterlist()
|
||||
for arg in self.args:
|
||||
param = addnodes.desc_parameter('', '', noemph=True)
|
||||
@@ -554,8 +554,8 @@ class ASTParametersQualifiers(ASTBase):
|
||||
|
||||
class ASTDeclSpecs(ASTBase):
|
||||
|
||||
def __init__(self, context, visibility, storage, inline, virtual, explicit, constexpr, volatile, const, trailing):
|
||||
self.context = context
|
||||
def __init__(self, outer, visibility, storage, inline, virtual, explicit, constexpr, volatile, const, trailing):
|
||||
self.outer = outer
|
||||
self.visibility = visibility
|
||||
self.storage = storage
|
||||
self.inline = inline
|
||||
@@ -574,39 +574,41 @@ class ASTDeclSpecs(ASTBase):
|
||||
return text_type(self)
|
||||
|
||||
def _print_visibility(self):
|
||||
return self.visibility and not (self.context in {'typeObject', 'memberObject', 'functionObject'} and self.visibility == 'public')
|
||||
return self.visibility and not (self.outer in {'type', 'member', 'function'} and self.visibility == 'public')
|
||||
|
||||
def __unicode__(self):
|
||||
res = []
|
||||
if self._print_visibility():
|
||||
res.append(self.visibility)
|
||||
res.append(' ')
|
||||
if self.storage:
|
||||
res.append(self.storage)
|
||||
res.append(' ')
|
||||
if self.inline: res.append('inline ')
|
||||
if self.virtual: res.append('virtual ')
|
||||
if self.explicit: res.append('explicit ')
|
||||
if self.constexpr: res.append('constexpr ')
|
||||
if self.volatile: res.append('volatile ')
|
||||
if self.const: res.append('const ')
|
||||
res.append(text_type(self.trailingTypeSpec))
|
||||
return u''.join(res)
|
||||
if self._print_visibility(): res.append(self.visibility)
|
||||
if self.storage: res.append(self.storage)
|
||||
if self.inline: res.append('inline')
|
||||
if self.virtual: res.append('virtual')
|
||||
if self.explicit: res.append('explicit')
|
||||
if self.constexpr: res.append('constexpr')
|
||||
if self.volatile: res.append('volatile')
|
||||
if self.const: res.append('const')
|
||||
if self.trailingTypeSpec: res.append(text_type(self.trailingTypeSpec))
|
||||
return u' '.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
def _add(signode, text):
|
||||
signode += addnodes.desc_annotation(text, text)
|
||||
signode += nodes.Text(' ')
|
||||
if self._print_visibility(): _add(signode, self.visibility)
|
||||
if self.storage: _add(signode, self.storage)
|
||||
if self.inline: _add(signode, 'inline')
|
||||
if self.virtual: _add(signode, 'virtual')
|
||||
if self.explicit: _add(signode, 'explicit')
|
||||
if self.constexpr: _add(signode, 'constexpr')
|
||||
if self.volatile: _add(signode, 'volatile')
|
||||
if self.const: _add(signode, 'const')
|
||||
self.trailingTypeSpec.describe_signature(signode, mode, env)
|
||||
_verify_description_mode(mode)
|
||||
modifiers = []
|
||||
def _add(modifiers, text):
|
||||
if len(modifiers) > 0:
|
||||
modifiers.append(nodes.Text(' '))
|
||||
modifiers.append(addnodes.desc_annotation(text, text))
|
||||
if self._print_visibility(): _add(modifiers, self.visibility)
|
||||
if self.storage: _add(modifiers, self.storage)
|
||||
if self.inline: _add(modifiers, 'inline')
|
||||
if self.virtual: _add(modifiers, 'virtual')
|
||||
if self.explicit: _add(modifiers, 'explicit')
|
||||
if self.constexpr: _add(modifiers, 'constexpr')
|
||||
if self.volatile: _add(modifiers, 'volatile')
|
||||
if self.const: _add(modifiers, 'const')
|
||||
for m in modifiers: signode += m
|
||||
if self.trailingTypeSpec:
|
||||
if len(modifiers) > 0:
|
||||
signode += nodes.Text(' ')
|
||||
self.trailingTypeSpec.describe_signature(signode, mode, env)
|
||||
|
||||
class ASTArray(ASTBase):
|
||||
|
||||
@@ -617,7 +619,7 @@ class ASTArray(ASTBase):
|
||||
return u''.join(['[', text_type(self.size), ']'])
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
signode += nodes.Text(text_type(self))
|
||||
|
||||
class ASTDeclerator(ASTBase):
|
||||
@@ -642,7 +644,7 @@ class ASTDeclerator(ASTBase):
|
||||
|
||||
def require_start_space(self):
|
||||
if '...' in self.ptrOps: return False
|
||||
return not not self.declId
|
||||
else: return self.declId != None
|
||||
|
||||
def __unicode__(self):
|
||||
res = []
|
||||
@@ -655,7 +657,7 @@ class ASTDeclerator(ASTBase):
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
for op in self.ptrOps:
|
||||
signode += nodes.Text(text_type(op))
|
||||
if op == '...' and self.declId: signode += nodes.Text(' ')
|
||||
@@ -671,7 +673,7 @@ class ASTInitializer(ASTBase):
|
||||
return u''.join([' = ', text_type(self.value)])
|
||||
|
||||
def describe_signature(self, signode, mode):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
signode += nodes.Text(text_type(self))
|
||||
|
||||
class ASTType(ASTBase):
|
||||
@@ -704,19 +706,17 @@ class ASTType(ASTBase):
|
||||
|
||||
def __unicode__(self):
|
||||
res = []
|
||||
res.append(text_type(self.declSpecs))
|
||||
if self.decl.require_start_space():
|
||||
declSpecs = text_type(self.declSpecs)
|
||||
res.append(declSpecs)
|
||||
if self.decl.require_start_space() and len(declSpecs) > 0:
|
||||
res.append(u' ')
|
||||
res.append(text_type(self.decl))
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
if self.decl.name:
|
||||
self.declSpecs.describe_signature(signode, 'markType', env)
|
||||
else:
|
||||
self.declSpecs.describe_signature(signode, mode, env)
|
||||
if self.decl.require_start_space():
|
||||
_verify_description_mode(mode)
|
||||
self.declSpecs.describe_signature(signode, 'markType', env)
|
||||
if self.decl.require_start_space() and len(text_type(self.declSpecs)) > 0:
|
||||
signode += nodes.Text(' ')
|
||||
self.decl.describe_signature(signode, mode, env)
|
||||
|
||||
@@ -746,7 +746,7 @@ class ASTTypeWithInit(ASTBase):
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
self.type.describe_signature(signode, mode, env)
|
||||
if self.init: self.init.describe_signature(signode, mode)
|
||||
|
||||
@@ -765,7 +765,7 @@ class ASTBaseClass(ASTBase):
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
if self.visibility != 'private':
|
||||
signode += addnodes.desc_annotation(self.visibility, self.visibility)
|
||||
signode += nodes.Text(' ')
|
||||
@@ -793,7 +793,7 @@ class ASTClass(ASTBase):
|
||||
return u''.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env):
|
||||
_verify_description_mod(mode)
|
||||
_verify_description_mode(mode)
|
||||
self.name.describe_signature(signode, mode, env)
|
||||
if len(self.bases) > 0:
|
||||
signode += nodes.Text(' : ')
|
||||
@@ -882,7 +882,7 @@ class DefinitionParser(object):
|
||||
self.fail('expected end of definition, got %r' %
|
||||
self.definition[self.pos:])
|
||||
|
||||
def _parse_operator(self, context):
|
||||
def _parse_operator(self):
|
||||
self.skip_ws()
|
||||
# adapted from the old code
|
||||
# thank god, a regular operator definition
|
||||
@@ -890,25 +890,23 @@ class DefinitionParser(object):
|
||||
return ASTOperatorBuildIn(self.matched_text)
|
||||
|
||||
# new/delete operator?
|
||||
if False:
|
||||
for allocop in 'new', 'delete':
|
||||
if not self.skip_word(allocop):
|
||||
continue
|
||||
for op in 'new', 'delete':
|
||||
if not self.skip_word(op):
|
||||
continue
|
||||
self.skip_ws()
|
||||
if self.skip_string('['):
|
||||
self.skip_ws()
|
||||
if self.skip_string('['):
|
||||
self.skip_ws()
|
||||
if not self.skip_string(']'):
|
||||
self.fail('expected "]" for ' + allocop)
|
||||
allocop += '[]'
|
||||
return NameDefExpr('operator ' + allocop)
|
||||
if not self.skip_string(']'):
|
||||
self.fail('Expected "]" after "operator ' + op + '["')
|
||||
op += '[]'
|
||||
return ASTOperatorBuildIn(' ' + op)
|
||||
|
||||
# oh well, looks like a cast operator definition.
|
||||
# In that case, eat another type.
|
||||
type = self._parse_type('abstractDecl')
|
||||
type = self._parse_type()
|
||||
return ASTOperatorType(type)
|
||||
|
||||
def _parse_nested_name(self, context):
|
||||
_verify_parsing_context(context)
|
||||
def _parse_nested_name(self):
|
||||
names = []
|
||||
|
||||
self.skip_ws()
|
||||
@@ -920,7 +918,7 @@ class DefinitionParser(object):
|
||||
self.fail("expected identifier")
|
||||
identifier = self.matched_text
|
||||
if identifier == 'operator':
|
||||
op = self._parse_operator(context)
|
||||
op = self._parse_operator()
|
||||
names.append(op)
|
||||
else:
|
||||
templateArgs = None
|
||||
@@ -930,7 +928,7 @@ class DefinitionParser(object):
|
||||
while 1:
|
||||
pos = self.pos
|
||||
try:
|
||||
type = self._parse_type('abstractDecl')
|
||||
type = self._parse_type(allowParams=True)
|
||||
templateArgs.append(type)
|
||||
except DefinitionError:
|
||||
self.pos = pos
|
||||
@@ -960,9 +958,7 @@ class DefinitionParser(object):
|
||||
if not self.skip_string('::'): break
|
||||
return ASTNestedName(names)
|
||||
|
||||
def _parse_trailing_type_spec(self, context):
|
||||
_verify_parsing_context(context)
|
||||
|
||||
def _parse_trailing_type_spec(self):
|
||||
# fundemental types
|
||||
self.skip_ws()
|
||||
for t in self._simple_fundemental_types:
|
||||
@@ -994,15 +990,13 @@ class DefinitionParser(object):
|
||||
prefix = k
|
||||
break
|
||||
|
||||
nestedName = self._parse_nested_name(context)
|
||||
nestedName = self._parse_nested_name()
|
||||
return ASTTrailingTypeSpecName(prefix, nestedName)
|
||||
|
||||
def _parse_parameters_and_qualifiers(self, context):
|
||||
_verify_parsing_context(context)
|
||||
|
||||
def _parse_parameters_and_qualifiers(self, paramMode):
|
||||
self.skip_ws()
|
||||
if not self.skip_string('('):
|
||||
if context == 'functionObject':
|
||||
if paramMode == 'function':
|
||||
self.fail('Expecting "(" in parameters_and_qualifiers.')
|
||||
else: return None
|
||||
args = []
|
||||
@@ -1016,10 +1010,10 @@ class DefinitionParser(object):
|
||||
if not self.skip_string(')'):
|
||||
self.fail('Expected ")" after "..." in parameters_and_qualifiers.')
|
||||
break
|
||||
if context == 'functionObjectArgument':
|
||||
arg = self._parse_type_with_init(context)
|
||||
if paramMode == 'function':
|
||||
arg = self._parse_type_with_init(named='maybe')
|
||||
else:
|
||||
arg = self._parse_type(context)
|
||||
arg = self._parse_type()
|
||||
# TODO: parse default parameters
|
||||
args.append(ASTFunctinoParameter(arg))
|
||||
|
||||
@@ -1028,6 +1022,9 @@ class DefinitionParser(object):
|
||||
elif self.skip_string(')'): break
|
||||
else: self.fail('Expecting "," or ")" in parameters_and_qualifiers, got "%s".' % self.current_char)
|
||||
|
||||
if paramMode != 'function':
|
||||
return ASTParametersQualifiers(args, None, None, None, None, None, None, None)
|
||||
|
||||
self.skip_ws()
|
||||
const = self.skip_word_and_ws('const')
|
||||
volatile = self.skip_word_and_ws('volatile')
|
||||
@@ -1042,40 +1039,38 @@ class DefinitionParser(object):
|
||||
override = None
|
||||
final = None
|
||||
initializer = None
|
||||
if context == 'functionObjectArgument':
|
||||
self.skip_ws()
|
||||
if self.skip_string('noexcept'):
|
||||
exceptionSpec = 'noexcept'
|
||||
self.skip_ws()
|
||||
if self.skip_string('noexcept'):
|
||||
exceptionSpec = 'noexcept'
|
||||
self.skip_ws()
|
||||
if self.skip_string('('):
|
||||
self.fail('Parameterised "noexcept" not implemented.')
|
||||
if self.skip_string('('):
|
||||
self.fail('Parameterised "noexcept" not implemented.')
|
||||
|
||||
self.skip_ws()
|
||||
override = self.skip_word_and_ws('override')
|
||||
final = self.skip_word_and_ws('final')
|
||||
if not override: override = self.skip_word_and_ws('override') # they can be permuted
|
||||
self.skip_ws()
|
||||
override = self.skip_word_and_ws('override')
|
||||
final = self.skip_word_and_ws('final')
|
||||
if not override: override = self.skip_word_and_ws('override') # they can be permuted
|
||||
|
||||
self.skip_ws()
|
||||
if self.skip_string('='):
|
||||
self.skip_ws()
|
||||
if self.skip_string('='):
|
||||
self.skip_ws()
|
||||
valid = {'0', 'delete', 'default'}
|
||||
for w in valid:
|
||||
if self.skip_word_and_ws(w):
|
||||
initializer = w
|
||||
break
|
||||
if not initializer:
|
||||
self.fail('Expected "%s" in initializer-specifier.' % u'" or "'.join(valid))
|
||||
valid = {'0', 'delete', 'default'}
|
||||
for w in valid:
|
||||
if self.skip_word_and_ws(w):
|
||||
initializer = w
|
||||
break
|
||||
if not initializer:
|
||||
self.fail('Expected "%s" in initializer-specifier.' % u'" or "'.join(valid))
|
||||
|
||||
return ASTParametersQualifiers(args, volatile, const, refQual, exceptionSpec, override, final, initializer)
|
||||
|
||||
def _parse_decl_specs(self, context):
|
||||
def _parse_decl_specs(self, outer, typed=True):
|
||||
"""
|
||||
visibility storage-class-specifier function-specifier "constexpr" "volatile" "const" trailing-type-specifier
|
||||
storage-class-specifier -> "static" (only for member_object and function_object)
|
||||
function-specifier -> "inline" | "virtual" | "explicit" (only for function_object)
|
||||
"constexpr" (only for member_object and function_object)
|
||||
"""
|
||||
_verify_parsing_context(context)
|
||||
visibility = None
|
||||
storage = None
|
||||
inline = None
|
||||
@@ -1085,30 +1080,28 @@ class DefinitionParser(object):
|
||||
volatile = None
|
||||
const = None
|
||||
|
||||
# visibility
|
||||
if context in {'typeObject', 'memberObject', 'functionObject'}:
|
||||
if outer:
|
||||
self.skip_ws()
|
||||
visibility = 'public'
|
||||
if self.match(_visibility_re):
|
||||
visibility = self.matched_text
|
||||
|
||||
while 1: # accept any permutation of a subset of some decl-specs
|
||||
self.skip_ws()
|
||||
if not storage:
|
||||
if context in {'memberObject', 'functionObject'}:
|
||||
if outer in {'member', 'function'}:
|
||||
if self.skip_word('static'):
|
||||
storage = 'static'
|
||||
continue
|
||||
if context == 'memberObject':
|
||||
if outer == 'member':
|
||||
if self.skip_word('mutable'):
|
||||
storage = 'mutable'
|
||||
continue
|
||||
if context == 'functionObject': # TODO: maybe in more contexts, missing test cases
|
||||
if outer == 'fuction': # TODO: maybe in more contexts, missing test cases
|
||||
if self.skip_word('register'):
|
||||
storage = 'register'
|
||||
continue
|
||||
|
||||
if context == 'functionObject':
|
||||
if outer == 'function':
|
||||
# function-specifiers
|
||||
if not inline:
|
||||
inline = self.skip_word('inline')
|
||||
@@ -1120,25 +1113,28 @@ class DefinitionParser(object):
|
||||
explicit = self.skip_word('explicit')
|
||||
if explicit: continue
|
||||
|
||||
if not constexpr and context in {'memberObject', 'functionObject'}:
|
||||
if not constexpr and outer in {'member', 'function'}:
|
||||
constexpr = self.skip_word("constexpr")
|
||||
if constexpr: continue
|
||||
if not volatile:
|
||||
if not volatile and typed:
|
||||
volatile = self.skip_word('volatile')
|
||||
if volatile: continue
|
||||
if not const:
|
||||
if not const and typed:
|
||||
const = self.skip_word('const')
|
||||
if const: continue
|
||||
break
|
||||
|
||||
trailing = self._parse_trailing_type_spec(context)
|
||||
return ASTDeclSpecs(context, visibility, storage, inline, virtual, explicit, constexpr, volatile, const, trailing)
|
||||
if typed: trailing = self._parse_trailing_type_spec()
|
||||
else: trailing = None
|
||||
return ASTDeclSpecs(outer, visibility, storage, inline, virtual, explicit, constexpr, volatile, const, trailing)
|
||||
|
||||
def _parse_declerator(self, context):
|
||||
_verify_parsing_context(context)
|
||||
|
||||
def _parse_declerator(self, named, paramMode=None, typed=True):
|
||||
if paramMode:
|
||||
if not paramMode in {'type', 'function'}:
|
||||
raise Exception("Internal error, unknown paramMode '%s'." % paramMode)
|
||||
ptrOps = []
|
||||
while 1:
|
||||
if not typed: break
|
||||
self.skip_ws()
|
||||
if self.skip_string('*'):
|
||||
op = '*'
|
||||
@@ -1152,27 +1148,20 @@ class DefinitionParser(object):
|
||||
break
|
||||
else: break
|
||||
|
||||
if context == 'abstractDecl':
|
||||
declId = None
|
||||
elif context in {'functionObjectArgument', 'functionObject', 'typeObject'}:
|
||||
# Function arguments don't need to have a name.
|
||||
# Some functions (constructors/destructors) don't ahve return type,
|
||||
# so the name has been parsed in the declSpecs.
|
||||
# Also conversion operators (e.g., "A::operator std::string()" will have no declId at this point
|
||||
# For types we want to allow the plain declaration that there is a type, i.e., "MyContainer::const_iterator"
|
||||
pos = self.pos
|
||||
if named == 'maybe':
|
||||
try:
|
||||
declId = self._parse_nested_name(context)
|
||||
declId = self._parse_nested_name()
|
||||
except DefinitionError:
|
||||
self.pos = pos
|
||||
declId = None
|
||||
elif named:
|
||||
declId = self._parse_nested_name()
|
||||
else:
|
||||
declId = self._parse_nested_name(context)
|
||||
declId = None
|
||||
|
||||
suffixOpts = []
|
||||
while 1:
|
||||
self.skip_ws()
|
||||
if self.skip_string('['):
|
||||
if typed and self.skip_string('['):
|
||||
startPos = self.pos - 1
|
||||
openCount = 1
|
||||
while not self.eof:
|
||||
@@ -1187,25 +1176,22 @@ class DefinitionParser(object):
|
||||
self.pos += 1
|
||||
suffixOpts.append(ASTArray(self.definition[startPos+1:self.pos-1].strip()))
|
||||
continue
|
||||
if context == 'functionObject':
|
||||
paramQual = self._parse_parameters_and_qualifiers('functionObjectArgument')
|
||||
else:
|
||||
paramQual = self._parse_parameters_and_qualifiers(context)
|
||||
if paramQual: suffixOpts.append(paramQual)
|
||||
if paramMode:
|
||||
paramQual = self._parse_parameters_and_qualifiers(paramMode)
|
||||
if paramQual: suffixOpts.append(paramQual)
|
||||
break
|
||||
|
||||
return ASTDeclerator(ptrOps, declId, suffixOpts)
|
||||
|
||||
def _parse_initializer(self, context):
|
||||
_verify_parsing_context(context)
|
||||
def _parse_initializer(self, outer=None):
|
||||
self.skip_ws()
|
||||
# TODO: support paren and brace initialization for memberObject
|
||||
if not self.skip_string('='): return None
|
||||
else:
|
||||
if context == 'memberObject':
|
||||
if outer == 'member':
|
||||
value = self.read_rest().strip()
|
||||
return ASTInitializer(value)
|
||||
elif context == 'functionObjectArgument':
|
||||
elif outer == None: # function parameter
|
||||
symbols = []
|
||||
startPos = self.pos
|
||||
self.skip_ws()
|
||||
@@ -1224,22 +1210,57 @@ class DefinitionParser(object):
|
||||
value = self.definition[startPos:self.pos].strip()
|
||||
return ASTInitializer(value)
|
||||
else:
|
||||
self.fail("Initializer for context '%s' not implemented." % context)
|
||||
self.fail("Internal error, initializer for outer '%s' not implemented." % outer)
|
||||
|
||||
def _parse_type(self, context):
|
||||
_verify_parsing_context(context)
|
||||
declSpecs = self._parse_decl_specs(context)
|
||||
decl = self._parse_declerator(context)
|
||||
def _parse_type(self, outer=None, named=False, allowParams=False):
|
||||
"""
|
||||
named=False|'maybe'|True: 'maybe' is e.g., for function objects which doesn't need to name the arguments
|
||||
"""
|
||||
if outer: # always named
|
||||
if not outer in {'type', 'member', 'function'}:
|
||||
raise Exception('Internal error, unknown outer "%s".' % outer)
|
||||
assert not named
|
||||
|
||||
if outer in {'type', 'function'}:
|
||||
# We allow type objects to just be a name.
|
||||
# Some functions don't have normal return types: constructors, destrutors, cast operators
|
||||
startPos = self.pos
|
||||
# first try without the type
|
||||
try:
|
||||
declSpecs = self._parse_decl_specs(outer=outer, typed=False)
|
||||
decl = self._parse_declerator(named=True, paramMode=outer, typed=False)
|
||||
self.assert_end()
|
||||
except DefinitionError as exUntyped:
|
||||
self.pos = startPos
|
||||
try:
|
||||
declSpecs = self._parse_decl_specs(outer=outer)
|
||||
decl = self._parse_declerator(named=True, paramMode=outer)
|
||||
except DefinitionError as exTyped:
|
||||
if outer == 'type':
|
||||
raise DefinitionError('Type must be either just a name or a typedef-like declaration.\nJust a name error: %s\nTypedef-like expression error: %s'
|
||||
% (exUntyped.description, exTyped.description))
|
||||
else: # do it again to get the proper traceback (how do you relieable save a traceback when an exception is constructed?)
|
||||
self.pos = startPos
|
||||
declSpecs = self._parse_decl_specs(outer=outer)
|
||||
decl = self._parse_declerator(named=True, paramMode=outer)
|
||||
else:
|
||||
if outer:
|
||||
named = True
|
||||
allowParams = True
|
||||
if allowParams: paramMode = 'type'
|
||||
else: paramMode = None
|
||||
declSpecs = self._parse_decl_specs(outer=outer)
|
||||
decl = self._parse_declerator(named=named, paramMode=paramMode)
|
||||
return ASTType(declSpecs, decl)
|
||||
|
||||
def _parse_type_with_init(self, context):
|
||||
_verify_parsing_context(context)
|
||||
type = self._parse_type(context)
|
||||
init = self._parse_initializer(context)
|
||||
def _parse_type_with_init(self, outer=None, named=False):
|
||||
if outer: assert outer in {'type', 'member', 'function'}
|
||||
type = self._parse_type(outer=outer, named=named)
|
||||
init = self._parse_initializer(outer=outer)
|
||||
return ASTTypeWithInit(type, init)
|
||||
|
||||
def _parse_class(self, context):
|
||||
name = self._parse_nested_name(context)
|
||||
def _parse_class(self):
|
||||
name = self._parse_nested_name()
|
||||
bases = []
|
||||
self.skip_ws()
|
||||
if self.skip_string(':'):
|
||||
@@ -1248,7 +1269,7 @@ class DefinitionParser(object):
|
||||
visibility = 'private'
|
||||
if self.match(_visibility_re):
|
||||
visibility = self.matched_text
|
||||
baseName = self._parse_nested_name('baseClass')
|
||||
baseName = self._parse_nested_name()
|
||||
bases.append(ASTBaseClass(baseName, visibility))
|
||||
self.skip_ws()
|
||||
if self.skip_string(','): continue
|
||||
@@ -1256,32 +1277,32 @@ class DefinitionParser(object):
|
||||
return ASTClass(name, bases)
|
||||
|
||||
def parse_type_object(self):
|
||||
res = self._parse_type('typeObject')
|
||||
res = self._parse_type(outer='type')
|
||||
res.objectType = 'type'
|
||||
return res
|
||||
|
||||
def parse_member_object(self):
|
||||
res = self._parse_type_with_init('memberObject')
|
||||
res = self._parse_type_with_init(outer='member')
|
||||
res.objectType = 'member'
|
||||
return res
|
||||
|
||||
def parse_function_object(self):
|
||||
res = self._parse_type('functionObject')
|
||||
res = self._parse_type(outer='function')
|
||||
res.objectType = 'function'
|
||||
return res
|
||||
|
||||
def parse_class_object(self):
|
||||
res = self._parse_class('classObject')
|
||||
res = self._parse_class()
|
||||
res.objectType = 'class'
|
||||
return res
|
||||
|
||||
def parse_namespace_object(self):
|
||||
res = self._parse_nested_name('namespaceObject')
|
||||
res = self._parse_nested_name()
|
||||
res.objectType = 'namespace'
|
||||
return res
|
||||
|
||||
def parse_xref_object(self):
|
||||
res = self._parse_nested_name('xrefObject')
|
||||
res = self._parse_nested_name()
|
||||
res.objectType = 'xref'
|
||||
return res
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ def check(name, input, output=None):
|
||||
raise DefinitionError("")
|
||||
# now check describe_signature
|
||||
ast.describe_signature([], 'lastIsName', None)
|
||||
#print ".. %s:: %s" % (name, input)
|
||||
|
||||
def test_type_definitions():
|
||||
check("type", "public bool b", "bool b")
|
||||
@@ -54,6 +55,7 @@ def test_type_definitions():
|
||||
check("type", "std::function<R(A1, A2, A3)> F")
|
||||
check("type", "std::function<R(A1, A2, A3, As...)> F")
|
||||
check("type", "MyContainer::const_iterator")
|
||||
check("type", "public MyContainer::const_iterator", "MyContainer::const_iterator")
|
||||
|
||||
check('member', ' const std::string & name = 42', 'const std::string &name = 42')
|
||||
check('member', ' const std::string & name', 'const std::string &name')
|
||||
@@ -61,6 +63,8 @@ def test_type_definitions():
|
||||
check('member', 'const std::vector< unsigned int, long> &name', 'const std::vector<unsigned int, long> &name')
|
||||
check('member', 'module::myclass foo[n]')
|
||||
|
||||
check('function', 'operator bool() const')
|
||||
check('function', 'bool namespaced::theclass::method(arg1, arg2)')
|
||||
x = 'std::vector<std::pair<std::string, int>> &module::test(register ' \
|
||||
'foo, bar, std::string baz = "foobar, blah, bleh") const = 0'
|
||||
check('function', x)
|
||||
@@ -78,7 +82,7 @@ def test_type_definitions():
|
||||
check('function', 'int get_value() const noexcept')
|
||||
check('function', 'int get_value() const noexcept = delete')
|
||||
check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default')
|
||||
check('function', 'MyClass::a_virtual_function() const override')
|
||||
check('function', 'virtual MyClass::a_virtual_function() const override')
|
||||
check('function', 'A B() override')
|
||||
check('function', 'A B() final')
|
||||
check('function', 'A B() final override')
|
||||
@@ -116,5 +120,6 @@ def test_bases():
|
||||
def test_operators():
|
||||
check('function', 'void operator new [ ] ()', 'void operator new[]()')
|
||||
check('function', 'void operator delete ()', 'void operator delete()')
|
||||
check('function', 'void operator bool() const', 'void operator bool() const')
|
||||
for op in '*-+=/%!':
|
||||
check('function', 'void operator %s ()' % op, 'void operator%s()' % op)
|
||||
|
||||
Reference in New Issue
Block a user