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,1484 @@
1
+ ###############################################################################
2
+ #
3
+ # Class: NaturalDocs::Languages::CSharp
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A subclass to handle the language variations of C#.
8
+ #
9
+ #
10
+ # Topic: Language Support
11
+ #
12
+ # Supported:
13
+ #
14
+ # - Classes
15
+ # - Namespaces (no topic generated)
16
+ # - Functions
17
+ # - Constructors and Destructors
18
+ # - Properties
19
+ # - Indexers
20
+ # - Operators
21
+ # - Delegates
22
+ # - Variables
23
+ # - Constants
24
+ # - Events
25
+ # - Enums
26
+ #
27
+ # Not supported yet:
28
+ #
29
+ # - Autodocumenting enum members
30
+ # - Using alias
31
+ #
32
+ ###############################################################################
33
+
34
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
35
+ # Natural Docs is licensed under the GPL
36
+
37
+ use strict;
38
+ use integer;
39
+
40
+ package NaturalDocs::Languages::CSharp;
41
+
42
+ use base 'NaturalDocs::Languages::Advanced';
43
+
44
+
45
+ ###############################################################################
46
+ # Group: Package Variables
47
+
48
+ #
49
+ # hash: classKeywords
50
+ # An existence hash of all the acceptable class keywords. The keys are in all lowercase.
51
+ #
52
+ my %classKeywords = ( 'class' => 1,
53
+ 'struct' => 1,
54
+ 'interface' => 1 );
55
+
56
+ #
57
+ # hash: classModifiers
58
+ # An existence hash of all the acceptable class modifiers. The keys are in all lowercase.
59
+ #
60
+ my %classModifiers = ( 'new' => 1,
61
+ 'public' => 1,
62
+ 'protected' => 1,
63
+ 'internal' => 1,
64
+ 'private' => 1,
65
+ 'abstract' => 1,
66
+ 'sealed' => 1,
67
+ 'unsafe' => 1,
68
+ 'static' => 1 );
69
+
70
+ #
71
+ # hash: functionModifiers
72
+ # An existence hash of all the acceptable function modifiers. Also applies to properties. Also encompasses those for operators
73
+ # and indexers, but have more than are valid for them. The keys are in all lowercase.
74
+ #
75
+ my %functionModifiers = ( 'new' => 1,
76
+ 'public' => 1,
77
+ 'protected' => 1,
78
+ 'internal' => 1,
79
+ 'private' => 1,
80
+ 'static' => 1,
81
+ 'virtual' => 1,
82
+ 'sealed' => 1,
83
+ 'override' => 1,
84
+ 'abstract' => 1,
85
+ 'extern' => 1,
86
+ 'unsafe' => 1 );
87
+
88
+ #
89
+ # hash: variableModifiers
90
+ # An existence hash of all the acceptable variable modifiers. The keys are in all lowercase.
91
+ #
92
+ my %variableModifiers = ( 'new' => 1,
93
+ 'public' => 1,
94
+ 'protected' => 1,
95
+ 'internal' => 1,
96
+ 'private' => 1,
97
+ 'static' => 1,
98
+ 'readonly' => 1,
99
+ 'volatile' => 1,
100
+ 'unsafe' => 1 );
101
+
102
+ #
103
+ # hash: enumTypes
104
+ # An existence hash of all the possible enum types. The keys are in all lowercase.
105
+ #
106
+ my %enumTypes = ( 'sbyte' => 1,
107
+ 'byte' => 1,
108
+ 'short' => 1,
109
+ 'ushort' => 1,
110
+ 'int' => 1,
111
+ 'uint' => 1,
112
+ 'long' => 1,
113
+ 'ulong' => 1 );
114
+
115
+ #
116
+ # hash: impossibleTypeWords
117
+ # An existence hash of all the reserved words that cannot be in a type. This includes 'enum' and all modifiers. The keys are in
118
+ # all lowercase.
119
+ #
120
+ my %impossibleTypeWords = ( 'abstract' => 1, 'as' => 1, 'base' => 1, 'break' => 1, 'case' => 1, 'catch' => 1,
121
+ 'checked' => 1, 'class' => 1, 'const' => 1, 'continue' => 1, 'default' => 1, 'delegate' => 1,
122
+ 'do' => 1, 'else' => 1, 'enum' => 1, 'event' => 1, 'explicit' => 1, 'extern' => 1,
123
+ 'false' => 1, 'finally' => 1, 'fixed' => 1, 'for' => 1, 'foreach' => 1, 'goto' => 1, 'if' => 1,
124
+ 'implicit' => 1, 'in' => 1, 'interface' => 1, 'internal' => 1, 'is' => 1, 'lock' => 1,
125
+ 'namespace' => 1, 'new' => 1, 'null' => 1, 'operator' => 1, 'out' => 1, 'override' => 1,
126
+ 'params' => 1, 'private' => 1, 'protected' => 1, 'public' => 1, 'readonly' => 1, 'ref' => 1,
127
+ 'return' => 1, 'sealed' => 1, 'sizeof' => 1, 'stackalloc' => 1, 'static' => 1,
128
+ 'struct' => 1, 'switch' => 1, 'this' => 1, 'throw' => 1, 'true' => 1, 'try' => 1, 'typeof' => 1,
129
+ 'unchecked' => 1, 'unsafe' => 1, 'using' => 1, 'virtual' => 1, 'volatile' => 1, 'while' => 1 );
130
+ # Deleted from the list: object, string, bool, decimal, sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, void
131
+
132
+
133
+
134
+ ###############################################################################
135
+ # Group: Interface Functions
136
+
137
+
138
+ #
139
+ # Function: PackageSeparator
140
+ # Returns the package separator symbol.
141
+ #
142
+ sub PackageSeparator
143
+ { return '.'; };
144
+
145
+
146
+ #
147
+ # Function: EnumValues
148
+ # Returns the <EnumValuesType> that describes how the language handles enums.
149
+ #
150
+ sub EnumValues
151
+ { return ::ENUM_UNDER_TYPE(); };
152
+
153
+
154
+ #
155
+ # Function: ParseFile
156
+ #
157
+ # Parses the passed source file, sending comments acceptable for documentation to <NaturalDocs::Parser->OnComment()>.
158
+ #
159
+ # Parameters:
160
+ #
161
+ # sourceFile - The <FileName> to parse.
162
+ # topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
163
+ #
164
+ # Returns:
165
+ #
166
+ # The array ( autoTopics, scopeRecord ).
167
+ #
168
+ # autoTopics - An arrayref of automatically generated topics from the file, or undef if none.
169
+ # scopeRecord - An arrayref of <NaturalDocs::Languages::Advanced::ScopeChanges>, or undef if none.
170
+ #
171
+ sub ParseFile #(sourceFile, topicsList)
172
+ {
173
+ my ($self, $sourceFile, $topicsList) = @_;
174
+
175
+ $self->ParseForCommentsAndTokens($sourceFile, [ '//' ], [ '/*', '*/' ], [ '///' ], [ '/**', '*/' ] );
176
+
177
+ my $tokens = $self->Tokens();
178
+ my $index = 0;
179
+ my $lineNumber = 1;
180
+
181
+ while ($index < scalar @$tokens)
182
+ {
183
+ if ($self->TryToSkipWhitespace(\$index, \$lineNumber) ||
184
+ $self->TryToGetNamespace(\$index, \$lineNumber) ||
185
+ $self->TryToGetUsing(\$index, \$lineNumber) ||
186
+ $self->TryToGetClass(\$index, \$lineNumber) ||
187
+ $self->TryToGetFunction(\$index, \$lineNumber) ||
188
+ $self->TryToGetOverloadedOperator(\$index, \$lineNumber) ||
189
+ $self->TryToGetVariable(\$index, \$lineNumber) ||
190
+ $self->TryToGetEnum(\$index, \$lineNumber) )
191
+ {
192
+ # The functions above will handle everything.
193
+ }
194
+
195
+ elsif ($tokens->[$index] eq '{')
196
+ {
197
+ $self->StartScope('}', $lineNumber, undef, undef, undef);
198
+ $index++;
199
+ }
200
+
201
+ elsif ($tokens->[$index] eq '}')
202
+ {
203
+ if ($self->ClosingScopeSymbol() eq '}')
204
+ { $self->EndScope($lineNumber); };
205
+
206
+ $index++;
207
+ }
208
+
209
+ else
210
+ {
211
+ $self->SkipRestOfStatement(\$index, \$lineNumber);
212
+ };
213
+ };
214
+
215
+
216
+ # Don't need to keep these around.
217
+ $self->ClearTokens();
218
+
219
+
220
+ my $autoTopics = $self->AutoTopics();
221
+
222
+ my $scopeRecord = $self->ScopeRecord();
223
+ if (defined $scopeRecord && !scalar @$scopeRecord)
224
+ { $scopeRecord = undef; };
225
+
226
+ return ( $autoTopics, $scopeRecord );
227
+ };
228
+
229
+
230
+
231
+ ###############################################################################
232
+ # Group: Statement Parsing Functions
233
+ # All functions here assume that the current position is at the beginning of a statement.
234
+ #
235
+ # 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
236
+ # 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.
237
+
238
+
239
+ #
240
+ # Function: TryToGetNamespace
241
+ #
242
+ # Determines whether the position is at a namespace declaration statement, and if so, adjusts the scope, skips it, and returns
243
+ # true.
244
+ #
245
+ # Why no topic?:
246
+ #
247
+ # The main reason we don't create a Natural Docs topic for a namespace is because in order to declare class A.B.C in C#,
248
+ # you must do this:
249
+ #
250
+ # > namespace A.B
251
+ # > {
252
+ # > class C
253
+ # > { ... }
254
+ # > }
255
+ #
256
+ # That would result in a namespace topic whose only purpose is really to qualify C. It would take the default page title, and
257
+ # thus the default menu title. So if you have files for A.B.X, A.B.Y, and A.B.Z, they all will appear as A.B on the menu.
258
+ #
259
+ # If something actually appears in the namespace besides a class, it will be handled by
260
+ # <NaturalDocs::Parser->AddPackageDelineators()>. That function will add a package topic to correct the scope.
261
+ #
262
+ # If the user actually documented it, it will still appear because of the manual topic.
263
+ #
264
+ sub TryToGetNamespace #(indexRef, lineNumberRef)
265
+ {
266
+ my ($self, $indexRef, $lineNumberRef) = @_;
267
+ my $tokens = $self->Tokens();
268
+
269
+ if (lc($tokens->[$$indexRef]) ne 'namespace')
270
+ { return undef; };
271
+
272
+ my $index = $$indexRef + 1;
273
+ my $lineNumber = $$lineNumberRef;
274
+
275
+ if (!$self->TryToSkipWhitespace(\$index, \$lineNumber))
276
+ { return undef; };
277
+
278
+ my $name;
279
+
280
+ while ($tokens->[$index] =~ /^[a-z_\.\@]/i)
281
+ {
282
+ $name .= $tokens->[$index];
283
+ $index++;
284
+ };
285
+
286
+ if (!defined $name)
287
+ { return undef; };
288
+
289
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
290
+
291
+ if ($tokens->[$index] ne '{')
292
+ { return undef; };
293
+
294
+ $index++;
295
+
296
+
297
+ # We found a valid one if we made it this far.
298
+
299
+ my $autoTopic = NaturalDocs::Parser::ParsedTopic->New(::TOPIC_CLASS(), $name,
300
+ $self->CurrentScope(), $self->CurrentUsing(),
301
+ undef,
302
+ undef, undef, $$lineNumberRef);
303
+
304
+ # We don't add an auto-topic for namespaces. See the function documentation above.
305
+
306
+ NaturalDocs::Parser->OnClass($autoTopic->Package());
307
+
308
+ $self->StartScope('}', $lineNumber, $autoTopic->Package());
309
+
310
+ $$indexRef = $index;
311
+ $$lineNumberRef = $lineNumber;
312
+
313
+ return 1;
314
+ };
315
+
316
+
317
+ #
318
+ # Function: TryToGetClass
319
+ #
320
+ # Determines whether the position is at a class declaration statement, and if so, generates a topic for it, skips it, and
321
+ # returns true.
322
+ #
323
+ # Supported Syntaxes:
324
+ #
325
+ # - Classes
326
+ # - Structs
327
+ # - Interfaces
328
+ #
329
+ sub TryToGetClass #(indexRef, lineNumberRef)
330
+ {
331
+ my ($self, $indexRef, $lineNumberRef) = @_;
332
+ my $tokens = $self->Tokens();
333
+
334
+ my $index = $$indexRef;
335
+ my $lineNumber = $$lineNumberRef;
336
+
337
+ my $startIndex = $index;
338
+ my $startLine = $lineNumber;
339
+ my $needsPrototype = 0;
340
+
341
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
342
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); }
343
+
344
+ my @modifiers;
345
+
346
+ while ($tokens->[$index] =~ /^[a-z]/i &&
347
+ !exists $classKeywords{lc($tokens->[$index])} &&
348
+ exists $classModifiers{lc($tokens->[$index])} )
349
+ {
350
+ push @modifiers, lc($tokens->[$index]);
351
+ $index++;
352
+
353
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
354
+ };
355
+
356
+ if (!exists $classKeywords{lc($tokens->[$index])})
357
+ { return undef; };
358
+
359
+ my $lcClassKeyword = lc($tokens->[$index]);
360
+
361
+ $index++;
362
+
363
+ if (!$self->TryToSkipWhitespace(\$index, \$lineNumber))
364
+ { return undef; };
365
+
366
+ my $name;
367
+
368
+ while ($tokens->[$index] =~ /^[a-z_\@]/i)
369
+ {
370
+ $name .= $tokens->[$index];
371
+ $index++;
372
+ };
373
+
374
+ if (!defined $name)
375
+ { return undef; };
376
+
377
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
378
+
379
+ if ($tokens->[$index] eq '<')
380
+ {
381
+ # XXX: This is half-assed.
382
+ $index++;
383
+ $needsPrototype = 1;
384
+
385
+ while ($index < scalar @$tokens && $tokens->[$index] ne '>')
386
+ {
387
+ $index++;
388
+ }
389
+
390
+ if ($index < scalar @$tokens)
391
+ {
392
+ $index++;
393
+ }
394
+ else
395
+ { return undef; }
396
+
397
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
398
+ }
399
+
400
+ my @parents;
401
+
402
+ if ($tokens->[$index] eq ':')
403
+ {
404
+ do
405
+ {
406
+ $index++;
407
+
408
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
409
+
410
+ my $parentName;
411
+
412
+ while ($tokens->[$index] =~ /^[a-z_\.\@]/i)
413
+ {
414
+ $parentName .= $tokens->[$index];
415
+ $index++;
416
+ };
417
+
418
+ if ($tokens->[$index] eq '<')
419
+ {
420
+ # XXX: This is still half-assed.
421
+ $index++;
422
+ $needsPrototype = 1;
423
+
424
+ while ($index < scalar @$tokens && $tokens->[$index] ne '>')
425
+ {
426
+ $index++;
427
+ }
428
+
429
+ if ($index < scalar @$tokens)
430
+ {
431
+ $index++;
432
+ }
433
+ else
434
+ { return undef; }
435
+
436
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
437
+ }
438
+
439
+ if (!defined $parentName)
440
+ { return undef; };
441
+
442
+ push @parents, NaturalDocs::SymbolString->FromText($parentName);
443
+
444
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
445
+ }
446
+ while ($tokens->[$index] eq ',')
447
+ };
448
+
449
+ if (lc($tokens->[$index]) eq 'where')
450
+ {
451
+ # XXX: This is also half-assed
452
+ $index++;
453
+
454
+ while ($index < scalar @$tokens && $tokens->[$index] ne '{')
455
+ {
456
+ $index++;
457
+ }
458
+ }
459
+
460
+ if ($tokens->[$index] ne '{')
461
+ { return undef; };
462
+
463
+
464
+ # If we made it this far, we have a valid class declaration.
465
+
466
+ my @scopeIdentifiers = NaturalDocs::SymbolString->IdentifiersOf($self->CurrentScope());
467
+ $name = join('.', @scopeIdentifiers, $name);
468
+
469
+ my $topicType;
470
+
471
+ if ($lcClassKeyword eq 'interface')
472
+ { $topicType = ::TOPIC_INTERFACE(); }
473
+ else
474
+ { $topicType = ::TOPIC_CLASS(); };
475
+
476
+ my $prototype;
477
+
478
+ if ($needsPrototype)
479
+ {
480
+ $prototype = $self->CreateString($startIndex, $index);
481
+ }
482
+
483
+ my $autoTopic = NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
484
+ undef, $self->CurrentUsing(),
485
+ $prototype,
486
+ undef, undef, $$lineNumberRef);
487
+
488
+ $self->AddAutoTopic($autoTopic);
489
+ NaturalDocs::Parser->OnClass($autoTopic->Package());
490
+
491
+ foreach my $parent (@parents)
492
+ {
493
+ NaturalDocs::Parser->OnClassParent($autoTopic->Package(), $parent, $self->CurrentScope(), undef,
494
+ ::RESOLVE_RELATIVE());
495
+ };
496
+
497
+ $self->StartScope('}', $lineNumber, $autoTopic->Package());
498
+
499
+ $index++;
500
+
501
+ $$indexRef = $index;
502
+ $$lineNumberRef = $lineNumber;
503
+
504
+ return 1;
505
+ };
506
+
507
+
508
+ #
509
+ # Function: TryToGetUsing
510
+ #
511
+ # Determines whether the position is at a using statement, and if so, adds it to the current scope, skips it, and returns
512
+ # true.
513
+ #
514
+ # Supported:
515
+ #
516
+ # - Using
517
+ #
518
+ # Unsupported:
519
+ #
520
+ # - Using with alias
521
+ #
522
+ sub TryToGetUsing #(indexRef, lineNumberRef)
523
+ {
524
+ my ($self, $indexRef, $lineNumberRef) = @_;
525
+ my $tokens = $self->Tokens();
526
+
527
+ my $index = $$indexRef;
528
+ my $lineNumber = $$lineNumberRef;
529
+
530
+ if (lc($tokens->[$index]) ne 'using')
531
+ { return undef; };
532
+
533
+ $index++;
534
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
535
+
536
+ my $name;
537
+
538
+ while ($tokens->[$index] =~ /^[a-z_\@\.]/i)
539
+ {
540
+ $name .= $tokens->[$index];
541
+ $index++;
542
+ };
543
+
544
+ if ($tokens->[$index] ne ';' ||
545
+ !defined $name)
546
+ { return undef; };
547
+
548
+ $index++;
549
+
550
+
551
+ $self->AddUsing( NaturalDocs::SymbolString->FromText($name) );
552
+
553
+ $$indexRef = $index;
554
+ $$lineNumberRef = $lineNumber;
555
+
556
+ return 1;
557
+ };
558
+
559
+
560
+
561
+ #
562
+ # Function: TryToGetFunction
563
+ #
564
+ # Determines if the position is on a function declaration, and if so, generates a topic for it, skips it, and returns true.
565
+ #
566
+ # Supported Syntaxes:
567
+ #
568
+ # - Functions
569
+ # - Constructors
570
+ # - Destructors
571
+ # - Properties
572
+ # - Indexers
573
+ # - Delegates
574
+ # - Events
575
+ #
576
+ sub TryToGetFunction #(indexRef, lineNumberRef)
577
+ {
578
+ my ($self, $indexRef, $lineNumberRef) = @_;
579
+ my $tokens = $self->Tokens();
580
+
581
+ my $index = $$indexRef;
582
+ my $lineNumber = $$lineNumberRef;
583
+
584
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
585
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); };
586
+
587
+ my $startIndex = $index;
588
+ my $startLine = $lineNumber;
589
+
590
+ my @modifiers;
591
+
592
+ while ($tokens->[$index] =~ /^[a-z]/i &&
593
+ exists $functionModifiers{lc($tokens->[$index])} )
594
+ {
595
+ push @modifiers, lc($tokens->[$index]);
596
+ $index++;
597
+
598
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
599
+ };
600
+
601
+ my $isDelegate;
602
+ my $isEvent;
603
+
604
+ if (lc($tokens->[$index]) eq 'delegate')
605
+ {
606
+ $isDelegate = 1;
607
+ $index++;
608
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
609
+ }
610
+ elsif (lc($tokens->[$index]) eq 'event')
611
+ {
612
+ $isEvent = 1;
613
+ $index++;
614
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
615
+ };
616
+
617
+ my $returnType = $self->TryToGetType(\$index, \$lineNumber);
618
+
619
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
620
+
621
+ my $name;
622
+ my $lastNameWord;
623
+
624
+ while ($tokens->[$index] =~ /^[a-z\_\@\.\~\<]/i)
625
+ {
626
+ $name .= $tokens->[$index];
627
+
628
+ # Ugly hack, but what else is new? For explicit generic interface definitions, such as:
629
+ # IDObjectType System.Collections.Generic.IEnumerator<IDObjectType>.Current
630
+
631
+ if ($tokens->[$index] eq '<')
632
+ {
633
+ do
634
+ {
635
+ $index++;
636
+ $name .= $tokens->[$index];
637
+ }
638
+ while ($index < @$tokens && $tokens->[$index] ne '>');
639
+ }
640
+
641
+ $lastNameWord = $tokens->[$index];
642
+ $index++;
643
+ };
644
+
645
+ if (!defined $name)
646
+ {
647
+ # Constructors and destructors don't have return types. It's possible their names were mistaken for the return type.
648
+ if (defined $returnType)
649
+ {
650
+ $name = $returnType;
651
+ $returnType = undef;
652
+
653
+ $name =~ /([a-z0-9_]+)$/i;
654
+ $lastNameWord = $1;
655
+ }
656
+ else
657
+ { return undef; };
658
+ };
659
+
660
+ # If there's no return type, make sure it's a constructor or destructor.
661
+ if (!defined $returnType)
662
+ {
663
+ my @identifiers = NaturalDocs::SymbolString->IdentifiersOf( $self->CurrentScope() );
664
+
665
+ if ($lastNameWord ne $identifiers[-1])
666
+ { return undef; };
667
+ };
668
+
669
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
670
+
671
+
672
+ # Skip the brackets on indexers.
673
+ if ($tokens->[$index] eq '[' && lc($lastNameWord) eq 'this')
674
+ {
675
+ # This should jump the brackets completely.
676
+ $self->GenericSkip(\$index, \$lineNumber);
677
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
678
+
679
+ $name .= '[]';
680
+ };
681
+
682
+
683
+ # Properties, indexers, events with braces
684
+
685
+ if ($tokens->[$index] eq '{')
686
+ {
687
+ my $prototype = $self->CreateString($startIndex, $index);
688
+
689
+ $index++;
690
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
691
+
692
+ my ($aWord, $bWord, $hasA, $hasB);
693
+
694
+ if ($isEvent)
695
+ {
696
+ $aWord = 'add';
697
+ $bWord = 'remove';
698
+ }
699
+ else
700
+ {
701
+ $aWord = 'get';
702
+ $bWord = 'set';
703
+ };
704
+
705
+ while ($index < scalar @$tokens)
706
+ {
707
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
708
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); };
709
+
710
+ if (lc($tokens->[$index]) eq $aWord)
711
+ { $hasA = 1; }
712
+ elsif (lc($tokens->[$index]) eq $bWord)
713
+ { $hasB = 1; }
714
+ elsif ($tokens->[$index] eq '}')
715
+ {
716
+ $index++;
717
+ last;
718
+ };
719
+
720
+ $self->SkipRestOfStatement(\$index, \$lineNumber);
721
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
722
+ };
723
+
724
+ if ($hasA && $hasB)
725
+ { $prototype .= ' { ' . $aWord . ', ' . $bWord . ' }'; }
726
+ elsif ($hasA)
727
+ { $prototype .= ' { ' . $aWord . ' }'; }
728
+ elsif ($hasB)
729
+ { $prototype .= ' { ' . $bWord . ' }'; };
730
+
731
+ $prototype = $self->NormalizePrototype($prototype);
732
+
733
+ my $topicType = ( $isEvent ? ::TOPIC_EVENT() : ::TOPIC_PROPERTY() );
734
+
735
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
736
+ $self->CurrentScope(), $self->CurrentUsing(),
737
+ $prototype,
738
+ undef, undef, $startLine));
739
+ }
740
+
741
+
742
+ # Functions, constructors, destructors, delegates.
743
+
744
+ elsif ($tokens->[$index] eq '(')
745
+ {
746
+ # This should jump the parenthesis completely.
747
+ $self->GenericSkip(\$index, \$lineNumber);
748
+
749
+ my $topicType = ( $isDelegate ? ::TOPIC_DELEGATE() : ::TOPIC_FUNCTION() );
750
+ my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
751
+
752
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($topicType, $name,
753
+ $self->CurrentScope(), $self->CurrentUsing(),
754
+ $prototype,
755
+ undef, undef, $startLine));
756
+
757
+ $self->SkipRestOfStatement(\$index, \$lineNumber);
758
+ }
759
+
760
+
761
+ # Events without braces
762
+
763
+ elsif ($isEvent && $tokens->[$index] eq ';')
764
+ {
765
+ my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
766
+
767
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New(::TOPIC_EVENT(), $name,
768
+ $self->CurrentScope(), $self->CurrentUsing(),
769
+ $prototype,
770
+ undef, undef, $startLine));
771
+ $index++;
772
+ }
773
+
774
+ else
775
+ { return undef; };
776
+
777
+
778
+ # We succeeded if we got this far.
779
+
780
+ $$indexRef = $index;
781
+ $$lineNumberRef = $lineNumber;
782
+
783
+ return 1;
784
+ };
785
+
786
+
787
+ #
788
+ # Function: TryToGetOverloadedOperator
789
+ #
790
+ # Determines if the position is on an operator overload declaration, and if so, generates a topic for it, skips it, and returns true.
791
+ #
792
+ sub TryToGetOverloadedOperator #(indexRef, lineNumberRef)
793
+ {
794
+ my ($self, $indexRef, $lineNumberRef) = @_;
795
+ my $tokens = $self->Tokens();
796
+
797
+ my $index = $$indexRef;
798
+ my $lineNumber = $$lineNumberRef;
799
+
800
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
801
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); };
802
+
803
+ my $startIndex = $index;
804
+ my $startLine = $lineNumber;
805
+
806
+ my @modifiers;
807
+
808
+ while ($tokens->[$index] =~ /^[a-z]/i &&
809
+ exists $functionModifiers{lc($tokens->[$index])} )
810
+ {
811
+ push @modifiers, lc($tokens->[$index]);
812
+ $index++;
813
+
814
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
815
+ };
816
+
817
+
818
+ my $name;
819
+
820
+
821
+ # Casting operators.
822
+
823
+ if (lc($tokens->[$index]) eq 'implicit' || lc($tokens->[$index]) eq 'explicit')
824
+ {
825
+ $index++;
826
+
827
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
828
+
829
+ if (lc($tokens->[$index]) ne 'operator')
830
+ { return undef; };
831
+
832
+ $index++;
833
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
834
+
835
+ $name = $self->TryToGetType(\$index, \$lineNumber);
836
+
837
+ if (!defined $name)
838
+ { return undef; };
839
+ }
840
+
841
+
842
+ # Symbol operators.
843
+
844
+ else
845
+ {
846
+ if (!$self->TryToGetType(\$index, \$lineNumber))
847
+ { return undef; };
848
+
849
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
850
+
851
+ if (lc($tokens->[$index]) ne 'operator')
852
+ { return undef; };
853
+
854
+ $index++;
855
+
856
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
857
+
858
+ if (lc($tokens->[$index]) eq 'true' || lc($tokens->[$index]) eq 'false')
859
+ {
860
+ $name = $tokens->[$index];
861
+ $index++;
862
+ }
863
+ else
864
+ {
865
+ while ($tokens->[$index] =~ /^[\+\-\!\~\*\/\%\&\|\^\<\>\=]$/)
866
+ {
867
+ $name .= $tokens->[$index];
868
+ $index++;
869
+ };
870
+ };
871
+ };
872
+
873
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
874
+
875
+ if ($tokens->[$index] ne '(')
876
+ { return undef; };
877
+
878
+ # This should skip the parenthesis completely.
879
+ $self->GenericSkip(\$index, \$lineNumber);
880
+
881
+ my $prototype = $self->NormalizePrototype( $self->CreateString($startIndex, $index) );
882
+
883
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New(::TOPIC_FUNCTION(), 'operator ' . $name,
884
+ $self->CurrentScope(), $self->CurrentUsing(),
885
+ $prototype,
886
+ undef, undef, $startLine));
887
+
888
+ $self->SkipRestOfStatement(\$index, \$lineNumber);
889
+
890
+
891
+ # We succeeded if we got this far.
892
+
893
+ $$indexRef = $index;
894
+ $$lineNumberRef = $lineNumber;
895
+
896
+ return 1;
897
+ };
898
+
899
+
900
+ #
901
+ # Function: TryToGetVariable
902
+ #
903
+ # Determines if the position is on a variable declaration statement, and if so, generates a topic for each variable, skips the
904
+ # statement, and returns true.
905
+ #
906
+ # Supported Syntaxes:
907
+ #
908
+ # - Variables
909
+ # - Constants
910
+ #
911
+ sub TryToGetVariable #(indexRef, lineNumberRef)
912
+ {
913
+ my ($self, $indexRef, $lineNumberRef) = @_;
914
+ my $tokens = $self->Tokens();
915
+
916
+ my $index = $$indexRef;
917
+ my $lineNumber = $$lineNumberRef;
918
+
919
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
920
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); };
921
+
922
+ my $startIndex = $index;
923
+ my $startLine = $lineNumber;
924
+
925
+ my @modifiers;
926
+
927
+ while ($tokens->[$index] =~ /^[a-z]/i &&
928
+ exists $variableModifiers{lc($tokens->[$index])} )
929
+ {
930
+ push @modifiers, lc($tokens->[$index]);
931
+ $index++;
932
+
933
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
934
+ };
935
+
936
+ my $type;
937
+ if (lc($tokens->[$index]) eq 'const')
938
+ {
939
+ $type = ::TOPIC_CONSTANT();
940
+ $index++;
941
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
942
+ }
943
+ else
944
+ {
945
+ $type = ::TOPIC_VARIABLE();
946
+ };
947
+
948
+ if (!$self->TryToGetType(\$index, \$lineNumber))
949
+ { return undef; };
950
+
951
+ my $endTypeIndex = $index;
952
+
953
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
954
+
955
+ my @names;
956
+
957
+ for (;;)
958
+ {
959
+ my $name;
960
+
961
+ while ($tokens->[$index] =~ /^[a-z\@\_]/i)
962
+ {
963
+ $name .= $tokens->[$index];
964
+ $index++;
965
+ };
966
+
967
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
968
+
969
+ if ($tokens->[$index] eq '=')
970
+ {
971
+ do
972
+ {
973
+ $self->GenericSkip(\$index, \$lineNumber);
974
+ }
975
+ while ($tokens->[$index] ne ',' && $tokens->[$index] ne ';');
976
+ };
977
+
978
+ push @names, $name;
979
+
980
+ if ($tokens->[$index] eq ';')
981
+ {
982
+ $index++;
983
+ last;
984
+ }
985
+ elsif ($tokens->[$index] eq ',')
986
+ {
987
+ $index++;
988
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
989
+ }
990
+ else
991
+ { return undef; };
992
+ };
993
+
994
+
995
+ # We succeeded if we got this far.
996
+
997
+ my $prototypePrefix = $self->CreateString($startIndex, $endTypeIndex);
998
+
999
+ foreach my $name (@names)
1000
+ {
1001
+ my $prototype = $self->NormalizePrototype( $prototypePrefix . ' ' . $name );
1002
+
1003
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New($type, $name,
1004
+ $self->CurrentScope(), $self->CurrentUsing(),
1005
+ $prototype,
1006
+ undef, undef, $startLine));
1007
+ };
1008
+
1009
+ $$indexRef = $index;
1010
+ $$lineNumberRef = $lineNumber;
1011
+
1012
+ return 1;
1013
+ };
1014
+
1015
+
1016
+ #
1017
+ # Function: TryToGetEnum
1018
+ #
1019
+ # Determines if the position is on an enum declaration statement, and if so, generates a topic for it.
1020
+ #
1021
+ # Supported Syntaxes:
1022
+ #
1023
+ # - Enums
1024
+ # - Enums with declared types
1025
+ #
1026
+ # Unsupported:
1027
+ #
1028
+ # - Documenting the members automatically
1029
+ #
1030
+ sub TryToGetEnum #(indexRef, lineNumberRef)
1031
+ {
1032
+ my ($self, $indexRef, $lineNumberRef) = @_;
1033
+ my $tokens = $self->Tokens();
1034
+
1035
+ my $index = $$indexRef;
1036
+ my $lineNumber = $$lineNumberRef;
1037
+
1038
+ if ($self->TryToSkipAttributes(\$index, \$lineNumber))
1039
+ { $self->TryToSkipWhitespace(\$index, \$lineNumber); };
1040
+
1041
+ my $startIndex = $index;
1042
+ my $startLine = $lineNumber;
1043
+
1044
+ my @modifiers;
1045
+
1046
+ while ($tokens->[$index] =~ /^[a-z]/i &&
1047
+ exists $variableModifiers{lc($tokens->[$index])} )
1048
+ {
1049
+ push @modifiers, lc($tokens->[$index]);
1050
+ $index++;
1051
+
1052
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1053
+ };
1054
+
1055
+ if (lc($tokens->[$index]) ne 'enum')
1056
+ { return undef; }
1057
+
1058
+ $index++;
1059
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1060
+
1061
+ my $name;
1062
+
1063
+ while ($tokens->[$index] =~ /^[a-z\@\_]/i)
1064
+ {
1065
+ $name .= $tokens->[$index];
1066
+ $index++;
1067
+ };
1068
+
1069
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1070
+
1071
+ if ($tokens->[$index] eq ':')
1072
+ {
1073
+ $index++;
1074
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1075
+
1076
+ if (!exists $enumTypes{ lc($tokens->[$index]) })
1077
+ { return undef; }
1078
+
1079
+ $index++;
1080
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1081
+ }
1082
+
1083
+ if ($tokens->[$index] ne '{')
1084
+ { return undef; }
1085
+
1086
+ # We succeeded if we got this far.
1087
+
1088
+ my $prototype = $self->CreateString($startIndex, $index);
1089
+ $prototype = $self->NormalizePrototype( $prototype );
1090
+
1091
+ $self->SkipRestOfStatement(\$index, \$lineNumber);
1092
+
1093
+ $self->AddAutoTopic(NaturalDocs::Parser::ParsedTopic->New(::TOPIC_ENUMERATION(), $name,
1094
+ $self->CurrentScope(), $self->CurrentUsing(),
1095
+ $prototype,
1096
+ undef, undef, $startLine));
1097
+
1098
+ $$indexRef = $index;
1099
+ $$lineNumberRef = $lineNumber;
1100
+
1101
+ return 1;
1102
+ };
1103
+
1104
+
1105
+ #
1106
+ # Function: TryToGetType
1107
+ #
1108
+ # Determines if the position is on a type identifier, and if so, skips it and returns it as a string. This function does _not_ allow
1109
+ # modifiers. You must take care of those beforehand.
1110
+ #
1111
+ sub TryToGetType #(indexRef, lineNumberRef)
1112
+ {
1113
+ my ($self, $indexRef, $lineNumberRef) = @_;
1114
+ my $tokens = $self->Tokens();
1115
+
1116
+ my $name;
1117
+ my $index = $$indexRef;
1118
+ my $lineNumber = $$lineNumberRef;
1119
+
1120
+ while ($tokens->[$index] =~ /^[a-z\@\.\_]/i)
1121
+ {
1122
+ if (exists $impossibleTypeWords{ lc($tokens->[$index]) } && $name !~ /\@$/)
1123
+ { return undef; };
1124
+
1125
+ $name .= $tokens->[$index];
1126
+ $index++;
1127
+ };
1128
+
1129
+ if (!defined $name)
1130
+ { return undef; };
1131
+
1132
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1133
+
1134
+ if ($tokens->[$index] eq '?')
1135
+ {
1136
+ $name .= '?';
1137
+ $index++;
1138
+
1139
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1140
+ }
1141
+
1142
+ if ($tokens->[$index] eq '<')
1143
+ {
1144
+ # XXX: This is half-assed.
1145
+ $name .= '<';
1146
+ $index++;
1147
+
1148
+ while ($index < scalar @$tokens && $tokens->[$index] ne '>')
1149
+ {
1150
+ $name .= $tokens->[$index];
1151
+ $index++;
1152
+ }
1153
+
1154
+ if ($index < scalar @$tokens)
1155
+ {
1156
+ $name .= '>';
1157
+ $index++;
1158
+ }
1159
+ else
1160
+ { return undef; }
1161
+
1162
+ $self->TryToSkipWhitespace(\$index, \$lineNumber);
1163
+ }
1164
+
1165
+ while ($tokens->[$index] eq '[')
1166
+ {
1167
+ $name .= '[';
1168
+ $index++;
1169
+
1170
+ while ($tokens->[$index] eq ',')
1171
+ {
1172
+ $name .= ',';
1173
+ $index++;
1174
+ };
1175
+
1176
+ if ($tokens->[$index] eq ']')
1177
+ {
1178
+ $name .= ']';
1179
+ $index++;
1180
+ }
1181
+ else
1182
+ { return undef; }
1183
+ };
1184
+
1185
+ $$indexRef = $index;
1186
+ $$lineNumberRef = $lineNumber;
1187
+
1188
+ return $name;
1189
+ };
1190
+
1191
+
1192
+
1193
+ ###############################################################################
1194
+ # Group: Low Level Parsing Functions
1195
+
1196
+
1197
+ #
1198
+ # Function: GenericSkip
1199
+ #
1200
+ # Advances the position one place through general code.
1201
+ #
1202
+ # - If the position is on a string, it will skip it completely.
1203
+ # - If the position is on an opening symbol, it will skip until the past the closing symbol.
1204
+ # - If the position is on whitespace (including comments and preprocessing directives), it will skip it completely.
1205
+ # - Otherwise it skips one token.
1206
+ #
1207
+ # Parameters:
1208
+ #
1209
+ # indexRef - A reference to the current index.
1210
+ # lineNumberRef - A reference to the current line number.
1211
+ #
1212
+ sub GenericSkip #(indexRef, lineNumberRef)
1213
+ {
1214
+ my ($self, $indexRef, $lineNumberRef) = @_;
1215
+ my $tokens = $self->Tokens();
1216
+
1217
+ # We can ignore the scope stack because we're just skipping everything without parsing, and we need recursion anyway.
1218
+ if ($tokens->[$$indexRef] eq '{')
1219
+ {
1220
+ $$indexRef++;
1221
+ $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, '}');
1222
+ }
1223
+ elsif ($tokens->[$$indexRef] eq '(')
1224
+ {
1225
+ $$indexRef++;
1226
+ $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ')');
1227
+ }
1228
+ elsif ($tokens->[$$indexRef] eq '[')
1229
+ {
1230
+ $$indexRef++;
1231
+ $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ']');
1232
+ }
1233
+
1234
+ elsif ($self->TryToSkipWhitespace($indexRef, $lineNumberRef) ||
1235
+ $self->TryToSkipString($indexRef, $lineNumberRef))
1236
+ {
1237
+ }
1238
+
1239
+ else
1240
+ { $$indexRef++; };
1241
+ };
1242
+
1243
+
1244
+ #
1245
+ # Function: GenericSkipUntilAfter
1246
+ #
1247
+ # Advances the position via <GenericSkip()> until a specific token is reached and passed.
1248
+ #
1249
+ sub GenericSkipUntilAfter #(indexRef, lineNumberRef, token)
1250
+ {
1251
+ my ($self, $indexRef, $lineNumberRef, $token) = @_;
1252
+ my $tokens = $self->Tokens();
1253
+
1254
+ while ($$indexRef < scalar @$tokens && $tokens->[$$indexRef] ne $token)
1255
+ { $self->GenericSkip($indexRef, $lineNumberRef); };
1256
+
1257
+ if ($tokens->[$$indexRef] eq "\n")
1258
+ { $$lineNumberRef++; };
1259
+ $$indexRef++;
1260
+ };
1261
+
1262
+
1263
+ #
1264
+ # Function: SkipRestOfStatement
1265
+ #
1266
+ # Advances the position via <GenericSkip()> until after the end of the current statement, which is defined as a semicolon or
1267
+ # a brace group. Of course, either of those appearing inside parenthesis, a nested brace group, etc. don't count.
1268
+ #
1269
+ sub SkipRestOfStatement #(indexRef, lineNumberRef)
1270
+ {
1271
+ my ($self, $indexRef, $lineNumberRef) = @_;
1272
+ my $tokens = $self->Tokens();
1273
+
1274
+ while ($$indexRef < scalar @$tokens &&
1275
+ $tokens->[$$indexRef] ne ';' &&
1276
+ $tokens->[$$indexRef] ne '{')
1277
+ {
1278
+ $self->GenericSkip($indexRef, $lineNumberRef);
1279
+ };
1280
+
1281
+ if ($tokens->[$$indexRef] eq ';')
1282
+ { $$indexRef++; }
1283
+ elsif ($tokens->[$$indexRef] eq '{')
1284
+ { $self->GenericSkip($indexRef, $lineNumberRef); };
1285
+ };
1286
+
1287
+
1288
+ #
1289
+ # Function: TryToSkipString
1290
+ # If the current position is on a string delimiter, skip past the string and return true.
1291
+ #
1292
+ # Parameters:
1293
+ #
1294
+ # indexRef - A reference to the index of the position to start at.
1295
+ # lineNumberRef - A reference to the line number of the position.
1296
+ #
1297
+ # Returns:
1298
+ #
1299
+ # Whether the position was at a string.
1300
+ #
1301
+ # Syntax Support:
1302
+ #
1303
+ # - Supports quotes, apostrophes, and at-quotes.
1304
+ #
1305
+ sub TryToSkipString #(indexRef, lineNumberRef)
1306
+ {
1307
+ my ($self, $indexRef, $lineNumberRef) = @_;
1308
+ my $tokens = $self->Tokens();
1309
+
1310
+ # The three string delimiters. All three are Perl variables when preceded by a dollar sign.
1311
+ if ($self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '\'') ||
1312
+ $self->SUPER::TryToSkipString($indexRef, $lineNumberRef, '"') )
1313
+ {
1314
+ return 1;
1315
+ }
1316
+ elsif ($tokens->[$$indexRef] eq '@' && $tokens->[$$indexRef+1] eq '"')
1317
+ {
1318
+ $$indexRef += 2;
1319
+
1320
+ # We need to do at-strings manually because backslash characters are accepted as regular characters, and two consecutive
1321
+ # quotes are accepted as well.
1322
+
1323
+ while ($$indexRef < scalar @$tokens && !($tokens->[$$indexRef] eq '"' && $tokens->[$$indexRef+1] ne '"') )
1324
+ {
1325
+ if ($tokens->[$$indexRef] eq '"')
1326
+ {
1327
+ # This is safe because the while condition will only let through quote pairs.
1328
+ $$indexRef += 2;
1329
+ }
1330
+ elsif ($tokens->[$$indexRef] eq "\n")
1331
+ {
1332
+ $$indexRef++;
1333
+ $$lineNumberRef++;
1334
+ }
1335
+ else
1336
+ {
1337
+ $$indexRef++;
1338
+ };
1339
+ };
1340
+
1341
+ # Skip the closing quote.
1342
+ if ($$indexRef < scalar @$tokens)
1343
+ { $$indexRef++; };
1344
+
1345
+ return 1;
1346
+ }
1347
+ else
1348
+ { return undef; };
1349
+ };
1350
+
1351
+
1352
+ #
1353
+ # Function: TryToSkipAttributes
1354
+ # If the current position is on an attribute section, skip it and return true. Skips multiple attribute sections if they appear
1355
+ # consecutively.
1356
+ #
1357
+ sub TryToSkipAttributes #(indexRef, lineNumberRef)
1358
+ {
1359
+ my ($self, $indexRef, $lineNumberRef) = @_;
1360
+ my $tokens = $self->Tokens();
1361
+
1362
+ my $success;
1363
+
1364
+ while ($tokens->[$$indexRef] eq '[')
1365
+ {
1366
+ $success = 1;
1367
+ $$indexRef++;
1368
+ $self->GenericSkipUntilAfter($indexRef, $lineNumberRef, ']');
1369
+ $self->TryToSkipWhitespace($indexRef, $lineNumberRef);
1370
+ };
1371
+
1372
+ return $success;
1373
+ };
1374
+
1375
+
1376
+ #
1377
+ # Function: TryToSkipWhitespace
1378
+ # If the current position is on a whitespace token, a line break token, a comment, or a preprocessing directive, it skips them
1379
+ # and returns true. If there are a number of these in a row, it skips them all.
1380
+ #
1381
+ sub TryToSkipWhitespace #(indexRef, lineNumberRef)
1382
+ {
1383
+ my ($self, $indexRef, $lineNumberRef) = @_;
1384
+ my $tokens = $self->Tokens();
1385
+
1386
+ my $result;
1387
+
1388
+ while ($$indexRef < scalar @$tokens)
1389
+ {
1390
+ if ($tokens->[$$indexRef] =~ /^[ \t]/)
1391
+ {
1392
+ $$indexRef++;
1393
+ $result = 1;
1394
+ }
1395
+ elsif ($tokens->[$$indexRef] eq "\n")
1396
+ {
1397
+ $$indexRef++;
1398
+ $$lineNumberRef++;
1399
+ $result = 1;
1400
+ }
1401
+ elsif ($self->TryToSkipComment($indexRef, $lineNumberRef) ||
1402
+ $self->TryToSkipPreprocessingDirective($indexRef, $lineNumberRef))
1403
+ {
1404
+ $result = 1;
1405
+ }
1406
+ else
1407
+ { last; };
1408
+ };
1409
+
1410
+ return $result;
1411
+ };
1412
+
1413
+
1414
+ #
1415
+ # Function: TryToSkipComment
1416
+ # If the current position is on a comment, skip past it and return true.
1417
+ #
1418
+ sub TryToSkipComment #(indexRef, lineNumberRef)
1419
+ {
1420
+ my ($self, $indexRef, $lineNumberRef) = @_;
1421
+
1422
+ return ( $self->TryToSkipLineComment($indexRef, $lineNumberRef) ||
1423
+ $self->TryToSkipMultilineComment($indexRef, $lineNumberRef) );
1424
+ };
1425
+
1426
+
1427
+ #
1428
+ # Function: TryToSkipLineComment
1429
+ # If the current position is on a line comment symbol, skip past it and return true.
1430
+ #
1431
+ sub TryToSkipLineComment #(indexRef, lineNumberRef)
1432
+ {
1433
+ my ($self, $indexRef, $lineNumberRef) = @_;
1434
+ my $tokens = $self->Tokens();
1435
+
1436
+ if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '/')
1437
+ {
1438
+ $self->SkipRestOfLine($indexRef, $lineNumberRef);
1439
+ return 1;
1440
+ }
1441
+ else
1442
+ { return undef; };
1443
+ };
1444
+
1445
+
1446
+ #
1447
+ # Function: TryToSkipMultilineComment
1448
+ # If the current position is on an opening comment symbol, skip past it and return true.
1449
+ #
1450
+ sub TryToSkipMultilineComment #(indexRef, lineNumberRef)
1451
+ {
1452
+ my ($self, $indexRef, $lineNumberRef) = @_;
1453
+ my $tokens = $self->Tokens();
1454
+
1455
+ if ($tokens->[$$indexRef] eq '/' && $tokens->[$$indexRef+1] eq '*')
1456
+ {
1457
+ $self->SkipUntilAfter($indexRef, $lineNumberRef, '*', '/');
1458
+ return 1;
1459
+ }
1460
+ else
1461
+ { return undef; };
1462
+ };
1463
+
1464
+
1465
+ #
1466
+ # Function: TryToSkipPreprocessingDirective
1467
+ # If the current position is on a preprocessing directive, skip past it and return true.
1468
+ #
1469
+ sub TryToSkipPreprocessingDirective #(indexRef, lineNumberRef)
1470
+ {
1471
+ my ($self, $indexRef, $lineNumberRef) = @_;
1472
+ my $tokens = $self->Tokens();
1473
+
1474
+ if ($tokens->[$$indexRef] eq '#' && $self->IsFirstLineToken($$indexRef))
1475
+ {
1476
+ $self->SkipRestOfLine($indexRef, $lineNumberRef);
1477
+ return 1;
1478
+ }
1479
+ else
1480
+ { return undef; };
1481
+ };
1482
+
1483
+
1484
+ 1;