bixbite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +49 -0
  3. data/VERSION +1 -0
  4. data/bin/bixbite +73 -0
  5. data/lib/bixbite.rb +13 -0
  6. data/lib/bixbite/command.rb +14 -0
  7. data/lib/bixbite/create.rb +76 -0
  8. data/template/Rakefile +25 -0
  9. data/template/assets/bixbite/Rakefile.rb +297 -0
  10. data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
  11. data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
  12. data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
  13. data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
  14. data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
  15. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
  16. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
  17. data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
  18. data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
  19. data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
  20. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
  21. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
  22. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
  23. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
  24. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
  25. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
  26. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
  27. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
  28. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
  29. data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
  30. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
  31. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
  32. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
  33. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
  34. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
  35. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
  36. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
  37. data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
  38. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
  39. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
  40. data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
  41. data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
  42. data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
  43. data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
  44. data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
  45. data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
  46. data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
  47. data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
  48. data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
  49. data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
  50. data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
  51. data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
  52. data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
  53. data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
  54. data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
  55. data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
  56. data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
  57. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
  58. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
  59. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
  60. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
  61. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
  62. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
  63. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
  64. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
  65. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
  66. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
  67. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
  68. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
  69. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
  70. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
  71. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
  72. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
  73. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
  74. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
  75. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
  76. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
  77. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
  78. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
  79. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
  80. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
  81. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
  82. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
  83. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
  84. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
  85. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
  86. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
  87. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
  88. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
  89. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
  90. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
  91. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
  92. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
  93. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
  94. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
  95. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
  96. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
  97. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
  98. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
  99. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
  100. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
  101. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
  102. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
  103. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
  104. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
  105. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
  106. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
  107. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
  108. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
  109. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
  110. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
  111. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
  112. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
  113. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
  114. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
  115. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
  116. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
  117. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
  118. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
  119. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
  120. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
  121. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
  122. data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
  123. data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
  124. data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
  125. data/template/assets/utilities/pngout +0 -0
  126. data/template/deploy/public_html/.htaccess +0 -0
  127. data/template/documentation/js/.htaccess +0 -0
  128. data/template/src/html/.htaccess +76 -0
  129. data/template/src/html/css/cmn/global.css +96 -0
  130. data/template/src/html/css/cmn/ie.css +15 -0
  131. data/template/src/html/css/cmn/ie6.css +15 -0
  132. data/template/src/html/images/cmn/.htaccess +0 -0
  133. data/template/src/html/images/tmp/.htaccess +0 -0
  134. data/template/src/html/includes/debug.inc +5 -0
  135. data/template/src/html/includes/footer.inc +52 -0
  136. data/template/src/html/includes/header.inc +61 -0
  137. data/template/src/html/includes/html.inc +3 -0
  138. data/template/src/html/includes/namespace.inc +19 -0
  139. data/template/src/html/includes/page.inc +151 -0
  140. data/template/src/html/index.html +35 -0
  141. data/template/src/html/js/cmn/bootstrap.js +74 -0
  142. data/template/src/html/js/cmn/global.js +142 -0
  143. data/template/src/html/js/cmn/lib/LAB.js +348 -0
  144. data/template/src/html/min/.htaccess +4 -0
  145. data/template/src/html/min/MinifyCLI.php +19 -0
  146. data/template/src/html/min/README.txt +132 -0
  147. data/template/src/html/min/builder/_index.js +242 -0
  148. data/template/src/html/min/builder/bm.js +36 -0
  149. data/template/src/html/min/builder/index.php +182 -0
  150. data/template/src/html/min/builder/ocCheck.php +36 -0
  151. data/template/src/html/min/builder/rewriteTest.js +1 -0
  152. data/template/src/html/min/config.php +187 -0
  153. data/template/src/html/min/groupsConfig.php +34 -0
  154. data/template/src/html/min/index.php +66 -0
  155. data/template/src/html/min/lib/FirePHP.php +1370 -0
  156. data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
  157. data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
  158. data/template/src/html/min/lib/JSMin.php +314 -0
  159. data/template/src/html/min/lib/JSMinPlus.php +1872 -0
  160. data/template/src/html/min/lib/Minify.php +532 -0
  161. data/template/src/html/min/lib/Minify/Build.php +103 -0
  162. data/template/src/html/min/lib/Minify/CSS.php +83 -0
  163. data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
  164. data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
  165. data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
  166. data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
  167. data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
  168. data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
  169. data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
  170. data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
  171. data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
  172. data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
  173. data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
  174. data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
  175. data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
  176. data/template/src/html/min/lib/Minify/HTML.php +245 -0
  177. data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
  178. data/template/src/html/min/lib/Minify/Lines.php +131 -0
  179. data/template/src/html/min/lib/Minify/Logger.php +45 -0
  180. data/template/src/html/min/lib/Minify/Packer.php +37 -0
  181. data/template/src/html/min/lib/Minify/Source.php +187 -0
  182. data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
  183. data/template/src/html/min/lib/Solar/Dir.php +199 -0
  184. data/template/src/html/min/lib/closure-compiler.jar +0 -0
  185. data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
  186. data/template/src/html/min/utils.php +90 -0
  187. data/template/src/templates/css/template.css +7 -0
  188. data/template/src/templates/js/template.js +72 -0
  189. data/template/src/templates/template.html +18 -0
  190. data/template/src/yaml/config.yml +46 -0
  191. data/template/src/yaml/deploy.yml +35 -0
  192. data/test/bixbite_test.rb +7 -0
  193. data/test/test_helper.rb +10 -0
  194. 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;