yard 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yard might be problematic. Click here for more details.

Files changed (264) hide show
  1. data/{LICENSE.txt → LICENSE} +1 -1
  2. data/README +211 -0
  3. data/Rakefile +31 -0
  4. data/benchmarks/builtins_vs_eval.rb +23 -0
  5. data/benchmarks/erb_vs_erubis.rb +53 -0
  6. data/benchmarks/generation.rb +37 -0
  7. data/benchmarks/parsing.rb +33 -0
  8. data/bin/view_generator +17 -0
  9. data/bin/yard-graph +4 -0
  10. data/bin/yardoc +1 -93
  11. data/bin/yri +12 -3
  12. data/lib/yard.rb +10 -5
  13. data/lib/yard/autoload.rb +116 -0
  14. data/lib/yard/cli/yard_graph.rb +86 -0
  15. data/lib/yard/cli/yardoc.rb +131 -0
  16. data/lib/yard/code_objects/base.rb +321 -0
  17. data/lib/yard/code_objects/class_object.rb +89 -0
  18. data/lib/yard/code_objects/class_variable_object.rb +4 -0
  19. data/lib/yard/code_objects/constant_object.rb +4 -0
  20. data/lib/yard/code_objects/method_object.rb +51 -0
  21. data/lib/yard/code_objects/module_object.rb +4 -0
  22. data/lib/yard/code_objects/namespace_object.rb +88 -0
  23. data/lib/yard/code_objects/proxy.rb +183 -0
  24. data/lib/yard/code_objects/root_object.rb +8 -0
  25. data/lib/yard/core_ext/file.rb +26 -0
  26. data/lib/yard/core_ext/logger.rb +5 -0
  27. data/lib/yard/core_ext/module.rb +9 -0
  28. data/lib/yard/core_ext/string.rb +13 -0
  29. data/lib/yard/core_ext/symbol_hash.rb +24 -0
  30. data/lib/yard/generators/attributes_generator.rb +22 -0
  31. data/lib/yard/generators/base.rb +285 -0
  32. data/lib/yard/generators/class_generator.rb +25 -0
  33. data/lib/yard/generators/constants_generator.rb +73 -0
  34. data/lib/yard/generators/constructor_generator.rb +25 -0
  35. data/lib/yard/generators/deprecated_generator.rb +15 -0
  36. data/lib/yard/generators/docstring_generator.rb +15 -0
  37. data/lib/yard/generators/full_doc_generator.rb +59 -0
  38. data/lib/yard/generators/helpers/base_helper.rb +52 -0
  39. data/lib/yard/generators/helpers/filter_helper.rb +21 -0
  40. data/lib/yard/generators/helpers/html_helper.rb +137 -0
  41. data/lib/yard/generators/helpers/method_helper.rb +27 -0
  42. data/lib/yard/generators/helpers/uml_helper.rb +16 -0
  43. data/lib/yard/generators/inheritance_generator.rb +16 -0
  44. data/lib/yard/generators/method_details_generator.rb +18 -0
  45. data/lib/yard/generators/method_generator.rb +31 -0
  46. data/lib/yard/generators/method_listing_generator.rb +105 -0
  47. data/lib/yard/generators/method_missing_generator.rb +25 -0
  48. data/lib/yard/generators/method_signature_generator.rb +19 -0
  49. data/lib/yard/generators/method_summary_generator.rb +21 -0
  50. data/lib/yard/generators/mixins_generator.rb +15 -0
  51. data/lib/yard/generators/module_generator.rb +22 -0
  52. data/lib/yard/generators/quick_doc_generator.rb +31 -0
  53. data/lib/yard/generators/source_generator.rb +26 -0
  54. data/lib/yard/generators/tags_generator.rb +50 -0
  55. data/lib/yard/generators/uml_generator.rb +92 -0
  56. data/lib/yard/generators/visibility_group_generator.rb +26 -0
  57. data/lib/yard/handlers/alias_handler.rb +32 -0
  58. data/lib/yard/handlers/attribute_handler.rb +54 -0
  59. data/lib/yard/handlers/base.rb +509 -0
  60. data/lib/yard/handlers/class_handler.rb +44 -0
  61. data/lib/yard/handlers/class_variable_handler.rb +13 -0
  62. data/lib/yard/handlers/constant_handler.rb +13 -0
  63. data/lib/yard/handlers/exception_handler.rb +12 -0
  64. data/lib/yard/handlers/method_handler.rb +27 -0
  65. data/lib/yard/handlers/mixin_handler.rb +16 -0
  66. data/lib/yard/handlers/module_handler.rb +9 -0
  67. data/lib/yard/handlers/visibility_handler.rb +14 -0
  68. data/lib/yard/handlers/yield_handler.rb +26 -0
  69. data/lib/yard/logging.rb +27 -0
  70. data/lib/yard/parser/ruby_lex.rb +1344 -0
  71. data/lib/yard/parser/source_parser.rb +109 -0
  72. data/lib/yard/parser/statement.rb +36 -0
  73. data/lib/yard/parser/statement_list.rb +167 -0
  74. data/lib/yard/parser/token_list.rb +58 -0
  75. data/lib/yard/rake/yardoc_task.rb +30 -0
  76. data/lib/yard/registry.rb +136 -0
  77. data/lib/yard/serializers/base.rb +16 -0
  78. data/lib/yard/serializers/file_system_serializer.rb +48 -0
  79. data/lib/yard/serializers/process_serializer.rb +14 -0
  80. data/lib/yard/serializers/stdout_serializer.rb +21 -0
  81. data/lib/yard/tags/default_factory.rb +98 -0
  82. data/lib/yard/tags/library.rb +109 -0
  83. data/lib/yard/tags/merbdoc_factory.rb +47 -0
  84. data/lib/yard/tags/tag.rb +35 -0
  85. data/spec/code_objects/base_spec.rb +219 -0
  86. data/spec/code_objects/class_object_spec.rb +176 -0
  87. data/spec/code_objects/code_object_list_spec.rb +33 -0
  88. data/spec/code_objects/constants_spec.rb +79 -0
  89. data/spec/code_objects/method_object_spec.rb +30 -0
  90. data/spec/code_objects/module_object_spec.rb +73 -0
  91. data/spec/code_objects/namespace_object_spec.rb +129 -0
  92. data/spec/code_objects/proxy_spec.rb +80 -0
  93. data/spec/code_objects/spec_helper.rb +3 -0
  94. data/spec/core_ext/file_spec.rb +20 -0
  95. data/spec/core_ext/string_spec.rb +4 -0
  96. data/spec/core_ext/symbol_hash_spec.rb +80 -0
  97. data/spec/generators/base_spec.rb +64 -0
  98. data/spec/generators/helpers/base_helper_spec.rb +15 -0
  99. data/spec/generators/helpers/html_helper_spec.rb +56 -0
  100. data/spec/generators/quick_doc_generator_spec.rb +13 -0
  101. data/spec/handlers/alias_handler_spec.rb +50 -0
  102. data/spec/handlers/attribute_handler_spec.rb +78 -0
  103. data/spec/handlers/base_spec.rb +165 -0
  104. data/spec/handlers/class_handler_spec.rb +68 -0
  105. data/spec/handlers/class_variable_handler_spec.rb +9 -0
  106. data/spec/handlers/constant_handler_spec.rb +13 -0
  107. data/spec/handlers/examples/alias_handler_001.rb.txt +24 -0
  108. data/spec/handlers/examples/attribute_handler_001.rb.txt +19 -0
  109. data/spec/handlers/examples/class_handler_001.rb.txt +39 -0
  110. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -0
  111. data/spec/handlers/examples/constant_handler_001.rb.txt +10 -0
  112. data/spec/handlers/examples/exception_handler_001.rb.txt +42 -0
  113. data/spec/handlers/examples/method_handler_001.rb.txt +35 -0
  114. data/spec/handlers/examples/mixin_handler_001.rb.txt +12 -0
  115. data/spec/handlers/examples/module_handler_001.rb.txt +16 -0
  116. data/spec/handlers/examples/visibility_handler_001.rb.txt +20 -0
  117. data/spec/handlers/examples/yield_handler_001.rb.txt +55 -0
  118. data/spec/handlers/exception_handler_spec.rb +35 -0
  119. data/spec/handlers/method_handler_spec.rb +35 -0
  120. data/spec/handlers/mixin_handler_spec.rb +30 -0
  121. data/spec/handlers/module_handler_spec.rb +25 -0
  122. data/spec/handlers/spec_helper.rb +21 -0
  123. data/spec/handlers/visibility_handler_spec.rb +24 -0
  124. data/spec/handlers/yield_handler_spec.rb +51 -0
  125. data/spec/parser/examples/example1.rb.txt +8 -0
  126. data/spec/parser/examples/tag_handler_001.rb.txt +8 -0
  127. data/spec/parser/source_parser_spec.rb +43 -0
  128. data/spec/parser/tag_parsing_spec.rb +18 -0
  129. data/spec/parser/token_list_spec.rb +35 -0
  130. data/spec/registry_spec.rb +70 -0
  131. data/spec/serializers/file_system_serializer_spec.rb +91 -0
  132. data/spec/serializers/spec_helper.rb +2 -0
  133. data/spec/spec_helper.rb +77 -0
  134. data/templates/default/attributes/html/header.erb +35 -0
  135. data/templates/default/attributes/text/header.erb +10 -0
  136. data/templates/default/class/html/header.erb +4 -0
  137. data/templates/default/constants/html/constants.erb +9 -0
  138. data/templates/default/constants/html/header.erb +3 -0
  139. data/templates/default/constants/html/included.erb +9 -0
  140. data/templates/default/constants/html/inherited.erb +9 -0
  141. data/templates/default/constructor/html/header.erb +10 -0
  142. data/templates/default/deprecated/html/main.erb +4 -0
  143. data/templates/default/deprecated/text/main.erb +3 -0
  144. data/templates/default/docstring/html/main.erb +3 -0
  145. data/templates/default/docstring/text/main.erb +3 -0
  146. data/templates/default/fulldoc/html/all_methods.erb +25 -0
  147. data/templates/default/fulldoc/html/all_namespaces.erb +19 -0
  148. data/templates/default/fulldoc/html/app.js +18 -0
  149. data/templates/default/fulldoc/html/header.erb +15 -0
  150. data/templates/default/fulldoc/html/html_head.erb +3 -0
  151. data/templates/default/fulldoc/html/index.erb +18 -0
  152. data/templates/default/fulldoc/html/jquery.js +11 -0
  153. data/templates/default/fulldoc/html/readme.erb +15 -0
  154. data/templates/default/fulldoc/html/style.css +65 -0
  155. data/templates/default/fulldoc/html/syntax_highlight.css +21 -0
  156. data/templates/default/inheritance/html/header.erb +8 -0
  157. data/templates/default/inheritance/text/header.erb +3 -0
  158. data/templates/default/method/html/aliases.erb +6 -0
  159. data/templates/default/method/html/header.erb +3 -0
  160. data/templates/default/method/html/title.erb +3 -0
  161. data/templates/default/methoddetails/html/header.erb +8 -0
  162. data/templates/default/methoddetails/html/method_header.erb +3 -0
  163. data/templates/default/methodmissing/html/header.erb +12 -0
  164. data/templates/default/methodsignature/html/main.erb +8 -0
  165. data/templates/default/methodsignature/text/main.erb +5 -0
  166. data/templates/default/methodsummary/html/header.erb +5 -0
  167. data/templates/default/methodsummary/html/included.erb +9 -0
  168. data/templates/default/methodsummary/html/inherited.erb +9 -0
  169. data/templates/default/methodsummary/html/summary.erb +25 -0
  170. data/templates/default/methodsummary/text/header.erb +5 -0
  171. data/templates/default/methodsummary/text/included.erb +0 -0
  172. data/templates/default/methodsummary/text/inherited.erb +0 -0
  173. data/templates/default/methodsummary/text/summary.erb +3 -0
  174. data/templates/default/mixins/html/header.erb +4 -0
  175. data/templates/default/module/html/header.erb +4 -0
  176. data/templates/default/quickdoc/html/header.erb +15 -0
  177. data/templates/default/quickdoc/text/header.erb +12 -0
  178. data/templates/default/source/html/main.erb +15 -0
  179. data/templates/default/source/text/main.erb +4 -0
  180. data/templates/default/tags/html/header.erb +4 -0
  181. data/templates/default/tags/html/see.erb +13 -0
  182. data/templates/default/tags/html/tags.erb +20 -0
  183. data/templates/default/tags/text/header.erb +3 -0
  184. data/templates/default/tags/text/see.erb +5 -0
  185. data/templates/default/tags/text/tags.erb +7 -0
  186. data/templates/default/uml/dot/child.erb +1 -0
  187. data/templates/default/uml/dot/dependencies.erb +10 -0
  188. data/templates/default/uml/dot/header.erb +6 -0
  189. data/templates/default/uml/dot/info.erb +14 -0
  190. data/templates/default/uml/dot/subgraph.erb +6 -0
  191. data/templates/default/uml/dot/superclasses.erb +9 -0
  192. data/templates/default/uml/dot/unknown.erb +3 -0
  193. data/templates/default/uml/dot/unknown_child.erb +1 -0
  194. data/templates/default/visibilitygroup/html/header.erb +6 -0
  195. data/templates/javadoc/attributes/html/header.erb +16 -0
  196. data/templates/javadoc/class/html/header.erb +4 -0
  197. data/templates/javadoc/constants/html/constants.erb +9 -0
  198. data/templates/javadoc/constants/html/header.erb +3 -0
  199. data/templates/javadoc/constants/html/included.erb +12 -0
  200. data/templates/javadoc/constants/html/inherited.erb +12 -0
  201. data/templates/javadoc/constructor/html/header.erb +10 -0
  202. data/templates/javadoc/deprecated/html/main.erb +0 -0
  203. data/templates/javadoc/docstring/html/main.erb +6 -0
  204. data/templates/javadoc/fulldoc/html/all_methods.erb +25 -0
  205. data/templates/javadoc/fulldoc/html/all_namespaces.erb +19 -0
  206. data/templates/javadoc/fulldoc/html/app.js +18 -0
  207. data/templates/javadoc/fulldoc/html/header.erb +15 -0
  208. data/templates/javadoc/fulldoc/html/html_head.erb +3 -0
  209. data/templates/javadoc/fulldoc/html/index.erb +18 -0
  210. data/templates/javadoc/fulldoc/html/jquery.js +11 -0
  211. data/templates/javadoc/fulldoc/html/readme.erb +15 -0
  212. data/templates/javadoc/fulldoc/html/style.css +22 -0
  213. data/templates/javadoc/fulldoc/html/syntax_highlight.css +21 -0
  214. data/templates/javadoc/inheritance/html/header.erb +6 -0
  215. data/templates/javadoc/method/html/aliases.erb +6 -0
  216. data/templates/javadoc/method/html/header.erb +4 -0
  217. data/templates/javadoc/method/html/title.erb +4 -0
  218. data/templates/javadoc/methoddetails/html/header.erb +8 -0
  219. data/templates/javadoc/methoddetails/html/method_header.erb +0 -0
  220. data/templates/javadoc/methodmissing/html/header.erb +12 -0
  221. data/templates/javadoc/methodsignature/html/main.erb +8 -0
  222. data/templates/javadoc/methodsummary/html/header.erb +5 -0
  223. data/templates/javadoc/methodsummary/html/included.erb +12 -0
  224. data/templates/javadoc/methodsummary/html/inherited.erb +12 -0
  225. data/templates/javadoc/methodsummary/html/summary.erb +25 -0
  226. data/templates/javadoc/mixins/html/header.erb +5 -0
  227. data/templates/javadoc/module/html/header.erb +4 -0
  228. data/templates/javadoc/source/html/main.erb +15 -0
  229. data/templates/javadoc/tags/html/header.erb +5 -0
  230. data/templates/javadoc/tags/html/see.erb +8 -0
  231. data/templates/javadoc/tags/html/tags.erb +19 -0
  232. data/templates/javadoc/visibilitygroup/html/header.erb +5 -0
  233. metadata +352 -50
  234. data/README.pdf +0 -0
  235. data/lib/code_object.rb +0 -337
  236. data/lib/extra.rb +0 -8
  237. data/lib/formatter.rb +0 -90
  238. data/lib/handlers/all_handlers.rb +0 -2
  239. data/lib/handlers/attribute_handler.rb +0 -51
  240. data/lib/handlers/class_handler.rb +0 -30
  241. data/lib/handlers/class_variable_handler.rb +0 -9
  242. data/lib/handlers/code_object_handler.rb +0 -104
  243. data/lib/handlers/constant_handler.rb +0 -11
  244. data/lib/handlers/exception_handler.rb +0 -20
  245. data/lib/handlers/method_handler.rb +0 -28
  246. data/lib/handlers/mixin_handler.rb +0 -15
  247. data/lib/handlers/module_handler.rb +0 -9
  248. data/lib/handlers/visibility_handler.rb +0 -7
  249. data/lib/handlers/yield_handler.rb +0 -33
  250. data/lib/logger.rb +0 -19
  251. data/lib/namespace.rb +0 -98
  252. data/lib/quick_doc.rb +0 -104
  253. data/lib/ruby_lex.rb +0 -1321
  254. data/lib/source_parser.rb +0 -253
  255. data/lib/tag_library.rb +0 -175
  256. data/lib/tag_type.rb +0 -155
  257. data/templates/default/html/_fulldoc.erb +0 -64
  258. data/templates/default/html/class.erb +0 -226
  259. data/templates/default/html/method.erb +0 -20
  260. data/templates/default/html/module.erb +0 -126
  261. data/test/fixtures/docstring.txt +0 -23
  262. data/test/fixtures/docstring2.txt +0 -4
  263. data/test/test_code_object.rb +0 -66
  264. data/test/test_namespace.rb +0 -10
@@ -0,0 +1,44 @@
1
+ class YARD::Handlers::ClassHandler < YARD::Handlers::Base
2
+ handles TkCLASS
3
+
4
+ def process
5
+ if statement.tokens.to_s =~ /^class\s+(#{NAMESPACEMATCH})\s*(?:<\s*(.+)|\Z)/m
6
+ classname = $1
7
+ superclass = parse_superclass($2)
8
+ undocsuper = $2 && superclass.nil?
9
+
10
+ klass = register ClassObject.new(namespace, classname) do |o|
11
+ o.superclass = superclass if superclass
12
+ o.superclass.type = :class if o.superclass.is_a?(Proxy)
13
+ end
14
+ parse_block(:namespace => klass)
15
+
16
+ if undocsuper
17
+ raise YARD::Handlers::UndocumentableError, 'superclass (class was added without superclass)'
18
+ end
19
+ elsif statement.tokens.to_s =~ /^class\s*<<\s*([\w\:]+)/
20
+ classname = $1
21
+ if classname == "self"
22
+ parse_block(:namespace => namespace, :scope => :class)
23
+ elsif classname[0,1] =~ /[A-Z]/
24
+ parse_block(:namespace => P(namespace, classname), :scope => :class)
25
+ else
26
+ raise YARD::Handlers::UndocumentableError, "class '#{classname}'"
27
+ end
28
+ else
29
+ raise YARD::Handlers::UndocumentableError, "class: #{statement.tokens}"
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def parse_superclass(superclass)
36
+ case superclass
37
+ when /\A(#{NAMESPACEMATCH})(?:\s|\Z)/,
38
+ /\A(Struct|OStruct)\.new/,
39
+ /\ADelegateClass\((.+?)\)\s*\Z/,
40
+ /\A(#{NAMESPACEMATCH})\(/
41
+ $1
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,13 @@
1
+ class YARD::Handlers::ClassVariableHandler < YARD::Handlers::Base
2
+ HANDLER_MATCH = /\A@@\S*\s*=\s*/m
3
+ handles HANDLER_MATCH
4
+
5
+ def process
6
+ # Don't document @@cvars if they're set in second class objects (methods) because
7
+ # they're not "static" when executed from a method
8
+ return unless owner.is_a? NamespaceObject
9
+
10
+ name, value = *statement.tokens.to_s.gsub(/\r?\n/, '').split(/\s*=\s*/, 2)
11
+ register ClassVariableObject.new(namespace, name) {|o| o.source = statement }
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class YARD::Handlers::ConstantHandler < YARD::Handlers::Base
2
+ HANDLER_MATCH = /\A[A-Z]\w*\s*=[^=]\s*/m
3
+ handles HANDLER_MATCH
4
+
5
+ def process
6
+ # Don't document CONSTANTS if they're set in second class objects (methods) because
7
+ # they're not "static" when executed from a method
8
+ return unless owner.is_a? NamespaceObject
9
+
10
+ name, value = *statement.tokens.to_s.gsub(/\r?\n/, '').split(/\s*=\s*/, 2)
11
+ register ConstantObject.new(namespace, name) {|o| o.source = statement }
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class YARD::Handlers::ExceptionHandler < YARD::Handlers::Base
2
+ handles /\Araise(\s|\()/
3
+
4
+ def process
5
+ return unless owner.is_a?(MethodObject) # Only methods yield
6
+ return if owner.has_tag? :raise
7
+
8
+ if klass = statement.tokens.to_s[/^raise[\(\s]*(#{NAMESPACEMATCH})(?:\)|,|\s|(?:\s*(?:\.|\:\:)\s*)?new|$)/, 1]
9
+ owner.tags << YARD::Tags::Tag.new(:raise, '', klass)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ class YARD::Handlers::MethodHandler < YARD::Handlers::Base
2
+ handles TkDEF
3
+
4
+ def process
5
+ nobj = namespace
6
+ mscope = scope
7
+
8
+ if meth = statement.tokens.to_s[/^def\s+(#{METHODMATCH})/m, 1]
9
+ meth.gsub!(/\s+/,'')
10
+ else
11
+ raise YARD::Handlers::UndocumentableError, "method: invalid name"
12
+ end
13
+
14
+ # Class method if prefixed by self(::|.) or Module(::|.)
15
+ if meth =~ /(?:#{NSEP}|\.)([^#{NSEP}\.]+)$/
16
+ mscope, meth = :class, $1
17
+ nobj = P(namespace, $`) unless $` == "self"
18
+ end
19
+
20
+ obj = register MethodObject.new(nobj, meth, mscope) do |o|
21
+ o.visibility = visibility
22
+ o.source = statement
23
+ o.explicit = true
24
+ end
25
+ parse_block(:owner => obj) # mainly for yield/exceptions
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ class YARD::Handlers::MixinHandler < YARD::Handlers::Base
2
+ handles /\Ainclude(\s|\()/
3
+
4
+ def process
5
+ statement.tokens[1..-1].to_s.split(/\s*,\s*/).each do |mixin|
6
+ mixin.strip!
7
+ if mixmatch = mixin[/\A(#{NAMESPACEMATCH})\s*/, 1]
8
+ obj = Proxy.new(namespace, mixmatch)
9
+ obj.type = :module if obj.is_a?(Proxy)
10
+ namespace.mixins << obj
11
+ else
12
+ raise YARD::Handlers::UndocumentableError, "mixin #{mixin} for class #{namespace.path}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ class YARD::Handlers::ModuleHandler < YARD::Handlers::Base
2
+ handles TkMODULE
3
+
4
+ def process
5
+ modname = statement.tokens.to_s[/^module\s+(#{NAMESPACEMATCH})/, 1]
6
+ mod = register ModuleObject.new(namespace, modname)
7
+ parse_block(:namespace => mod)
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ class YARD::Handlers::VisibilityHandler < YARD::Handlers::Base
2
+ handles /\A(protected|private|public)(\s|\(|$)/
3
+
4
+ def process
5
+ vis = statement.tokens.first.text
6
+ if statement.tokens.size == 1
7
+ self.visibility = vis
8
+ else
9
+ tokval_list(statement.tokens[2..-1], :attr).each do |name|
10
+ MethodObject.new(namespace, name, scope) {|o| o.visibility = vis }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ class YARD::Handlers::YieldHandler < YARD::Handlers::Base
2
+ handles TkYIELD
3
+
4
+ def process
5
+ return unless owner.is_a?(MethodObject) # Only methods yield
6
+ return if owner.has_tag? :yield # Don't override yield tags
7
+ return if owner.has_tag? :yieldparam # Same thing.
8
+
9
+ yieldtag = YARD::Tags::Tag.new(:yield, "", [])
10
+ owner.tags << yieldtag
11
+ tokval_list(statement.tokens[2..-1], Token).each do |item|
12
+ item = item.inspect unless item.is_a?(String)
13
+ if item == "self"
14
+ yieldtag.types << '_self'
15
+ owner.tags << YARD::Tags::Tag.new(:yieldparam,
16
+ "the object that the method was called on", owner.namespace.path, '_self')
17
+ elsif item == "super"
18
+ yieldtag.types << '_super'
19
+ owner.tags << YARD::Tags::Tag.new(:yieldparam,
20
+ "the result of the method from the superclass", nil, '_super')
21
+ else
22
+ yieldtag.types << item
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require "logger"
2
+
3
+ module YARD
4
+ class Logger < ::Logger
5
+ def initialize(*args)
6
+ super
7
+ self.level = INFO
8
+ end
9
+
10
+ def debug(*args)
11
+ self.level = DEBUG if $DEBUG
12
+ super
13
+ end
14
+
15
+ def enter_level(new_level = level, &block)
16
+ old_level, self.level = level, new_level
17
+ yield
18
+ self.level = old_level
19
+ end
20
+ end
21
+
22
+ def self.logger
23
+ @logger ||= YARD::Logger.new(STDERR)
24
+ end
25
+ end
26
+
27
+ def log; YARD.logger end
@@ -0,0 +1,1344 @@
1
+ require "e2mmap"
2
+ require "irb/slex"
3
+
4
+ module YARD
5
+ module Parser
6
+ module RubyToken
7
+ EXPR_BEG = :EXPR_BEG
8
+ EXPR_MID = :EXPR_MID
9
+ EXPR_END = :EXPR_END
10
+ EXPR_ARG = :EXPR_ARG
11
+ EXPR_FNAME = :EXPR_FNAME
12
+ EXPR_DOT = :EXPR_DOT
13
+ EXPR_CLASS = :EXPR_CLASS
14
+
15
+ class Token
16
+ NO_TEXT = "??".freeze
17
+ attr :text
18
+
19
+ def initialize(line_no, char_no)
20
+ @line_no = line_no
21
+ @char_no = char_no
22
+ @text = NO_TEXT
23
+ end
24
+
25
+ # Because we're used in contexts that expect to return a token,
26
+ # we set the text string and then return ourselves
27
+ def set_text(text)
28
+ @text = text
29
+ self
30
+ end
31
+
32
+ attr_reader :line_no, :char_no, :text
33
+ attr_accessor :lex_state
34
+ end
35
+
36
+ class TkNode < Token
37
+ attr :node
38
+ end
39
+
40
+ class TkWhitespace < Token
41
+ end
42
+
43
+ class TkId < Token
44
+ def initialize(line_no, char_no, name)
45
+ super(line_no, char_no)
46
+ @name = name
47
+ end
48
+ attr :name
49
+ end
50
+
51
+ class TkKW < TkId
52
+ end
53
+
54
+ class TkVal < Token
55
+ def initialize(line_no, char_no, value = nil)
56
+ super(line_no, char_no)
57
+ set_text(value)
58
+ end
59
+ end
60
+
61
+ class TkOp < Token
62
+ def name
63
+ self.class.op_name
64
+ end
65
+ end
66
+
67
+ class TkOPASGN < TkOp
68
+ def initialize(line_no, char_no, op)
69
+ super(line_no, char_no)
70
+ op = TkReading2Token[op] unless op.kind_of?(Symbol)
71
+ @op = op
72
+ end
73
+ attr :op
74
+ end
75
+
76
+ class TkUnknownChar < Token
77
+ def initialize(line_no, char_no, id)
78
+ super(line_no, char_no)
79
+ @name = char_no.chr
80
+ end
81
+ attr :name
82
+ end
83
+
84
+ class TkError < Token
85
+ end
86
+
87
+ def set_token_position(line, char)
88
+ @prev_line_no = line
89
+ @prev_char_no = char
90
+ end
91
+
92
+ def Token(token, value = nil)
93
+ tk = nil
94
+ case token
95
+ when String, Symbol
96
+ source = token.kind_of?(String) ? TkReading2Token : TkSymbol2Token
97
+ if (tk = source[token]).nil?
98
+ IRB.fail TkReading2TokenNoKey, token
99
+ end
100
+ tk = Token(tk[0], value)
101
+ else
102
+ if token
103
+ tk = if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
104
+ token.new(@prev_line_no, @prev_char_no)
105
+ else
106
+ token.new(@prev_line_no, @prev_char_no, value)
107
+ end
108
+ end
109
+ end
110
+ tk
111
+ end
112
+
113
+ TokenDefinitions = [
114
+ [:TkCLASS, TkKW, "class", EXPR_CLASS],
115
+ [:TkMODULE, TkKW, "module", EXPR_BEG],
116
+ [:TkDEF, TkKW, "def", EXPR_FNAME],
117
+ [:TkUNDEF, TkKW, "undef", EXPR_FNAME],
118
+ [:TkBEGIN, TkKW, "begin", EXPR_BEG],
119
+ [:TkRESCUE, TkKW, "rescue", EXPR_MID],
120
+ [:TkENSURE, TkKW, "ensure", EXPR_BEG],
121
+ [:TkEND, TkKW, "end", EXPR_END],
122
+ [:TkIF, TkKW, "if", EXPR_BEG, :TkIF_MOD],
123
+ [:TkUNLESS, TkKW, "unless", EXPR_BEG, :TkUNLESS_MOD],
124
+ [:TkTHEN, TkKW, "then", EXPR_BEG],
125
+ [:TkELSIF, TkKW, "elsif", EXPR_BEG],
126
+ [:TkELSE, TkKW, "else", EXPR_BEG],
127
+ [:TkCASE, TkKW, "case", EXPR_BEG],
128
+ [:TkWHEN, TkKW, "when", EXPR_BEG],
129
+ [:TkWHILE, TkKW, "while", EXPR_BEG, :TkWHILE_MOD],
130
+ [:TkUNTIL, TkKW, "until", EXPR_BEG, :TkUNTIL_MOD],
131
+ [:TkFOR, TkKW, "for", EXPR_BEG],
132
+ [:TkBREAK, TkKW, "break", EXPR_END],
133
+ [:TkNEXT, TkKW, "next", EXPR_END],
134
+ [:TkREDO, TkKW, "redo", EXPR_END],
135
+ [:TkRETRY, TkKW, "retry", EXPR_END],
136
+ [:TkIN, TkKW, "in", EXPR_BEG],
137
+ [:TkDO, TkKW, "do", EXPR_BEG],
138
+ [:TkRETURN, TkKW, "return", EXPR_MID],
139
+ [:TkYIELD, TkKW, "yield", EXPR_END],
140
+ [:TkSUPER, TkKW, "super", EXPR_END],
141
+ [:TkSELF, TkKW, "self", EXPR_END],
142
+ [:TkNIL, TkKW, "nil", EXPR_END],
143
+ [:TkTRUE, TkKW, "true", EXPR_END],
144
+ [:TkFALSE, TkKW, "false", EXPR_END],
145
+ [:TkAND, TkKW, "and", EXPR_BEG],
146
+ [:TkOR, TkKW, "or", EXPR_BEG],
147
+ [:TkNOT, TkKW, "not", EXPR_BEG],
148
+ [:TkIF_MOD, TkKW],
149
+ [:TkUNLESS_MOD, TkKW],
150
+ [:TkWHILE_MOD, TkKW],
151
+ [:TkUNTIL_MOD, TkKW],
152
+ [:TkALIAS, TkKW, "alias", EXPR_FNAME],
153
+ [:TkDEFINED, TkKW, "defined?", EXPR_END],
154
+ [:TklBEGIN, TkKW, "BEGIN", EXPR_END],
155
+ [:TklEND, TkKW, "END", EXPR_END],
156
+ [:Tk__LINE__, TkKW, "__LINE__", EXPR_END],
157
+ [:Tk__FILE__, TkKW, "__FILE__", EXPR_END],
158
+
159
+ [:TkIDENTIFIER, TkId],
160
+ [:TkFID, TkId],
161
+ [:TkGVAR, TkId],
162
+ [:TkIVAR, TkId],
163
+ [:TkCONSTANT, TkId],
164
+
165
+ [:TkINTEGER, TkVal],
166
+ [:TkFLOAT, TkVal],
167
+ [:TkSYMBOL, TkVal],
168
+ [:TkSTRING, TkVal],
169
+ [:TkXSTRING, TkVal],
170
+ [:TkREGEXP, TkVal],
171
+ [:TkCOMMENT, TkVal],
172
+
173
+ [:TkDSTRING, TkNode],
174
+ [:TkDXSTRING, TkNode],
175
+ [:TkDREGEXP, TkNode],
176
+ [:TkNTH_REF, TkId],
177
+ [:TkBACK_REF, TkId],
178
+
179
+ [:TkUPLUS, TkOp, "+@"],
180
+ [:TkUMINUS, TkOp, "-@"],
181
+ [:TkPOW, TkOp, "**"],
182
+ [:TkCMP, TkOp, "<=>"],
183
+ [:TkEQ, TkOp, "=="],
184
+ [:TkEQQ, TkOp, "==="],
185
+ [:TkNEQ, TkOp, "!="],
186
+ [:TkGEQ, TkOp, ">="],
187
+ [:TkLEQ, TkOp, "<="],
188
+ [:TkANDOP, TkOp, "&&"],
189
+ [:TkOROP, TkOp, "||"],
190
+ [:TkMATCH, TkOp, "=~"],
191
+ [:TkNMATCH, TkOp, "!~"],
192
+ [:TkDOT2, TkOp, ".."],
193
+ [:TkDOT3, TkOp, "..."],
194
+ [:TkAREF, TkOp, "[]"],
195
+ [:TkASET, TkOp, "[]="],
196
+ [:TkLSHFT, TkOp, "<<"],
197
+ [:TkRSHFT, TkOp, ">>"],
198
+ [:TkCOLON2, TkOp],
199
+ [:TkCOLON3, TkOp],
200
+ [:OPASGN, TkOp], # +=, -= etc. #
201
+ [:TkASSOC, TkOp, "=>"],
202
+ [:TkQUESTION, TkOp, "?"], #?
203
+ [:TkCOLON, TkOp, ":"], #:
204
+
205
+ # [:TkfLPAREN], # func( #
206
+ # [:TkfLBRACK], # func[ #
207
+ # [:TkfLBRACE], # func{ #
208
+ [:TkSTAR], # *arg
209
+ [:TkAMPER], # &arg #
210
+ # [:TkSYMBOL, TkId], # :SYMBOL
211
+ [:TkSYMBEG, TkId],
212
+ [:TkGT, TkOp, ">"],
213
+ [:TkLT, TkOp, "<"],
214
+ [:TkPLUS, TkOp, "+"],
215
+ [:TkMINUS, TkOp, "-"],
216
+ [:TkMULT, TkOp, "*"],
217
+ [:TkDIV, TkOp, "/"],
218
+ [:TkMOD, TkOp, "%"],
219
+ [:TkBITOR, TkOp, "|"],
220
+ [:TkBITXOR, TkOp, "^"],
221
+ [:TkBITAND, TkOp, "&"],
222
+ [:TkBITNOT, TkOp, "~"],
223
+ [:TkNOTOP, TkOp, "!"],
224
+
225
+ [:TkBACKQUOTE, TkOp, "`"],
226
+
227
+ [:TkASSIGN, Token, "="],
228
+ [:TkDOT, Token, "."],
229
+ [:TkLPAREN, Token, "("], #(exp)
230
+ [:TkLBRACK, Token, "["], #[arry]
231
+ [:TkLBRACE, Token, "{"], #{hash}
232
+ [:TkRPAREN, Token, ")"],
233
+ [:TkRBRACK, Token, "]"],
234
+ [:TkRBRACE, Token, "}"],
235
+ [:TkCOMMA, Token, ","],
236
+ [:TkSEMICOLON, Token, ";"],
237
+
238
+ # [:TkRD_COMMENT, TkVal],
239
+ [:TkSPACE, TkWhitespace],
240
+ [:TkNL, TkWhitespace],
241
+ [:TkEND_OF_SCRIPT, TkWhitespace],
242
+
243
+ [:TkBACKSLASH, TkUnknownChar, "\\"],
244
+ [:TkAT, TkUnknownChar, "@"],
245
+ [:TkDOLLAR, TkUnknownChar, "\$"], #"
246
+ ]
247
+
248
+ # {reading => token_class}
249
+ # {reading => [token_class, *opt]}
250
+ TkReading2Token = {}
251
+ TkSymbol2Token = {}
252
+
253
+ def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts)
254
+ token_n = token_n.id2name unless token_n.kind_of?(String)
255
+ if RubyToken.const_defined?(token_n)
256
+ #IRB.fail AlreadyDefinedToken, token_n
257
+ end
258
+
259
+ token_c = Class.new super_token
260
+ RubyToken.const_set token_n, token_c
261
+ # token_c.inspect
262
+
263
+ if reading
264
+ if TkReading2Token[reading]
265
+ IRB.fail TkReading2TokenDuplicateError, token_n, reading
266
+ end
267
+ if opts.empty?
268
+ TkReading2Token[reading] = [token_c]
269
+ else
270
+ TkReading2Token[reading] = [token_c].concat(opts)
271
+ end
272
+ end
273
+ TkSymbol2Token[token_n.intern] = token_c
274
+
275
+ if token_c <= TkOp
276
+ token_c.class_eval %{
277
+ def self.op_name; "#{reading}"; end
278
+ }
279
+ end
280
+ end
281
+
282
+ for defs in TokenDefinitions
283
+ def_token(*defs)
284
+ end
285
+
286
+ NEWLINE_TOKEN = TkNL.new(0,0)
287
+ NEWLINE_TOKEN.set_text("\n")
288
+
289
+ end
290
+
291
+
292
+
293
+ # Lexical analyzer for Ruby source
294
+
295
+ class RubyLex
296
+
297
+ ######################################################################
298
+ #
299
+ # Read an input stream character by character. We allow for unlimited
300
+ # ungetting of characters just read.
301
+ #
302
+ # We simplify the implementation greatly by reading the entire input
303
+ # into a buffer initially, and then simply traversing it using
304
+ # pointers.
305
+ #
306
+ # We also have to allow for the <i>here document diversion</i>. This
307
+ # little gem comes about when the lexer encounters a here
308
+ # document. At this point we effectively need to split the input
309
+ # stream into two parts: one to read the body of the here document,
310
+ # the other to read the rest of the input line where the here
311
+ # document was initially encountered. For example, we might have
312
+ #
313
+ # do_something(<<-A, <<-B)
314
+ # stuff
315
+ # for
316
+ # A
317
+ # stuff
318
+ # for
319
+ # B
320
+ #
321
+ # When the lexer encounters the <<A, it reads until the end of the
322
+ # line, and keeps it around for later. It then reads the body of the
323
+ # here document. Once complete, it needs to read the rest of the
324
+ # original line, but then skip the here document body.
325
+ #
326
+
327
+ class BufferedReader
328
+
329
+ attr_reader :line_num
330
+
331
+ def initialize(content)
332
+ if /\t/ =~ content
333
+ tab_width = 2
334
+ content = content.split(/\n/).map do |line|
335
+ 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)} && $~ #`
336
+ line
337
+ end .join("\n")
338
+ end
339
+ @content = content
340
+ @content << "\n" unless @content[-1,1] == "\n"
341
+ @size = @content.size
342
+ @offset = 0
343
+ @hwm = 0
344
+ @line_num = 1
345
+ @read_back_offset = 0
346
+ @last_newline = 0
347
+ @newline_pending = false
348
+ end
349
+
350
+ def column
351
+ @offset - @last_newline
352
+ end
353
+
354
+ def getc
355
+ return nil if @offset >= @size
356
+ ch = @content[@offset, 1]
357
+
358
+ @offset += 1
359
+ @hwm = @offset if @hwm < @offset
360
+
361
+ if @newline_pending
362
+ @line_num += 1
363
+ @last_newline = @offset - 1
364
+ @newline_pending = false
365
+ end
366
+
367
+ if ch == "\n"
368
+ @newline_pending = true
369
+ end
370
+ ch
371
+ end
372
+
373
+ def getc_already_read
374
+ getc
375
+ end
376
+
377
+ def ungetc(ch)
378
+ raise "unget past beginning of file" if @offset <= 0
379
+ @offset -= 1
380
+ if @content[@offset] == ?\n
381
+ @newline_pending = false
382
+ end
383
+ end
384
+
385
+ def get_read
386
+ res = @content[@read_back_offset...@offset]
387
+ @read_back_offset = @offset
388
+ res
389
+ end
390
+
391
+ def peek(at)
392
+ pos = @offset + at
393
+ if pos >= @size
394
+ nil
395
+ else
396
+ @content[pos, 1]
397
+ end
398
+ end
399
+
400
+ def peek_equal(str)
401
+ @content[@offset, str.length] == str
402
+ end
403
+
404
+ def divert_read_from(reserve)
405
+ @content[@offset, 0] = reserve
406
+ @size = @content.size
407
+ end
408
+ end
409
+
410
+ # end of nested class BufferedReader
411
+
412
+ extend Exception2MessageMapper
413
+ def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
414
+ def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
415
+ def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
416
+ def_exception(:TkReading2TokenDuplicateError,
417
+ "key duplicate(token_n='%s', key='%s')")
418
+ def_exception(:SyntaxError, "%s")
419
+
420
+ include RubyToken
421
+ include IRB
422
+
423
+ attr_reader :continue
424
+ attr_reader :lex_state
425
+
426
+ def RubyLex.debug?
427
+ false
428
+ end
429
+
430
+ def initialize(content)
431
+ lex_init
432
+
433
+ @reader = BufferedReader.new(content)
434
+
435
+ @exp_line_no = @line_no = 1
436
+ @base_char_no = 0
437
+ @indent = 0
438
+
439
+ @ltype = nil
440
+ @quoted = nil
441
+ @lex_state = EXPR_BEG
442
+ @space_seen = false
443
+
444
+ @continue = false
445
+ @line = ""
446
+
447
+ @skip_space = false
448
+ @read_auto_clean_up = false
449
+ @exception_on_syntax_error = true
450
+ end
451
+
452
+ attr :skip_space, true
453
+ attr :read_auto_clean_up, true
454
+ attr :exception_on_syntax_error, true
455
+
456
+ attr :indent
457
+
458
+ # io functions
459
+ def line_no
460
+ @reader.line_num
461
+ end
462
+
463
+ def char_no
464
+ @reader.column
465
+ end
466
+
467
+ def get_read
468
+ @reader.get_read
469
+ end
470
+
471
+ def getc
472
+ @reader.getc
473
+ end
474
+
475
+ def getc_of_rests
476
+ @reader.getc_already_read
477
+ end
478
+
479
+ def gets
480
+ c = getc or return
481
+ l = ""
482
+ begin
483
+ l.concat c unless c == "\r"
484
+ break if c == "\n"
485
+ end while c = getc
486
+ l
487
+ end
488
+
489
+
490
+ def ungetc(c = nil)
491
+ @reader.ungetc(c)
492
+ end
493
+
494
+ def peek_equal?(str)
495
+ @reader.peek_equal(str)
496
+ end
497
+
498
+ def peek(i = 0)
499
+ @reader.peek(i)
500
+ end
501
+
502
+ def lex
503
+ catch(:eof) do
504
+ until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) &&
505
+ !@continue or
506
+ tk.nil?)
507
+ end
508
+ line = get_read
509
+
510
+ if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil?
511
+ nil
512
+ else
513
+ line
514
+ end
515
+ end
516
+ end
517
+
518
+ def token
519
+ set_token_position(line_no, char_no)
520
+ catch(:eof) do
521
+ begin
522
+ begin
523
+ tk = @OP.match(self)
524
+ @space_seen = tk.kind_of?(TkSPACE)
525
+ rescue SyntaxError
526
+ abort if @exception_on_syntax_error
527
+ tk = TkError.new(line_no, char_no)
528
+ end
529
+ end while @skip_space and tk.kind_of?(TkSPACE)
530
+ if @read_auto_clean_up
531
+ get_read
532
+ end
533
+ # throw :eof unless tk
534
+ p tk if $DEBUG
535
+ tk.lex_state = lex_state if tk
536
+ tk
537
+ end
538
+ end
539
+
540
+ ENINDENT_CLAUSE = [
541
+ "case", "class", "def", "do", "for", "if",
542
+ "module", "unless", "until", "while", "begin" #, "when"
543
+ ]
544
+ ACCEPTS_COLON = ["if", "for", "unless", "until", "while"]
545
+ DEINDENT_CLAUSE = ["end" #, "when"
546
+ ]
547
+
548
+ PERCENT_LTYPE = {
549
+ "q" => "\'",
550
+ "Q" => "\"",
551
+ "x" => "\`",
552
+ "r" => "/",
553
+ "w" => "]",
554
+ "W" => "]"
555
+ }
556
+
557
+ PERCENT_PAREN = {
558
+ "{" => "}",
559
+ "[" => "]",
560
+ "<" => ">",
561
+ "(" => ")"
562
+ }
563
+
564
+ Ltype2Token = {
565
+ "\'" => TkSTRING,
566
+ "\"" => TkSTRING,
567
+ "\`" => TkXSTRING,
568
+ "/" => TkREGEXP,
569
+ "]" => TkDSTRING
570
+ }
571
+ Ltype2Token.default = TkSTRING
572
+
573
+ DLtype2Token = {
574
+ "\"" => TkDSTRING,
575
+ "\`" => TkDXSTRING,
576
+ "/" => TkDREGEXP,
577
+ }
578
+
579
+ def lex_init()
580
+ @OP = SLex.new
581
+ @OP.def_rules("\0", "\004", "\032") do |chars, io|
582
+ Token(TkEND_OF_SCRIPT).set_text(chars)
583
+ end
584
+
585
+ @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |chars, io|
586
+ @space_seen = TRUE
587
+ while (ch = getc) =~ /[ \t\f\r\13]/
588
+ chars << ch
589
+ end
590
+ ungetc
591
+ Token(TkSPACE).set_text(chars)
592
+ end
593
+
594
+ @OP.def_rule("#") do
595
+ |op, io|
596
+ identify_comment
597
+ end
598
+
599
+ @OP.def_rule("=begin", proc{@prev_char_no == 0 && peek(0) =~ /\s/}) do
600
+ |op, io|
601
+ str = op
602
+ @ltype = "="
603
+
604
+
605
+ begin
606
+ line = ""
607
+ begin
608
+ ch = getc
609
+ line << ch
610
+ end until ch == "\n"
611
+ str << line
612
+ end until line =~ /^=end/
613
+
614
+ ungetc
615
+
616
+ @ltype = nil
617
+
618
+ if str =~ /\A=begin\s+rdoc/i
619
+ str.sub!(/\A=begin.*\n/, '')
620
+ str.sub!(/^=end.*/m, '')
621
+ Token(TkCOMMENT).set_text(str)
622
+ else
623
+ Token(TkCOMMENT).set_text(str)
624
+ end
625
+ end
626
+
627
+ @OP.def_rule("\n") do
628
+ print "\\n\n" if RubyLex.debug?
629
+ @colonblock_seen = false
630
+ case @lex_state
631
+ when EXPR_BEG, EXPR_FNAME, EXPR_DOT
632
+ @continue = TRUE
633
+ else
634
+ @continue = FALSE
635
+ @lex_state = EXPR_BEG
636
+ end
637
+ Token(TkNL).set_text("\n")
638
+ end
639
+
640
+ @OP.def_rules("*", "**",
641
+ "!", "!=", "!~",
642
+ "=", "==", "===",
643
+ "=~", "<=>",
644
+ "<", "<=",
645
+ ">", ">=", ">>") do |op, io|
646
+ @lex_state = EXPR_BEG
647
+ Token(op).set_text(op)
648
+ end
649
+
650
+ @OP.def_rules("<<") do |op, io|
651
+ tk = nil
652
+ if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
653
+ (@lex_state != EXPR_ARG || @space_seen)
654
+ c = peek(0)
655
+ tk = identify_here_document if /[-\w_\"\'\`]/ =~ c
656
+ end
657
+ if !tk
658
+ @lex_state = EXPR_BEG
659
+ tk = Token(op).set_text(op)
660
+ end
661
+ tk
662
+ end
663
+
664
+ @OP.def_rules("'", '"') do |op, io|
665
+ identify_string(op)
666
+ end
667
+
668
+ @OP.def_rules("`") do |op, io|
669
+ if @lex_state == EXPR_FNAME
670
+ Token(op).set_text(op)
671
+ else
672
+ identify_string(op)
673
+ end
674
+ end
675
+
676
+ @OP.def_rules('?') do |op, io|
677
+ if @lex_state == EXPR_END
678
+ @lex_state = EXPR_BEG
679
+ Token(TkQUESTION).set_text(op)
680
+ else
681
+ ch = getc
682
+ if @lex_state == EXPR_ARG && ch !~ /\s/
683
+ ungetc
684
+ @lex_state = EXPR_BEG
685
+ Token(TkQUESTION).set_text(op)
686
+ else
687
+ str = op
688
+ str << ch
689
+ if (ch == '\\') #'
690
+ str << read_escape
691
+ end
692
+ @lex_state = EXPR_END
693
+ Token(TkINTEGER).set_text(str)
694
+ end
695
+ end
696
+ end
697
+
698
+ @OP.def_rules("&", "&&", "|", "||") do |op, io|
699
+ @lex_state = EXPR_BEG
700
+ Token(op).set_text(op)
701
+ end
702
+
703
+ @OP.def_rules("+=", "-=", "*=", "**=",
704
+ "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, io|
705
+ @lex_state = EXPR_BEG
706
+ op =~ /^(.*)=$/
707
+ Token(TkOPASGN, $1).set_text(op)
708
+ end
709
+
710
+ @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) do |op, io|
711
+ Token(TkUPLUS).set_text(op)
712
+ end
713
+
714
+ @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) do |op, io|
715
+ Token(TkUMINUS).set_text(op)
716
+ end
717
+
718
+ @OP.def_rules("+", "-") do |op, io|
719
+ catch(:RET) do
720
+ if @lex_state == EXPR_ARG
721
+ if @space_seen and peek(0) =~ /[0-9]/
722
+ throw :RET, identify_number(op)
723
+ else
724
+ @lex_state = EXPR_BEG
725
+ end
726
+ elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
727
+ throw :RET, identify_number(op)
728
+ else
729
+ @lex_state = EXPR_BEG
730
+ end
731
+ Token(op).set_text(op)
732
+ end
733
+ end
734
+
735
+ @OP.def_rule(".") do
736
+ @lex_state = EXPR_BEG
737
+ if peek(0) =~ /[0-9]/
738
+ ungetc
739
+ identify_number("")
740
+ else
741
+ # for obj.if
742
+ @lex_state = EXPR_DOT
743
+ Token(TkDOT).set_text(".")
744
+ end
745
+ end
746
+
747
+ @OP.def_rules("..", "...") do |op, io|
748
+ @lex_state = EXPR_BEG
749
+ Token(op).set_text(op)
750
+ end
751
+
752
+ lex_int2
753
+ end
754
+
755
+ def lex_int2
756
+ @OP.def_rules("]", "}", ")") do
757
+ |op, io|
758
+ @lex_state = EXPR_END
759
+ @indent -= 1
760
+ Token(op).set_text(op)
761
+ end
762
+
763
+ @OP.def_rule(":") do
764
+ if @colonblock_seen || peek(0) =~ /\s/
765
+ @lex_state = EXPR_BEG
766
+ tk = Token(TkCOLON)
767
+ else
768
+ @lex_state = EXPR_FNAME
769
+ tk = Token(TkSYMBEG)
770
+ end
771
+ tk.set_text(":")
772
+ end
773
+
774
+ @OP.def_rule("::") do
775
+ # p @lex_state.id2name, @space_seen
776
+ if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
777
+ @lex_state = EXPR_BEG
778
+ tk = Token(TkCOLON3)
779
+ else
780
+ @lex_state = EXPR_DOT
781
+ tk = Token(TkCOLON2)
782
+ end
783
+ tk.set_text("::")
784
+ end
785
+
786
+ @OP.def_rule("/") do |op, io|
787
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
788
+ identify_string(op)
789
+ elsif peek(0) == '='
790
+ getc
791
+ @lex_state = EXPR_BEG
792
+ Token(TkOPASGN, :/).set_text("/=") #")
793
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
794
+ identify_string(op)
795
+ else
796
+ @lex_state = EXPR_BEG
797
+ Token("/").set_text(op)
798
+ end
799
+ end
800
+
801
+ @OP.def_rules("^") do
802
+ @lex_state = EXPR_BEG
803
+ Token("^").set_text("^")
804
+ end
805
+
806
+ # @OP.def_rules("^=") do
807
+ # @lex_state = EXPR_BEG
808
+ # Token(TkOPASGN, :^)
809
+ # end
810
+
811
+ @OP.def_rules(",", ";") do |op, io|
812
+ @colonblock_seen = false
813
+ @lex_state = EXPR_BEG
814
+ Token(op).set_text(op)
815
+ end
816
+
817
+ @OP.def_rule("~") do
818
+ @lex_state = EXPR_BEG
819
+ Token("~").set_text("~")
820
+ end
821
+
822
+ @OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) do
823
+ @lex_state = EXPR_BEG
824
+ Token("~").set_text("~@")
825
+ end
826
+
827
+ @OP.def_rule("(") do
828
+ @indent += 1
829
+ #if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
830
+ # @lex_state = EXPR_BEG
831
+ # tk = Token(TkfLPAREN)
832
+ #else
833
+ @lex_state = EXPR_BEG
834
+ tk = Token(TkLPAREN)
835
+ #end
836
+ tk.set_text("(")
837
+ end
838
+
839
+ @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) do
840
+ Token("[]").set_text("[]")
841
+ end
842
+
843
+ @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) do
844
+ Token("[]=").set_text("[]=")
845
+ end
846
+
847
+ @OP.def_rule("[") do
848
+ @indent += 1
849
+ # if @lex_state == EXPR_FNAME
850
+ # t = Token(TkfLBRACK)
851
+ # else
852
+ # if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
853
+ # t = Token(TkLBRACK)
854
+ # elsif @lex_state == EXPR_ARG && @space_seen
855
+ # else
856
+ # t = Token(TkfLBRACK)
857
+ # end
858
+ # end
859
+ t = Token(TkLBRACK)
860
+ @lex_state = EXPR_BEG
861
+ t.set_text("[")
862
+ end
863
+
864
+ @OP.def_rule("{") do
865
+ @indent += 1
866
+ #if @lex_state != EXPR_END && @lex_state != EXPR_ARG
867
+ # t = Token(TkLBRACE)
868
+ #else
869
+ # t = Token(TkfLBRACE)
870
+ #end
871
+ t = Token(TkLBRACE)
872
+ @lex_state = EXPR_BEG
873
+ t.set_text("{")
874
+ end
875
+
876
+ @OP.def_rule('\\') do #'
877
+ if getc == "\n"
878
+ @space_seen = true
879
+ @continue = true
880
+ Token(TkSPACE).set_text("\\\n")
881
+ else
882
+ ungetc
883
+ Token("\\").set_text("\\") #"
884
+ end
885
+ end
886
+
887
+ @OP.def_rule('%') do
888
+ |op, io|
889
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
890
+ identify_quotation('%')
891
+ elsif peek(0) == '='
892
+ getc
893
+ Token(TkOPASGN, "%").set_text("%=")
894
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
895
+ identify_quotation('%')
896
+ else
897
+ @lex_state = EXPR_BEG
898
+ Token("%").set_text("%")
899
+ end
900
+ end
901
+
902
+ @OP.def_rule('$') do #'
903
+ identify_gvar
904
+ end
905
+
906
+ @OP.def_rule('@') do
907
+ if peek(0) =~ /[@\w_]/
908
+ ungetc
909
+ identify_identifier
910
+ else
911
+ Token("@").set_text("@")
912
+ end
913
+ end
914
+
915
+ # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
916
+ # |op, io|
917
+ # @indent += 1
918
+ # @lex_state = EXPR_FNAME
919
+ # # @lex_state = EXPR_END
920
+ # # until @rests[0] == "\n" or @rests[0] == ";"
921
+ # # rests.shift
922
+ # # end
923
+ # end
924
+
925
+ @OP.def_rule("__END__", proc{@prev_char_no == 0 && peek(0) =~ /[\r\n]/}) do
926
+ throw :eof
927
+ end
928
+
929
+ @OP.def_rule("") do
930
+ |op, io|
931
+ printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
932
+ if peek(0) =~ /[0-9]/
933
+ t = identify_number("")
934
+ elsif peek(0) =~ /[\w_]/
935
+ t = identify_identifier
936
+ end
937
+ printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
938
+ t
939
+ end
940
+
941
+ p @OP if RubyLex.debug?
942
+ end
943
+
944
+ def identify_gvar
945
+ @lex_state = EXPR_END
946
+ str = "$"
947
+
948
+ tk = case ch = getc
949
+ when /[~_*$?!@\/\\;,=:<>".]/ #"
950
+ str << ch
951
+ Token(TkGVAR, str)
952
+
953
+ when "-"
954
+ str << "-" << getc
955
+ Token(TkGVAR, str)
956
+
957
+ when "&", "`", "'", "+"
958
+ str << ch
959
+ Token(TkBACK_REF, str)
960
+
961
+ when /[1-9]/
962
+ str << ch
963
+ while (ch = getc) =~ /[0-9]/
964
+ str << ch
965
+ end
966
+ ungetc
967
+ Token(TkNTH_REF)
968
+ when /\w/
969
+ ungetc
970
+ ungetc
971
+ return identify_identifier
972
+ else
973
+ ungetc
974
+ Token("$")
975
+ end
976
+ tk.set_text(str)
977
+ end
978
+
979
+ def identify_identifier
980
+ token = ""
981
+ token.concat getc if peek(0) =~ /[$@]/
982
+ token.concat getc if peek(0) == "@"
983
+
984
+ while (ch = getc) =~ /\w|_/
985
+ print ":", ch, ":" if RubyLex.debug?
986
+ token.concat ch
987
+ end
988
+ ungetc
989
+
990
+ if ch == "!" or ch == "?"
991
+ token.concat getc
992
+ end
993
+ # fix token
994
+
995
+ # $stderr.puts "identifier - #{token}, state = #@lex_state"
996
+
997
+ case token
998
+ when /^\$/
999
+ return Token(TkGVAR, token).set_text(token)
1000
+ when /^\@/
1001
+ @lex_state = EXPR_END
1002
+ return Token(TkIVAR, token).set_text(token)
1003
+ end
1004
+
1005
+ if @lex_state != EXPR_DOT
1006
+ print token, "\n" if RubyLex.debug?
1007
+
1008
+ token_c, *trans = TkReading2Token[token]
1009
+ if token_c
1010
+ # reserved word?
1011
+
1012
+ if (@lex_state != EXPR_BEG &&
1013
+ @lex_state != EXPR_FNAME &&
1014
+ trans[1])
1015
+ # modifiers
1016
+ token_c = TkSymbol2Token[trans[1]]
1017
+ @lex_state = trans[0]
1018
+ else
1019
+ if @lex_state != EXPR_FNAME
1020
+ if ENINDENT_CLAUSE.include?(token)
1021
+ @indent += 1
1022
+
1023
+ if ACCEPTS_COLON.include?(token)
1024
+ @colonblock_seen = true
1025
+ else
1026
+ @colonblock_seen = false
1027
+ end
1028
+ elsif DEINDENT_CLAUSE.include?(token)
1029
+ @indent -= 1
1030
+ @colonblock_seen = false
1031
+ end
1032
+ @lex_state = trans[0]
1033
+ else
1034
+ @lex_state = EXPR_END
1035
+ end
1036
+ end
1037
+ return Token(token_c, token).set_text(token)
1038
+ end
1039
+ end
1040
+
1041
+ if @lex_state == EXPR_FNAME
1042
+ @lex_state = EXPR_END
1043
+ if peek(0) == '='
1044
+ token.concat getc
1045
+ end
1046
+ elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
1047
+ @lex_state = EXPR_ARG
1048
+ else
1049
+ @lex_state = EXPR_END
1050
+ end
1051
+
1052
+ if token[0, 1] =~ /[A-Z]/
1053
+ return Token(TkCONSTANT, token).set_text(token)
1054
+ elsif token[token.size - 1, 1] =~ /[!?]/
1055
+ return Token(TkFID, token).set_text(token)
1056
+ else
1057
+ return Token(TkIDENTIFIER, token).set_text(token)
1058
+ end
1059
+ end
1060
+
1061
+ def identify_here_document
1062
+ ch = getc
1063
+ if ch == "-"
1064
+ ch = getc
1065
+ indent = true
1066
+ end
1067
+ if /['"`]/ =~ ch # '
1068
+ lt = ch
1069
+ quoted = ""
1070
+ while (c = getc) && c != lt
1071
+ quoted.concat c
1072
+ end
1073
+ else
1074
+ lt = '"'
1075
+ quoted = ch.dup
1076
+ while (c = getc) && c =~ /\w/
1077
+ quoted.concat c
1078
+ end
1079
+ ungetc
1080
+ end
1081
+
1082
+ ltback, @ltype = @ltype, lt
1083
+ reserve = ""
1084
+
1085
+ while ch = getc
1086
+ reserve << ch
1087
+ if ch == "\\" #"
1088
+ ch = getc
1089
+ reserve << ch
1090
+ elsif ch == "\n"
1091
+ break
1092
+ end
1093
+ end
1094
+
1095
+ str = ""
1096
+ while (l = gets)
1097
+ l.chomp!
1098
+ l.strip! if indent
1099
+ break if l == quoted
1100
+ str << l.chomp << "\n"
1101
+ end
1102
+
1103
+ @reader.divert_read_from(reserve)
1104
+
1105
+ @ltype = ltback
1106
+ @lex_state = EXPR_END
1107
+ Token(Ltype2Token[lt], str).set_text(str.dump)
1108
+ end
1109
+
1110
+ def identify_quotation(initial_char)
1111
+ ch = getc
1112
+ if lt = PERCENT_LTYPE[ch]
1113
+ initial_char += ch
1114
+ ch = getc
1115
+ elsif ch =~ /\W/
1116
+ lt = "\""
1117
+ else
1118
+ # RubyLex.fail SyntaxError, "unknown type of %string ('#{ch}')"
1119
+ end
1120
+ # if ch !~ /\W/
1121
+ # ungetc
1122
+ # next
1123
+ # end
1124
+ #@ltype = lt
1125
+ @quoted = ch unless @quoted = PERCENT_PAREN[ch]
1126
+ identify_string(lt, @quoted, ch, initial_char) if lt
1127
+ end
1128
+
1129
+ def identify_number(start)
1130
+ str = start.dup
1131
+
1132
+ if start == "+" or start == "-" or start == ""
1133
+ start = getc
1134
+ str << start
1135
+ end
1136
+
1137
+ @lex_state = EXPR_END
1138
+
1139
+ if start == "0"
1140
+ if peek(0) == "x"
1141
+ ch = getc
1142
+ str << ch
1143
+ match = /[0-9a-f_]/
1144
+ else
1145
+ match = /[0-7_]/
1146
+ end
1147
+ while ch = getc
1148
+ if ch !~ match
1149
+ ungetc
1150
+ break
1151
+ else
1152
+ str << ch
1153
+ end
1154
+ end
1155
+ return Token(TkINTEGER).set_text(str)
1156
+ end
1157
+
1158
+ type = TkINTEGER
1159
+ allow_point = TRUE
1160
+ allow_e = TRUE
1161
+ while ch = getc
1162
+ case ch
1163
+ when /[0-9_]/
1164
+ str << ch
1165
+
1166
+ when allow_point && "."
1167
+ type = TkFLOAT
1168
+ if peek(0) !~ /[0-9]/
1169
+ ungetc
1170
+ break
1171
+ end
1172
+ str << ch
1173
+ allow_point = false
1174
+
1175
+ when allow_e && "e", allow_e && "E"
1176
+ str << ch
1177
+ type = TkFLOAT
1178
+ if peek(0) =~ /[+-]/
1179
+ str << getc
1180
+ end
1181
+ allow_e = false
1182
+ allow_point = false
1183
+ else
1184
+ ungetc
1185
+ break
1186
+ end
1187
+ end
1188
+ Token(type).set_text(str)
1189
+ end
1190
+
1191
+ def identify_string(ltype, quoted = ltype, opener=nil, initial_char = nil)
1192
+ @ltype = ltype
1193
+ @quoted = quoted
1194
+ subtype = nil
1195
+
1196
+ str = ""
1197
+ str << initial_char if initial_char
1198
+ str << (opener||quoted)
1199
+
1200
+ nest = 0
1201
+ begin
1202
+ while ch = getc
1203
+ str << ch
1204
+ if @quoted == ch
1205
+ if nest == 0
1206
+ break
1207
+ else
1208
+ nest -= 1
1209
+ end
1210
+ elsif opener == ch
1211
+ nest += 1
1212
+ elsif @ltype != "'" && @ltype != "]" and ch == "#"
1213
+ ch = getc
1214
+ if ch == "{"
1215
+ subtype = true
1216
+ str << ch << skip_inner_expression
1217
+ else
1218
+ ungetc(ch)
1219
+ end
1220
+ elsif ch == '\\' #'
1221
+ str << read_escape
1222
+ end
1223
+ end
1224
+ if @ltype == "/"
1225
+ if peek(0) =~ /i|o|n|e|s/
1226
+ str << getc
1227
+ end
1228
+ end
1229
+ if subtype
1230
+ Token(DLtype2Token[ltype], str)
1231
+ else
1232
+ Token(Ltype2Token[ltype], str)
1233
+ end.set_text(str)
1234
+ ensure
1235
+ @ltype = nil
1236
+ @quoted = nil
1237
+ @lex_state = EXPR_END
1238
+ end
1239
+ end
1240
+
1241
+ def skip_inner_expression
1242
+ res = ""
1243
+ nest = 0
1244
+ while (ch = getc)
1245
+ res << ch
1246
+ if ch == '}'
1247
+ break if nest.zero?
1248
+ nest -= 1
1249
+ elsif ch == '{'
1250
+ nest += 1
1251
+ end
1252
+ end
1253
+ res
1254
+ end
1255
+
1256
+ def identify_comment
1257
+ @ltype = "#"
1258
+ comment = "#"
1259
+ while ch = getc
1260
+ if ch == "\\"
1261
+ ch = getc
1262
+ if ch == "\n"
1263
+ ch = " "
1264
+ else
1265
+ comment << "\\"
1266
+ end
1267
+ else
1268
+ if ch == "\n"
1269
+ @ltype = nil
1270
+ ungetc
1271
+ break
1272
+ end
1273
+ end
1274
+ comment << ch
1275
+ end
1276
+ return Token(TkCOMMENT).set_text(comment)
1277
+ end
1278
+
1279
+ def read_escape
1280
+ res = ""
1281
+ case ch = getc
1282
+ when /[0-7]/
1283
+ ungetc ch
1284
+ 3.times do
1285
+ case ch = getc
1286
+ when /[0-7]/
1287
+ when nil
1288
+ break
1289
+ else
1290
+ ungetc
1291
+ break
1292
+ end
1293
+ res << ch
1294
+ end
1295
+
1296
+ when "x"
1297
+ res << ch
1298
+ 2.times do
1299
+ case ch = getc
1300
+ when /[0-9a-fA-F]/
1301
+ when nil
1302
+ break
1303
+ else
1304
+ ungetc
1305
+ break
1306
+ end
1307
+ res << ch
1308
+ end
1309
+
1310
+ when "M"
1311
+ res << ch
1312
+ if (ch = getc) != '-'
1313
+ ungetc
1314
+ else
1315
+ res << ch
1316
+ if (ch = getc) == "\\" #"
1317
+ res << ch
1318
+ res << read_escape
1319
+ else
1320
+ res << ch
1321
+ end
1322
+ end
1323
+
1324
+ when "C", "c" #, "^"
1325
+ res << ch
1326
+ if ch == "C" and (ch = getc) != "-"
1327
+ ungetc
1328
+ else
1329
+ res << ch
1330
+ if (ch = getc) == "\\" #"
1331
+ res << ch
1332
+ res << read_escape
1333
+ else
1334
+ res << ch
1335
+ end
1336
+ end
1337
+ else
1338
+ res << ch
1339
+ end
1340
+ res
1341
+ end
1342
+ end
1343
+ end
1344
+ end