about summary refs log tree commit diff
path: root/docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm
diff options
context:
space:
mode:
Diffstat (limited to 'docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm')
-rw-r--r--docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm1215
1 files changed, 0 insertions, 1215 deletions
diff --git a/docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm b/docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm
deleted file mode 100644
index 72f2b871..00000000
--- a/docs/doctool/Modules/NaturalDocs/Languages/CSharp.pm
+++ /dev/null
@@ -1,1215 +0,0 @@
-###############################################################################
-#
-#   Class: NaturalDocs::Languages::CSharp
-#
-###############################################################################
-#
-#   A subclass to handle the language variations of C#.
-#
-#
-#   Topic: Language Support
-#
-#       Supported:
-#
-#       - Classes
-#       - Namespaces (no topic generated)
-#       - Functions
-#       - Constructors and Destructors
-#       - Properties
-#       - Indexers
-#       - Operators
-#       - Delegates
-#       - Variables
-#       - Constants
-#       - Events
-#
-#       Not supported yet:
-#
-#       - Enums
-#       - Using
-#       - Using alias
-#
-###############################################################################
-
-# This file is part of Natural Docs, which is Copyright (C) 2003-2005 Greg Valure
-# Natural Docs is licensed under the GPL
-
-use strict;
-use integer;
-
-package NaturalDocs::Languages::CSharp;
-
-use base 'NaturalDocs::Languages::Advanced';
-
-
-###############################################################################
-# Group: Package Variables
-
-#
-#   hash: classKeywords
-#   An existence hash of all the acceptable class keywords.  The keys are in all lowercase.
-#
-my %classKeywords = ( 'class' => 1,
-                                    'struct' => 1,
-                                    'interface' => 1 );
-
-#
-#   hash: classModifiers
-#   An existence hash of all the acceptable class modifiers.  The keys are in all lowercase.
-#
-my %classModifiers = ( 'new' => 1,
-                                   'public' => 1,
-                                   'protected' => 1,
-                                   'internal' => 1,
-                                   'private' => 1,
-                                   'abstract' => 1,
-                                   'sealed' => 1,
-                                   'unsafe' => 1 );
-
-#
-#   hash: functionModifiers
-#   An existence hash of all the acceptable function modifiers.  Also applies to properties.  Also encompasses those for operators
-#   and indexers, but have more than are valid for them.  The keys are in all lowercase.
-#
-my %functionModifiers = ( 'new' => 1,
-                                       'public' => 1,
-                                       'protected' => 1,
-                                       'internal' => 1,
-                                       'private' => 1,
-                                       'static' => 1,
-                                       'virtual' => 1,
-                                       'sealed' => 1,
-                                       'override' => 1,
-                                       'abstract' => 1,
-                                       'extern' => 1,
-                                       'unsafe' => 1 );
-
-#
-#   hash: variableModifiers
-#   An existence hash of all the acceptable variable modifiers.  The keys are in all lowercase.
-#
-my %variableModifiers = ( 'new' => 1,
-                                       'public' => 1,
-                                       'protected' => 1,
-                                       'internal' => 1,
-                                       'private' => 1,
-                                       'static' => 1,
-                                       'readonly' => 1,
-                                       'volatile' => 1,
-                                       'unsafe' => 1 );
-
-#
-#   hash: impossibleTypeWords
-#   An existence hash of all the reserved words that cannot be in a type.  This includes 'enum' and all modifiers.  The keys are in
-#   all lowercase.
-#
-my %impossibleTypeWords = ( 'abstract' => 1, 'as' => 1, 'base' => 1, 'break' => 1, 'case' => 1, 'catch' => 1,
-                                              'checked' => 1, 'class' => 1, 'const' => 1, 'continue' => 1, 'default' => 1, 'delegate' => 1,
-                                              'do' => 1, 'else' => 1, 'enum' => 1, 'event' => 1, 'explicit' => 1, 'extern' => 1,
-                                              'false' => 1, 'finally' => 1, 'fixed' => 1, 'for' => 1, 'foreach' => 1, 'goto' => 1, 'if' => 1,
-                                              'implicit' => 1, 'in' => 1, 'interface' => 1, 'internal' => 1, 'is' => 1, 'lock' => 1,
-                                              'namespace' => 1, 'new' => 1, 'null' => 1, 'operator' => 1, 'out' => 1, 'override' => 1,
-                                              'params' => 1, 'private' => 1, 'protected' => 1, 'public' => 1, 'readonly' => 1, 'ref' => 1,
-                                              'return' => 1, 'sealed' => 1, 'sizeof' => 1, 'stackalloc' => 1, 'static' => 1,
-                                              'struct' => 1, 'switch' => 1, 'this' => 1, 'throw' => 1, 'true' => 1, 'try' => 1, 'typeof' => 1,
-                                              'unchecked' => 1, 'unsafe' => 1, 'using' => 1, 'virtual' => 1, 'volatile' => 1, 'while' => 1 );
-# Deleted from the list: object, string, bool, decimal, sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, void
-
-
-
-###############################################################################
-# Group: Interface Functions
-
-
-#
-#   Function: PackageSeparator
-#   Returns the package separator symbol.
-#
-sub PackageSeparator
-    {  return '.';  };
-
-
-#
-#   Function: EnumValues
-#   Returns the <EnumValuesType> that describes how the language handles enums.
-#
-sub EnumValues
-    {  return ::ENUM_UNDER_TYPE();  };
-
-
-#
-#   Function: ParseFile
-#
-#   Parses the passed source file, sending comments acceptable for documentation to <NaturalDocs::Parser->OnComment()>.
-#
-#   Parameters:
-#
-#       sourceFile - The <FileName> to parse.
-#       topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
-#
-#   Returns:
-#
-#       The array ( autoTopics, scopeRecord ).
-#
-#       autoTopics - An arrayref of automatically generated topics from the file, or undef if none.
-#       scopeRecord - An arrayref of <NaturalDocs::Languages::Advanced::ScopeChanges>, or undef if none.
-#
-sub ParseFile #(sourceFile, topicsList)
-    {
-    my ($self, $sourceFile, $topicsList) = @_;
-
-    $self->ParseForCommentsAndTokens($sourceFile, [ '//' ], [ '/*', '*/' ] );
-
-    my $tokens = $self->Tokens();
-    my $index = 0;
-    my $lineNumber = 1;
-
-    while ($index < scalar @$tokens)
-        {
-        if ($self->TryToSkipWhitespace(\$index, \$lineNumber) ||
-            $self->TryToGetNamespace(\$index, \$lineNumber) ||
-            $self->TryToGetClass(\$index, \$lineNumber) ||
-            $self->TryToGetFunction(\$index, \$lineNumber) ||
-            $self->TryToGetOverloadedOperator(\$index, \$lineNumber) ||
-            $self->TryToGetVariable(\$index, \$lineNumber) )
-            {
-            # The functions above will handle everything.
-            }
-
-        elsif ($tokens->[$index] eq '{')
-            {
-            $self->StartScope('}', $lineNumber, undef, undef, undef);
-            $index++;
-            }
-
-        elsif ($tokens->[$index] eq '}')
-            {
-            if ($self->ClosingScopeSymbol() eq '}')
-                {  $self->EndScope($lineNumber);  };
-
-            $index++;
-            }
-
-        else
-            {
-            $self->SkipRestOfStatement(\$index, \$lineNumber);
-            };
-        };
-
-
-    # Don't need to keep these around.
-    $self->ClearTokens();
-
-
-    my $autoTopics = $self->AutoTopics();
-
-    my $scopeRecord = $self->ScopeRecord();
-    if (defined $scopeRecord && !scalar @$scopeRecord)
-        {  $scopeRecord = undef;  };
-
-    return ( $autoTopics, $scopeRecord );
-    };
-
-
-
-###############################################################################
-# Group: Statement Parsing Functions
-# All functions here assume that the current position is at the beginning of a statement.
-#
-# Note for developers: I am well aware that the code in these functions do not check if we're past the end of the tokens as
-# often as it should.  We're making use of the fact that Perl will always return undef in these cases to keep the code simpler.
-
-
-#
-#   Function: TryToGetNamespace
-#
-#   Determines whether the position is at a namespace declaration statement, and if so, adjusts the scope, skips it, and returns
-#   true.
-#
-#   Why no topic?:
-#
-#       The main reason we don't create a Natural Docs topic for a namespace is because in order to declare class A.B.C in C#,
-#       you must do this:
-#
-#       > namespace A.B
-#       >    {
-#       >    class C
-#       >        { ... }
-#       >    }
-#
-#       That would result in a namespace topic whose only purpose is really to qualify C.  It would take the default page title, and
-#       thus the default menu title.  So if you have files for A.B.X, A.B.Y, and A.B.Z, they all will appear as A.B on the menu.
-#
-#       If something actually appears in the namespace besides a class, it will be handled by
-#       <NaturalDocs::Parser->AddPackageDelineators()>.  That function will add a package topic to correct the scope.
-#
-#       If the user actually documented it, it will still appear because of the manual topic.
-#
-sub TryToGetNamespace #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    if (lc($tokens->[$$indexRef]) ne 'namespace')
-        {  return undef;  };
-
-    my $index = $$indexRef + 1;
-    my $lineNumber = $$lineNumberRef;
-
-    if (!$self->TryToSkipWhitespace(\$index, \$lineNumber))
-        {  return undef;  };
-
-    my $name;
-
-    while ($tokens->[$index] =~ /^[a-z_\.\@]/i)
-        {
-        $name .= $tokens->[$index];
-        $index++;
-        };
-
-    if (!defined $name)
-        {  return undef;  };
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-    if ($tokens->[$index] ne '{')
-        {  return undef;  };
-
-    $index++;
-
-
-    # We found a valid one if we made it this far.
-
-    my $autoTopic = NaturalDocs::Parser::ParsedTopic->New(::TOPIC_CLASS(), $name,
-                                                                                         $self->CurrentScope(), undef,
-                                                                                         undef,
-                                                                                         undef, undef, $$lineNumberRef);
-
-    # We don't add an auto-topic for namespaces.  See the function documentation above.
-
-    NaturalDocs::Parser->OnClass($autoTopic->Package());
-
-    $self->StartScope('}', $lineNumber, $autoTopic->Package());
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return 1;
-    };
-
-
-#
-#   Function: TryToGetClass
-#
-#   Determines whether the position is at a class declaration statement, and if so, generates a topic for it, skips it, and
-#   returns true.
-#
-#   Supported Syntaxes:
-#
-#       - Classes
-#       - Structs
-#       - Interfaces
-#
-sub TryToGetClass #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $index = $$indexRef;
-    my $lineNumber = $$lineNumberRef;
-
-    if ($self->TryToSkipAttributes(\$index, \$lineNumber))
-        {  $self->TryToSkipWhitespace(\$index, \$lineNumber);  }
-
-    my @modifiers;
-
-    while ($tokens->[$index] =~ /^[a-z]/i &&
-              !exists $classKeywords{lc($tokens->[$index])} &&
-              exists $classModifiers{lc($tokens->[$index])} )
-        {
-        push @modifiers, lc($tokens->[$index]);
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        };
-
-    if (!exists $classKeywords{lc($tokens->[$index])})
-        {  return undef;  };
-
-    my $lcClassKeyword = lc($tokens->[$index]);
-
-    $index++;
-
-    if (!$self->TryToSkipWhitespace(\$index, \$lineNumber))
-        {  return undef;  };
-
-    my $name;
-
-    while ($tokens->[$index] =~ /^[a-z_\@]/i)
-        {
-        $name .= $tokens->[$index];
-        $index++;
-        };
-
-    if (!defined $name)
-        {  return undef;  };
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-    my @parents;
-
-    if ($tokens->[$index] eq ':')
-        {
-        do
-            {
-            $index++;
-
-            $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-            my $parentName;
-
-            while ($tokens->[$index] =~ /^[a-z_\.\@]/i)
-                {
-                $parentName .= $tokens->[$index];
-                $index++;
-                };
-
-            if (!defined $parentName)
-                {  return undef;  };
-
-            push @parents, NaturalDocs::SymbolString->FromText($parentName);
-
-            $self->TryToSkipWhitespace(\$index, \$lineNumber);
-            }
-        while ($tokens->[$index] eq ',')
-        };
-
-    if ($tokens->[$index] ne '{')
-        {  return undef;  };
-
-    $index++;
-
-
-    # If we made it this far, we have a valid class declaration.
-
-    my @scopeIdentifiers = NaturalDocs::SymbolString->IdentifiersOf($self->CurrentScope());
-    $name = join('.', @scopeIdentifiers, $name);
-
-    my $topicType;
-
-    if ($lcClassKeyword eq 'interface')
-        {  $topicType = ::TOPIC_INTERFACE();  }
-    else
-        {  $topicType = ::TOPIC_CLASS();  };
-
-    my $autoTopic = NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
-                                                                                         undef, undef,
-                                                                                         undef,
-                                                                                         undef, undef, $$lineNumberRef);
-
-    $self->AddAutoTopic($autoTopic);
-    NaturalDocs::Parser->OnClass($autoTopic->Package());
-
-    foreach my $parent (@parents)
-        {
-        NaturalDocs::Parser->OnClassParent($autoTopic->Package(), $parent, $self->CurrentScope(), undef,
-                                                               ::RESOLVE_RELATIVE());
-        };
-
-    $self->StartScope('}', $lineNumber, $autoTopic->Package());
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return 1;
-    };
-
-
-#
-#   Function: TryToGetFunction
-#
-#   Determines if the position is on a function declaration, and if so, generates a topic for it, skips it, and returns true.
-#
-#   Supported Syntaxes:
-#
-#       - Functions
-#       - Constructors
-#       - Destructors
-#       - Properties
-#       - Indexers
-#       - Delegates
-#       - Events
-#
-sub TryToGetFunction #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $index = $$indexRef;
-    my $lineNumber = $$lineNumberRef;
-
-    if ($self->TryToSkipAttributes(\$index, \$lineNumber))
-        {  $self->TryToSkipWhitespace(\$index, \$lineNumber);  };
-
-    my $startIndex = $index;
-    my $startLine = $lineNumber;
-
-    my @modifiers;
-
-    while ($tokens->[$index] =~ /^[a-z]/i &&
-              exists $functionModifiers{lc($tokens->[$index])} )
-        {
-        push @modifiers, lc($tokens->[$index]);
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        };
-
-    my $isDelegate;
-    my $isEvent;
-
-    if (lc($tokens->[$index]) eq 'delegate')
-        {
-        $isDelegate = 1;
-        $index++;
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        }
-    elsif (lc($tokens->[$index]) eq 'event')
-        {
-        $isEvent = 1;
-        $index++;
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        };
-
-    my $returnType = $self->TryToGetType(\$index, \$lineNumber);
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-    my $name;
-    my $lastNameWord;
-
-    while ($tokens->[$index] =~ /^[a-z\_\@\.\~]/i)
-        {
-        $name .= $tokens->[$index];
-        $lastNameWord = $tokens->[$index];
-        $index++;
-        };
-
-    if (!defined $name)
-        {
-        # Constructors and destructors don't have return types.  It's possible their names were mistaken for the return type.
-        if (defined $returnType)
-            {
-            $name = $returnType;
-            $returnType = undef;
-
-            $name =~ /([a-z0-9_]+)$/i;
-            $lastNameWord = $1;
-            }
-        else
-            {  return undef;  };
-        };
-
-    # If there's no return type, make sure it's a constructor or destructor.
-    if (!defined $returnType)
-        {
-        my @identifiers = NaturalDocs::SymbolString->IdentifiersOf( $self->CurrentScope() );
-
-        if ($lastNameWord ne $identifiers[-1])
-            {  return undef;  };
-        };
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-
-    # Skip the brackets on indexers.
-    if ($tokens->[$index] eq '[' && lc($lastNameWord) eq 'this')
-        {
-        # This should jump the brackets completely.
-        $self->GenericSkip(\$index, \$lineNumber);
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        $name .= '[]';
-        };
-
-
-    # Properties, indexers, events with braces
-
-    if ($tokens->[$index] eq '{')
-        {
-        my $prototype = $self->CreateString($startIndex, $index);
-
-        $index++;
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        my ($aWord, $bWord, $hasA, $hasB);
-
-        if ($isEvent)
-            {
-            $aWord = 'add';
-            $bWord = 'remove';
-            }
-        else
-            {
-            $aWord = 'get';
-            $bWord = 'set';
-            };
-
-        while ($index < scalar @$tokens)
-            {
-            if ($self->TryToSkipAttributes(\$index, \$lineNumber))
-                {  $self->TryToSkipWhitespace(\$index, \$lineNumber);  };
-
-            if (lc($tokens->[$index]) eq $aWord)
-                {  $hasA = 1;  }
-            elsif (lc($tokens->[$index]) eq $bWord)
-                {  $hasB = 1;  }
-            elsif ($tokens->[$index] eq '}')
-                {
-                $index++;
-                last;
-                };
-
-            $self->SkipRestOfStatement(\$index, \$lineNumber);
-            $self->TryToSkipWhitespace(\$index, \$lineNumber);
-            };
-
-        if ($hasA && $hasB)
-            {  $prototype .= ' { ' . $aWord . ', ' . $bWord . ' }';  }
-        elsif ($hasA)
-            {  $prototype .= ' { ' . $aWord . ' }';  }
-        elsif ($hasB)
-            {  $prototype .= ' { ' . $bWord . ' }';  };
-
-        $prototype = $self->NormalizePrototype($prototype);
-
-        my $topicType = ( $isEvent ? ::TOPIC_EVENT() : ::TOPIC_PROPERTY() );
-
-        $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
-                                                                                                  $self->CurrentScope(), undef,
-                                                                                                  $prototype,
-                                                                                                  undef, undef, $startLine));
-        }
-
-
-    # Functions, constructors, destructors, delegates.
-
-    elsif ($tokens->[$index] eq '(')
-        {
-        # This should jump the parenthesis completely.
-        $self->GenericSkip(\$index, \$lineNumber);
-
-        my $topicType = ( $isDelegate ? ::TOPIC_DELEGATE() : ::TOPIC_FUNCTION() );
-        my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
-
-        $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
-                                                                                                  $self->CurrentScope(), undef,
-                                                                                                  $prototype,
-                                                                                                  undef, undef, $startLine));
-
-        $self->SkipRestOfStatement(\$index, \$lineNumber);
-        }
-
-
-    # Events without braces
-
-    elsif ($isEvent && $tokens->[$index] eq ';')
-        {
-        my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
-
-        $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New(::TOPIC_EVENT(), $name,
-                                                                                                  $self->CurrentScope(), undef,
-                                                                                                  $prototype,
-                                                                                                  undef, undef, $startLine));
-        $index++;
-        }
-
-    else
-        {  return undef;  };
-
-
-    # We succeeded if we got this far.
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return 1;
-    };
-
-
-#
-#   Function: TryToGetOverloadedOperator
-#
-#   Determines if the position is on an operator overload declaration, and if so, generates a topic for it, skips it, and returns true.
-#
-sub TryToGetOverloadedOperator #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $index = $$indexRef;
-    my $lineNumber = $$lineNumberRef;
-
-    if ($self->TryToSkipAttributes(\$index, \$lineNumber))
-        {  $self->TryToSkipWhitespace(\$index, \$lineNumber);  };
-
-    my $startIndex = $index;
-    my $startLine = $lineNumber;
-
-    my @modifiers;
-
-    while ($tokens->[$index] =~ /^[a-z]/i &&
-              exists $functionModifiers{lc($tokens->[$index])} )
-        {
-        push @modifiers, lc($tokens->[$index]);
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        };
-
-
-    my $name;
-
-
-    # Casting operators.
-
-    if (lc($tokens->[$index]) eq 'implicit' || lc($tokens->[$index]) eq 'explicit')
-        {
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        if (lc($tokens->[$index]) ne 'operator')
-            {  return undef;  };
-
-        $index++;
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        $name = $self->TryToGetType(\$index, \$lineNumber);
-
-        if (!defined $name)
-            {  return undef;  };
-        }
-
-
-    # Symbol operators.
-
-    else
-        {
-        if (!$self->TryToGetType(\$index, \$lineNumber))
-            {  return undef;  };
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        if (lc($tokens->[$index]) ne 'operator')
-            {  return undef;  };
-
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        if (lc($tokens->[$index]) eq 'true' || lc($tokens->[$index]) eq 'false')
-            {
-            $name = $tokens->[$index];
-            $index++;
-            }
-        else
-            {
-            while ($tokens->[$index] =~ /^[\+\-\!\~\*\/\%\&\|\^\<\>\=]$/)
-                {
-                $name .= $tokens->[$index];
-                $index++;
-                };
-            };
-        };
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-    if ($tokens->[$index] ne '(')
-        {  return undef;  };
-
-    # This should skip the parenthesis completely.
-    $self->GenericSkip(\$index, \$lineNumber);
-
-    my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
-
-    $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New(::TOPIC_FUNCTION(), 'operator ' . $name,
-                                                                                              $self->CurrentScope(), undef,
-                                                                                              $prototype,
-                                                                                              undef, undef, $startLine));
-
-    $self->SkipRestOfStatement(\$index, \$lineNumber);
-
-
-    # We succeeded if we got this far.
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return 1;
-    };
-
-
-#
-#   Function: TryToGetVariable
-#
-#   Determines if the position is on a variable declaration statement, and if so, generates a topic for each variable, skips the
-#   statement, and returns true.
-#
-#   Supported Syntaxes:
-#
-#       - Variables
-#       - Constants
-#
-sub TryToGetVariable #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $index = $$indexRef;
-    my $lineNumber = $$lineNumberRef;
-
-    if ($self->TryToSkipAttributes(\$index, \$lineNumber))
-        {  $self->TryToSkipWhitespace(\$index, \$lineNumber);  };
-
-    my $startIndex = $index;
-    my $startLine = $lineNumber;
-
-    my @modifiers;
-
-    while ($tokens->[$index] =~ /^[a-z]/i &&
-              exists $variableModifiers{lc($tokens->[$index])} )
-        {
-        push @modifiers, lc($tokens->[$index]);
-        $index++;
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        };
-
-    my $type;
-    if (lc($tokens->[$index]) eq 'const')
-        {
-        $type = ::TOPIC_CONSTANT();
-        $index++;
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-        }
-    else
-        {
-        $type = ::TOPIC_VARIABLE();
-        };
-
-    if (!$self->TryToGetType(\$index, \$lineNumber))
-        {  return undef;  };
-
-    my $endTypeIndex = $index;
-
-    $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-    my @names;
-
-    for (;;)
-        {
-        my $name;
-
-        while ($tokens->[$index] =~ /^[a-z\@\_]/i)
-            {
-            $name .= $tokens->[$index];
-            $index++;
-            };
-
-        $self->TryToSkipWhitespace(\$index, \$lineNumber);
-
-        if ($tokens->[$index] eq '=')
-            {
-            do
-                {
-                $self->GenericSkip(\$index, \$lineNumber);
-                }
-            while ($tokens->[$index] ne ',' && $tokens->[$index] ne ';');
-            };
-
-        push @names, $name;
-
-        if ($tokens->[$index] eq ';')
-            {
-            $index++;
-            last;
-            }
-        elsif ($tokens->[$index] eq ',')
-            {
-            $index++;
-            $self->TryToSkipWhitespace(\$index, \$lineNumber);
-            }
-        else
-            {  return undef;  };
-        };
-
-
-    # We succeeded if we got this far.
-
-    my $prototypePrefix = $self->CreateString($startIndex, $endTypeIndex);
-
-    foreach my $name (@names)
-        {
-        my $prototype = $self->NormalizePrototype( $prototypePrefix . ' ' . $name );
-
-        $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($type, $name,
-                                                                                                  $self->CurrentScope(), undef,
-                                                                                                  $prototype,
-                                                                                                  undef, undef, $startLine));
-        };
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return 1;
-    };
-
-
-#
-#   Function: TryToGetType
-#
-#   Determines if the position is on a type identifier, and if so, skips it and returns it as a string.  This function does _not_ allow
-#   modifiers.  You must take care of those beforehand.
-#
-sub TryToGetType #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $name;
-    my $index = $$indexRef;
-    my $lineNumber = $$lineNumberRef;
-
-    while ($tokens->[$index] =~ /^[a-z\@\.\_]/i)
-        {
-        if (exists $impossibleTypeWords{ lc($tokens->[$index]) } && $name !~ /\@$/)
-            {  return undef;  };
-
-        $name .= $tokens->[$index];
-        $index++;
-        };
-
-    if (!defined $name)
-        {  return undef;  };
-
-    while ($tokens->[$index] eq '[')
-        {
-        $name .= '[';
-        $index++;
-
-        while ($tokens->[$index] eq ',')
-            {
-            $name .= ',';
-            $index++;
-            };
-
-        if ($tokens->[$index] eq ']')
-            {
-            $name .= ']';
-            $index++;
-            }
-        else
-            {  return undef;  }
-        };
-
-    $$indexRef = $index;
-    $$lineNumberRef = $lineNumber;
-
-    return $name;
-    };
-
-
-
-###############################################################################
-# Group: Low Level Parsing Functions
-
-
-#
-#   Function: GenericSkip
-#
-#   Advances the position one place through general code.
-#
-#   - If the position is on a string, it will skip it completely.
-#   - If the position is on an opening symbol, it will skip until the past the closing symbol.
-#   - If the position is on whitespace (including comments and preprocessing directives), it will skip it completely.
-#   - Otherwise it skips one token.
-#
-#   Parameters:
-#
-#       indexRef - A reference to the current index.
-#       lineNumberRef - A reference to the current line number.
-#
-sub GenericSkip #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    # We can ignore the scope stack because we're just skipping everything without parsing, and we need recursion anyway.
-    if ($tokens->[$$indexRef] eq '{')
-        {
-        $$indexRef++;
-        $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
-        }
-    elsif ($tokens->[$$indexRef] eq '(')
-        {
-        $$indexRef++;
-        $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ')');
-        }
-    elsif ($tokens->[$$indexRef] eq '[')
-        {
-        $$indexRef++;
-        $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ']');
-        }
-
-    elsif ($self->TryToSkipWhitespace($indexRef, $lineNumberRef) ||
-            $self->TryToSkipString($indexRef, $lineNumberRef))
-        {
-        }
-
-    else
-        {  $$indexRef++;  };
-    };
-
-
-#
-#   Function: GenericSkipUntilAfter
-#
-#   Advances the position via <GenericSkip()> until a specific token is reached and passed.
-#
-sub GenericSkipUntilAfter #(indexRef, lineNumberRef, token)
-    {
-    my ($self, $indexRef, $lineNumberRef, $token) = @_;
-    my $tokens = $self->Tokens();
-
-    while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] ne $token)
-        {  $self->GenericSkip($indexRef, $lineNumberRef);  };
-
-    if ($tokens->[$$indexRef] eq "\n")
-        {  $$lineNumberRef++;  };
-    $$indexRef++;
-    };
-
-
-#
-#   Function: SkipRestOfStatement
-#
-#   Advances the position via <GenericSkip()> until after the end of the current statement, which is defined as a semicolon or
-#   a brace group.  Of course, either of those appearing inside parenthesis, a nested brace group, etc. don't count.
-#
-sub SkipRestOfStatement #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    while ($$indexRef < scalar @$tokens &&
-             $tokens->[$$indexRef] ne ';' &&
-             $tokens->[$$indexRef] ne '{')
-        {
-        $self->GenericSkip($indexRef, $lineNumberRef);
-        };
-
-    if ($tokens->[$$indexRef] eq ';')
-        {  $$indexRef++;  }
-    elsif ($tokens->[$$indexRef] eq '{')
-        {  $self->GenericSkip($indexRef, $lineNumberRef);  };
-    };
-
-
-#
-#   Function: TryToSkipString
-#   If the current position is on a string delimiter, skip past the string and return true.
-#
-#   Parameters:
-#
-#       indexRef - A reference to the index of the position to start at.
-#       lineNumberRef - A reference to the line number of the position.
-#
-#   Returns:
-#
-#       Whether the position was at a string.
-#
-#   Syntax Support:
-#
-#       - Supports quotes, apostrophes, and at-quotes.
-#
-sub TryToSkipString #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    # The three string delimiters.  All three are Perl variables when preceded by a dollar sign.
-    if ($self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '\'') ||
-        $self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '"') )
-        {
-        return 1;
-        }
-    elsif ($tokens->[$$indexRef] eq '@' && $tokens->[$$indexRef+1] eq '"')
-        {
-        $$indexRef += 2;
-
-        # We need to do at-strings manually because backslash characters are accepted as regular characters, and two consecutive
-        # quotes are accepted as well.
-
-        while ($$indexRef < scalar @$tokens && !($tokens->[$$indexRef] eq '"' && $tokens->[$$indexRef+1] ne '"') )
-            {
-            if ($tokens->[$$indexRef] eq '"')
-                {
-                # This is safe because the while condition will only let through quote pairs.
-                $$indexRef += 2;
-                }
-            elsif ($tokens->[$$indexRef] eq "\n")
-                {
-                $$indexRef++;
-                $$lineNumberRef++;
-                }
-            else
-                {
-                $$indexRef++;
-                };
-            };
-
-        # Skip the closing quote.
-        if ($$indexRef < scalar @$tokens)
-            {  $$indexRef++;  };
-
-        return 1;
-        }
-    else
-        {  return undef;  };
-    };
-
-
-#
-#   Function: TryToSkipAttributes
-#   If the current position is on an attribute section, skip it and return true.  Skips multiple attribute sections if they appear
-#   consecutively.
-#
-sub TryToSkipAttributes #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $success;
-
-    while ($tokens->[$$indexRef] eq '[')
-        {
-        $success = 1;
-        $$indexRef++;
-        $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ']');
-        $self->TryToSkipWhitespace($indexRef, $lineNumberRef);
-        };
-
-    return $success;
-    };
-
-
-#
-#   Function: TryToSkipWhitespace
-#   If the current position is on a whitespace token, a line break token, a comment, or a preprocessing directive, it skips them
-#   and returns true.  If there are a number of these in a row, it skips them all.
-#
-sub TryToSkipWhitespace #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    my $result;
-
-    while ($$indexRef < scalar @$tokens)
-        {
-        if ($tokens->[$$indexRef] =~ /^[ \t]/)
-            {
-            $$indexRef++;
-            $result = 1;
-            }
-        elsif ($tokens->[$$indexRef] eq "\n")
-            {
-            $$indexRef++;
-            $$lineNumberRef++;
-            $result = 1;
-            }
-        elsif ($self->TryToSkipComment($indexRef, $lineNumberRef) ||
-                $self->TryToSkipPreprocessingDirective($indexRef, $lineNumberRef))
-            {
-            $result = 1;
-            }
-        else
-            {  last;  };
-        };
-
-    return $result;
-    };
-
-
-#
-#   Function: TryToSkipComment
-#   If the current position is on a comment, skip past it and return true.
-#
-sub TryToSkipComment #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-
-    return ( $self->TryToSkipLineComment($indexRef, $lineNumberRef) ||
-                $self->TryToSkipMultilineComment($indexRef, $lineNumberRef) );
-    };
-
-
-#
-#   Function: TryToSkipLineComment
-#   If the current position is on a line comment symbol, skip past it and return true.
-#
-sub TryToSkipLineComment #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '/')
-        {
-        $self->SkipRestOfLine($indexRef, $lineNumberRef);
-        return 1;
-        }
-    else
-        {  return undef;  };
-    };
-
-
-#
-#   Function: TryToSkipMultilineComment
-#   If the current position is on an opening comment symbol, skip past it and return true.
-#
-sub TryToSkipMultilineComment #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '*')
-        {
-        $self->SkipUntilAfter($indexRef, $lineNumberRef, '*', '/');
-        return 1;
-        }
-    else
-        {  return undef;  };
-    };
-
-
-#
-#   Function: TryToSkipPreprocessingDirective
-#   If the current position is on a preprocessing directive, skip past it and return true.
-#
-sub TryToSkipPreprocessingDirective #(indexRef, lineNumberRef)
-    {
-    my ($self, $indexRef, $lineNumberRef) = @_;
-    my $tokens = $self->Tokens();
-
-    if ($tokens->[$$indexRef] eq '#' && $self->IsFirstLineToken($$indexRef))
-        {
-        $self->SkipRestOfLine($indexRef, $lineNumberRef);
-        return 1;
-        }
-    else
-        {  return undef;  };
-    };
-
-
-1;