bixbite 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.markdown +49 -0
- data/VERSION +1 -0
- data/bin/bixbite +73 -0
- data/lib/bixbite.rb +13 -0
- data/lib/bixbite/command.rb +14 -0
- data/lib/bixbite/create.rb +76 -0
- data/template/Rakefile +25 -0
- data/template/assets/bixbite/Rakefile.rb +297 -0
- data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
- data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
- data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
- data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
- data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
- data/template/assets/utilities/pngout +0 -0
- data/template/deploy/public_html/.htaccess +0 -0
- data/template/documentation/js/.htaccess +0 -0
- data/template/src/html/.htaccess +76 -0
- data/template/src/html/css/cmn/global.css +96 -0
- data/template/src/html/css/cmn/ie.css +15 -0
- data/template/src/html/css/cmn/ie6.css +15 -0
- data/template/src/html/images/cmn/.htaccess +0 -0
- data/template/src/html/images/tmp/.htaccess +0 -0
- data/template/src/html/includes/debug.inc +5 -0
- data/template/src/html/includes/footer.inc +52 -0
- data/template/src/html/includes/header.inc +61 -0
- data/template/src/html/includes/html.inc +3 -0
- data/template/src/html/includes/namespace.inc +19 -0
- data/template/src/html/includes/page.inc +151 -0
- data/template/src/html/index.html +35 -0
- data/template/src/html/js/cmn/bootstrap.js +74 -0
- data/template/src/html/js/cmn/global.js +142 -0
- data/template/src/html/js/cmn/lib/LAB.js +348 -0
- data/template/src/html/min/.htaccess +4 -0
- data/template/src/html/min/MinifyCLI.php +19 -0
- data/template/src/html/min/README.txt +132 -0
- data/template/src/html/min/builder/_index.js +242 -0
- data/template/src/html/min/builder/bm.js +36 -0
- data/template/src/html/min/builder/index.php +182 -0
- data/template/src/html/min/builder/ocCheck.php +36 -0
- data/template/src/html/min/builder/rewriteTest.js +1 -0
- data/template/src/html/min/config.php +187 -0
- data/template/src/html/min/groupsConfig.php +34 -0
- data/template/src/html/min/index.php +66 -0
- data/template/src/html/min/lib/FirePHP.php +1370 -0
- data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
- data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
- data/template/src/html/min/lib/JSMin.php +314 -0
- data/template/src/html/min/lib/JSMinPlus.php +1872 -0
- data/template/src/html/min/lib/Minify.php +532 -0
- data/template/src/html/min/lib/Minify/Build.php +103 -0
- data/template/src/html/min/lib/Minify/CSS.php +83 -0
- data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
- data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
- data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
- data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
- data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
- data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
- data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
- data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
- data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
- data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
- data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
- data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
- data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
- data/template/src/html/min/lib/Minify/HTML.php +245 -0
- data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
- data/template/src/html/min/lib/Minify/Lines.php +131 -0
- data/template/src/html/min/lib/Minify/Logger.php +45 -0
- data/template/src/html/min/lib/Minify/Packer.php +37 -0
- data/template/src/html/min/lib/Minify/Source.php +187 -0
- data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
- data/template/src/html/min/lib/Solar/Dir.php +199 -0
- data/template/src/html/min/lib/closure-compiler.jar +0 -0
- data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
- data/template/src/html/min/utils.php +90 -0
- data/template/src/templates/css/template.css +7 -0
- data/template/src/templates/js/template.js +72 -0
- data/template/src/templates/template.html +18 -0
- data/template/src/yaml/config.yml +46 -0
- data/template/src/yaml/deploy.yml +35 -0
- data/test/bixbite_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +278 -0
@@ -0,0 +1,1473 @@
|
|
1
|
+
###############################################################################
|
2
|
+
#
|
3
|
+
# Class: NaturalDocs::Languages::ActionScript
|
4
|
+
#
|
5
|
+
###############################################################################
|
6
|
+
#
|
7
|
+
# A subclass to handle the language variations of Flash ActionScript.
|
8
|
+
#
|
9
|
+
###############################################################################
|
10
|
+
|
11
|
+
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
|
12
|
+
# Natural Docs is licensed under the GPL
|
13
|
+
|
14
|
+
use strict;
|
15
|
+
use integer;
|
16
|
+
|
17
|
+
package NaturalDocs::Languages::ActionScript;
|
18
|
+
|
19
|
+
use base 'NaturalDocs::Languages::Advanced';
|
20
|
+
|
21
|
+
|
22
|
+
################################################################################
|
23
|
+
# Group: Constants and Types
|
24
|
+
|
25
|
+
|
26
|
+
#
|
27
|
+
# Constants: XML Tag Type
|
28
|
+
#
|
29
|
+
# XML_OPENING_TAG - The tag is an opening one, such as <tag>.
|
30
|
+
# XML_CLOSING_TAG - The tag is a closing one, such as </tag>.
|
31
|
+
# XML_SELF_CONTAINED_TAG - The tag is self contained, such as <tag />.
|
32
|
+
#
|
33
|
+
use constant XML_OPENING_TAG => 1;
|
34
|
+
use constant XML_CLOSING_TAG => 2;
|
35
|
+
use constant XML_SELF_CONTAINED_TAG => 3;
|
36
|
+
|
37
|
+
|
38
|
+
################################################################################
|
39
|
+
# Group: Package Variables
|
40
|
+
|
41
|
+
#
|
42
|
+
# hash: classModifiers
|
43
|
+
# An existence hash of all the acceptable class modifiers. The keys are in all lowercase.
|
44
|
+
#
|
45
|
+
my %classModifiers = ( 'dynamic' => 1,
|
46
|
+
'intrinsic' => 1,
|
47
|
+
'final' => 1,
|
48
|
+
'internal' => 1,
|
49
|
+
'public' => 1 );
|
50
|
+
|
51
|
+
#
|
52
|
+
# hash: memberModifiers
|
53
|
+
# An existence hash of all the acceptable class member modifiers. The keys are in all lowercase.
|
54
|
+
#
|
55
|
+
my %memberModifiers = ( 'public' => 1,
|
56
|
+
'private' => 1,
|
57
|
+
'protected' => 1,
|
58
|
+
'static' => 1,
|
59
|
+
'internal' => 1,
|
60
|
+
'override' => 1 );
|
61
|
+
|
62
|
+
|
63
|
+
#
|
64
|
+
# hash: declarationEnders
|
65
|
+
# An existence hash of all the tokens that can end a declaration. This is important because statements don't require a semicolon
|
66
|
+
# to end. The keys are in all lowercase.
|
67
|
+
#
|
68
|
+
my %declarationEnders = ( ';' => 1,
|
69
|
+
'}' => 1,
|
70
|
+
'{' => 1,
|
71
|
+
'public' => 1,
|
72
|
+
'private' => 1,
|
73
|
+
'protected' => 1,
|
74
|
+
'static' => 1,
|
75
|
+
'internal' => 1,
|
76
|
+
'dynamic' => 1,
|
77
|
+
'intrinsic' => 1,
|
78
|
+
'final' => 1,
|
79
|
+
'override' => 1,
|
80
|
+
'class' => 1,
|
81
|
+
'interface' => 1,
|
82
|
+
'var' => 1,
|
83
|
+
'function' => 1,
|
84
|
+
'const' => 1,
|
85
|
+
'namespace' => 1,
|
86
|
+
'import' => 1 );
|
87
|
+
|
88
|
+
|
89
|
+
#
|
90
|
+
# var: isEscaped
|
91
|
+
# Whether the current file being parsed uses escapement.
|
92
|
+
#
|
93
|
+
my $isEscaped;
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
################################################################################
|
98
|
+
# Group: Interface Functions
|
99
|
+
|
100
|
+
|
101
|
+
#
|
102
|
+
# Function: PackageSeparator
|
103
|
+
# Returns the package separator symbol.
|
104
|
+
#
|
105
|
+
sub PackageSeparator
|
106
|
+
{ return '.'; };
|
107
|
+
|
108
|
+
|
109
|
+
#
|
110
|
+
# Function: EnumValues
|
111
|
+
# Returns the <EnumValuesType> that describes how the language handles enums.
|
112
|
+
#
|
113
|
+
sub EnumValues
|
114
|
+
{ return ::ENUM_GLOBAL(); };
|
115
|
+
|
116
|
+
|
117
|
+
#
|
118
|
+
# Function: ParseParameterLine
|
119
|
+
# Parses a prototype parameter line and returns it as a <NaturalDocs::Languages::Prototype::Parameter> object.
|
120
|
+
#
|
121
|
+
sub ParseParameterLine #(line)
|
122
|
+
{
|
123
|
+
my ($self, $line) = @_;
|
124
|
+
|
125
|
+
if ($line =~ /^ ?\.\.\.\ (.+)$/)
|
126
|
+
{
|
127
|
+
# This puts them in the wrong fields as $1 should be the name and ... should be the type. However, this is necessary
|
128
|
+
# because the order in the source is reversed from other parameter declarations and it's more important for the output
|
129
|
+
# to match the source.
|
130
|
+
return NaturalDocs::Languages::Prototype::Parameter->New($1, undef, '...', undef, undef, undef);
|
131
|
+
}
|
132
|
+
else
|
133
|
+
{ return $self->ParsePascalParameterLine($line); };
|
134
|
+
};
|
135
|
+
|
136
|
+
|
137
|
+
#
|
138
|
+
# Function: TypeBeforeParameter
|
139
|
+
# Returns whether the type appears before the parameter in prototypes.
|
140
|
+
#
|
141
|
+
sub TypeBeforeParameter
|
142
|
+
{ return 0; };
|
143
|
+
|
144
|
+
|
145
|
+
#
|
146
|
+
# Function: PreprocessFile
|
147
|
+
#
|
148
|
+
# If the file is escaped, strips out all unescaped code. Will translate any unescaped comments into comments surrounded by
|
149
|
+
# "\x1C\x1D\x1E\x1F" and "\x1F\x1E\x1D" characters, so chosen because they are the same character lengths as <!-- and -->
|
150
|
+
# and will not appear in normal code.
|
151
|
+
#
|
152
|
+
sub PreprocessFile
|
153
|
+
{
|
154
|
+
my ($self, $lines) = @_;
|
155
|
+
|
156
|
+
if (!$isEscaped)
|
157
|
+
{ return; };
|
158
|
+
|
159
|
+
use constant MODE_UNESCAPED_REGULAR => 1;
|
160
|
+
use constant MODE_UNESCAPED_PI => 2;
|
161
|
+
use constant MODE_UNESCAPED_CDATA => 3;
|
162
|
+
use constant MODE_UNESCAPED_COMMENT => 4;
|
163
|
+
use constant MODE_ESCAPED_UNKNOWN_CDATA => 5;
|
164
|
+
use constant MODE_ESCAPED_CDATA => 6;
|
165
|
+
use constant MODE_ESCAPED_NO_CDATA => 7;
|
166
|
+
|
167
|
+
my $mode = MODE_UNESCAPED_REGULAR;
|
168
|
+
|
169
|
+
for (my $i = 0; $i < scalar @$lines; $i++)
|
170
|
+
{
|
171
|
+
my @tokens = split(/(<[ \t]*\/?[ \t]*mx:Script[^>]*>|<\?|\?>|<\!--|-->|<\!\[CDATA\[|\]\]\>)/, $lines->[$i]);
|
172
|
+
my $newLine;
|
173
|
+
|
174
|
+
foreach my $token (@tokens)
|
175
|
+
{
|
176
|
+
if ($mode == MODE_UNESCAPED_REGULAR)
|
177
|
+
{
|
178
|
+
if ($token eq '<?')
|
179
|
+
{ $mode = MODE_UNESCAPED_PI; }
|
180
|
+
elsif ($token eq '<![CDATA[')
|
181
|
+
{ $mode = MODE_UNESCAPED_CDATA; }
|
182
|
+
elsif ($token eq '<!--')
|
183
|
+
{
|
184
|
+
$mode = MODE_UNESCAPED_COMMENT;
|
185
|
+
$newLine .= "\x1C\x1D\x1E\x1F";
|
186
|
+
}
|
187
|
+
elsif ($token =~ /^<[ \t]*mx:Script/)
|
188
|
+
{ $mode = MODE_ESCAPED_UNKNOWN_CDATA; };
|
189
|
+
}
|
190
|
+
|
191
|
+
elsif ($mode == MODE_UNESCAPED_PI)
|
192
|
+
{
|
193
|
+
if ($token eq '?>')
|
194
|
+
{ $mode = MODE_UNESCAPED_REGULAR; };
|
195
|
+
}
|
196
|
+
|
197
|
+
elsif ($mode == MODE_UNESCAPED_CDATA)
|
198
|
+
{
|
199
|
+
if ($token eq ']]>')
|
200
|
+
{ $mode = MODE_UNESCAPED_REGULAR; };
|
201
|
+
}
|
202
|
+
|
203
|
+
elsif ($mode == MODE_UNESCAPED_COMMENT)
|
204
|
+
{
|
205
|
+
if ($token eq '-->')
|
206
|
+
{
|
207
|
+
$mode = MODE_UNESCAPED_REGULAR;
|
208
|
+
$newLine .= "\x1F\x1E\x1D";
|
209
|
+
}
|
210
|
+
else
|
211
|
+
{ $newLine .= $token; };
|
212
|
+
}
|
213
|
+
|
214
|
+
elsif ($mode == MODE_ESCAPED_UNKNOWN_CDATA)
|
215
|
+
{
|
216
|
+
if ($token eq '<![CDATA[')
|
217
|
+
{ $mode = MODE_ESCAPED_CDATA; }
|
218
|
+
elsif ($token =~ /^<[ \t]*\/[ \t]*mx:Script/)
|
219
|
+
{
|
220
|
+
$mode = MODE_UNESCAPED_REGULAR;
|
221
|
+
$newLine .= '; ';
|
222
|
+
}
|
223
|
+
elsif ($token !~ /^[ \t]*$/)
|
224
|
+
{
|
225
|
+
$mode = MODE_ESCAPED_NO_CDATA;
|
226
|
+
$newLine .= $token;
|
227
|
+
};
|
228
|
+
}
|
229
|
+
|
230
|
+
elsif ($mode == MODE_ESCAPED_CDATA)
|
231
|
+
{
|
232
|
+
if ($token eq ']]>')
|
233
|
+
{
|
234
|
+
$mode = MODE_UNESCAPED_REGULAR;
|
235
|
+
$newLine .= '; ';
|
236
|
+
}
|
237
|
+
else
|
238
|
+
{ $newLine .= $token; };
|
239
|
+
}
|
240
|
+
|
241
|
+
else #($mode == MODE_ESCAPED_NO_CDATA)
|
242
|
+
{
|
243
|
+
if ($token =~ /^<[ \t]*\/[ \t]*mx:Script/)
|
244
|
+
{
|
245
|
+
$mode = MODE_UNESCAPED_REGULAR;
|
246
|
+
$newLine .= '; ';
|
247
|
+
}
|
248
|
+
else
|
249
|
+
{ $newLine .= $token; };
|
250
|
+
};
|
251
|
+
|
252
|
+
};
|
253
|
+
|
254
|
+
$lines->[$i] = $newLine;
|
255
|
+
};
|
256
|
+
};
|
257
|
+
|
258
|
+
|
259
|
+
#
|
260
|
+
# Function: ParseFile
|
261
|
+
#
|
262
|
+
# Parses the passed source file, sending comments acceptable for documentation to <NaturalDocs::Parser->OnComment()>.
|
263
|
+
#
|
264
|
+
# Parameters:
|
265
|
+
#
|
266
|
+
# sourceFile - The <FileName> to parse.
|
267
|
+
# topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
|
268
|
+
#
|
269
|
+
# Returns:
|
270
|
+
#
|
271
|
+
# The array ( autoTopics, scopeRecord ).
|
272
|
+
#
|
273
|
+
# autoTopics - An arrayref of automatically generated topics from the file, or undef if none.
|
274
|
+
# scopeRecord - An arrayref of <NaturalDocs::Languages::Advanced::ScopeChanges>, or undef if none.
|
275
|
+
#
|
276
|
+
sub ParseFile #(sourceFile, topicsList)
|
277
|
+
{
|
278
|
+
my ($self, $sourceFile, $topicsList) = @_;
|
279
|
+
|
280
|
+
# The \x1# comment symbols are inserted by PreprocessFile() to stand in for XML comments in escaped files.
|
281
|
+
my @parseParameters = ( [ '//' ], [ '/*', '*/', "\x1C\x1D\x1E\x1F", "\x1F\x1E\x1D" ], [ '///' ], [ '/**', '*/' ] );
|
282
|
+
|
283
|
+
my $extension = lc(NaturalDocs::File->ExtensionOf($sourceFile));
|
284
|
+
$isEscaped = ($extension eq 'mxml');
|
285
|
+
|
286
|
+
$self->ParseForCommentsAndTokens($sourceFile, @parseParameters);
|
287
|
+
|
288
|
+
my $tokens = $self->Tokens();
|
289
|
+
my $index = 0;
|
290
|
+
my $lineNumber = 1;
|
291
|
+
|
292
|
+
while ($index < scalar @$tokens)
|
293
|
+
{
|
294
|
+
if ($self->TryToSkipWhitespace(\$index, \$lineNumber) ||
|
295
|
+
$self->TryToGetImport(\$index, \$lineNumber) ||
|
296
|
+
$self->TryToGetClass(\$index, \$lineNumber) ||
|
297
|
+
$self->TryToGetFunction(\$index, \$lineNumber) ||
|
298
|
+
$self->TryToGetVariable(\$index, \$lineNumber) )
|
299
|
+
{
|
300
|
+
# The functions above will handle everything.
|
301
|
+
}
|
302
|
+
|
303
|
+
elsif ($tokens->[$index] eq '{')
|
304
|
+
{
|
305
|
+
$self->StartScope('}', $lineNumber, undef, undef, undef);
|
306
|
+
$index++;
|
307
|
+
}
|
308
|
+
|
309
|
+
elsif ($tokens->[$index] eq '}')
|
310
|
+
{
|
311
|
+
if ($self->ClosingScopeSymbol() eq '}')
|
312
|
+
{ $self->EndScope($lineNumber); };
|
313
|
+
|
314
|
+
$index++;
|
315
|
+
}
|
316
|
+
|
317
|
+
else
|
318
|
+
{
|
319
|
+
$self->SkipToNextStatement(\$index, \$lineNumber);
|
320
|
+
};
|
321
|
+
};
|
322
|
+
|
323
|
+
|
324
|
+
# Don't need to keep these around.
|
325
|
+
$self->ClearTokens();
|
326
|
+
|
327
|
+
|
328
|
+
my $autoTopics = $self->AutoTopics();
|
329
|
+
|
330
|
+
my $scopeRecord = $self->ScopeRecord();
|
331
|
+
if (defined $scopeRecord && !scalar @$scopeRecord)
|
332
|
+
{ $scopeRecord = undef; };
|
333
|
+
|
334
|
+
return ( $autoTopics, $scopeRecord );
|
335
|
+
};
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
################################################################################
|
340
|
+
# Group: Statement Parsing Functions
|
341
|
+
# All functions here assume that the current position is at the beginning of a statement.
|
342
|
+
#
|
343
|
+
# 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
|
344
|
+
# 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.
|
345
|
+
|
346
|
+
|
347
|
+
#
|
348
|
+
# Function: TryToGetIdentifier
|
349
|
+
#
|
350
|
+
# Determines whether the position is at an identifier, and if so, skips it and returns the complete identifier as a string. Returns
|
351
|
+
# undef otherwise.
|
352
|
+
#
|
353
|
+
# Parameters:
|
354
|
+
#
|
355
|
+
# indexRef - A reference to the current token index.
|
356
|
+
# lineNumberRef - A reference to the current line number.
|
357
|
+
# allowStar - If set, allows the last identifier to be a star.
|
358
|
+
#
|
359
|
+
sub TryToGetIdentifier #(indexRef, lineNumberRef, allowStar)
|
360
|
+
{
|
361
|
+
my ($self, $indexRef, $lineNumberRef, $allowStar) = @_;
|
362
|
+
my $tokens = $self->Tokens();
|
363
|
+
|
364
|
+
my $index = $$indexRef;
|
365
|
+
|
366
|
+
use constant MODE_IDENTIFIER_START => 1;
|
367
|
+
use constant MODE_IN_IDENTIFIER => 2;
|
368
|
+
use constant MODE_AFTER_STAR => 3;
|
369
|
+
|
370
|
+
my $identifier;
|
371
|
+
my $mode = MODE_IDENTIFIER_START;
|
372
|
+
|
373
|
+
while ($index < scalar @$tokens)
|
374
|
+
{
|
375
|
+
if ($mode == MODE_IDENTIFIER_START)
|
376
|
+
{
|
377
|
+
if ($tokens->[$index] =~ /^[a-z\$\_]/i)
|
378
|
+
{
|
379
|
+
$identifier .= $tokens->[$index];
|
380
|
+
$index++;
|
381
|
+
|
382
|
+
$mode = MODE_IN_IDENTIFIER;
|
383
|
+
}
|
384
|
+
elsif ($allowStar && $tokens->[$index] eq '*')
|
385
|
+
{
|
386
|
+
$identifier .= '*';
|
387
|
+
$index++;
|
388
|
+
|
389
|
+
$mode = MODE_AFTER_STAR;
|
390
|
+
}
|
391
|
+
else
|
392
|
+
{ return undef; };
|
393
|
+
}
|
394
|
+
|
395
|
+
elsif ($mode == MODE_IN_IDENTIFIER)
|
396
|
+
{
|
397
|
+
if ($tokens->[$index] eq '.')
|
398
|
+
{
|
399
|
+
$identifier .= '.';
|
400
|
+
$index++;
|
401
|
+
|
402
|
+
$mode = MODE_IDENTIFIER_START;
|
403
|
+
}
|
404
|
+
elsif ($tokens->[$index] =~ /^[a-z0-9\$\_]/i)
|
405
|
+
{
|
406
|
+
$identifier .= $tokens->[$index];
|
407
|
+
$index++;
|
408
|
+
}
|
409
|
+
else
|
410
|
+
{ last; };
|
411
|
+
}
|
412
|
+
|
413
|
+
else #($mode == MODE_AFTER_STAR)
|
414
|
+
{
|
415
|
+
if ($tokens->[$index] =~ /^[a-z0-9\$\_\.]/i)
|
416
|
+
{ return undef; }
|
417
|
+
else
|
418
|
+
{ last; };
|
419
|
+
};
|
420
|
+
};
|
421
|
+
|
422
|
+
# We need to check again because we may have run out of tokens after a dot.
|
423
|
+
if ($mode != MODE_IDENTIFIER_START)
|
424
|
+
{
|
425
|
+
$$indexRef = $index;
|
426
|
+
return $identifier;
|
427
|
+
}
|
428
|
+
else
|
429
|
+
{ return undef; };
|
430
|
+
};
|
431
|
+
|
432
|
+
|
433
|
+
#
|
434
|
+
# Function: TryToGetImport
|
435
|
+
#
|
436
|
+
# Determines whether the position is at a import statement, and if so, adds it as a Using statement to the current scope, skips
|
437
|
+
# it, and returns true.
|
438
|
+
#
|
439
|
+
sub TryToGetImport #(indexRef, lineNumberRef)
|
440
|
+
{
|
441
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
442
|
+
my $tokens = $self->Tokens();
|
443
|
+
|
444
|
+
my $index = $$indexRef;
|
445
|
+
my $lineNumber = $$lineNumberRef;
|
446
|
+
|
447
|
+
if ($tokens->[$index] ne 'import')
|
448
|
+
{ return undef; };
|
449
|
+
|
450
|
+
$index++;
|
451
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
452
|
+
|
453
|
+
my $identifier = $self->TryToGetIdentifier(\$index, \$lineNumber, 1);
|
454
|
+
if (!$identifier)
|
455
|
+
{ return undef; };
|
456
|
+
|
457
|
+
|
458
|
+
# Currently we implement importing by stripping the last package level and treating it as a using. So "import p1.p2.p3" makes
|
459
|
+
# p1.p2 the using path, which is over-tolerant but that's okay. "import p1.p2.*" is treated the same way, but in this case it's
|
460
|
+
# not over-tolerant. If there's no dot, there's no point to including it.
|
461
|
+
|
462
|
+
if (index($identifier, '.') != -1)
|
463
|
+
{
|
464
|
+
$identifier =~ s/\.[^\.]+$//;
|
465
|
+
$self->AddUsing( NaturalDocs::SymbolString->FromText($identifier) );
|
466
|
+
};
|
467
|
+
|
468
|
+
$$indexRef = $index;
|
469
|
+
$$lineNumberRef = $lineNumber;
|
470
|
+
|
471
|
+
return 1;
|
472
|
+
};
|
473
|
+
|
474
|
+
|
475
|
+
#
|
476
|
+
# Function: TryToGetClass
|
477
|
+
#
|
478
|
+
# Determines whether the position is at a class declaration statement, and if so, generates a topic for it, skips it, and
|
479
|
+
# returns true.
|
480
|
+
#
|
481
|
+
# Supported Syntaxes:
|
482
|
+
#
|
483
|
+
# - Classes
|
484
|
+
# - Interfaces
|
485
|
+
# - Classes and interfaces with _global
|
486
|
+
#
|
487
|
+
sub TryToGetClass #(indexRef, lineNumberRef)
|
488
|
+
{
|
489
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
490
|
+
my $tokens = $self->Tokens();
|
491
|
+
|
492
|
+
my $index = $$indexRef;
|
493
|
+
my $lineNumber = $$lineNumberRef;
|
494
|
+
|
495
|
+
my @modifiers;
|
496
|
+
|
497
|
+
while ($tokens->[$index] =~ /^[a-z]/i &&
|
498
|
+
exists $classModifiers{lc($tokens->[$index])} )
|
499
|
+
{
|
500
|
+
push @modifiers, lc($tokens->[$index]);
|
501
|
+
$index++;
|
502
|
+
|
503
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
504
|
+
};
|
505
|
+
|
506
|
+
my $type;
|
507
|
+
|
508
|
+
if ($tokens->[$index] eq 'class' || $tokens->[$index] eq 'interface')
|
509
|
+
{
|
510
|
+
$type = $tokens->[$index];
|
511
|
+
|
512
|
+
$index++;
|
513
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
514
|
+
}
|
515
|
+
else
|
516
|
+
{ return undef; };
|
517
|
+
|
518
|
+
my $className = $self->TryToGetIdentifier(\$index, \$lineNumber);
|
519
|
+
|
520
|
+
if (!$className)
|
521
|
+
{ return undef; };
|
522
|
+
|
523
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
524
|
+
|
525
|
+
my @parents;
|
526
|
+
|
527
|
+
if ($tokens->[$index] eq 'extends')
|
528
|
+
{
|
529
|
+
$index++;
|
530
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
531
|
+
|
532
|
+
my $parent = $self->TryToGetIdentifier(\$index, \$lineNumber);
|
533
|
+
if (!$parent)
|
534
|
+
{ return undef; };
|
535
|
+
|
536
|
+
push @parents, $parent;
|
537
|
+
|
538
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
539
|
+
};
|
540
|
+
|
541
|
+
if ($type eq 'class' && $tokens->[$index] eq 'implements')
|
542
|
+
{
|
543
|
+
$index++;
|
544
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
545
|
+
|
546
|
+
for (;;)
|
547
|
+
{
|
548
|
+
my $parent = $self->TryToGetIdentifier(\$index, \$lineNumber);
|
549
|
+
if (!$parent)
|
550
|
+
{ return undef; };
|
551
|
+
|
552
|
+
push @parents, $parent;
|
553
|
+
|
554
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
555
|
+
|
556
|
+
if ($tokens->[$index] ne ',')
|
557
|
+
{ last; }
|
558
|
+
else
|
559
|
+
{
|
560
|
+
$index++;
|
561
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
562
|
+
};
|
563
|
+
};
|
564
|
+
};
|
565
|
+
|
566
|
+
if ($tokens->[$index] ne '{')
|
567
|
+
{ return undef; };
|
568
|
+
|
569
|
+
$index++;
|
570
|
+
|
571
|
+
|
572
|
+
# If we made it this far, we have a valid class declaration.
|
573
|
+
|
574
|
+
my $topicType;
|
575
|
+
|
576
|
+
if ($type eq 'interface')
|
577
|
+
{ $topicType = ::TOPIC_INTERFACE(); }
|
578
|
+
else
|
579
|
+
{ $topicType = ::TOPIC_CLASS(); };
|
580
|
+
|
581
|
+
$className =~ s/^_global.//;
|
582
|
+
|
583
|
+
my $autoTopic = NaturalDocs::Parser::ParsedTopic->New($topicType, $className,
|
584
|
+
undef, $self->CurrentUsing(),
|
585
|
+
undef,
|
586
|
+
undef, undef, $$lineNumberRef);
|
587
|
+
|
588
|
+
$self->AddAutoTopic($autoTopic);
|
589
|
+
NaturalDocs::Parser->OnClass($autoTopic->Package());
|
590
|
+
|
591
|
+
foreach my $parent (@parents)
|
592
|
+
{
|
593
|
+
NaturalDocs::Parser->OnClassParent($autoTopic->Package(), NaturalDocs::SymbolString->FromText($parent),
|
594
|
+
undef, $self->CurrentUsing(), ::RESOLVE_ABSOLUTE());
|
595
|
+
};
|
596
|
+
|
597
|
+
$self->StartScope('}', $lineNumber, $autoTopic->Package());
|
598
|
+
|
599
|
+
$$indexRef = $index;
|
600
|
+
$$lineNumberRef = $lineNumber;
|
601
|
+
|
602
|
+
return 1;
|
603
|
+
};
|
604
|
+
|
605
|
+
|
606
|
+
#
|
607
|
+
# Function: TryToGetFunction
|
608
|
+
#
|
609
|
+
# Determines if the position is on a function declaration, and if so, generates a topic for it, skips it, and returns true.
|
610
|
+
#
|
611
|
+
# Supported Syntaxes:
|
612
|
+
#
|
613
|
+
# - Functions
|
614
|
+
# - Constructors
|
615
|
+
# - Properties
|
616
|
+
# - Functions with _global
|
617
|
+
# - Functions with namespaces
|
618
|
+
#
|
619
|
+
sub TryToGetFunction #(indexRef, lineNumberRef)
|
620
|
+
{
|
621
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
622
|
+
my $tokens = $self->Tokens();
|
623
|
+
|
624
|
+
my $index = $$indexRef;
|
625
|
+
my $lineNumber = $$lineNumberRef;
|
626
|
+
|
627
|
+
my $startIndex = $index;
|
628
|
+
my $startLine = $lineNumber;
|
629
|
+
|
630
|
+
my @modifiers;
|
631
|
+
my $namespace;
|
632
|
+
|
633
|
+
while ($tokens->[$index] =~ /^[a-z]/i)
|
634
|
+
{
|
635
|
+
if ($tokens->[$index] eq 'function')
|
636
|
+
{ last; }
|
637
|
+
|
638
|
+
elsif (exists $memberModifiers{lc($tokens->[$index])})
|
639
|
+
{
|
640
|
+
push @modifiers, lc($tokens->[$index]);
|
641
|
+
$index++;
|
642
|
+
|
643
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
644
|
+
}
|
645
|
+
|
646
|
+
elsif (!$namespace)
|
647
|
+
{
|
648
|
+
do
|
649
|
+
{
|
650
|
+
$namespace .= $tokens->[$index];
|
651
|
+
$index++;
|
652
|
+
}
|
653
|
+
while ($tokens->[$index] =~ /^[a-z0-9_]/i);
|
654
|
+
|
655
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
656
|
+
}
|
657
|
+
|
658
|
+
else
|
659
|
+
{ last; };
|
660
|
+
};
|
661
|
+
|
662
|
+
if ($tokens->[$index] ne 'function')
|
663
|
+
{ return undef; };
|
664
|
+
$index++;
|
665
|
+
|
666
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
667
|
+
|
668
|
+
my $type;
|
669
|
+
|
670
|
+
if ($tokens->[$index] eq 'get' || $tokens->[$index] eq 'set')
|
671
|
+
{
|
672
|
+
# This can either be a property ("function get Something()") or a function name ("function get()").
|
673
|
+
|
674
|
+
my $nextIndex = $index;
|
675
|
+
my $nextLineNumber = $lineNumber;
|
676
|
+
|
677
|
+
$nextIndex++;
|
678
|
+
$self->TryToSkipWhitespace(\$nextIndex, \$nextLineNumber);
|
679
|
+
|
680
|
+
if ($tokens->[$nextIndex] eq '(')
|
681
|
+
{
|
682
|
+
$type = ::TOPIC_FUNCTION();
|
683
|
+
# Ignore the movement and let the code ahead pick it up as the name.
|
684
|
+
}
|
685
|
+
else
|
686
|
+
{
|
687
|
+
$type = ::TOPIC_PROPERTY();
|
688
|
+
$index = $nextIndex;
|
689
|
+
$lineNumber = $nextLineNumber;
|
690
|
+
};
|
691
|
+
}
|
692
|
+
else
|
693
|
+
{ $type = ::TOPIC_FUNCTION(); };
|
694
|
+
|
695
|
+
my $name = $self->TryToGetIdentifier(\$index, \$lineNumber);
|
696
|
+
if (!$name)
|
697
|
+
{ return undef; };
|
698
|
+
|
699
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
700
|
+
|
701
|
+
if ($tokens->[$index] ne '(')
|
702
|
+
{ return undef; };
|
703
|
+
|
704
|
+
$index++;
|
705
|
+
$self->GenericSkipUntilAfter(\$index, \$lineNumber, ')');
|
706
|
+
|
707
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
708
|
+
|
709
|
+
if ($tokens->[$index] eq ':')
|
710
|
+
{
|
711
|
+
$index++;
|
712
|
+
|
713
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
714
|
+
|
715
|
+
$self->TryToGetIdentifier(\$index, \$lineNumber, 1);
|
716
|
+
|
717
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
718
|
+
};
|
719
|
+
|
720
|
+
|
721
|
+
my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
|
722
|
+
|
723
|
+
if ($tokens->[$index] eq '{')
|
724
|
+
{ $self->GenericSkip(\$index, \$lineNumber); }
|
725
|
+
elsif (!exists $declarationEnders{$tokens->[$index]})
|
726
|
+
{ return undef; };
|
727
|
+
|
728
|
+
|
729
|
+
my $scope = $self->CurrentScope();
|
730
|
+
|
731
|
+
if ($name =~ s/^_global.//)
|
732
|
+
{ $scope = undef; };
|
733
|
+
if ($namespace)
|
734
|
+
{ $scope = NaturalDocs::SymbolString->Join($scope, $namespace); };
|
735
|
+
|
736
|
+
$self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($type, $name,
|
737
|
+
$scope, $self->CurrentUsing(),
|
738
|
+
$prototype,
|
739
|
+
undef, undef, $startLine));
|
740
|
+
|
741
|
+
|
742
|
+
# We succeeded if we got this far.
|
743
|
+
|
744
|
+
$$indexRef = $index;
|
745
|
+
$$lineNumberRef = $lineNumber;
|
746
|
+
|
747
|
+
return 1;
|
748
|
+
};
|
749
|
+
|
750
|
+
|
751
|
+
#
|
752
|
+
# Function: TryToGetVariable
|
753
|
+
#
|
754
|
+
# Determines if the position is on a variable declaration statement, and if so, generates a topic for each variable, skips the
|
755
|
+
# statement, and returns true.
|
756
|
+
#
|
757
|
+
# Supported Syntaxes:
|
758
|
+
#
|
759
|
+
# - Variables
|
760
|
+
# - Variables with _global
|
761
|
+
# - Variables with type * (untyped)
|
762
|
+
# - Constants
|
763
|
+
# - Variables and constants with namespaces
|
764
|
+
#
|
765
|
+
sub TryToGetVariable #(indexRef, lineNumberRef)
|
766
|
+
{
|
767
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
768
|
+
my $tokens = $self->Tokens();
|
769
|
+
|
770
|
+
my $index = $$indexRef;
|
771
|
+
my $lineNumber = $$lineNumberRef;
|
772
|
+
|
773
|
+
my $startIndex = $index;
|
774
|
+
my $startLine = $lineNumber;
|
775
|
+
|
776
|
+
my @modifiers;
|
777
|
+
my $namespace;
|
778
|
+
|
779
|
+
while ($tokens->[$index] =~ /^[a-z]/i)
|
780
|
+
{
|
781
|
+
if ($tokens->[$index] eq 'var' || $tokens->[$index] eq 'const')
|
782
|
+
{ last; }
|
783
|
+
|
784
|
+
elsif (exists $memberModifiers{lc($tokens->[$index])})
|
785
|
+
{
|
786
|
+
push @modifiers, lc($tokens->[$index]);
|
787
|
+
$index++;
|
788
|
+
|
789
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
790
|
+
}
|
791
|
+
|
792
|
+
elsif (!$namespace)
|
793
|
+
{
|
794
|
+
do
|
795
|
+
{
|
796
|
+
$namespace .= $tokens->[$index];
|
797
|
+
$index++;
|
798
|
+
}
|
799
|
+
while ($tokens->[$index] =~ /^[a-z0-9_]/i);
|
800
|
+
|
801
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
802
|
+
}
|
803
|
+
|
804
|
+
else
|
805
|
+
{ last; };
|
806
|
+
};
|
807
|
+
|
808
|
+
my $type;
|
809
|
+
|
810
|
+
if ($tokens->[$index] eq 'var')
|
811
|
+
{ $type = ::TOPIC_VARIABLE(); }
|
812
|
+
elsif ($tokens->[$index] eq 'const')
|
813
|
+
{ $type = ::TOPIC_CONSTANT(); }
|
814
|
+
else
|
815
|
+
{ return undef; };
|
816
|
+
$index++;
|
817
|
+
|
818
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
819
|
+
|
820
|
+
my $endTypeIndex = $index;
|
821
|
+
my @names;
|
822
|
+
my @types;
|
823
|
+
|
824
|
+
for (;;)
|
825
|
+
{
|
826
|
+
my $name = $self->TryToGetIdentifier(\$index, \$lineNumber);
|
827
|
+
if (!$name)
|
828
|
+
{ return undef; };
|
829
|
+
|
830
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
831
|
+
|
832
|
+
my $type;
|
833
|
+
|
834
|
+
if ($tokens->[$index] eq ':')
|
835
|
+
{
|
836
|
+
$index++;
|
837
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
838
|
+
|
839
|
+
$type = ': ' . $self->TryToGetIdentifier(\$index, \$lineNumber, 1);
|
840
|
+
|
841
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
842
|
+
};
|
843
|
+
|
844
|
+
if ($tokens->[$index] eq '=')
|
845
|
+
{
|
846
|
+
do
|
847
|
+
{
|
848
|
+
$self->GenericSkip(\$index, \$lineNumber);
|
849
|
+
}
|
850
|
+
while ($tokens->[$index] ne ',' && !exists $declarationEnders{$tokens->[$index]} && $index < scalar @$tokens);
|
851
|
+
};
|
852
|
+
|
853
|
+
push @names, $name;
|
854
|
+
push @types, $type;
|
855
|
+
|
856
|
+
if ($tokens->[$index] eq ',')
|
857
|
+
{
|
858
|
+
$index++;
|
859
|
+
$self->TryToSkipWhitespace(\$index, \$lineNumber);
|
860
|
+
}
|
861
|
+
elsif (exists $declarationEnders{$tokens->[$index]})
|
862
|
+
{ last; }
|
863
|
+
else
|
864
|
+
{ return undef; };
|
865
|
+
};
|
866
|
+
|
867
|
+
|
868
|
+
# We succeeded if we got this far.
|
869
|
+
|
870
|
+
my $prototypePrefix = $self->CreateString($startIndex, $endTypeIndex);
|
871
|
+
|
872
|
+
for (my $i = 0; $i < scalar @names; $i++)
|
873
|
+
{
|
874
|
+
my $prototype = $self->NormalizePrototype( $prototypePrefix . ' ' . $names[$i] . $types[$i]);
|
875
|
+
my $scope = $self->CurrentScope();
|
876
|
+
|
877
|
+
if ($names[$i] =~ s/^_global.//)
|
878
|
+
{ $scope = undef; };
|
879
|
+
if ($namespace)
|
880
|
+
{ $scope = NaturalDocs::SymbolString->Join($scope, $namespace); };
|
881
|
+
|
882
|
+
$self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($type, $names[$i],
|
883
|
+
$scope, $self->CurrentUsing(),
|
884
|
+
$prototype,
|
885
|
+
undef, undef, $startLine));
|
886
|
+
};
|
887
|
+
|
888
|
+
$$indexRef = $index;
|
889
|
+
$$lineNumberRef = $lineNumber;
|
890
|
+
|
891
|
+
return 1;
|
892
|
+
};
|
893
|
+
|
894
|
+
|
895
|
+
|
896
|
+
################################################################################
|
897
|
+
# Group: Low Level Parsing Functions
|
898
|
+
|
899
|
+
|
900
|
+
#
|
901
|
+
# Function: GenericSkip
|
902
|
+
#
|
903
|
+
# Advances the position one place through general code.
|
904
|
+
#
|
905
|
+
# - If the position is on a string, it will skip it completely.
|
906
|
+
# - If the position is on an opening symbol, it will skip until the past the closing symbol.
|
907
|
+
# - If the position is on whitespace (including comments), it will skip it completely.
|
908
|
+
# - Otherwise it skips one token.
|
909
|
+
#
|
910
|
+
# Parameters:
|
911
|
+
#
|
912
|
+
# indexRef - A reference to the current index.
|
913
|
+
# lineNumberRef - A reference to the current line number.
|
914
|
+
#
|
915
|
+
sub GenericSkip #(indexRef, lineNumberRef)
|
916
|
+
{
|
917
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
918
|
+
my $tokens = $self->Tokens();
|
919
|
+
|
920
|
+
# We can ignore the scope stack because we're just skipping everything without parsing, and we need recursion anyway.
|
921
|
+
if ($tokens->[$$indexRef] eq '{')
|
922
|
+
{
|
923
|
+
$$indexRef++;
|
924
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
|
925
|
+
}
|
926
|
+
elsif ($tokens->[$$indexRef] eq '(')
|
927
|
+
{
|
928
|
+
$$indexRef++;
|
929
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ')');
|
930
|
+
}
|
931
|
+
elsif ($tokens->[$$indexRef] eq '[')
|
932
|
+
{
|
933
|
+
$$indexRef++;
|
934
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ']');
|
935
|
+
}
|
936
|
+
|
937
|
+
elsif ($self->TryToSkipWhitespace($indexRef, $lineNumberRef) ||
|
938
|
+
$self->TryToSkipString($indexRef, $lineNumberRef) ||
|
939
|
+
$self->TryToSkipRegExp($indexRef, $lineNumberRef) ||
|
940
|
+
$self->TryToSkipXML($indexRef, $lineNumberRef) )
|
941
|
+
{
|
942
|
+
}
|
943
|
+
|
944
|
+
else
|
945
|
+
{ $$indexRef++; };
|
946
|
+
};
|
947
|
+
|
948
|
+
|
949
|
+
#
|
950
|
+
# Function: GenericSkipUntilAfter
|
951
|
+
#
|
952
|
+
# Advances the position via <GenericSkip()> until a specific token is reached and passed.
|
953
|
+
#
|
954
|
+
sub GenericSkipUntilAfter #(indexRef, lineNumberRef, token)
|
955
|
+
{
|
956
|
+
my ($self, $indexRef, $lineNumberRef, $token) = @_;
|
957
|
+
my $tokens = $self->Tokens();
|
958
|
+
|
959
|
+
while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] ne $token)
|
960
|
+
{ $self->GenericSkip($indexRef, $lineNumberRef); };
|
961
|
+
|
962
|
+
if ($tokens->[$$indexRef] eq "\n")
|
963
|
+
{ $$lineNumberRef++; };
|
964
|
+
$$indexRef++;
|
965
|
+
};
|
966
|
+
|
967
|
+
|
968
|
+
#
|
969
|
+
# Function: IndiscriminateSkipUntilAfterSequence
|
970
|
+
#
|
971
|
+
# Advances the position indiscriminately until a specific token sequence is reached and passed.
|
972
|
+
#
|
973
|
+
sub IndiscriminateSkipUntilAfterSequence #(indexRef, lineNumberRef, token, token, ...)
|
974
|
+
{
|
975
|
+
my ($self, $indexRef, $lineNumberRef, @sequence) = @_;
|
976
|
+
my $tokens = $self->Tokens();
|
977
|
+
|
978
|
+
while ($$indexRef < scalar @$tokens && !$self->IsAtSequence($$indexRef, @sequence))
|
979
|
+
{
|
980
|
+
if ($tokens->[$$indexRef] eq "\n")
|
981
|
+
{ $$lineNumberRef++; };
|
982
|
+
$$indexRef++;
|
983
|
+
};
|
984
|
+
|
985
|
+
if ($self->IsAtSequence($$indexRef, @sequence))
|
986
|
+
{
|
987
|
+
$$indexRef += scalar @sequence;
|
988
|
+
foreach my $token (@sequence)
|
989
|
+
{
|
990
|
+
if ($token eq "\n")
|
991
|
+
{ $$lineNumberRef++; };
|
992
|
+
};
|
993
|
+
};
|
994
|
+
};
|
995
|
+
|
996
|
+
|
997
|
+
#
|
998
|
+
# Function: SkipToNextStatement
|
999
|
+
#
|
1000
|
+
# Advances the position via <GenericSkip()> until the next statement, which is defined as anything in <declarationEnders> not
|
1001
|
+
# appearing in brackets or strings. It will always advance at least one token.
|
1002
|
+
#
|
1003
|
+
sub SkipToNextStatement #(indexRef, lineNumberRef)
|
1004
|
+
{
|
1005
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1006
|
+
my $tokens = $self->Tokens();
|
1007
|
+
|
1008
|
+
if ($tokens->[$$indexRef] eq ';')
|
1009
|
+
{ $$indexRef++; }
|
1010
|
+
|
1011
|
+
else
|
1012
|
+
{
|
1013
|
+
do
|
1014
|
+
{
|
1015
|
+
$self->GenericSkip($indexRef, $lineNumberRef);
|
1016
|
+
}
|
1017
|
+
while ( $$indexRef < scalar @$tokens &&
|
1018
|
+
!exists $declarationEnders{$tokens->[$$indexRef]} );
|
1019
|
+
};
|
1020
|
+
};
|
1021
|
+
|
1022
|
+
|
1023
|
+
#
|
1024
|
+
# Function: TryToSkipRegExp
|
1025
|
+
# If the current position is on a regular expression, skip past it and return true.
|
1026
|
+
#
|
1027
|
+
sub TryToSkipRegExp #(indexRef, lineNumberRef)
|
1028
|
+
{
|
1029
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1030
|
+
my $tokens = $self->Tokens();
|
1031
|
+
|
1032
|
+
if ($tokens->[$$indexRef] eq '/')
|
1033
|
+
{
|
1034
|
+
# A slash can either start a regular expression or be a divide symbol. Skip backwards to see what the previous symbol is.
|
1035
|
+
my $index = $$indexRef - 1;
|
1036
|
+
|
1037
|
+
while ($index >= 0 && $tokens->[$index] =~ /^(?: |\t|\n)/)
|
1038
|
+
{ $index--; };
|
1039
|
+
|
1040
|
+
if ($index < 0 || $tokens->[$index] !~ /^\=\(\[\,]/)
|
1041
|
+
{ return 0; };
|
1042
|
+
|
1043
|
+
$$indexRef++;
|
1044
|
+
|
1045
|
+
while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] ne '/')
|
1046
|
+
{
|
1047
|
+
if ($tokens->[$$indexRef] eq '\\')
|
1048
|
+
{ $$indexRef += 2; }
|
1049
|
+
elsif ($tokens->[$$indexRef] eq "\n")
|
1050
|
+
{
|
1051
|
+
$$indexRef++;
|
1052
|
+
$$lineNumberRef++;
|
1053
|
+
}
|
1054
|
+
else
|
1055
|
+
{ $$indexRef++; }
|
1056
|
+
};
|
1057
|
+
|
1058
|
+
if ($$indexRef < scalar @$tokens)
|
1059
|
+
{
|
1060
|
+
$$indexRef++;
|
1061
|
+
|
1062
|
+
if ($tokens->[$$indexRef] =~ /^[gimsx]+$/i)
|
1063
|
+
{ $$indexRef++; };
|
1064
|
+
};
|
1065
|
+
|
1066
|
+
return 1;
|
1067
|
+
}
|
1068
|
+
else
|
1069
|
+
{ return 0; };
|
1070
|
+
};
|
1071
|
+
|
1072
|
+
|
1073
|
+
#
|
1074
|
+
# Function: TryToSkipXML
|
1075
|
+
# If the current position is on an XML literal, skip past it and return true.
|
1076
|
+
#
|
1077
|
+
sub TryToSkipXML #(indexRef, lineNumberRef)
|
1078
|
+
{
|
1079
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1080
|
+
my $tokens = $self->Tokens();
|
1081
|
+
|
1082
|
+
if ($tokens->[$$indexRef] eq '<')
|
1083
|
+
{
|
1084
|
+
# A < can either start an XML literal or be a comparison or shift operator. First check the next character for << or <=.
|
1085
|
+
|
1086
|
+
my $index = $$indexRef + 1;
|
1087
|
+
|
1088
|
+
while ($index < scalar @$tokens && $tokens->[$index] =~ /^[\=\<]$/)
|
1089
|
+
{ return 0; };
|
1090
|
+
|
1091
|
+
|
1092
|
+
# Next try the previous character.
|
1093
|
+
|
1094
|
+
$index = $$indexRef - 1;
|
1095
|
+
|
1096
|
+
while ($index >= 0 && $tokens->[$index] =~ /^[ |\t|\n]/)
|
1097
|
+
{ $index--; };
|
1098
|
+
|
1099
|
+
if ($index < 0 || $tokens->[$index] !~ /^[\=\(\[\,\>]/)
|
1100
|
+
{ return 0; };
|
1101
|
+
}
|
1102
|
+
else
|
1103
|
+
{ return 0; };
|
1104
|
+
|
1105
|
+
|
1106
|
+
# Only handle the tag here if it's not an irregular XML section.
|
1107
|
+
if (!$self->TryToSkipIrregularXML($indexRef, $lineNumberRef))
|
1108
|
+
{
|
1109
|
+
my @tagStack;
|
1110
|
+
|
1111
|
+
my ($tagType, $tagIdentifier) = $self->GetAndSkipXMLTag($indexRef, $lineNumberRef);
|
1112
|
+
if ($tagType == XML_OPENING_TAG)
|
1113
|
+
{ push @tagStack, $tagIdentifier; };
|
1114
|
+
|
1115
|
+
while (scalar @tagStack && $$indexRef < scalar @$tokens)
|
1116
|
+
{
|
1117
|
+
$self->SkipToNextXMLTag($indexRef, $lineNumberRef);
|
1118
|
+
($tagType, $tagIdentifier) = $self->GetAndSkipXMLTag($indexRef, $lineNumberRef);
|
1119
|
+
|
1120
|
+
if ($tagType == XML_OPENING_TAG)
|
1121
|
+
{ push @tagStack, $tagIdentifier; }
|
1122
|
+
elsif ($tagType == XML_CLOSING_TAG && $tagIdentifier eq $tagStack[-1])
|
1123
|
+
{ pop @tagStack; };
|
1124
|
+
};
|
1125
|
+
};
|
1126
|
+
|
1127
|
+
|
1128
|
+
return 1;
|
1129
|
+
};
|
1130
|
+
|
1131
|
+
|
1132
|
+
#
|
1133
|
+
# Function: TryToSkipIrregularXML
|
1134
|
+
#
|
1135
|
+
# If the current position is on an irregular XML tag, skip past it and return true. Irregular XML tags are defined as
|
1136
|
+
#
|
1137
|
+
# CDATA - <![CDATA[ ... ]]>
|
1138
|
+
# Comments - <!-- ... -->
|
1139
|
+
# PI - <? ... ?>
|
1140
|
+
#
|
1141
|
+
sub TryToSkipIrregularXML #(indexRef, lineNumberRef)
|
1142
|
+
{
|
1143
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1144
|
+
|
1145
|
+
if ($self->IsAtSequence($$indexRef, '<', '!', '[', 'CDATA', '['))
|
1146
|
+
{
|
1147
|
+
$$indexRef += 5;
|
1148
|
+
$self->IndiscriminateSkipUntilAfterSequence($indexRef, $lineNumberRef, ']', ']', '>');
|
1149
|
+
return 1;
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
elsif ($self->IsAtSequence($$indexRef, '<', '!', '-', '-'))
|
1153
|
+
{
|
1154
|
+
$$indexRef += 4;
|
1155
|
+
$self->IndiscriminateSkipUntilAfterSequence($indexRef, $lineNumberRef, '-', '-', '>');
|
1156
|
+
return 1;
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
elsif ($self->IsAtSequence($$indexRef, '<', '?'))
|
1160
|
+
{
|
1161
|
+
$$indexRef += 2;
|
1162
|
+
$self->IndiscriminateSkipUntilAfterSequence($indexRef, $lineNumberRef, '?', '>');
|
1163
|
+
return 1;
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
else
|
1167
|
+
{ return 0; };
|
1168
|
+
};
|
1169
|
+
|
1170
|
+
|
1171
|
+
#
|
1172
|
+
# Function: GetAndSkipXMLTag
|
1173
|
+
#
|
1174
|
+
# Processes the XML tag at the current position, moves beyond it, and returns information about it. Assumes the position is on
|
1175
|
+
# the opening angle bracket of the tag and the tag is a normal XML tag, not one of the ones handled by
|
1176
|
+
# <TryToSkipIrregularXML()>.
|
1177
|
+
#
|
1178
|
+
# Parameters:
|
1179
|
+
#
|
1180
|
+
# indexRef - A reference to the index of the position of the opening angle bracket.
|
1181
|
+
# lineNumberRef - A reference to the line number of the position of the opening angle bracket.
|
1182
|
+
#
|
1183
|
+
# Returns:
|
1184
|
+
#
|
1185
|
+
# The array ( tagType, name ).
|
1186
|
+
#
|
1187
|
+
# tagType - One of the <XML Tag Type> constants.
|
1188
|
+
# identifier - The identifier of the tag. If it's an empty tag (<> or </>), this will be "(anonymous)".
|
1189
|
+
#
|
1190
|
+
sub GetAndSkipXMLTag #(indexRef, lineNumberRef)
|
1191
|
+
{
|
1192
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1193
|
+
my $tokens = $self->Tokens();
|
1194
|
+
|
1195
|
+
if ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] ne '<')
|
1196
|
+
{ die "Tried to call GetXMLTag when the position isn't on an opening bracket."; };
|
1197
|
+
|
1198
|
+
# Get the anonymous ones out of the way so we don't have to worry about them below, since they're rather exceptional.
|
1199
|
+
|
1200
|
+
if ($self->IsAtSequence($$indexRef, '<', '>'))
|
1201
|
+
{
|
1202
|
+
$$indexRef += 2;
|
1203
|
+
return ( XML_OPENING_TAG, '(anonymous)' );
|
1204
|
+
}
|
1205
|
+
elsif ($self->IsAtSequence($$indexRef, '<', '/', '>'))
|
1206
|
+
{
|
1207
|
+
$$indexRef += 3;
|
1208
|
+
return ( XML_CLOSING_TAG, '(anonymous)' );
|
1209
|
+
};
|
1210
|
+
|
1211
|
+
|
1212
|
+
# Grab the identifier.
|
1213
|
+
|
1214
|
+
my $tagType = XML_OPENING_TAG;
|
1215
|
+
my $identifier;
|
1216
|
+
|
1217
|
+
$$indexRef++;
|
1218
|
+
|
1219
|
+
if ($tokens->[$$indexRef] eq '/')
|
1220
|
+
{
|
1221
|
+
$$indexRef++;
|
1222
|
+
$tagType = XML_CLOSING_TAG;
|
1223
|
+
};
|
1224
|
+
|
1225
|
+
$self->TryToSkipXMLWhitespace($indexRef, $lineNumberRef);
|
1226
|
+
|
1227
|
+
|
1228
|
+
# The identifier could be a native expression in braces.
|
1229
|
+
|
1230
|
+
if ($tokens->[$$indexRef] eq '{')
|
1231
|
+
{
|
1232
|
+
my $startOfIdentifier = $$indexRef;
|
1233
|
+
|
1234
|
+
$$indexRef++;
|
1235
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
|
1236
|
+
|
1237
|
+
$identifier = $self->CreateString($startOfIdentifier, $$indexRef);
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
|
1241
|
+
# Otherwise just grab content until whitespace or the end of the tag.
|
1242
|
+
|
1243
|
+
else
|
1244
|
+
{
|
1245
|
+
while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] !~ /^[\/\>\ \t]$/)
|
1246
|
+
{
|
1247
|
+
$identifier .= $tokens->[$$indexRef];
|
1248
|
+
$$indexRef++;
|
1249
|
+
};
|
1250
|
+
};
|
1251
|
+
|
1252
|
+
|
1253
|
+
# Skip to the end of the tag.
|
1254
|
+
|
1255
|
+
while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] !~ /^[\/\>]$/)
|
1256
|
+
{
|
1257
|
+
if ($tokens->[$$indexRef] eq '{')
|
1258
|
+
{
|
1259
|
+
$$indexRef++;
|
1260
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
elsif ($self->TryToSkipXMLWhitespace($indexRef, $lineNumberRef))
|
1264
|
+
{ }
|
1265
|
+
|
1266
|
+
# We don't need to do special handling for attribute quotes or anything like that because there's no backslashing in
|
1267
|
+
# XML. It's all handled with entity characters.
|
1268
|
+
else
|
1269
|
+
{ $$indexRef++; };
|
1270
|
+
};
|
1271
|
+
|
1272
|
+
|
1273
|
+
if ($tokens->[$$indexRef] eq '/')
|
1274
|
+
{
|
1275
|
+
if ($tagType == XML_OPENING_TAG)
|
1276
|
+
{ $tagType = XML_SELF_CONTAINED_TAG; };
|
1277
|
+
|
1278
|
+
$$indexRef++;
|
1279
|
+
};
|
1280
|
+
|
1281
|
+
if ($tokens->[$$indexRef] eq '>')
|
1282
|
+
{ $$indexRef++; };
|
1283
|
+
|
1284
|
+
if (!$identifier)
|
1285
|
+
{ $identifier = '(anonymous)'; };
|
1286
|
+
|
1287
|
+
|
1288
|
+
return ( $tagType, $identifier );
|
1289
|
+
};
|
1290
|
+
|
1291
|
+
|
1292
|
+
#
|
1293
|
+
# Function: SkipToNextXMLTag
|
1294
|
+
# Skips to the next normal XML tag. It will not stop at elements handled by <TryToSkipIrregularXML()>. Note that if the
|
1295
|
+
# position is already at an XML tag, it will not move.
|
1296
|
+
#
|
1297
|
+
sub SkipToNextXMLTag #(indexRef, lineNumberRef)
|
1298
|
+
{
|
1299
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1300
|
+
my $tokens = $self->Tokens();
|
1301
|
+
|
1302
|
+
while ($$indexRef < scalar @$tokens)
|
1303
|
+
{
|
1304
|
+
if ($tokens->[$$indexRef] eq '{')
|
1305
|
+
{
|
1306
|
+
$$indexRef++;
|
1307
|
+
$self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
elsif ($self->TryToSkipIrregularXML($indexRef, $lineNumberRef))
|
1311
|
+
{ }
|
1312
|
+
|
1313
|
+
elsif ($tokens->[$$indexRef] eq '<')
|
1314
|
+
{ last; }
|
1315
|
+
|
1316
|
+
else
|
1317
|
+
{
|
1318
|
+
if ($tokens->[$$indexRef] eq "\n")
|
1319
|
+
{ $$lineNumberRef++; };
|
1320
|
+
|
1321
|
+
$$indexRef++;
|
1322
|
+
};
|
1323
|
+
};
|
1324
|
+
};
|
1325
|
+
|
1326
|
+
|
1327
|
+
#
|
1328
|
+
# Function: TryToSkipXMLWhitespace
|
1329
|
+
# If the current position is on XML whitespace, skip past it and return true.
|
1330
|
+
#
|
1331
|
+
sub TryToSkipXMLWhitespace #(indexRef, lineNumberRef)
|
1332
|
+
{
|
1333
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1334
|
+
my $tokens = $self->Tokens();
|
1335
|
+
|
1336
|
+
my $result;
|
1337
|
+
|
1338
|
+
while ($$indexRef < scalar @$tokens)
|
1339
|
+
{
|
1340
|
+
if ($tokens->[$$indexRef] =~ /^[ \t]/)
|
1341
|
+
{
|
1342
|
+
$$indexRef++;
|
1343
|
+
$result = 1;
|
1344
|
+
}
|
1345
|
+
elsif ($tokens->[$$indexRef] eq "\n")
|
1346
|
+
{
|
1347
|
+
$$indexRef++;
|
1348
|
+
$$lineNumberRef++;
|
1349
|
+
$result = 1;
|
1350
|
+
}
|
1351
|
+
else
|
1352
|
+
{ last; };
|
1353
|
+
};
|
1354
|
+
|
1355
|
+
return $result;
|
1356
|
+
};
|
1357
|
+
|
1358
|
+
|
1359
|
+
#
|
1360
|
+
# Function: TryToSkipString
|
1361
|
+
# If the current position is on a string delimiter, skip past the string and return true.
|
1362
|
+
#
|
1363
|
+
# Parameters:
|
1364
|
+
#
|
1365
|
+
# indexRef - A reference to the index of the position to start at.
|
1366
|
+
# lineNumberRef - A reference to the line number of the position.
|
1367
|
+
#
|
1368
|
+
# Returns:
|
1369
|
+
#
|
1370
|
+
# Whether the position was at a string.
|
1371
|
+
#
|
1372
|
+
# Syntax Support:
|
1373
|
+
#
|
1374
|
+
# - Supports quotes and apostrophes.
|
1375
|
+
#
|
1376
|
+
sub TryToSkipString #(indexRef, lineNumberRef)
|
1377
|
+
{
|
1378
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1379
|
+
|
1380
|
+
return ($self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '\'') ||
|
1381
|
+
$self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '"') );
|
1382
|
+
};
|
1383
|
+
|
1384
|
+
|
1385
|
+
#
|
1386
|
+
# Function: TryToSkipWhitespace
|
1387
|
+
# If the current position is on a whitespace token, a line break token, or a comment, it skips them and returns true. If there are
|
1388
|
+
# a number of these in a row, it skips them all.
|
1389
|
+
#
|
1390
|
+
sub TryToSkipWhitespace #(indexRef, lineNumberRef)
|
1391
|
+
{
|
1392
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1393
|
+
my $tokens = $self->Tokens();
|
1394
|
+
|
1395
|
+
my $result;
|
1396
|
+
|
1397
|
+
while ($$indexRef < scalar @$tokens)
|
1398
|
+
{
|
1399
|
+
if ($tokens->[$$indexRef] =~ /^[ \t]/)
|
1400
|
+
{
|
1401
|
+
$$indexRef++;
|
1402
|
+
$result = 1;
|
1403
|
+
}
|
1404
|
+
elsif ($tokens->[$$indexRef] eq "\n")
|
1405
|
+
{
|
1406
|
+
$$indexRef++;
|
1407
|
+
$$lineNumberRef++;
|
1408
|
+
$result = 1;
|
1409
|
+
}
|
1410
|
+
elsif ($self->TryToSkipComment($indexRef, $lineNumberRef))
|
1411
|
+
{
|
1412
|
+
$result = 1;
|
1413
|
+
}
|
1414
|
+
else
|
1415
|
+
{ last; };
|
1416
|
+
};
|
1417
|
+
|
1418
|
+
return $result;
|
1419
|
+
};
|
1420
|
+
|
1421
|
+
|
1422
|
+
#
|
1423
|
+
# Function: TryToSkipComment
|
1424
|
+
# If the current position is on a comment, skip past it and return true.
|
1425
|
+
#
|
1426
|
+
sub TryToSkipComment #(indexRef, lineNumberRef)
|
1427
|
+
{
|
1428
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1429
|
+
|
1430
|
+
return ( $self->TryToSkipLineComment($indexRef, $lineNumberRef) ||
|
1431
|
+
$self->TryToSkipMultilineComment($indexRef, $lineNumberRef) );
|
1432
|
+
};
|
1433
|
+
|
1434
|
+
|
1435
|
+
#
|
1436
|
+
# Function: TryToSkipLineComment
|
1437
|
+
# If the current position is on a line comment symbol, skip past it and return true.
|
1438
|
+
#
|
1439
|
+
sub TryToSkipLineComment #(indexRef, lineNumberRef)
|
1440
|
+
{
|
1441
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1442
|
+
my $tokens = $self->Tokens();
|
1443
|
+
|
1444
|
+
if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '/')
|
1445
|
+
{
|
1446
|
+
$self->SkipRestOfLine($indexRef, $lineNumberRef);
|
1447
|
+
return 1;
|
1448
|
+
}
|
1449
|
+
else
|
1450
|
+
{ return undef; };
|
1451
|
+
};
|
1452
|
+
|
1453
|
+
|
1454
|
+
#
|
1455
|
+
# Function: TryToSkipMultilineComment
|
1456
|
+
# If the current position is on an opening comment symbol, skip past it and return true.
|
1457
|
+
#
|
1458
|
+
sub TryToSkipMultilineComment #(indexRef, lineNumberRef)
|
1459
|
+
{
|
1460
|
+
my ($self, $indexRef, $lineNumberRef) = @_;
|
1461
|
+
my $tokens = $self->Tokens();
|
1462
|
+
|
1463
|
+
if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '*')
|
1464
|
+
{
|
1465
|
+
$self->SkipUntilAfter($indexRef, $lineNumberRef, '*', '/');
|
1466
|
+
return 1;
|
1467
|
+
}
|
1468
|
+
else
|
1469
|
+
{ return undef; };
|
1470
|
+
};
|
1471
|
+
|
1472
|
+
|
1473
|
+
1;
|