diff --git a/sphinxcontrib/doxylink/parsing.py b/sphinxcontrib/doxylink/parsing.py index ffa11e3..bf8a7eb 100644 --- a/sphinxcontrib/doxylink/parsing.py +++ b/sphinxcontrib/doxylink/parsing.py @@ -1,11 +1,11 @@ from typing import Tuple -from pyparsing import Word, Literal, nums, alphanums, OneOrMore, Opt,\ - SkipTo, ParseException, Group, Combine, delimitedList, quotedString,\ - nestedExpr, ParseResults, oneOf, ungroup, Keyword +from pyparsing import Word, Literal, nums, alphanums, OneOrMore, Opt, \ + SkipTo, ParseException, Group, Combine, delimitedList, quotedString, \ + nestedExpr, ParseResults, oneOf, ungroup, Keyword, ZeroOrMore # define punctuation - reuse of expressions helps packratting work better -LPAR, RPAR, LBRACK, RBRACK, COMMA, EQ = map(Literal, "()[],=") +LPAR, RPAR, LBRACK, RBRACK, LCBRACK, RCBRACK, COMMA, EQ = map(Literal, "()[]{},=") # Qualifier to go in front of type in the argument list (unsigned const int foo) qualifier_grouped = OneOrMore(Keyword('const') ^ Keyword('volatile') ^ Keyword('typename') ^ Keyword('struct') ^ Keyword('enum')) @@ -34,6 +34,7 @@ def normalise_templates(toks): # TODO Fix for nesting brackets parentheses_pair = LPAR + SkipTo(RPAR) + RPAR square_bracket_pair = LBRACK + SkipTo(RBRACK) + RBRACK +curly_bracket_pair = LCBRACK + SkipTo(RCBRACK) + RCBRACK # TODO I guess this should be a delimited list (by '::') of name and angle brackets nonfundamental_input_type = Combine(Word(alphanums + ':_') + Opt(angle_bracket_pair + Opt(Word(alphanums + ':_')))) @@ -47,17 +48,16 @@ def normalise_templates(toks): input_name = OneOrMore(Word(alphanums + '_') | angle_bracket_pair | parentheses_pair | square_bracket_pair) # Grab the '&', '*' or '**' type bit in (const QString & foo, int ** bar) -pointer_or_reference = Combine(oneOf('* &') + Opt('...')) +pointer = Literal('*') + Opt(Literal('const') | Literal('volatile')) +reference = Literal('&') +pointer_or_reference = pointer | reference # The '=QString()' or '=false' bit in (int foo = 4, bool bar = false) -default_value = Literal('=') + OneOrMore(number | quotedString | input_type | parentheses_pair | angle_bracket_pair | square_bracket_pair | Word('|&^')) +default_value = Literal('=') + OneOrMore(number | quotedString | input_type | parentheses_pair | angle_bracket_pair | square_bracket_pair | curly_bracket_pair | Word('|&^')) # A combination building up the interesting bit -- the argument type, e.g. 'const QString &', 'int' or 'char*' -argument_type = Opt(qualifier, default='')("qualifier") + \ - input_type('input_type').setParseAction(' '.join) + \ - Opt(pointer_or_reference, default='')("pointer_or_reference1") + \ - Opt('const')('const_pointer_or_reference') + \ - Opt(pointer_or_reference, default='')("pointer_or_reference2") +argument_type = Opt(qualifier, default='')("qualifier1") + \ + input_type("input_type").setParseAction(' '.join) + Opt(qualifier, default='')("qualifier2") + Group(ZeroOrMore(pointer_or_reference))("pointer_or_references") # Argument + variable name + default argument = Group(argument_type('argument_type') + Opt(input_name) + Opt(default_value)) @@ -128,19 +128,14 @@ def normalise(symbol: str) -> Tuple[str, str]: for arg in result.arg_list: # Here is where we build up our normalised form of the argument argument_string_list = [''] - if arg.qualifier: - argument_string_list.append(''.join((arg.qualifier, ' '))) + if arg.qualifier1: + argument_string_list.append(''.join((arg.qualifier1, ' '))) + if arg.qualifier2: + argument_string_list.append(''.join((arg.qualifier2, ' '))) argument_string_list.append(arg.input_type) # Functions can have a funny combination of *, & and const between the type and the name so build up a list of those here: - const_pointer_ref_list = [] - const_pointer_ref_list.append(arg.pointer_or_reference1) - if arg.const_pointer_or_reference: - const_pointer_ref_list.append(''.join((' ', arg.const_pointer_or_reference, ' '))) - # same here - const_pointer_ref_list.append(arg.pointer_or_reference2) - # And combine them into a single normalised string and add them to the argument list - argument_string_list.extend(const_pointer_ref_list) + argument_string_list.extend(''.join(arg.pointer_or_references)) # Finally we join our argument string and add it to our list normalised_arg_list.append(''.join(argument_string_list)) diff --git a/tests/test_parser.py b/tests/test_parser.py index e462299..4773d68 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -10,12 +10,13 @@ ('( QUrl source )', ('', '(QUrl)')), ('( QUrl * source )', ('', '(QUrl*)')), ('( QUrl ** source )', ('', '(QUrl**)')), + ('( QUrl ***&&** source )', ('', '(QUrl***&&**)')), ('( const QUrl ** source )', ('', '(const QUrl**)')), ('( const QUrl source )', ('', '(const QUrl)')), ('( QUrl & source )', ('', '(QUrl&)')), ('( const QUrl & source )', ('', '(const QUrl&)')), ('( const QUrl * source )', ('', '(const QUrl*)')), - ('( const QUrl const * source )', ('', '(const QUrl const *)')), + ('( const QUrl * const source )', ('', '(const QUrl*const)')), ('( const QByteArray & data, const QUrl & documentUri = QUrl() )', ('', '(const QByteArray&, const QUrl&)')), ('(void)', ('', '(void)')), ('(uint32_t uNoOfBlocksToProcess=(std::numeric_limits< uint32_t >::max)())', ('', '(uint32_t)')), @@ -31,6 +32,7 @@ ('() &', ('', '()&')), ('() &&', ('', '()&&')), ('( int index = 0 )', ('', '(int)')), + ('( int index = {0} )', ('', '(int)')), ('( bool ascending = true )', ('', '(bool)')), ('( const QIcon & icon, const QString & label, int width = -1 )', ('', '(const QIcon&, const QString&, int)')), ('( QWidget * parent = 0, const char * name = 0, Qt::WindowFlags f = Qt::WType_TopLevel )', ('', '(QWidget*, const char*, Qt::WindowFlags)')), @@ -43,14 +45,14 @@ ('( const QString & path, const QString & nameFilter, SortFlags sort = SortFlags( Name | IgnoreCase ))', ('', '(const QString&, const QString&, SortFlags)')), ('( GLuint texture_id )', ('', '(GLuint)')), ('( Q3ValueList::size_type i )', ('', '(Q3ValueList< T >::size_type)')), - ('(STLAllocator< T, P > const *, STLAllocator< T2, P > const &)', ('', '(STLAllocator< T, P > const *, STLAllocator< T2, P > const &)')), - ('(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)', ('', '(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)')), + ('(STLAllocator< T, P > const *, STLAllocator< T2, P > const &)', ('', '(const STLAllocator< T, P >*, const STLAllocator< T2, P >&)')), + ('(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)', ('', '(const STLAllocator< T, P >&, const STLAllocator< T2, P >&)')), ('(const String &errorMessage, String logName="")', ('', '(const String&, String)')), ('(PixelFormat = PF_BYTE)', ('', '(PixelFormat)')), ('(const SharedPtr< ControllerValue< T > > &src)', ('', '(const SharedPtr< ControllerValue < T > >&)')), ('(typename T::iterator start, typename T::iterator last)', ('', '(typename T::iterator, typename T::iterator)')), - ('(const Matrix4 *const *blendMatrices)', ('', '(const Matrix4* const *)')), - ('(const Matrix4 *const *blendMatrices) const =0', ('', '(const Matrix4* const *) const')), + ('(const Matrix4 *const *blendMatrices)', ('', '(const Matrix4*const*)')), + ('(const Matrix4 *const *blendMatrices) const =0', ('', '(const Matrix4*const*) const')), ] varargs = [