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.
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;