yard 0.9.18 → 0.9.23

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 (590) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +2 -0
  3. data/.github/ISSUE_TEMPLATE.md +33 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
  5. data/.gitignore +14 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +99 -0
  8. data/.travis.yml +52 -0
  9. data/.yardopts +26 -26
  10. data/.yardopts_guide +19 -0
  11. data/.yardopts_i18n +23 -0
  12. data/CHANGELOG.md +781 -728
  13. data/CODE_OF_CONDUCT.md +15 -0
  14. data/CONTRIBUTING.md +140 -0
  15. data/Dockerfile.samus +28 -0
  16. data/Gemfile +32 -0
  17. data/LEGAL +66 -66
  18. data/LICENSE +22 -22
  19. data/README.md +330 -328
  20. data/Rakefile +37 -53
  21. data/SECURITY.md +26 -0
  22. data/benchmarks/builtins_vs_eval.rb +24 -24
  23. data/benchmarks/concat_vs_join.rb +13 -13
  24. data/benchmarks/erb_vs_erubis.rb +54 -54
  25. data/benchmarks/format_args.rb +47 -47
  26. data/benchmarks/generation.rb +38 -38
  27. data/benchmarks/marshal_vs_dbm.rb +64 -64
  28. data/benchmarks/parsing.rb +46 -46
  29. data/benchmarks/pathname_vs_string.rb +50 -50
  30. data/benchmarks/rdoc_vs_yardoc.rb +11 -11
  31. data/benchmarks/registry_store_types.rb +49 -49
  32. data/benchmarks/ri_vs_yri.rb +19 -19
  33. data/benchmarks/ripper_parser.rb +13 -13
  34. data/benchmarks/splat_vs_flatten.rb +13 -13
  35. data/benchmarks/template_erb.rb +23 -23
  36. data/benchmarks/template_format.rb +7 -7
  37. data/benchmarks/template_profile.rb +18 -18
  38. data/benchmarks/yri_cache.rb +20 -20
  39. data/bin/yard +13 -13
  40. data/bin/yardoc +13 -13
  41. data/bin/yri +13 -13
  42. data/docs/CodeObjects.md +115 -115
  43. data/docs/GettingStarted.md +679 -679
  44. data/docs/Handlers.md +152 -152
  45. data/docs/Overview.md +61 -61
  46. data/docs/Parser.md +191 -191
  47. data/docs/Tags.md +283 -283
  48. data/docs/TagsArch.md +123 -123
  49. data/docs/Templates.md +496 -496
  50. data/docs/WhatsNew.md +1245 -1245
  51. data/docs/templates/default/fulldoc/html/full_list_tag.erb +8 -8
  52. data/docs/templates/default/fulldoc/html/setup.rb +6 -6
  53. data/docs/templates/default/layout/html/setup.rb +9 -9
  54. data/docs/templates/default/layout/html/tag_list.erb +11 -11
  55. data/docs/templates/default/yard_tags/html/list.erb +18 -18
  56. data/docs/templates/default/yard_tags/html/setup.rb +26 -26
  57. data/docs/templates/plugin.rb +70 -70
  58. data/lib/rubygems_plugin.rb +9 -9
  59. data/lib/yard.rb +69 -69
  60. data/lib/yard/autoload.rb +308 -303
  61. data/lib/yard/cli/command.rb +85 -85
  62. data/lib/yard/cli/command_parser.rb +93 -93
  63. data/lib/yard/cli/config.rb +198 -198
  64. data/lib/yard/cli/diff.rb +270 -270
  65. data/lib/yard/cli/display.rb +69 -69
  66. data/lib/yard/cli/gems.rb +84 -84
  67. data/lib/yard/cli/graph.rb +125 -125
  68. data/lib/yard/cli/help.rb +20 -20
  69. data/lib/yard/cli/i18n.rb +70 -70
  70. data/lib/yard/cli/list.rb +23 -23
  71. data/lib/yard/cli/markup_types.rb +32 -32
  72. data/lib/yard/cli/server.rb +257 -257
  73. data/lib/yard/cli/stats.rb +231 -231
  74. data/lib/yard/cli/yardoc.rb +789 -788
  75. data/lib/yard/cli/yardopts_command.rb +110 -110
  76. data/lib/yard/cli/yri.rb +215 -215
  77. data/lib/yard/code_objects/base.rb +622 -615
  78. data/lib/yard/code_objects/class_object.rb +146 -146
  79. data/lib/yard/code_objects/class_variable_object.rb +11 -11
  80. data/lib/yard/code_objects/constant_object.rb +16 -16
  81. data/lib/yard/code_objects/extended_method_object.rb +24 -24
  82. data/lib/yard/code_objects/extra_file_object.rb +134 -131
  83. data/lib/yard/code_objects/macro_object.rb +172 -172
  84. data/lib/yard/code_objects/method_object.rb +196 -196
  85. data/lib/yard/code_objects/module_object.rb +21 -21
  86. data/lib/yard/code_objects/namespace_mapper.rb +114 -114
  87. data/lib/yard/code_objects/namespace_object.rb +200 -200
  88. data/lib/yard/code_objects/proxy.rb +244 -240
  89. data/lib/yard/code_objects/root_object.rb +19 -19
  90. data/lib/yard/config.rb +270 -270
  91. data/lib/yard/core_ext/array.rb +16 -16
  92. data/lib/yard/core_ext/file.rb +69 -69
  93. data/lib/yard/core_ext/hash.rb +16 -16
  94. data/lib/yard/core_ext/insertion.rb +63 -63
  95. data/lib/yard/core_ext/module.rb +11 -20
  96. data/lib/yard/core_ext/string.rb +68 -68
  97. data/lib/yard/core_ext/symbol_hash.rb +75 -75
  98. data/lib/yard/docstring.rb +386 -386
  99. data/lib/yard/docstring_parser.rb +345 -345
  100. data/lib/yard/gem_index.rb +29 -29
  101. data/lib/yard/globals.rb +22 -22
  102. data/lib/yard/handlers/base.rb +595 -595
  103. data/lib/yard/handlers/c/alias_handler.rb +16 -16
  104. data/lib/yard/handlers/c/attribute_handler.rb +13 -13
  105. data/lib/yard/handlers/c/base.rb +129 -129
  106. data/lib/yard/handlers/c/class_handler.rb +27 -27
  107. data/lib/yard/handlers/c/constant_handler.rb +13 -13
  108. data/lib/yard/handlers/c/handler_methods.rb +212 -211
  109. data/lib/yard/handlers/c/init_handler.rb +20 -20
  110. data/lib/yard/handlers/c/method_handler.rb +45 -45
  111. data/lib/yard/handlers/c/mixin_handler.rb +21 -21
  112. data/lib/yard/handlers/c/module_handler.rb +17 -17
  113. data/lib/yard/handlers/c/override_comment_handler.rb +31 -31
  114. data/lib/yard/handlers/c/path_handler.rb +11 -11
  115. data/lib/yard/handlers/c/struct_handler.rb +13 -13
  116. data/lib/yard/handlers/c/symbol_handler.rb +8 -8
  117. data/lib/yard/handlers/common/method_handler.rb +19 -0
  118. data/lib/yard/handlers/processor.rb +200 -200
  119. data/lib/yard/handlers/ruby/alias_handler.rb +45 -44
  120. data/lib/yard/handlers/ruby/attribute_handler.rb +87 -87
  121. data/lib/yard/handlers/ruby/base.rb +165 -165
  122. data/lib/yard/handlers/ruby/class_condition_handler.rb +92 -92
  123. data/lib/yard/handlers/ruby/class_handler.rb +119 -119
  124. data/lib/yard/handlers/ruby/class_variable_handler.rb +17 -17
  125. data/lib/yard/handlers/ruby/comment_handler.rb +10 -10
  126. data/lib/yard/handlers/ruby/constant_handler.rb +55 -59
  127. data/lib/yard/handlers/ruby/decorator_handler_methods.rb +123 -123
  128. data/lib/yard/handlers/ruby/dsl_handler.rb +15 -15
  129. data/lib/yard/handlers/ruby/dsl_handler_methods.rb +96 -96
  130. data/lib/yard/handlers/ruby/exception_handler.rb +27 -27
  131. data/lib/yard/handlers/ruby/extend_handler.rb +22 -22
  132. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +37 -37
  133. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +65 -65
  134. data/lib/yard/handlers/ruby/legacy/base.rb +245 -245
  135. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +83 -83
  136. data/lib/yard/handlers/ruby/legacy/class_handler.rb +113 -113
  137. data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +15 -15
  138. data/lib/yard/handlers/ruby/legacy/comment_handler.rb +10 -10
  139. data/lib/yard/handlers/ruby/legacy/constant_handler.rb +29 -29
  140. data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +17 -17
  141. data/lib/yard/handlers/ruby/legacy/exception_handler.rb +13 -13
  142. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +21 -21
  143. data/lib/yard/handlers/ruby/legacy/method_handler.rb +90 -90
  144. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +39 -39
  145. data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +19 -19
  146. data/lib/yard/handlers/ruby/legacy/module_handler.rb +12 -12
  147. data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +22 -22
  148. data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +22 -22
  149. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +17 -17
  150. data/lib/yard/handlers/ruby/legacy/yield_handler.rb +29 -29
  151. data/lib/yard/handlers/ruby/method_condition_handler.rb +9 -9
  152. data/lib/yard/handlers/ruby/method_handler.rb +104 -118
  153. data/lib/yard/handlers/ruby/mixin_handler.rb +49 -37
  154. data/lib/yard/handlers/ruby/module_function_handler.rb +27 -27
  155. data/lib/yard/handlers/ruby/module_handler.rb +12 -12
  156. data/lib/yard/handlers/ruby/private_class_method_handler.rb +14 -14
  157. data/lib/yard/handlers/ruby/private_constant_handler.rb +43 -43
  158. data/lib/yard/handlers/ruby/public_class_method_handler.rb +14 -14
  159. data/lib/yard/handlers/ruby/struct_handler_methods.rb +143 -143
  160. data/lib/yard/handlers/ruby/visibility_handler.rb +22 -22
  161. data/lib/yard/handlers/ruby/yield_handler.rb +31 -31
  162. data/lib/yard/i18n/locale.rb +67 -67
  163. data/lib/yard/i18n/message.rb +57 -57
  164. data/lib/yard/i18n/messages.rb +56 -56
  165. data/lib/yard/i18n/po_parser.rb +61 -61
  166. data/lib/yard/i18n/pot_generator.rb +290 -290
  167. data/lib/yard/i18n/text.rb +173 -173
  168. data/lib/yard/logging.rb +205 -205
  169. data/lib/yard/options.rb +217 -217
  170. data/lib/yard/parser/base.rb +57 -57
  171. data/lib/yard/parser/c/c_parser.rb +235 -235
  172. data/lib/yard/parser/c/comment_parser.rb +134 -134
  173. data/lib/yard/parser/c/statement.rb +66 -64
  174. data/lib/yard/parser/ruby/ast_node.rb +551 -540
  175. data/lib/yard/parser/ruby/legacy/irb/slex.rb +276 -0
  176. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1345 -1354
  177. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +32 -32
  178. data/lib/yard/parser/ruby/legacy/statement.rb +68 -66
  179. data/lib/yard/parser/ruby/legacy/statement_list.rb +394 -394
  180. data/lib/yard/parser/ruby/legacy/token_list.rb +74 -74
  181. data/lib/yard/parser/ruby/ruby_parser.rb +699 -687
  182. data/lib/yard/parser/ruby/token_resolver.rb +156 -156
  183. data/lib/yard/parser/source_parser.rb +526 -526
  184. data/lib/yard/rake/yardoc_task.rb +81 -81
  185. data/lib/yard/registry.rb +439 -439
  186. data/lib/yard/registry_resolver.rb +231 -189
  187. data/lib/yard/registry_store.rb +342 -337
  188. data/lib/yard/rubygems/backports.rb +10 -10
  189. data/lib/yard/rubygems/backports/LICENSE.txt +57 -57
  190. data/lib/yard/rubygems/backports/MIT.txt +20 -20
  191. data/lib/yard/rubygems/backports/gem.rb +10 -10
  192. data/lib/yard/rubygems/backports/source_index.rb +365 -365
  193. data/lib/yard/rubygems/doc_manager.rb +90 -90
  194. data/lib/yard/rubygems/hook.rb +197 -197
  195. data/lib/yard/rubygems/specification.rb +50 -50
  196. data/lib/yard/serializers/base.rb +83 -83
  197. data/lib/yard/serializers/file_system_serializer.rb +123 -123
  198. data/lib/yard/serializers/process_serializer.rb +24 -24
  199. data/lib/yard/serializers/stdout_serializer.rb +34 -34
  200. data/lib/yard/serializers/yardoc_serializer.rb +152 -152
  201. data/lib/yard/server.rb +13 -13
  202. data/lib/yard/server/adapter.rb +100 -100
  203. data/lib/yard/server/commands/base.rb +209 -209
  204. data/lib/yard/server/commands/display_file_command.rb +29 -29
  205. data/lib/yard/server/commands/display_object_command.rb +65 -65
  206. data/lib/yard/server/commands/frames_command.rb +16 -16
  207. data/lib/yard/server/commands/library_command.rb +187 -187
  208. data/lib/yard/server/commands/library_index_command.rb +28 -28
  209. data/lib/yard/server/commands/list_command.rb +25 -25
  210. data/lib/yard/server/commands/root_request_command.rb +15 -15
  211. data/lib/yard/server/commands/search_command.rb +79 -79
  212. data/lib/yard/server/commands/static_file_command.rb +23 -23
  213. data/lib/yard/server/commands/static_file_helpers.rb +61 -62
  214. data/lib/yard/server/doc_server_helper.rb +91 -91
  215. data/lib/yard/server/doc_server_serializer.rb +39 -39
  216. data/lib/yard/server/library_version.rb +277 -277
  217. data/lib/yard/server/rack_adapter.rb +89 -89
  218. data/lib/yard/server/router.rb +187 -187
  219. data/lib/yard/server/static_caching.rb +46 -46
  220. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +127 -127
  221. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +11 -11
  222. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +37 -37
  223. data/lib/yard/server/templates/default/layout/html/script_setup.erb +7 -7
  224. data/lib/yard/server/templates/default/layout/html/setup.rb +8 -8
  225. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -4
  226. data/lib/yard/server/templates/default/method_details/html/setup.rb +5 -5
  227. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +8 -8
  228. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +14 -14
  229. data/lib/yard/server/templates/doc_server/library_list/html/listing.erb +13 -13
  230. data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +6 -6
  231. data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -2
  232. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +52 -52
  233. data/lib/yard/server/templates/doc_server/processing/html/setup.rb +4 -4
  234. data/lib/yard/server/templates/doc_server/search/html/search.erb +18 -18
  235. data/lib/yard/server/templates/doc_server/search/html/setup.rb +9 -9
  236. data/lib/yard/server/webrick_adapter.rb +45 -45
  237. data/lib/yard/tags/default_factory.rb +191 -191
  238. data/lib/yard/tags/default_tag.rb +13 -13
  239. data/lib/yard/tags/directives.rb +616 -616
  240. data/lib/yard/tags/library.rb +633 -633
  241. data/lib/yard/tags/option_tag.rb +13 -13
  242. data/lib/yard/tags/overload_tag.rb +71 -71
  243. data/lib/yard/tags/ref_tag.rb +8 -8
  244. data/lib/yard/tags/ref_tag_list.rb +28 -28
  245. data/lib/yard/tags/tag.rb +71 -71
  246. data/lib/yard/tags/tag_format_error.rb +7 -7
  247. data/lib/yard/tags/types_explainer.rb +162 -162
  248. data/lib/yard/templates/engine.rb +186 -186
  249. data/lib/yard/templates/erb_cache.rb +23 -23
  250. data/lib/yard/templates/helpers/base_helper.rb +215 -215
  251. data/lib/yard/templates/helpers/filter_helper.rb +27 -27
  252. data/lib/yard/templates/helpers/html_helper.rb +663 -646
  253. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +78 -78
  254. data/lib/yard/templates/helpers/markup/rdoc_markdown.rb +23 -23
  255. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +109 -109
  256. data/lib/yard/templates/helpers/markup_helper.rb +172 -172
  257. data/lib/yard/templates/helpers/method_helper.rb +75 -75
  258. data/lib/yard/templates/helpers/module_helper.rb +21 -21
  259. data/lib/yard/templates/helpers/text_helper.rb +112 -112
  260. data/lib/yard/templates/helpers/uml_helper.rb +47 -47
  261. data/lib/yard/templates/section.rb +105 -105
  262. data/lib/yard/templates/template.rb +418 -418
  263. data/lib/yard/templates/template_options.rb +92 -92
  264. data/lib/yard/verifier.rb +151 -151
  265. data/lib/yard/version.rb +6 -6
  266. data/po/ja.po +31108 -0
  267. data/samus.json +80 -0
  268. data/spec/cli/command_parser_spec.rb +43 -43
  269. data/spec/cli/command_spec.rb +36 -36
  270. data/spec/cli/config_spec.rb +148 -148
  271. data/spec/cli/diff_spec.rb +254 -254
  272. data/spec/cli/display_spec.rb +30 -30
  273. data/spec/cli/gems_spec.rb +81 -81
  274. data/spec/cli/graph_spec.rb +18 -18
  275. data/spec/cli/help_spec.rb +22 -22
  276. data/spec/cli/i18n_spec.rb +107 -107
  277. data/spec/cli/list_spec.rb +8 -8
  278. data/spec/cli/markup_types_spec.rb +22 -22
  279. data/spec/cli/server_spec.rb +324 -324
  280. data/spec/cli/stats_spec.rb +96 -96
  281. data/spec/cli/yard_on_yard_spec.rb +38 -38
  282. data/spec/cli/yardoc_spec.rb +896 -862
  283. data/spec/cli/yri_spec.rb +101 -101
  284. data/spec/code_objects/base_spec.rb +485 -470
  285. data/spec/code_objects/class_object_spec.rb +226 -226
  286. data/spec/code_objects/code_object_list_spec.rb +36 -36
  287. data/spec/code_objects/constants_spec.rb +116 -116
  288. data/spec/code_objects/extra_file_object_spec.rb +161 -160
  289. data/spec/code_objects/macro_object_spec.rb +150 -150
  290. data/spec/code_objects/method_object_spec.rb +184 -184
  291. data/spec/code_objects/module_object_spec.rb +142 -142
  292. data/spec/code_objects/namespace_object_spec.rb +171 -171
  293. data/spec/code_objects/proxy_spec.rb +147 -141
  294. data/spec/code_objects/spec_helper.rb +3 -3
  295. data/spec/config_spec.rb +171 -171
  296. data/spec/core_ext/array_spec.rb +13 -13
  297. data/spec/core_ext/file_spec.rb +72 -72
  298. data/spec/core_ext/hash_spec.rb +14 -14
  299. data/spec/core_ext/insertion_spec.rb +37 -37
  300. data/spec/core_ext/module_spec.rb +9 -15
  301. data/spec/core_ext/string_spec.rb +42 -42
  302. data/spec/core_ext/symbol_hash_spec.rb +89 -89
  303. data/spec/docstring_parser_spec.rb +280 -280
  304. data/spec/docstring_spec.rb +373 -373
  305. data/spec/handlers/alias_handler_spec.rb +82 -82
  306. data/spec/handlers/attribute_handler_spec.rb +96 -96
  307. data/spec/handlers/base_spec.rb +216 -216
  308. data/spec/handlers/c/alias_handler_spec.rb +34 -34
  309. data/spec/handlers/c/attribute_handler_spec.rb +41 -41
  310. data/spec/handlers/c/class_handler_spec.rb +78 -78
  311. data/spec/handlers/c/constant_handler_spec.rb +71 -71
  312. data/spec/handlers/c/init_handler_spec.rb +48 -48
  313. data/spec/handlers/c/method_handler_spec.rb +327 -325
  314. data/spec/handlers/c/mixin_handler_spec.rb +44 -44
  315. data/spec/handlers/c/module_handler_spec.rb +71 -71
  316. data/spec/handlers/c/override_comment_handler_spec.rb +47 -47
  317. data/spec/handlers/c/path_handler_spec.rb +36 -36
  318. data/spec/handlers/c/spec_helper.rb +23 -23
  319. data/spec/handlers/c/struct_handler_spec.rb +16 -16
  320. data/spec/handlers/class_condition_handler_spec.rb +87 -87
  321. data/spec/handlers/class_handler_spec.rb +247 -247
  322. data/spec/handlers/class_method_handler_shared_examples.rb +133 -133
  323. data/spec/handlers/class_variable_handler_spec.rb +12 -12
  324. data/spec/handlers/constant_handler_spec.rb +112 -112
  325. data/spec/handlers/decorator_handler_methods_spec.rb +393 -393
  326. data/spec/handlers/dsl_handler_spec.rb +226 -219
  327. data/spec/handlers/examples/alias_handler_001.rb.txt +45 -45
  328. data/spec/handlers/examples/attribute_handler_001.rb.txt +31 -31
  329. data/spec/handlers/examples/class_condition_handler_001.rb.txt +68 -68
  330. data/spec/handlers/examples/class_handler_001.rb.txt +120 -120
  331. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -9
  332. data/spec/handlers/examples/constant_handler_001.rb.txt +35 -35
  333. data/spec/handlers/examples/dsl_handler_001.rb.txt +156 -154
  334. data/spec/handlers/examples/exception_handler_001.rb.txt +58 -58
  335. data/spec/handlers/examples/extend_handler_001.rb.txt +19 -16
  336. data/spec/handlers/examples/method_condition_handler_001.rb.txt +9 -9
  337. data/spec/handlers/examples/method_handler_001.rb.txt +128 -128
  338. data/spec/handlers/examples/mixin_handler_001.rb.txt +40 -37
  339. data/spec/handlers/examples/module_handler_001.rb.txt +29 -29
  340. data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -8
  341. data/spec/handlers/examples/process_handler_001.rb.txt +11 -11
  342. data/spec/handlers/examples/visibility_handler_001.rb.txt +35 -35
  343. data/spec/handlers/examples/yield_handler_001.rb.txt +54 -54
  344. data/spec/handlers/exception_handler_spec.rb +49 -49
  345. data/spec/handlers/extend_handler_spec.rb +28 -24
  346. data/spec/handlers/legacy_base_spec.rb +128 -128
  347. data/spec/handlers/method_condition_handler_spec.rb +15 -15
  348. data/spec/handlers/method_handler_spec.rb +214 -190
  349. data/spec/handlers/mixin_handler_spec.rb +60 -56
  350. data/spec/handlers/module_function_handler_spec.rb +106 -106
  351. data/spec/handlers/module_handler_spec.rb +35 -35
  352. data/spec/handlers/private_class_method_handler_spec.rb +11 -11
  353. data/spec/handlers/private_constant_handler_spec.rb +25 -25
  354. data/spec/handlers/processor_spec.rb +35 -35
  355. data/spec/handlers/public_class_method_handler_spec.rb +11 -11
  356. data/spec/handlers/ruby/base_spec.rb +95 -95
  357. data/spec/handlers/ruby/legacy/base_spec.rb +84 -84
  358. data/spec/handlers/spec_helper.rb +33 -33
  359. data/spec/handlers/visibility_handler_spec.rb +44 -44
  360. data/spec/handlers/yield_handler_spec.rb +52 -52
  361. data/spec/i18n/locale_spec.rb +81 -81
  362. data/spec/i18n/message_spec.rb +52 -52
  363. data/spec/i18n/messages_spec.rb +67 -67
  364. data/spec/i18n/pot_generator_spec.rb +295 -295
  365. data/spec/i18n/text_spec.rb +184 -184
  366. data/spec/logging_spec.rb +44 -44
  367. data/spec/options_spec.rb +171 -171
  368. data/spec/parser/base_spec.rb +24 -24
  369. data/spec/parser/c_parser_spec.rb +236 -236
  370. data/spec/parser/examples/array.c.txt +6267 -6267
  371. data/spec/parser/examples/example1.rb.txt +7 -7
  372. data/spec/parser/examples/extrafile.c.txt +8 -8
  373. data/spec/parser/examples/file.c.txt +28 -28
  374. data/spec/parser/examples/multifile.c.txt +22 -22
  375. data/spec/parser/examples/namespace.cpp.txt +68 -68
  376. data/spec/parser/examples/override.c.txt +424 -424
  377. data/spec/parser/examples/parse_in_order_001.rb.txt +2 -2
  378. data/spec/parser/examples/parse_in_order_002.rb.txt +1 -1
  379. data/spec/parser/examples/tag_handler_001.rb.txt +7 -7
  380. data/spec/parser/ruby/ast_node_spec.rb +33 -33
  381. data/spec/parser/ruby/legacy/statement_list_spec.rb +299 -299
  382. data/spec/parser/ruby/legacy/token_list_spec.rb +79 -79
  383. data/spec/parser/ruby/ruby_parser_spec.rb +508 -508
  384. data/spec/parser/ruby/token_resolver_spec.rb +165 -165
  385. data/spec/parser/source_parser_spec.rb +727 -727
  386. data/spec/parser/tag_parsing_spec.rb +17 -17
  387. data/spec/rake/yardoc_task_spec.rb +118 -118
  388. data/spec/registry_spec.rb +463 -463
  389. data/spec/registry_store_spec.rb +327 -316
  390. data/spec/rubygems/doc_manager_spec.rb +112 -112
  391. data/spec/serializers/data/serialized_yardoc/checksums +1 -1
  392. data/spec/serializers/file_system_serializer_spec.rb +145 -145
  393. data/spec/serializers/spec_helper.rb +2 -2
  394. data/spec/serializers/yardoc_serializer_spec.rb +78 -78
  395. data/spec/server/adapter_spec.rb +39 -39
  396. data/spec/server/commands/base_spec.rb +91 -91
  397. data/spec/server/commands/library_command_spec.rb +39 -39
  398. data/spec/server/doc_server_helper_spec.rb +72 -72
  399. data/spec/server/doc_server_serializer_spec.rb +60 -60
  400. data/spec/server/rack_adapter_spec.rb +21 -21
  401. data/spec/server/router_spec.rb +123 -123
  402. data/spec/server/spec_helper.rb +22 -22
  403. data/spec/server/static_caching_spec.rb +47 -47
  404. data/spec/server/webrick_servlet_spec.rb +20 -20
  405. data/spec/server_spec.rb +19 -19
  406. data/spec/spec_helper.rb +212 -212
  407. data/spec/tags/default_factory_spec.rb +168 -168
  408. data/spec/tags/default_tag_spec.rb +11 -11
  409. data/spec/tags/directives_spec.rb +463 -463
  410. data/spec/tags/library_spec.rb +48 -48
  411. data/spec/tags/overload_tag_spec.rb +53 -53
  412. data/spec/tags/ref_tag_list_spec.rb +53 -53
  413. data/spec/tags/types_explainer_spec.rb +203 -203
  414. data/spec/templates/class_spec.rb +45 -45
  415. data/spec/templates/constant_spec.rb +41 -41
  416. data/spec/templates/engine_spec.rb +131 -131
  417. data/spec/templates/examples/class001.html +308 -308
  418. data/spec/templates/examples/class001.txt +36 -36
  419. data/spec/templates/examples/class002.html +39 -39
  420. data/spec/templates/examples/constant001.txt +24 -24
  421. data/spec/templates/examples/constant002.txt +6 -6
  422. data/spec/templates/examples/constant003.txt +10 -10
  423. data/spec/templates/examples/method001.html +137 -137
  424. data/spec/templates/examples/method001.txt +35 -35
  425. data/spec/templates/examples/method002.html +91 -91
  426. data/spec/templates/examples/method002.txt +20 -20
  427. data/spec/templates/examples/method003.html +165 -165
  428. data/spec/templates/examples/method003.txt +45 -45
  429. data/spec/templates/examples/method004.html +48 -48
  430. data/spec/templates/examples/method004.txt +10 -10
  431. data/spec/templates/examples/method005.html +105 -105
  432. data/spec/templates/examples/method005.txt +33 -33
  433. data/spec/templates/examples/method006.html +107 -107
  434. data/spec/templates/examples/method006.txt +20 -20
  435. data/spec/templates/examples/module001.dot +33 -33
  436. data/spec/templates/examples/module001.html +833 -833
  437. data/spec/templates/examples/module001.txt +33 -33
  438. data/spec/templates/examples/module002.html +341 -341
  439. data/spec/templates/examples/module003.html +202 -202
  440. data/spec/templates/examples/module004.html +394 -394
  441. data/spec/templates/examples/module005.html +81 -81
  442. data/spec/templates/examples/tag001.txt +82 -82
  443. data/spec/templates/helpers/base_helper_spec.rb +171 -171
  444. data/spec/templates/helpers/html_helper_spec.rb +687 -668
  445. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +65 -65
  446. data/spec/templates/helpers/markup/rdoc_markup_spec.rb +84 -84
  447. data/spec/templates/helpers/markup_helper_spec.rb +136 -136
  448. data/spec/templates/helpers/method_helper_spec.rb +107 -107
  449. data/spec/templates/helpers/module_helper_spec.rb +35 -35
  450. data/spec/templates/helpers/shared_signature_examples.rb +126 -126
  451. data/spec/templates/helpers/text_helper_spec.rb +65 -65
  452. data/spec/templates/markup_processor_integrations/asciidoctor_spec.rb +60 -0
  453. data/spec/templates/markup_processor_integrations/integration_spec_helper.rb +46 -0
  454. data/spec/templates/markup_processor_integrations/rdoc_markdown_spec.rb +59 -0
  455. data/spec/templates/markup_processor_integrations/rdoc_spec.rb +39 -0
  456. data/spec/templates/markup_processor_integrations/redcarpet_spec.rb +59 -0
  457. data/spec/templates/markup_processor_integrations/redcloth_spec.rb +48 -0
  458. data/spec/templates/method_spec.rb +118 -118
  459. data/spec/templates/module_spec.rb +203 -203
  460. data/spec/templates/onefile_spec.rb +66 -66
  461. data/spec/templates/section_spec.rb +144 -144
  462. data/spec/templates/spec_helper.rb +76 -76
  463. data/spec/templates/tag_spec.rb +52 -52
  464. data/spec/templates/template_spec.rb +410 -410
  465. data/spec/verifier_spec.rb +106 -106
  466. data/templates/default/class/dot/setup.rb +7 -7
  467. data/templates/default/class/dot/superklass.erb +2 -2
  468. data/templates/default/class/html/constructor_details.erb +8 -8
  469. data/templates/default/class/html/setup.rb +2 -2
  470. data/templates/default/class/html/subclasses.erb +4 -4
  471. data/templates/default/class/setup.rb +36 -36
  472. data/templates/default/class/text/setup.rb +12 -12
  473. data/templates/default/class/text/subclasses.erb +5 -5
  474. data/templates/default/constant/text/header.erb +11 -11
  475. data/templates/default/constant/text/setup.rb +4 -4
  476. data/templates/default/docstring/html/abstract.erb +4 -4
  477. data/templates/default/docstring/html/deprecated.erb +1 -1
  478. data/templates/default/docstring/html/index.erb +5 -5
  479. data/templates/default/docstring/html/note.erb +6 -6
  480. data/templates/default/docstring/html/private.erb +4 -4
  481. data/templates/default/docstring/html/text.erb +1 -1
  482. data/templates/default/docstring/html/todo.erb +6 -6
  483. data/templates/default/docstring/setup.rb +52 -52
  484. data/templates/default/docstring/text/abstract.erb +2 -2
  485. data/templates/default/docstring/text/deprecated.erb +2 -2
  486. data/templates/default/docstring/text/index.erb +2 -2
  487. data/templates/default/docstring/text/note.erb +3 -3
  488. data/templates/default/docstring/text/private.erb +2 -2
  489. data/templates/default/docstring/text/text.erb +1 -1
  490. data/templates/default/docstring/text/todo.erb +3 -3
  491. data/templates/default/fulldoc/html/css/full_list.css +58 -58
  492. data/templates/default/fulldoc/html/css/style.css +496 -496
  493. data/templates/default/fulldoc/html/frames.erb +17 -17
  494. data/templates/default/fulldoc/html/full_list.erb +37 -37
  495. data/templates/default/fulldoc/html/full_list_class.erb +2 -2
  496. data/templates/default/fulldoc/html/full_list_file.erb +7 -7
  497. data/templates/default/fulldoc/html/full_list_method.erb +10 -10
  498. data/templates/default/fulldoc/html/js/app.js +314 -292
  499. data/templates/default/fulldoc/html/js/full_list.js +216 -216
  500. data/templates/default/fulldoc/html/js/jquery.js +3 -3
  501. data/templates/default/fulldoc/html/setup.rb +241 -241
  502. data/templates/default/layout/dot/header.erb +5 -5
  503. data/templates/default/layout/dot/setup.rb +15 -15
  504. data/templates/default/layout/html/breadcrumb.erb +11 -11
  505. data/templates/default/layout/html/files.erb +11 -11
  506. data/templates/default/layout/html/footer.erb +5 -5
  507. data/templates/default/layout/html/headers.erb +15 -15
  508. data/templates/default/layout/html/index.erb +2 -2
  509. data/templates/default/layout/html/layout.erb +23 -23
  510. data/templates/default/layout/html/listing.erb +4 -4
  511. data/templates/default/layout/html/objects.erb +32 -32
  512. data/templates/default/layout/html/script_setup.erb +4 -4
  513. data/templates/default/layout/html/search.erb +12 -12
  514. data/templates/default/layout/html/setup.rb +89 -89
  515. data/templates/default/method/html/header.erb +16 -16
  516. data/templates/default/method/setup.rb +4 -4
  517. data/templates/default/method_details/html/header.erb +2 -2
  518. data/templates/default/method_details/html/method_signature.erb +24 -24
  519. data/templates/default/method_details/html/source.erb +9 -9
  520. data/templates/default/method_details/setup.rb +11 -11
  521. data/templates/default/method_details/text/header.erb +10 -10
  522. data/templates/default/method_details/text/method_signature.erb +12 -12
  523. data/templates/default/method_details/text/setup.rb +11 -11
  524. data/templates/default/module/dot/child.erb +1 -1
  525. data/templates/default/module/dot/dependencies.erb +2 -2
  526. data/templates/default/module/dot/header.erb +6 -6
  527. data/templates/default/module/dot/info.erb +13 -13
  528. data/templates/default/module/dot/setup.rb +15 -15
  529. data/templates/default/module/html/attribute_details.erb +10 -10
  530. data/templates/default/module/html/attribute_summary.erb +8 -8
  531. data/templates/default/module/html/box_info.erb +43 -43
  532. data/templates/default/module/html/children.erb +8 -8
  533. data/templates/default/module/html/constant_summary.erb +17 -17
  534. data/templates/default/module/html/defines.erb +2 -2
  535. data/templates/default/module/html/header.erb +5 -5
  536. data/templates/default/module/html/inherited_attributes.erb +14 -14
  537. data/templates/default/module/html/inherited_constants.erb +8 -8
  538. data/templates/default/module/html/inherited_methods.erb +18 -18
  539. data/templates/default/module/html/item_summary.erb +40 -40
  540. data/templates/default/module/html/method_details_list.erb +9 -9
  541. data/templates/default/module/html/method_summary.erb +13 -13
  542. data/templates/default/module/html/methodmissing.erb +12 -12
  543. data/templates/default/module/setup.rb +167 -167
  544. data/templates/default/module/text/children.erb +9 -9
  545. data/templates/default/module/text/class_meths_list.erb +7 -7
  546. data/templates/default/module/text/extends.erb +7 -7
  547. data/templates/default/module/text/header.erb +7 -7
  548. data/templates/default/module/text/includes.erb +7 -7
  549. data/templates/default/module/text/instance_meths_list.erb +7 -7
  550. data/templates/default/module/text/setup.rb +13 -13
  551. data/templates/default/onefile/html/files.erb +4 -4
  552. data/templates/default/onefile/html/headers.erb +6 -6
  553. data/templates/default/onefile/html/layout.erb +17 -17
  554. data/templates/default/onefile/html/readme.erb +2 -2
  555. data/templates/default/onefile/html/setup.rb +62 -62
  556. data/templates/default/root/dot/child.erb +2 -2
  557. data/templates/default/root/dot/setup.rb +6 -6
  558. data/templates/default/root/html/setup.rb +2 -2
  559. data/templates/default/tags/html/example.erb +10 -10
  560. data/templates/default/tags/html/index.erb +2 -2
  561. data/templates/default/tags/html/option.erb +24 -24
  562. data/templates/default/tags/html/overload.erb +13 -13
  563. data/templates/default/tags/html/see.erb +7 -7
  564. data/templates/default/tags/html/tag.erb +20 -20
  565. data/templates/default/tags/setup.rb +57 -57
  566. data/templates/default/tags/text/example.erb +12 -12
  567. data/templates/default/tags/text/index.erb +1 -1
  568. data/templates/default/tags/text/option.erb +20 -20
  569. data/templates/default/tags/text/overload.erb +19 -19
  570. data/templates/default/tags/text/see.erb +11 -11
  571. data/templates/default/tags/text/tag.erb +13 -13
  572. data/templates/guide/class/html/setup.rb +2 -2
  573. data/templates/guide/docstring/html/setup.rb +2 -2
  574. data/templates/guide/fulldoc/html/css/style.css +108 -108
  575. data/templates/guide/fulldoc/html/js/app.js +33 -33
  576. data/templates/guide/fulldoc/html/setup.rb +74 -74
  577. data/templates/guide/layout/html/layout.erb +81 -81
  578. data/templates/guide/layout/html/setup.rb +25 -25
  579. data/templates/guide/method/html/header.erb +17 -17
  580. data/templates/guide/method/html/setup.rb +22 -22
  581. data/templates/guide/module/html/header.erb +6 -6
  582. data/templates/guide/module/html/method_list.erb +4 -4
  583. data/templates/guide/module/html/setup.rb +27 -27
  584. data/templates/guide/onefile/html/files.erb +4 -4
  585. data/templates/guide/onefile/html/setup.rb +6 -6
  586. data/templates/guide/onefile/html/toc.erb +3 -3
  587. data/templates/guide/tags/html/setup.rb +9 -9
  588. data/yard.gemspec +24 -43
  589. metadata +28 -21
  590. data/spec/examples.txt +0 -1875
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/slex.rb - simple lex analyzer
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require "irb/notifier"
14
+
15
+ # @private
16
+ module IRB
17
+ class SLex
18
+ DOUT = Notifier::def_notifier("SLex::")
19
+ D_WARN = DOUT::def_notifier(1, "Warn: ")
20
+ D_DEBUG = DOUT::def_notifier(2, "Debug: ")
21
+ D_DETAIL = DOUT::def_notifier(4, "Detail: ")
22
+
23
+ DOUT.level = Notifier::D_NOMSG
24
+
25
+ def initialize
26
+ @head = Node.new("")
27
+ end
28
+
29
+ def def_rule(token, preproc = nil, postproc = nil, &block)
30
+ D_DETAIL.pp token
31
+
32
+ postproc = block if block_given?
33
+ create(token, preproc, postproc)
34
+ end
35
+
36
+ def def_rules(*tokens, &block)
37
+ if block_given?
38
+ p = block
39
+ end
40
+ for token in tokens
41
+ def_rule(token, nil, p)
42
+ end
43
+ end
44
+
45
+ def preproc(token, proc)
46
+ node = search(token)
47
+ node.preproc=proc
48
+ end
49
+
50
+ # need a check?
51
+ def postproc(token)
52
+ node = search(token, proc)
53
+ node.postproc=proc
54
+ end
55
+
56
+ def search(token)
57
+ @head.search(token.split(//))
58
+ end
59
+
60
+ def create(token, preproc = nil, postproc = nil)
61
+ @head.create_subnode(token.split(//), preproc, postproc)
62
+ end
63
+
64
+ def match(token)
65
+ case token
66
+ when Array
67
+ when String
68
+ return match(token.split(//))
69
+ else
70
+ return @head.match_io(token)
71
+ end
72
+ ret = @head.match(token)
73
+ D_DETAIL.exec_if{D_DETAIL.printf "match end: %s:%s\n", ret, token.inspect}
74
+ ret
75
+ end
76
+
77
+ def inspect
78
+ format("<SLex: @head = %s>", @head.inspect)
79
+ end
80
+
81
+ #----------------------------------------------------------------------
82
+ #
83
+ # class Node -
84
+ #
85
+ #----------------------------------------------------------------------
86
+ class Node
87
+ # if postproc is nil, this node is an abstract node.
88
+ # if postproc is non-nil, this node is a real node.
89
+ def initialize(preproc = nil, postproc = nil)
90
+ @Tree = {}
91
+ @preproc = preproc
92
+ @postproc = postproc
93
+ end
94
+
95
+ attr_accessor :preproc
96
+ attr_accessor :postproc
97
+
98
+ def search(chrs, opt = nil)
99
+ return self if chrs.empty?
100
+ ch = chrs.shift
101
+ if node = @Tree[ch]
102
+ node.search(chrs, opt)
103
+ else
104
+ if opt
105
+ chrs.unshift ch
106
+ self.create_subnode(chrs)
107
+ else
108
+ raise "node nothing"
109
+ end
110
+ end
111
+ end
112
+
113
+ def create_subnode(chrs, preproc = nil, postproc = nil)
114
+ if chrs.empty?
115
+ if @postproc
116
+ D_DETAIL.pp node
117
+ raise "node already exists"
118
+ else
119
+ D_DEBUG.puts "change abstract node to real node."
120
+ @preproc = preproc
121
+ @postproc = postproc
122
+ end
123
+ return self
124
+ end
125
+
126
+ ch = chrs.shift
127
+ if node = @Tree[ch]
128
+ if chrs.empty?
129
+ if node.postproc
130
+ DebugLogger.pp node
131
+ DebugLogger.pp self
132
+ DebugLogger.pp ch
133
+ DebugLogger.pp chrs
134
+ raise "node already exists"
135
+ else
136
+ D_WARN.puts "change abstract node to real node"
137
+ node.preproc = preproc
138
+ node.postproc = postproc
139
+ end
140
+ else
141
+ node.create_subnode(chrs, preproc, postproc)
142
+ end
143
+ else
144
+ if chrs.empty?
145
+ node = Node.new(preproc, postproc)
146
+ else
147
+ node = Node.new
148
+ node.create_subnode(chrs, preproc, postproc)
149
+ end
150
+ @Tree[ch] = node
151
+ end
152
+ node
153
+ end
154
+
155
+ #
156
+ # chrs: String
157
+ # character array
158
+ # io must have getc()/ungetc(); and ungetc() must be
159
+ # able to be called arbitrary number of times.
160
+ #
161
+ def match(chrs, op = "")
162
+ D_DETAIL.print "match>: ", chrs, "op:", op, "\n"
163
+ if chrs.empty?
164
+ if @preproc.nil? || @preproc.call(op, chrs)
165
+ DOUT.printf(D_DETAIL, "op1: %s\n", op)
166
+ @postproc.call(op, chrs)
167
+ else
168
+ nil
169
+ end
170
+ else
171
+ ch = chrs.shift
172
+ if node = @Tree[ch]
173
+ if ret = node.match(chrs, op+ch)
174
+ return ret
175
+ else
176
+ chrs.unshift ch
177
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
178
+ DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect)
179
+ ret = @postproc.call(op, chrs)
180
+ return ret
181
+ else
182
+ return nil
183
+ end
184
+ end
185
+ else
186
+ chrs.unshift ch
187
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
188
+ DOUT.printf(D_DETAIL, "op3: %s\n", op)
189
+ @postproc.call(op, chrs)
190
+ return ""
191
+ else
192
+ return nil
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ def match_io(io, op = "")
199
+ if op == ""
200
+ ch = io.getc
201
+ if ch == nil
202
+ return nil
203
+ end
204
+ else
205
+ ch = io.getc_of_rests
206
+ end
207
+ if ch.nil?
208
+ if @preproc.nil? || @preproc.call(op, io)
209
+ D_DETAIL.printf("op1: %s\n", op)
210
+ @postproc.call(op, io)
211
+ else
212
+ nil
213
+ end
214
+ else
215
+ if node = @Tree[ch]
216
+ if ret = node.match_io(io, op+ch)
217
+ ret
218
+ else
219
+ io.ungetc ch
220
+ if @postproc and @preproc.nil? || @preproc.call(op, io)
221
+ DOUT.exec_if{D_DETAIL.printf "op2: %s\n", op.inspect}
222
+ @postproc.call(op, io)
223
+ else
224
+ nil
225
+ end
226
+ end
227
+ else
228
+ io.ungetc ch
229
+ if @postproc and @preproc.nil? || @preproc.call(op, io)
230
+ D_DETAIL.printf("op3: %s\n", op)
231
+ @postproc.call(op, io)
232
+ else
233
+ nil
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+ # :startdoc:
242
+
243
+ if $0 == __FILE__
244
+ case $1
245
+ when "1"
246
+ tr = SLex.new
247
+ print "0: ", tr.inspect, "\n"
248
+ tr.def_rule("=") {print "=\n"}
249
+ print "1: ", tr.inspect, "\n"
250
+ tr.def_rule("==") {print "==\n"}
251
+ print "2: ", tr.inspect, "\n"
252
+
253
+ print "case 1:\n"
254
+ print tr.match("="), "\n"
255
+ print "case 2:\n"
256
+ print tr.match("=="), "\n"
257
+ print "case 3:\n"
258
+ print tr.match("=>"), "\n"
259
+
260
+ when "2"
261
+ tr = SLex.new
262
+ print "0: ", tr.inspect, "\n"
263
+ tr.def_rule("=") {print "=\n"}
264
+ print "1: ", tr.inspect, "\n"
265
+ tr.def_rule("==", proc{false}) {print "==\n"}
266
+ print "2: ", tr.inspect, "\n"
267
+
268
+ print "case 1:\n"
269
+ print tr.match("="), "\n"
270
+ print "case 2:\n"
271
+ print tr.match("=="), "\n"
272
+ print "case 3:\n"
273
+ print tr.match("=>"), "\n"
274
+ end
275
+ exit
276
+ end
@@ -1,1354 +1,1345 @@
1
- require "e2mmap"
2
- require "irb/slex"
3
-
4
- module YARD
5
- module Parser::Ruby::Legacy
6
- # Legacy lexical tokenizer module.
7
- module RubyToken
8
- EXPR_BEG = :EXPR_BEG
9
- EXPR_MID = :EXPR_MID
10
- EXPR_END = :EXPR_END
11
- EXPR_ARG = :EXPR_ARG
12
- EXPR_FNAME = :EXPR_FNAME
13
- EXPR_DOT = :EXPR_DOT
14
- EXPR_CLASS = :EXPR_CLASS
15
-
16
- # Represents a token in the Ruby lexer
17
- class Token
18
- # @return [Integer] the line number in the file/stream the token is
19
- # located.
20
- attr_reader :line_no
21
-
22
- # @return [Integer] the character number in the file/stream the token
23
- # is located.
24
- attr_reader :char_no
25
-
26
- # @return [String] the token text value
27
- attr_reader :text
28
-
29
- # @return [Symbol] the lexical state at the token
30
- attr_accessor :lex_state
31
-
32
- # @private
33
- NO_TEXT = "??".freeze
34
-
35
- # Creates a new Token object
36
- # @param [Integer] line_no the line number to initialize the token to
37
- # @param [Integer] char_no the char number to initialize the token to
38
- def initialize(line_no, char_no)
39
- @line_no = line_no
40
- @char_no = char_no
41
- @text = NO_TEXT
42
- end
43
-
44
- # Chainable way to sets the text attribute
45
- #
46
- # @param [String] text the new text
47
- # @return [Token] this token object
48
- def set_text(text)
49
- @text = text
50
- self
51
- end
52
- end
53
-
54
- # Represents a block
55
- class TkBlockContents < Token
56
- def text; '...' end
57
- end
58
-
59
- # Represents an end statement
60
- class TkStatementEnd < Token
61
- def text; '' end
62
- end
63
-
64
- class TkNode < Token
65
- attr :node
66
- end
67
-
68
- # Represents whitespace
69
- class TkWhitespace < Token
70
- end
71
-
72
- # Represents a Ruby identifier
73
- class TkId < Token
74
- def initialize(line_no, char_no, name)
75
- super(line_no, char_no)
76
- @name = name
77
- end
78
- attr :name
79
- end
80
-
81
- # Represents a Ruby keyword
82
- class TkKW < TkId
83
- end
84
-
85
- # Represents a Ruby value
86
- class TkVal < Token
87
- def initialize(line_no, char_no, value = nil)
88
- super(line_no, char_no)
89
- set_text(value)
90
- end
91
- end
92
-
93
- class TkOp < Token
94
- def name
95
- self.class.op_name
96
- end
97
- end
98
-
99
- class TkOPASGN < TkOp
100
- def initialize(line_no, char_no, op)
101
- super(line_no, char_no)
102
- op = TkReading2Token[op] unless op.is_a?(Symbol)
103
- @op = op
104
- end
105
- attr :op
106
- end
107
-
108
- class TkUnknownChar < Token
109
- def initialize(line_no, char_no, _id)
110
- super(line_no, char_no)
111
- @name = char_no > 255 ? '?' : char_no.chr
112
- end
113
- attr :name
114
- end
115
-
116
- class TkError < Token
117
- end
118
-
119
- # @private
120
- def set_token_position(line, char)
121
- @prev_line_no = line
122
- @prev_char_no = char
123
- end
124
-
125
- # @private
126
- def Token(token, value = nil) # rubocop:disable Style/MethodName
127
- tk = nil
128
- case token
129
- when String, Symbol
130
- source = token.is_a?(String) ? TkReading2Token : TkSymbol2Token
131
- if (tk = source[token]).nil?
132
- IRB.fail TkReading2TokenNoKey, token
133
- end
134
- tk = Token(tk[0], value)
135
- else
136
- if token
137
- tk = if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
138
- token.new(@prev_line_no, @prev_char_no)
139
- else
140
- token.new(@prev_line_no, @prev_char_no, value)
141
- end
142
- end
143
- end
144
- tk
145
- end
146
-
147
- # @private
148
- TokenDefinitions = [
149
- [:TkCLASS, TkKW, "class", EXPR_CLASS],
150
- [:TkMODULE, TkKW, "module", EXPR_BEG],
151
- [:TkDEF, TkKW, "def", EXPR_FNAME],
152
- [:TkUNDEF, TkKW, "undef", EXPR_FNAME],
153
- [:TkBEGIN, TkKW, "begin", EXPR_BEG],
154
- [:TkRESCUE, TkKW, "rescue", EXPR_MID],
155
- [:TkENSURE, TkKW, "ensure", EXPR_BEG],
156
- [:TkEND, TkKW, "end", EXPR_END],
157
- [:TkIF, TkKW, "if", EXPR_BEG, :TkIF_MOD],
158
- [:TkUNLESS, TkKW, "unless", EXPR_BEG, :TkUNLESS_MOD],
159
- [:TkTHEN, TkKW, "then", EXPR_BEG],
160
- [:TkELSIF, TkKW, "elsif", EXPR_BEG],
161
- [:TkELSE, TkKW, "else", EXPR_BEG],
162
- [:TkCASE, TkKW, "case", EXPR_BEG],
163
- [:TkWHEN, TkKW, "when", EXPR_BEG],
164
- [:TkWHILE, TkKW, "while", EXPR_BEG, :TkWHILE_MOD],
165
- [:TkUNTIL, TkKW, "until", EXPR_BEG, :TkUNTIL_MOD],
166
- [:TkFOR, TkKW, "for", EXPR_BEG],
167
- [:TkBREAK, TkKW, "break", EXPR_END],
168
- [:TkNEXT, TkKW, "next", EXPR_END],
169
- [:TkREDO, TkKW, "redo", EXPR_END],
170
- [:TkRETRY, TkKW, "retry", EXPR_END],
171
- [:TkIN, TkKW, "in", EXPR_BEG],
172
- [:TkDO, TkKW, "do", EXPR_BEG],
173
- [:TkRETURN, TkKW, "return", EXPR_MID],
174
- [:TkYIELD, TkKW, "yield", EXPR_END],
175
- [:TkSUPER, TkKW, "super", EXPR_END],
176
- [:TkSELF, TkKW, "self", EXPR_END],
177
- [:TkNIL, TkKW, "nil", EXPR_END],
178
- [:TkTRUE, TkKW, "true", EXPR_END],
179
- [:TkFALSE, TkKW, "false", EXPR_END],
180
- [:TkAND, TkKW, "and", EXPR_BEG],
181
- [:TkOR, TkKW, "or", EXPR_BEG],
182
- [:TkNOT, TkKW, "not", EXPR_BEG],
183
- [:TkIF_MOD, TkKW],
184
- [:TkUNLESS_MOD, TkKW],
185
- [:TkWHILE_MOD, TkKW],
186
- [:TkUNTIL_MOD, TkKW],
187
- [:TkALIAS, TkKW, "alias", EXPR_FNAME],
188
- [:TkDEFINED, TkKW, "defined?", EXPR_END],
189
- [:TklBEGIN, TkKW, "BEGIN", EXPR_END],
190
- [:TklEND, TkKW, "END", EXPR_END],
191
- [:Tk__LINE__, TkKW, "__LINE__", EXPR_END],
192
- [:Tk__FILE__, TkKW, "__FILE__", EXPR_END],
193
- [:TkIDENTIFIER, TkId],
194
- [:TkFID, TkId],
195
- [:TkGVAR, TkId],
196
- [:TkIVAR, TkId],
197
- [:TkCONSTANT, TkId],
198
- [:TkINTEGER, TkVal],
199
- [:TkFLOAT, TkVal],
200
- [:TkSYMBOL, TkVal],
201
- [:TkLABEL, TkVal],
202
- [:TkSTRING, TkVal],
203
- [:TkXSTRING, TkVal],
204
- [:TkREGEXP, TkVal],
205
- [:TkCOMMENT, TkVal],
206
- [:TkDSTRING, TkNode],
207
- [:TkDXSTRING, TkNode],
208
- [:TkDREGEXP, TkNode],
209
- [:TkNTH_REF, TkId],
210
- [:TkBACK_REF, TkId],
211
- [:TkUPLUS, TkOp, "+@"],
212
- [:TkUMINUS, TkOp, "-@"],
213
- [:TkPOW, TkOp, "**"],
214
- [:TkCMP, TkOp, "<=>"],
215
- [:TkEQ, TkOp, "=="],
216
- [:TkEQQ, TkOp, "==="],
217
- [:TkNEQ, TkOp, "!="],
218
- [:TkGEQ, TkOp, ">="],
219
- [:TkLEQ, TkOp, "<="],
220
- [:TkANDOP, TkOp, "&&"],
221
- [:TkOROP, TkOp, "||"],
222
- [:TkMATCH, TkOp, "=~"],
223
- [:TkNMATCH, TkOp, "!~"],
224
- [:TkDOT2, TkOp, ".."],
225
- [:TkDOT3, TkOp, "..."],
226
- [:TkAREF, TkOp, "[]"],
227
- [:TkASET, TkOp, "[]="],
228
- [:TkLSHFT, TkOp, "<<"],
229
- [:TkRSHFT, TkOp, ">>"],
230
- [:TkCOLON2, TkOp],
231
- [:TkCOLON3, TkOp],
232
- [:OPASGN, TkOp], # +=, -= etc. #
233
- [:TkASSOC, TkOp, "=>"],
234
- [:TkQUESTION, TkOp, "?"], #?
235
- [:TkCOLON, TkOp, ":"], #:
236
- [:TkSTAR], # *arg
237
- [:TkAMPER], # &arg #
238
- [:TkSYMBEG, TkId],
239
- [:TkGT, TkOp, ">"],
240
- [:TkLT, TkOp, "<"],
241
- [:TkPLUS, TkOp, "+"],
242
- [:TkMINUS, TkOp, "-"],
243
- [:TkMULT, TkOp, "*"],
244
- [:TkDIV, TkOp, "/"],
245
- [:TkMOD, TkOp, "%"],
246
- [:TkBITOR, TkOp, "|"],
247
- [:TkBITXOR, TkOp, "^"],
248
- [:TkBITAND, TkOp, "&"],
249
- [:TkBITNOT, TkOp, "~"],
250
- [:TkNOTOP, TkOp, "!"],
251
- [:TkBACKQUOTE, TkOp, "`"],
252
- [:TkASSIGN, Token, "="],
253
- [:TkDOT, Token, "."],
254
- [:TkLPAREN, Token, "("], # (exp)
255
- [:TkLBRACK, Token, "["], # [arry]
256
- [:TkLBRACE, Token, "{"], # {hash}
257
- [:TkRPAREN, Token, ")"],
258
- [:TkRBRACK, Token, "]"],
259
- [:TkRBRACE, Token, "}"],
260
- [:TkCOMMA, Token, ","],
261
- [:TkSEMICOLON, Token, ";"],
262
- [:TkSPACE, TkWhitespace],
263
- [:TkNL, TkWhitespace],
264
- [:TkEND_OF_SCRIPT, TkWhitespace],
265
- [:TkBACKSLASH, TkUnknownChar, "\\"],
266
- [:TkAT, TkUnknownChar, "@"],
267
- [:TkDOLLAR, TkUnknownChar, "\$"]
268
- ]
269
-
270
- # { reading => token_class }
271
- # { reading => [token_class, *opt] }
272
- TkReading2Token = {}
273
- TkSymbol2Token = {}
274
-
275
- # @private
276
- def self.def_token(token_n, super_token = Token, reading = nil, *opts)
277
- token_n = token_n.id2name unless token_n.is_a?(String)
278
- if RubyToken.const_defined?(token_n)
279
- # IRB.fail AlreadyDefinedToken, token_n
280
- end
281
-
282
- token_c = Class.new super_token
283
- RubyToken.const_set token_n, token_c
284
- # token_c.inspect
285
-
286
- if reading
287
- if TkReading2Token[reading]
288
- IRB.fail TkReading2TokenDuplicateError, token_n, reading
289
- end
290
- if opts.empty?
291
- TkReading2Token[reading] = [token_c]
292
- else
293
- TkReading2Token[reading] = [token_c].concat(opts)
294
- end
295
- end
296
- TkSymbol2Token[token_n.intern] = token_c
297
-
298
- if token_c <= TkOp
299
- token_c.class_eval %{
300
- def self.op_name; "#{reading}"; end
301
- }
302
- end
303
- end
304
-
305
- for defs in TokenDefinitions
306
- def_token(*defs)
307
- end
308
-
309
- NEWLINE_TOKEN = TkNL.new(0, 0)
310
- NEWLINE_TOKEN.set_text("\n")
311
- end
312
-
313
- # Lexical analyzer for Ruby source
314
- # @private
315
- class RubyLex
316
- # Read an input stream character by character. We allow for unlimited
317
- # ungetting of characters just read.
318
- #
319
- # We simplify the implementation greatly by reading the entire input
320
- # into a buffer initially, and then simply traversing it using
321
- # pointers.
322
- #
323
- # We also have to allow for the <i>here document diversion</i>. This
324
- # little gem comes about when the lexer encounters a here
325
- # document. At this point we effectively need to split the input
326
- # stream into two parts: one to read the body of the here document,
327
- # the other to read the rest of the input line where the here
328
- # document was initially encountered. For example, we might have
329
- #
330
- # do_something(<<-A, <<-B)
331
- # stuff
332
- # for
333
- # A
334
- # stuff
335
- # for
336
- # B
337
- #
338
- # When the lexer encounters the <<A, it reads until the end of the
339
- # line, and keeps it around for later. It then reads the body of the
340
- # here document. Once complete, it needs to read the rest of the
341
- # original line, but then skip the here document body.
342
- #
343
- # @private
344
- class BufferedReader
345
- attr_reader :line_num
346
-
347
- def initialize(content)
348
- if /\t/ =~ content
349
- tab_width = 2
350
- content = content.split(/\n/).map do |line|
351
- 1 while line.gsub!(/\t+/) { ' ' * (tab_width * $&.length - $`.length % tab_width) } && $~ #`
352
- line
353
- end .join("\n")
354
- end
355
- @content = String.new(content)
356
- @content << "\n" unless @content[-1, 1] == "\n"
357
- @size = @content.size
358
- @offset = 0
359
- @hwm = 0
360
- @line_num = 1
361
- @read_back_offset = 0
362
- @last_newline = 0
363
- @newline_pending = false
364
- end
365
-
366
- def column
367
- @offset - @last_newline
368
- end
369
-
370
- def getc
371
- return nil if @offset >= @size
372
- ch = @content[@offset, 1]
373
-
374
- @offset += 1
375
- @hwm = @offset if @hwm < @offset
376
-
377
- if @newline_pending
378
- @line_num += 1
379
- @last_newline = @offset - 1
380
- @newline_pending = false
381
- end
382
-
383
- if ch == "\n"
384
- @newline_pending = true
385
- end
386
- ch
387
- end
388
-
389
- def getc_already_read
390
- getc
391
- end
392
-
393
- def ungetc(_ch)
394
- raise "unget past beginning of file" if @offset <= 0
395
- @offset -= 1
396
- if @content[@offset] == ?\n
397
- @newline_pending = false
398
- end
399
- end
400
-
401
- def get_read
402
- res = @content[@read_back_offset...@offset]
403
- @read_back_offset = @offset
404
- res
405
- end
406
-
407
- def peek(at)
408
- pos = @offset + at
409
- if pos >= @size
410
- nil
411
- else
412
- @content[pos, 1]
413
- end
414
- end
415
-
416
- def peek_equal(str)
417
- @content[@offset, str.length] == str
418
- end
419
-
420
- def divert_read_from(reserve)
421
- @content[@offset, 0] = reserve
422
- @size = @content.size
423
- end
424
- end
425
-
426
- # end of nested class BufferedReader
427
-
428
- extend Exception2MessageMapper
429
- def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
430
- def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
431
- def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
432
- def_exception(:TkReading2TokenDuplicateError,
433
- "key duplicate(token_n='%s', key='%s')")
434
- def_exception(:SyntaxError, "%s")
435
-
436
- include RubyToken
437
- include IRB
438
-
439
- attr_reader :continue
440
- attr_reader :lex_state
441
-
442
- def self.debug?
443
- false
444
- end
445
-
446
- def initialize(content)
447
- lex_init
448
-
449
- @reader = BufferedReader.new(content)
450
-
451
- @exp_line_no = @line_no = 1
452
- @base_char_no = 0
453
- @indent = 0
454
-
455
- @ltype = nil
456
- @quoted = nil
457
- @lex_state = EXPR_BEG
458
- @space_seen = false
459
-
460
- @continue = false
461
- @line = ""
462
-
463
- @skip_space = false
464
- @read_auto_clean_up = false
465
- @exception_on_syntax_error = true
466
-
467
- @colonblock_seen = false
468
- end
469
-
470
- attr_accessor :skip_space
471
- attr_accessor :read_auto_clean_up
472
- attr_accessor :exception_on_syntax_error
473
-
474
- attr :indent
475
-
476
- # io functions
477
- def line_no
478
- @reader.line_num
479
- end
480
-
481
- def char_no
482
- @reader.column
483
- end
484
-
485
- def get_read
486
- @reader.get_read
487
- end
488
-
489
- def getc
490
- @reader.getc
491
- end
492
-
493
- def getc_of_rests
494
- @reader.getc_already_read
495
- end
496
-
497
- def gets
498
- (c = getc) || return
499
- l = ""
500
- begin
501
- l.concat c unless c == "\r"
502
- break if c == "\n"
503
- end while c = getc # rubocop:disable Lint/Loop
504
- l
505
- end
506
-
507
- def ungetc(c = nil)
508
- @reader.ungetc(c)
509
- end
510
-
511
- def peek_equal?(str)
512
- @reader.peek_equal(str)
513
- end
514
-
515
- def peek(i = 0)
516
- @reader.peek(i)
517
- end
518
-
519
- def lex
520
- catch(:eof) do
521
- until ((tk = token).is_a?(TkNL) || tk.is_a?(TkEND_OF_SCRIPT)) &&
522
- !@continue ||
523
- tk.nil?
524
- end
525
- line = get_read
526
-
527
- if line == "" && tk.is_a?(TkEND_OF_SCRIPT) || tk.nil?
528
- nil
529
- else
530
- line
531
- end
532
- end
533
- end
534
-
535
- def token
536
- set_token_position(line_no, char_no)
537
- catch(:eof) do
538
- begin
539
- begin
540
- tk = @OP.match(self)
541
- @space_seen = tk.is_a?(TkSPACE)
542
- rescue SyntaxError
543
- abort if @exception_on_syntax_error
544
- tk = TkError.new(line_no, char_no)
545
- end
546
- end while @skip_space && tk.is_a?(TkSPACE)
547
- if @read_auto_clean_up
548
- get_read
549
- end
550
- # throw :eof unless tk
551
- p tk if $DEBUG
552
- tk.lex_state = lex_state if tk
553
- tk
554
- end
555
- end
556
-
557
- ENINDENT_CLAUSE = [
558
- "case", "class", "def", "do", "for", "if",
559
- "module", "unless", "until", "while", "begin"
560
- ] #, "when"
561
- ACCEPTS_COLON = ["if", "for", "unless", "until", "while"]
562
- DEINDENT_CLAUSE = ["end"] #, "when"
563
-
564
- PERCENT_LTYPE = {
565
- "q" => "\'",
566
- "Q" => "\"",
567
- "x" => "\`",
568
- "r" => "/",
569
- "w" => "]",
570
- "W" => "]"
571
- }
572
-
573
- PERCENT_PAREN = {
574
- "{" => "}",
575
- "[" => "]",
576
- "<" => ">",
577
- "(" => ")"
578
- }
579
-
580
- Ltype2Token = {
581
- "\'" => TkSTRING,
582
- "\"" => TkSTRING,
583
- "\`" => TkXSTRING,
584
- "/" => TkREGEXP,
585
- "]" => TkDSTRING
586
- }
587
- Ltype2Token.default = TkSTRING
588
-
589
- DLtype2Token = {
590
- "\"" => TkDSTRING,
591
- "\`" => TkDXSTRING,
592
- "/" => TkDREGEXP
593
- }
594
-
595
- def lex_init()
596
- @OP = SLex.new
597
- @OP.def_rules("\0", "\004", "\032") do |chars, _io|
598
- Token(TkEND_OF_SCRIPT).set_text(chars)
599
- end
600
-
601
- @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |chars, _io|
602
- @space_seen = true
603
- while (ch = getc) =~ /[ \t\f\r\13]/
604
- chars << ch
605
- end
606
- ungetc
607
- Token(TkSPACE).set_text(chars)
608
- end
609
-
610
- @OP.def_rule("#") do |_op, _io|
611
- identify_comment
612
- end
613
-
614
- @OP.def_rule("=begin", proc { @prev_char_no == 0 && peek(0) =~ /\s/ }) do |op, _io|
615
- str = String.new(op)
616
- @ltype = "="
617
-
618
- begin
619
- line = String.new
620
- begin
621
- ch = getc
622
- line << ch
623
- end until ch == "\n"
624
- str << line
625
- end until line =~ /^=end/
626
-
627
- ungetc
628
-
629
- @ltype = nil
630
-
631
- if str =~ /\A=begin\s+rdoc/i
632
- str.sub!(/\A=begin.*\n/, '')
633
- str.sub!(/^=end.*/m, '')
634
- Token(TkCOMMENT).set_text(str)
635
- else
636
- Token(TkCOMMENT).set_text(str)
637
- end
638
- end
639
-
640
- @OP.def_rule("\n") do
641
- print "\\n\n" if RubyLex.debug?
642
- @colonblock_seen = false
643
- case @lex_state
644
- when EXPR_BEG, EXPR_FNAME, EXPR_DOT
645
- @continue = true
646
- else
647
- @continue = false
648
- @lex_state = EXPR_BEG
649
- end
650
- Token(TkNL).set_text("\n")
651
- end
652
-
653
- @OP.def_rules("*", "**",
654
- "!", "!=", "!~",
655
- "=", "==", "===",
656
- "=~", "<=>",
657
- "<", "<=",
658
- ">", ">=", ">>") do |op, _io|
659
- @lex_state = EXPR_BEG
660
- Token(op).set_text(op)
661
- end
662
-
663
- @OP.def_rules("<<") do |op, _io|
664
- tk = nil
665
- if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
666
- (@lex_state != EXPR_ARG || @space_seen)
667
- c = peek(0)
668
- tk = identify_here_document if /[-\w\"\'\`]/ =~ c
669
- end
670
- if !tk
671
- @lex_state = EXPR_BEG
672
- tk = Token(op).set_text(op)
673
- end
674
- tk
675
- end
676
-
677
- @OP.def_rules("'", '"') do |op, _io|
678
- identify_string(op)
679
- end
680
-
681
- @OP.def_rules("`") do |op, _io|
682
- if @lex_state == EXPR_FNAME
683
- Token(op).set_text(op)
684
- else
685
- identify_string(op)
686
- end
687
- end
688
-
689
- @OP.def_rules('?') do |op, _io|
690
- if @lex_state == EXPR_END
691
- @lex_state = EXPR_BEG
692
- Token(TkQUESTION).set_text(op)
693
- else
694
- ch = getc
695
- if @lex_state == EXPR_ARG && ch !~ /\s/
696
- ungetc
697
- @lex_state = EXPR_BEG
698
- Token(TkQUESTION).set_text(op)
699
- else
700
- str = String.new(op)
701
- str << ch
702
- if ch == '\\' #'
703
- str << read_escape
704
- end
705
- @lex_state = EXPR_END
706
- Token(TkINTEGER).set_text(str)
707
- end
708
- end
709
- end
710
-
711
- @OP.def_rules("&", "&&", "|", "||") do |op, _io|
712
- @lex_state = EXPR_BEG
713
- Token(op).set_text(op)
714
- end
715
-
716
- @OP.def_rules("+=", "-=", "*=", "**=",
717
- "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, _io|
718
- @lex_state = EXPR_BEG
719
- op =~ /^(.*)=$/
720
- Token(TkOPASGN, $1).set_text(op)
721
- end
722
-
723
- @OP.def_rule("+@", proc { @lex_state == EXPR_FNAME }) do |op, _io|
724
- Token(TkUPLUS).set_text(op)
725
- end
726
-
727
- @OP.def_rule("-@", proc { @lex_state == EXPR_FNAME }) do |op, _io|
728
- Token(TkUMINUS).set_text(op)
729
- end
730
-
731
- @OP.def_rules("+", "-") do |op, _io|
732
- catch(:RET) do
733
- if @lex_state == EXPR_ARG
734
- if @space_seen && peek(0) =~ /[0-9]/
735
- throw :RET, identify_number(op)
736
- else
737
- @lex_state = EXPR_BEG
738
- end
739
- elsif @lex_state != EXPR_END && peek(0) =~ /[0-9]/
740
- throw :RET, identify_number(op)
741
- else
742
- @lex_state = EXPR_BEG
743
- end
744
- Token(op).set_text(op)
745
- end
746
- end
747
-
748
- @OP.def_rule(".") do
749
- @lex_state = EXPR_BEG
750
- if peek(0) =~ /[0-9]/
751
- ungetc
752
- identify_number("")
753
- else
754
- # for obj.if
755
- @lex_state = EXPR_DOT
756
- Token(TkDOT).set_text(".")
757
- end
758
- end
759
-
760
- @OP.def_rules("..", "...") do |op, _io|
761
- @lex_state = EXPR_BEG
762
- Token(op).set_text(op)
763
- end
764
-
765
- lex_int2
766
- end
767
-
768
- def lex_int2
769
- @OP.def_rules("]", "}", ")") do |op, _io|
770
- @lex_state = EXPR_END
771
- @indent -= 1
772
- Token(op).set_text(op)
773
- end
774
-
775
- @OP.def_rule(":") do
776
- if (@colonblock_seen && @lex_state != EXPR_BEG) || peek(0) =~ /\s/
777
- @lex_state = EXPR_BEG
778
- tk = Token(TkCOLON)
779
- else
780
- @lex_state = EXPR_FNAME
781
- tk = Token(TkSYMBEG)
782
- end
783
- tk.set_text(":")
784
- end
785
-
786
- @OP.def_rule("::") do
787
- # p @lex_state.id2name, @space_seen
788
- if @lex_state == EXPR_BEG || @lex_state == EXPR_ARG && @space_seen
789
- @lex_state = EXPR_BEG
790
- tk = Token(TkCOLON3)
791
- else
792
- @lex_state = EXPR_DOT
793
- tk = Token(TkCOLON2)
794
- end
795
- tk.set_text("::")
796
- end
797
-
798
- @OP.def_rule("/") do |op, _io|
799
- if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
800
- identify_string(op)
801
- elsif peek(0) == '='
802
- getc
803
- @lex_state = EXPR_BEG
804
- Token(TkOPASGN, :/).set_text("/=") #")
805
- elsif @lex_state == EXPR_ARG && @space_seen && peek(0) !~ /\s/
806
- identify_string(op)
807
- else
808
- @lex_state = EXPR_BEG
809
- Token("/").set_text(op)
810
- end
811
- end
812
-
813
- @OP.def_rules("^") do
814
- @lex_state = EXPR_BEG
815
- Token("^").set_text("^")
816
- end
817
-
818
- # @OP.def_rules("^=") do
819
- # @lex_state = EXPR_BEG
820
- # Token(TkOPASGN, :^)
821
- # end
822
-
823
- @OP.def_rules(",", ";") do |op, _io|
824
- @colonblock_seen = false
825
- @lex_state = EXPR_BEG
826
- Token(op).set_text(op)
827
- end
828
-
829
- @OP.def_rule("~") do
830
- @lex_state = EXPR_BEG
831
- Token("~").set_text("~")
832
- end
833
-
834
- @OP.def_rule("~@", proc { @lex_state = EXPR_FNAME }) do
835
- @lex_state = EXPR_BEG
836
- Token("~").set_text("~@")
837
- end
838
-
839
- @OP.def_rule("(") do
840
- @indent += 1
841
- # if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
842
- # @lex_state = EXPR_BEG
843
- # tk = Token(TkfLPAREN)
844
- # else
845
- @lex_state = EXPR_BEG
846
- tk = Token(TkLPAREN)
847
- # end
848
- tk.set_text("(")
849
- end
850
-
851
- @OP.def_rule("[]", proc { @lex_state == EXPR_FNAME }) do
852
- Token("[]").set_text("[]")
853
- end
854
-
855
- @OP.def_rule("[]=", proc { @lex_state == EXPR_FNAME }) do
856
- Token("[]=").set_text("[]=")
857
- end
858
-
859
- @OP.def_rule("[") do
860
- @indent += 1
861
- # if @lex_state == EXPR_FNAME
862
- # t = Token(TkfLBRACK)
863
- # else
864
- # if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
865
- # t = Token(TkLBRACK)
866
- # elsif @lex_state == EXPR_ARG && @space_seen
867
- # else
868
- # t = Token(TkfLBRACK)
869
- # end
870
- # end
871
- t = Token(TkLBRACK)
872
- @lex_state = EXPR_BEG
873
- t.set_text("[")
874
- end
875
-
876
- @OP.def_rule("{") do
877
- @indent += 1
878
- # if @lex_state != EXPR_END && @lex_state != EXPR_ARG
879
- # t = Token(TkLBRACE)
880
- # else
881
- # t = Token(TkfLBRACE)
882
- # end
883
- t = Token(TkLBRACE)
884
- @lex_state = EXPR_BEG
885
- t.set_text("{")
886
- end
887
-
888
- @OP.def_rule('\\') do #'
889
- if getc == "\n"
890
- @space_seen = true
891
- @continue = true
892
- Token(TkSPACE).set_text("\\\n")
893
- else
894
- ungetc
895
- Token("\\").set_text("\\") #"
896
- end
897
- end
898
-
899
- @OP.def_rule('%') do |_op, _io|
900
- if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
901
- identify_quotation('%')
902
- elsif peek(0) == '='
903
- getc
904
- Token(TkOPASGN, "%").set_text("%=")
905
- elsif @lex_state == EXPR_ARG && @space_seen && peek(0) !~ /\s/
906
- identify_quotation('%')
907
- else
908
- @lex_state = EXPR_BEG
909
- Token("%").set_text("%")
910
- end
911
- end
912
-
913
- @OP.def_rule('$') do #'
914
- identify_gvar
915
- end
916
-
917
- @OP.def_rule('@') do
918
- if peek(0) =~ /[@\w]/
919
- ungetc
920
- identify_identifier
921
- else
922
- Token("@").set_text("@")
923
- end
924
- end
925
-
926
- # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
927
- # |op, io|
928
- # @indent += 1
929
- # @lex_state = EXPR_FNAME
930
- # # @lex_state = EXPR_END
931
- # # until @rests[0] == "\n" or @rests[0] == ";"
932
- # # rests.shift
933
- # # end
934
- # end
935
-
936
- @OP.def_rule("__END__", proc { @prev_char_no == 0 && peek(0) =~ /[\r\n]/ }) do
937
- throw :eof
938
- end
939
-
940
- @OP.def_rule("") do |op, io|
941
- printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
942
- if peek(0) =~ /[0-9]/
943
- t = identify_number("")
944
- elsif peek(0) =~ /[\w]/
945
- t = identify_identifier
946
- end
947
- printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
948
- t
949
- end
950
-
951
- p @OP if RubyLex.debug?
952
- end
953
-
954
- def identify_gvar
955
- @lex_state = EXPR_END
956
- str = String.new("$")
957
-
958
- tk = case ch = getc
959
- when %r{[~_*$?!@/\\;,=:<>".]}
960
- str << ch
961
- Token(TkGVAR, str)
962
-
963
- when "-"
964
- str << "-" << getc
965
- Token(TkGVAR, str)
966
-
967
- when "&", "`", "'", "+"
968
- str << ch
969
- Token(TkBACK_REF, str)
970
-
971
- when /[1-9]/
972
- str << ch
973
- while (ch = getc) =~ /[0-9]/
974
- str << ch
975
- end
976
- ungetc
977
- Token(TkNTH_REF)
978
- when /\w/
979
- ungetc
980
- ungetc
981
- return identify_identifier
982
- else
983
- ungetc
984
- Token("$")
985
- end
986
- tk.set_text(str)
987
- end
988
-
989
- def identify_identifier
990
- token = ""
991
- token.concat getc if peek(0) =~ /[$@]/
992
- token.concat getc if peek(0) == "@"
993
-
994
- while (ch = getc) =~ /\w|_/
995
- print ":", ch, ":" if RubyLex.debug?
996
- token.concat ch
997
- end
998
- ungetc
999
-
1000
- if ch == "!" || ch == "?"
1001
- token.concat getc
1002
- end
1003
- # fix token
1004
-
1005
- # $stderr.puts "identifier - #{token}, state = #@lex_state"
1006
-
1007
- case token
1008
- when /^\$/
1009
- return Token(TkGVAR, token).set_text(token)
1010
- when /^\@/
1011
- @lex_state = EXPR_END
1012
- return Token(TkIVAR, token).set_text(token)
1013
- end
1014
-
1015
- if @lex_state != EXPR_DOT
1016
- print token, "\n" if RubyLex.debug?
1017
-
1018
- token_c, *trans = TkReading2Token[token]
1019
- if token_c
1020
- # reserved word?
1021
-
1022
- if @lex_state != EXPR_BEG &&
1023
- @lex_state != EXPR_FNAME &&
1024
- trans[1]
1025
- # modifiers
1026
- token_c = TkSymbol2Token[trans[1]]
1027
- @lex_state = trans[0]
1028
- else
1029
- if @lex_state != EXPR_FNAME
1030
- if ENINDENT_CLAUSE.include?(token)
1031
- @indent += 1
1032
-
1033
- if ACCEPTS_COLON.include?(token)
1034
- @colonblock_seen = true
1035
- else
1036
- @colonblock_seen = false
1037
- end
1038
- elsif DEINDENT_CLAUSE.include?(token)
1039
- @indent -= 1
1040
- @colonblock_seen = false
1041
- end
1042
- @lex_state = trans[0]
1043
- else
1044
- @lex_state = EXPR_END
1045
- end
1046
- end
1047
- return Token(token_c, token).set_text(token)
1048
- end
1049
- end
1050
-
1051
- if @lex_state == EXPR_FNAME
1052
- @lex_state = EXPR_END
1053
- if peek(0) == '='
1054
- token.concat getc
1055
- end
1056
- elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
1057
- @lex_state = EXPR_ARG
1058
- else
1059
- @lex_state = EXPR_END
1060
- end
1061
-
1062
- if token[0, 1] =~ /[A-Z]/
1063
- return Token(TkCONSTANT, token).set_text(token)
1064
- elsif token[token.size - 1, 1] =~ /[!?]/
1065
- return Token(TkFID, token).set_text(token)
1066
- else
1067
- return Token(TkIDENTIFIER, token).set_text(token)
1068
- end
1069
- end
1070
-
1071
- def identify_here_document
1072
- ch = getc
1073
- if ch == "-"
1074
- ch = getc
1075
- indent = true
1076
- end
1077
- if /['"`]/ =~ ch # '
1078
- lt = ch
1079
- quoted = ""
1080
- while (c = getc) && c != lt
1081
- quoted.concat c
1082
- end
1083
- else
1084
- lt = '"'
1085
- quoted = ch.dup
1086
- while (c = getc) && c =~ /\w/
1087
- quoted.concat c
1088
- end
1089
- ungetc
1090
- end
1091
-
1092
- ltback, @ltype = @ltype, lt
1093
- reserve = String.new
1094
-
1095
- while ch = getc
1096
- reserve << ch
1097
- if ch == "\\" #"
1098
- ch = getc
1099
- reserve << ch
1100
- elsif ch == "\n"
1101
- break
1102
- end
1103
- end
1104
-
1105
- str = String.new
1106
- while (l = gets)
1107
- l.chomp!
1108
- l.strip! if indent
1109
- break if l == quoted
1110
- str << l.chomp << "\n"
1111
- end
1112
-
1113
- @reader.divert_read_from(reserve)
1114
-
1115
- @ltype = ltback
1116
- @lex_state = EXPR_END
1117
- Token(Ltype2Token[lt], str).set_text(str.dump)
1118
- end
1119
-
1120
- def identify_quotation(initial_char)
1121
- ch = getc
1122
- if lt = PERCENT_LTYPE[ch]
1123
- initial_char += ch
1124
- ch = getc
1125
- elsif ch =~ /\W/
1126
- lt = "\""
1127
- else
1128
- # RubyLex.fail SyntaxError, "unknown type of %string ('#{ch}')"
1129
- end
1130
- # if ch !~ /\W/
1131
- # ungetc
1132
- # next
1133
- # end
1134
- # @ltype = lt
1135
- @quoted = ch unless @quoted = PERCENT_PAREN[ch]
1136
- identify_string(lt, @quoted, ch, initial_char) if lt
1137
- end
1138
-
1139
- def identify_number(start)
1140
- str = start.dup
1141
-
1142
- if start == "+" || start == "-" || start == ""
1143
- start = getc
1144
- str << start
1145
- end
1146
-
1147
- @lex_state = EXPR_END
1148
-
1149
- if start == "0"
1150
- if peek(0) == "x"
1151
- ch = getc
1152
- str << ch
1153
- match = /[0-9a-f_]/
1154
- else
1155
- match = /[0-7_]/
1156
- end
1157
- while ch = getc
1158
- if ch !~ match
1159
- ungetc
1160
- break
1161
- else
1162
- str << ch
1163
- end
1164
- end
1165
- return Token(TkINTEGER).set_text(str)
1166
- end
1167
-
1168
- type = TkINTEGER
1169
- allow_point = true
1170
- allow_e = true
1171
- while ch = getc
1172
- case ch
1173
- when /[0-9_]/
1174
- str << ch
1175
-
1176
- when allow_point && "."
1177
- type = TkFLOAT
1178
- if peek(0) !~ /[0-9]/
1179
- ungetc
1180
- break
1181
- end
1182
- str << ch
1183
- allow_point = false
1184
-
1185
- when allow_e && "e", allow_e && "E"
1186
- str << ch
1187
- type = TkFLOAT
1188
- if peek(0) =~ /[+-]/
1189
- str << getc
1190
- end
1191
- allow_e = false
1192
- allow_point = false
1193
- else
1194
- ungetc
1195
- break
1196
- end
1197
- end
1198
- Token(type).set_text(str)
1199
- end
1200
-
1201
- def identify_string(ltype, quoted = ltype, opener = nil, initial_char = nil)
1202
- @ltype = ltype
1203
- @quoted = quoted
1204
- subtype = nil
1205
-
1206
- str = String.new
1207
- str << initial_char if initial_char
1208
- str << (opener || quoted)
1209
-
1210
- nest = 0
1211
- begin
1212
- while ch = getc
1213
- str << ch
1214
- if @quoted == ch
1215
- if nest == 0
1216
- break
1217
- else
1218
- nest -= 1
1219
- end
1220
- elsif opener == ch
1221
- nest += 1
1222
- elsif @ltype != "'" && @ltype != "]" && ch == "#"
1223
- ch = getc
1224
- if ch == "{"
1225
- subtype = true
1226
- str << ch << skip_inner_expression
1227
- else
1228
- ungetc(ch)
1229
- end
1230
- elsif ch == '\\' #'
1231
- str << read_escape
1232
- end
1233
- end
1234
- if @ltype == "/"
1235
- if peek(0) =~ /i|o|n|e|s/
1236
- str << getc
1237
- end
1238
- end
1239
- if subtype
1240
- Token(DLtype2Token[ltype], str)
1241
- else
1242
- Token(Ltype2Token[ltype], str)
1243
- end.set_text(str)
1244
- ensure
1245
- @ltype = nil
1246
- @quoted = nil
1247
- @lex_state = EXPR_END
1248
- end
1249
- end
1250
-
1251
- def skip_inner_expression
1252
- res = String.new
1253
- nest = 0
1254
- while (ch = getc)
1255
- res << ch
1256
- if ch == '}'
1257
- break if nest == 0
1258
- nest -= 1
1259
- elsif ch == '{'
1260
- nest += 1
1261
- end
1262
- end
1263
- res
1264
- end
1265
-
1266
- def identify_comment
1267
- @ltype = "#"
1268
- comment = String.new("#")
1269
- while ch = getc
1270
- if ch == "\\"
1271
- ch = getc
1272
- if ch == "\n"
1273
- ch = " "
1274
- else
1275
- comment << "\\"
1276
- end
1277
- else
1278
- if ch == "\n"
1279
- @ltype = nil
1280
- ungetc
1281
- break
1282
- end
1283
- end
1284
- comment << ch
1285
- end
1286
- Token(TkCOMMENT).set_text(comment)
1287
- end
1288
-
1289
- def read_escape
1290
- res = String.new
1291
- case ch = getc
1292
- when /[0-7]/
1293
- ungetc ch
1294
- 3.times do
1295
- case ch = getc
1296
- when /[0-7]/
1297
- when nil
1298
- break
1299
- else
1300
- ungetc
1301
- break
1302
- end
1303
- res << ch
1304
- end
1305
-
1306
- when "x"
1307
- res << ch
1308
- 2.times do
1309
- case ch = getc
1310
- when /[0-9a-fA-F]/
1311
- when nil
1312
- break
1313
- else
1314
- ungetc
1315
- break
1316
- end
1317
- res << ch
1318
- end
1319
-
1320
- when "M"
1321
- res << ch
1322
- if (ch = getc) != '-'
1323
- ungetc
1324
- else
1325
- res << ch
1326
- if (ch = getc) == "\\" #"
1327
- res << ch
1328
- res << read_escape
1329
- else
1330
- res << ch
1331
- end
1332
- end
1333
-
1334
- when "C", "c" #, "^"
1335
- res << ch
1336
- if ch == "C" && (ch = getc) != "-"
1337
- ungetc
1338
- else
1339
- res << ch
1340
- if (ch = getc) == "\\" #"
1341
- res << ch
1342
- res << read_escape
1343
- else
1344
- res << ch
1345
- end
1346
- end
1347
- else
1348
- res << ch
1349
- end
1350
- res
1351
- end
1352
- end
1353
- end
1354
- end
1
+ require_relative 'irb/slex'
2
+
3
+ module YARD
4
+ module Parser::Ruby::Legacy
5
+ # Legacy lexical tokenizer module.
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
+ # Represents a token in the Ruby lexer
16
+ class Token
17
+ # @return [Integer] the line number in the file/stream the token is
18
+ # located.
19
+ attr_reader :line_no
20
+
21
+ # @return [Integer] the character number in the file/stream the token
22
+ # is located.
23
+ attr_reader :char_no
24
+
25
+ # @return [String] the token text value
26
+ attr_reader :text
27
+
28
+ # @return [Symbol] the lexical state at the token
29
+ attr_accessor :lex_state
30
+
31
+ # @private
32
+ NO_TEXT = "??".freeze
33
+
34
+ # Creates a new Token object
35
+ # @param [Integer] line_no the line number to initialize the token to
36
+ # @param [Integer] char_no the char number to initialize the token to
37
+ def initialize(line_no, char_no)
38
+ @line_no = line_no
39
+ @char_no = char_no
40
+ @text = NO_TEXT
41
+ end
42
+
43
+ # Chainable way to sets the text attribute
44
+ #
45
+ # @param [String] text the new text
46
+ # @return [Token] this token object
47
+ def set_text(text)
48
+ @text = text
49
+ self
50
+ end
51
+ end
52
+
53
+ # Represents a block
54
+ class TkBlockContents < Token
55
+ def text; '...' end
56
+ end
57
+
58
+ # Represents an end statement
59
+ class TkStatementEnd < Token
60
+ def text; '' end
61
+ end
62
+
63
+ class TkNode < Token
64
+ attr :node
65
+ end
66
+
67
+ # Represents whitespace
68
+ class TkWhitespace < Token
69
+ end
70
+
71
+ # Represents a Ruby identifier
72
+ class TkId < Token
73
+ def initialize(line_no, char_no, name)
74
+ super(line_no, char_no)
75
+ @name = name
76
+ end
77
+ attr :name
78
+ end
79
+
80
+ # Represents a Ruby keyword
81
+ class TkKW < TkId
82
+ end
83
+
84
+ # Represents a Ruby value
85
+ class TkVal < Token
86
+ def initialize(line_no, char_no, value = nil)
87
+ super(line_no, char_no)
88
+ set_text(value)
89
+ end
90
+ end
91
+
92
+ class TkOp < Token
93
+ def name
94
+ self.class.op_name
95
+ end
96
+ end
97
+
98
+ class TkOPASGN < TkOp
99
+ def initialize(line_no, char_no, op)
100
+ super(line_no, char_no)
101
+ op = TkReading2Token[op] unless op.is_a?(Symbol)
102
+ @op = op
103
+ end
104
+ attr :op
105
+ end
106
+
107
+ class TkUnknownChar < Token
108
+ def initialize(line_no, char_no, _id)
109
+ super(line_no, char_no)
110
+ @name = char_no > 255 ? '?' : char_no.chr
111
+ end
112
+ attr :name
113
+ end
114
+
115
+ class TkError < Token
116
+ end
117
+
118
+ # @private
119
+ def set_token_position(line, char)
120
+ @prev_line_no = line
121
+ @prev_char_no = char
122
+ end
123
+
124
+ # @private
125
+ def Token(token, value = nil) # rubocop:disable Style/MethodName
126
+ tk = nil
127
+ case token
128
+ when String, Symbol
129
+ source = token.is_a?(String) ? TkReading2Token : TkSymbol2Token
130
+ if (tk = source[token]).nil?
131
+ raise "no key #{token}"
132
+ end
133
+ tk = Token(tk[0], value)
134
+ else
135
+ if token
136
+ tk = if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
137
+ token.new(@prev_line_no, @prev_char_no)
138
+ else
139
+ token.new(@prev_line_no, @prev_char_no, value)
140
+ end
141
+ end
142
+ end
143
+ tk
144
+ end
145
+
146
+ # @private
147
+ TokenDefinitions = [
148
+ [:TkCLASS, TkKW, "class", EXPR_CLASS],
149
+ [:TkMODULE, TkKW, "module", EXPR_BEG],
150
+ [:TkDEF, TkKW, "def", EXPR_FNAME],
151
+ [:TkUNDEF, TkKW, "undef", EXPR_FNAME],
152
+ [:TkBEGIN, TkKW, "begin", EXPR_BEG],
153
+ [:TkRESCUE, TkKW, "rescue", EXPR_MID],
154
+ [:TkENSURE, TkKW, "ensure", EXPR_BEG],
155
+ [:TkEND, TkKW, "end", EXPR_END],
156
+ [:TkIF, TkKW, "if", EXPR_BEG, :TkIF_MOD],
157
+ [:TkUNLESS, TkKW, "unless", EXPR_BEG, :TkUNLESS_MOD],
158
+ [:TkTHEN, TkKW, "then", EXPR_BEG],
159
+ [:TkELSIF, TkKW, "elsif", EXPR_BEG],
160
+ [:TkELSE, TkKW, "else", EXPR_BEG],
161
+ [:TkCASE, TkKW, "case", EXPR_BEG],
162
+ [:TkWHEN, TkKW, "when", EXPR_BEG],
163
+ [:TkWHILE, TkKW, "while", EXPR_BEG, :TkWHILE_MOD],
164
+ [:TkUNTIL, TkKW, "until", EXPR_BEG, :TkUNTIL_MOD],
165
+ [:TkFOR, TkKW, "for", EXPR_BEG],
166
+ [:TkBREAK, TkKW, "break", EXPR_END],
167
+ [:TkNEXT, TkKW, "next", EXPR_END],
168
+ [:TkREDO, TkKW, "redo", EXPR_END],
169
+ [:TkRETRY, TkKW, "retry", EXPR_END],
170
+ [:TkIN, TkKW, "in", EXPR_BEG],
171
+ [:TkDO, TkKW, "do", EXPR_BEG],
172
+ [:TkRETURN, TkKW, "return", EXPR_MID],
173
+ [:TkYIELD, TkKW, "yield", EXPR_END],
174
+ [:TkSUPER, TkKW, "super", EXPR_END],
175
+ [:TkSELF, TkKW, "self", EXPR_END],
176
+ [:TkNIL, TkKW, "nil", EXPR_END],
177
+ [:TkTRUE, TkKW, "true", EXPR_END],
178
+ [:TkFALSE, TkKW, "false", EXPR_END],
179
+ [:TkAND, TkKW, "and", EXPR_BEG],
180
+ [:TkOR, TkKW, "or", EXPR_BEG],
181
+ [:TkNOT, TkKW, "not", EXPR_BEG],
182
+ [:TkIF_MOD, TkKW],
183
+ [:TkUNLESS_MOD, TkKW],
184
+ [:TkWHILE_MOD, TkKW],
185
+ [:TkUNTIL_MOD, TkKW],
186
+ [:TkALIAS, TkKW, "alias", EXPR_FNAME],
187
+ [:TkDEFINED, TkKW, "defined?", EXPR_END],
188
+ [:TklBEGIN, TkKW, "BEGIN", EXPR_END],
189
+ [:TklEND, TkKW, "END", EXPR_END],
190
+ [:Tk__LINE__, TkKW, "__LINE__", EXPR_END],
191
+ [:Tk__FILE__, TkKW, "__FILE__", EXPR_END],
192
+ [:TkIDENTIFIER, TkId],
193
+ [:TkFID, TkId],
194
+ [:TkGVAR, TkId],
195
+ [:TkIVAR, TkId],
196
+ [:TkCONSTANT, TkId],
197
+ [:TkINTEGER, TkVal],
198
+ [:TkFLOAT, TkVal],
199
+ [:TkSYMBOL, TkVal],
200
+ [:TkLABEL, TkVal],
201
+ [:TkSTRING, TkVal],
202
+ [:TkXSTRING, TkVal],
203
+ [:TkREGEXP, TkVal],
204
+ [:TkCOMMENT, TkVal],
205
+ [:TkDSTRING, TkNode],
206
+ [:TkDXSTRING, TkNode],
207
+ [:TkDREGEXP, TkNode],
208
+ [:TkNTH_REF, TkId],
209
+ [:TkBACK_REF, TkId],
210
+ [:TkUPLUS, TkOp, "+@"],
211
+ [:TkUMINUS, TkOp, "-@"],
212
+ [:TkPOW, TkOp, "**"],
213
+ [:TkCMP, TkOp, "<=>"],
214
+ [:TkEQ, TkOp, "=="],
215
+ [:TkEQQ, TkOp, "==="],
216
+ [:TkNEQ, TkOp, "!="],
217
+ [:TkGEQ, TkOp, ">="],
218
+ [:TkLEQ, TkOp, "<="],
219
+ [:TkANDOP, TkOp, "&&"],
220
+ [:TkOROP, TkOp, "||"],
221
+ [:TkMATCH, TkOp, "=~"],
222
+ [:TkNMATCH, TkOp, "!~"],
223
+ [:TkDOT2, TkOp, ".."],
224
+ [:TkDOT3, TkOp, "..."],
225
+ [:TkAREF, TkOp, "[]"],
226
+ [:TkASET, TkOp, "[]="],
227
+ [:TkLSHFT, TkOp, "<<"],
228
+ [:TkRSHFT, TkOp, ">>"],
229
+ [:TkCOLON2, TkOp],
230
+ [:TkCOLON3, TkOp],
231
+ [:OPASGN, TkOp], # +=, -= etc. #
232
+ [:TkASSOC, TkOp, "=>"],
233
+ [:TkQUESTION, TkOp, "?"], #?
234
+ [:TkCOLON, TkOp, ":"], #:
235
+ [:TkSTAR], # *arg
236
+ [:TkAMPER], # &arg #
237
+ [:TkSYMBEG, TkId],
238
+ [:TkGT, TkOp, ">"],
239
+ [:TkLT, TkOp, "<"],
240
+ [:TkPLUS, TkOp, "+"],
241
+ [:TkMINUS, TkOp, "-"],
242
+ [:TkMULT, TkOp, "*"],
243
+ [:TkDIV, TkOp, "/"],
244
+ [:TkMOD, TkOp, "%"],
245
+ [:TkBITOR, TkOp, "|"],
246
+ [:TkBITXOR, TkOp, "^"],
247
+ [:TkBITAND, TkOp, "&"],
248
+ [:TkBITNOT, TkOp, "~"],
249
+ [:TkNOTOP, TkOp, "!"],
250
+ [:TkBACKQUOTE, TkOp, "`"],
251
+ [:TkASSIGN, Token, "="],
252
+ [:TkDOT, Token, "."],
253
+ [:TkLPAREN, Token, "("], # (exp)
254
+ [:TkLBRACK, Token, "["], # [arry]
255
+ [:TkLBRACE, Token, "{"], # {hash}
256
+ [:TkRPAREN, Token, ")"],
257
+ [:TkRBRACK, Token, "]"],
258
+ [:TkRBRACE, Token, "}"],
259
+ [:TkCOMMA, Token, ","],
260
+ [:TkSEMICOLON, Token, ";"],
261
+ [:TkSPACE, TkWhitespace],
262
+ [:TkNL, TkWhitespace],
263
+ [:TkEND_OF_SCRIPT, TkWhitespace],
264
+ [:TkBACKSLASH, TkUnknownChar, "\\"],
265
+ [:TkAT, TkUnknownChar, "@"],
266
+ [:TkDOLLAR, TkUnknownChar, "\$"]
267
+ ]
268
+
269
+ # { reading => token_class }
270
+ # { reading => [token_class, *opt] }
271
+ TkReading2Token = {}
272
+ TkSymbol2Token = {}
273
+
274
+ # @private
275
+ def self.def_token(token_n, super_token = Token, reading = nil, *opts)
276
+ token_n = token_n.id2name unless token_n.is_a?(String)
277
+ if RubyToken.const_defined?(token_n)
278
+ # IRB.fail AlreadyDefinedToken, token_n
279
+ end
280
+
281
+ token_c = Class.new super_token
282
+ RubyToken.const_set token_n, token_c
283
+ # token_c.inspect
284
+
285
+ if reading
286
+ if TkReading2Token[reading]
287
+ raise "duplicate #{token_n} #{reading}"
288
+ end
289
+ if opts.empty?
290
+ TkReading2Token[reading] = [token_c]
291
+ else
292
+ TkReading2Token[reading] = [token_c].concat(opts)
293
+ end
294
+ end
295
+ TkSymbol2Token[token_n.intern] = token_c
296
+
297
+ if token_c <= TkOp
298
+ token_c.class_eval %{
299
+ def self.op_name; "#{reading}"; end
300
+ }
301
+ end
302
+ end
303
+
304
+ for defs in TokenDefinitions
305
+ def_token(*defs)
306
+ end
307
+
308
+ NEWLINE_TOKEN = TkNL.new(0, 0)
309
+ NEWLINE_TOKEN.set_text("\n")
310
+ end
311
+
312
+ # Lexical analyzer for Ruby source
313
+ # @private
314
+ class RubyLex
315
+ # Read an input stream character by character. We allow for unlimited
316
+ # ungetting of characters just read.
317
+ #
318
+ # We simplify the implementation greatly by reading the entire input
319
+ # into a buffer initially, and then simply traversing it using
320
+ # pointers.
321
+ #
322
+ # We also have to allow for the <i>here document diversion</i>. This
323
+ # little gem comes about when the lexer encounters a here
324
+ # document. At this point we effectively need to split the input
325
+ # stream into two parts: one to read the body of the here document,
326
+ # the other to read the rest of the input line where the here
327
+ # document was initially encountered. For example, we might have
328
+ #
329
+ # do_something(<<-A, <<-B)
330
+ # stuff
331
+ # for
332
+ # A
333
+ # stuff
334
+ # for
335
+ # B
336
+ #
337
+ # When the lexer encounters the <<A, it reads until the end of the
338
+ # line, and keeps it around for later. It then reads the body of the
339
+ # here document. Once complete, it needs to read the rest of the
340
+ # original line, but then skip the here document body.
341
+ #
342
+ # @private
343
+ class BufferedReader
344
+ attr_reader :line_num
345
+
346
+ def initialize(content)
347
+ if /\t/ =~ content
348
+ tab_width = 2
349
+ content = content.split(/\n/).map do |line|
350
+ 1 while line.gsub!(/\t+/) { ' ' * (tab_width * $&.length - $`.length % tab_width) } && $~ #`
351
+ line
352
+ end .join("\n")
353
+ end
354
+ @content = String.new(content)
355
+ @content << "\n" unless @content[-1, 1] == "\n"
356
+ @size = @content.size
357
+ @offset = 0
358
+ @hwm = 0
359
+ @line_num = 1
360
+ @read_back_offset = 0
361
+ @last_newline = 0
362
+ @newline_pending = false
363
+ end
364
+
365
+ def column
366
+ @offset - @last_newline
367
+ end
368
+
369
+ def getc
370
+ return nil if @offset >= @size
371
+ ch = @content[@offset, 1]
372
+
373
+ @offset += 1
374
+ @hwm = @offset if @hwm < @offset
375
+
376
+ if @newline_pending
377
+ @line_num += 1
378
+ @last_newline = @offset - 1
379
+ @newline_pending = false
380
+ end
381
+
382
+ if ch == "\n"
383
+ @newline_pending = true
384
+ end
385
+ ch
386
+ end
387
+
388
+ def getc_already_read
389
+ getc
390
+ end
391
+
392
+ def ungetc(_ch)
393
+ raise "unget past beginning of file" if @offset <= 0
394
+ @offset -= 1
395
+ if @content[@offset] == ?\n
396
+ @newline_pending = false
397
+ end
398
+ end
399
+
400
+ def get_read
401
+ res = @content[@read_back_offset...@offset]
402
+ @read_back_offset = @offset
403
+ res
404
+ end
405
+
406
+ def peek(at)
407
+ pos = @offset + at
408
+ if pos >= @size
409
+ nil
410
+ else
411
+ @content[pos, 1]
412
+ end
413
+ end
414
+
415
+ def peek_equal(str)
416
+ @content[@offset, str.length] == str
417
+ end
418
+
419
+ def divert_read_from(reserve)
420
+ @content[@offset, 0] = reserve
421
+ @size = @content.size
422
+ end
423
+ end
424
+
425
+ # end of nested class BufferedReader
426
+
427
+ include RubyToken
428
+ include IRB
429
+
430
+ attr_reader :continue
431
+ attr_reader :lex_state
432
+
433
+ def self.debug?
434
+ false
435
+ end
436
+
437
+ def initialize(content)
438
+ lex_init
439
+
440
+ @reader = BufferedReader.new(content)
441
+
442
+ @exp_line_no = @line_no = 1
443
+ @base_char_no = 0
444
+ @indent = 0
445
+
446
+ @ltype = nil
447
+ @quoted = nil
448
+ @lex_state = EXPR_BEG
449
+ @space_seen = false
450
+
451
+ @continue = false
452
+ @line = ""
453
+
454
+ @skip_space = false
455
+ @read_auto_clean_up = false
456
+ @exception_on_syntax_error = true
457
+
458
+ @colonblock_seen = false
459
+ end
460
+
461
+ attr_accessor :skip_space
462
+ attr_accessor :read_auto_clean_up
463
+ attr_accessor :exception_on_syntax_error
464
+
465
+ attr :indent
466
+
467
+ # io functions
468
+ def line_no
469
+ @reader.line_num
470
+ end
471
+
472
+ def char_no
473
+ @reader.column
474
+ end
475
+
476
+ def get_read
477
+ @reader.get_read
478
+ end
479
+
480
+ def getc
481
+ @reader.getc
482
+ end
483
+
484
+ def getc_of_rests
485
+ @reader.getc_already_read
486
+ end
487
+
488
+ def gets
489
+ (c = getc) || return
490
+ l = ""
491
+ begin
492
+ l.concat c unless c == "\r"
493
+ break if c == "\n"
494
+ end while c = getc # rubocop:disable Lint/Loop
495
+ l
496
+ end
497
+
498
+ def ungetc(c = nil)
499
+ @reader.ungetc(c)
500
+ end
501
+
502
+ def peek_equal?(str)
503
+ @reader.peek_equal(str)
504
+ end
505
+
506
+ def peek(i = 0)
507
+ @reader.peek(i)
508
+ end
509
+
510
+ def lex
511
+ catch(:eof) do
512
+ until ((tk = token).is_a?(TkNL) || tk.is_a?(TkEND_OF_SCRIPT)) &&
513
+ !@continue ||
514
+ tk.nil?
515
+ end
516
+ line = get_read
517
+
518
+ if line == "" && tk.is_a?(TkEND_OF_SCRIPT) || tk.nil?
519
+ nil
520
+ else
521
+ line
522
+ end
523
+ end
524
+ end
525
+
526
+ def token
527
+ set_token_position(line_no, char_no)
528
+ catch(:eof) do
529
+ begin
530
+ begin
531
+ tk = @OP.match(self)
532
+ @space_seen = tk.is_a?(TkSPACE)
533
+ rescue SyntaxError
534
+ abort if @exception_on_syntax_error
535
+ tk = TkError.new(line_no, char_no)
536
+ end
537
+ end while @skip_space && tk.is_a?(TkSPACE)
538
+ if @read_auto_clean_up
539
+ get_read
540
+ end
541
+ # throw :eof unless tk
542
+ p tk if $DEBUG
543
+ tk.lex_state = lex_state if tk
544
+ tk
545
+ end
546
+ end
547
+
548
+ ENINDENT_CLAUSE = [
549
+ "case", "class", "def", "do", "for", "if",
550
+ "module", "unless", "until", "while", "begin"
551
+ ] #, "when"
552
+ ACCEPTS_COLON = ["if", "for", "unless", "until", "while"]
553
+ DEINDENT_CLAUSE = ["end"] #, "when"
554
+
555
+ PERCENT_LTYPE = {
556
+ "q" => "\'",
557
+ "Q" => "\"",
558
+ "x" => "\`",
559
+ "r" => "/",
560
+ "w" => "]",
561
+ "W" => "]"
562
+ }
563
+
564
+ PERCENT_PAREN = {
565
+ "{" => "}",
566
+ "[" => "]",
567
+ "<" => ">",
568
+ "(" => ")"
569
+ }
570
+
571
+ Ltype2Token = {
572
+ "\'" => TkSTRING,
573
+ "\"" => TkSTRING,
574
+ "\`" => TkXSTRING,
575
+ "/" => TkREGEXP,
576
+ "]" => TkDSTRING
577
+ }
578
+ Ltype2Token.default = TkSTRING
579
+
580
+ DLtype2Token = {
581
+ "\"" => TkDSTRING,
582
+ "\`" => TkDXSTRING,
583
+ "/" => TkDREGEXP
584
+ }
585
+
586
+ def lex_init()
587
+ @OP = SLex.new
588
+ @OP.def_rules("\0", "\004", "\032") do |chars, _io|
589
+ Token(TkEND_OF_SCRIPT).set_text(chars)
590
+ end
591
+
592
+ @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |chars, _io|
593
+ @space_seen = true
594
+ while (ch = getc) =~ /[ \t\f\r\13]/
595
+ chars << ch
596
+ end
597
+ ungetc
598
+ Token(TkSPACE).set_text(chars)
599
+ end
600
+
601
+ @OP.def_rule("#") do |_op, _io|
602
+ identify_comment
603
+ end
604
+
605
+ @OP.def_rule("=begin", proc { @prev_char_no == 0 && peek(0) =~ /\s/ }) do |op, _io|
606
+ str = String.new(op)
607
+ @ltype = "="
608
+
609
+ begin
610
+ line = String.new
611
+ begin
612
+ ch = getc
613
+ line << ch
614
+ end until ch == "\n"
615
+ str << line
616
+ end until line =~ /^=end/
617
+
618
+ ungetc
619
+
620
+ @ltype = nil
621
+
622
+ if str =~ /\A=begin\s+rdoc/i
623
+ str.sub!(/\A=begin.*\n/, '')
624
+ str.sub!(/^=end.*/m, '')
625
+ Token(TkCOMMENT).set_text(str)
626
+ else
627
+ Token(TkCOMMENT).set_text(str)
628
+ end
629
+ end
630
+
631
+ @OP.def_rule("\n") do
632
+ print "\\n\n" if RubyLex.debug?
633
+ @colonblock_seen = false
634
+ case @lex_state
635
+ when EXPR_BEG, EXPR_FNAME, EXPR_DOT
636
+ @continue = true
637
+ else
638
+ @continue = false
639
+ @lex_state = EXPR_BEG
640
+ end
641
+ Token(TkNL).set_text("\n")
642
+ end
643
+
644
+ @OP.def_rules("*", "**",
645
+ "!", "!=", "!~",
646
+ "=", "==", "===",
647
+ "=~", "<=>",
648
+ "<", "<=",
649
+ ">", ">=", ">>") do |op, _io|
650
+ @lex_state = EXPR_BEG
651
+ Token(op).set_text(op)
652
+ end
653
+
654
+ @OP.def_rules("<<") do |op, _io|
655
+ tk = nil
656
+ if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
657
+ (@lex_state != EXPR_ARG || @space_seen)
658
+ c = peek(0)
659
+ tk = identify_here_document if /[-\w\"\'\`]/ =~ c
660
+ end
661
+ if !tk
662
+ @lex_state = EXPR_BEG
663
+ tk = Token(op).set_text(op)
664
+ end
665
+ tk
666
+ end
667
+
668
+ @OP.def_rules("'", '"') do |op, _io|
669
+ identify_string(op)
670
+ end
671
+
672
+ @OP.def_rules("`") do |op, _io|
673
+ if @lex_state == EXPR_FNAME
674
+ Token(op).set_text(op)
675
+ else
676
+ identify_string(op)
677
+ end
678
+ end
679
+
680
+ @OP.def_rules('?') do |op, _io|
681
+ if @lex_state == EXPR_END
682
+ @lex_state = EXPR_BEG
683
+ Token(TkQUESTION).set_text(op)
684
+ else
685
+ ch = getc
686
+ if @lex_state == EXPR_ARG && ch !~ /\s/
687
+ ungetc
688
+ @lex_state = EXPR_BEG
689
+ Token(TkQUESTION).set_text(op)
690
+ else
691
+ str = String.new(op)
692
+ str << ch
693
+ if ch == '\\' #'
694
+ str << read_escape
695
+ end
696
+ @lex_state = EXPR_END
697
+ Token(TkINTEGER).set_text(str)
698
+ end
699
+ end
700
+ end
701
+
702
+ @OP.def_rules("&", "&&", "|", "||") do |op, _io|
703
+ @lex_state = EXPR_BEG
704
+ Token(op).set_text(op)
705
+ end
706
+
707
+ @OP.def_rules("+=", "-=", "*=", "**=",
708
+ "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do |op, _io|
709
+ @lex_state = EXPR_BEG
710
+ op =~ /^(.*)=$/
711
+ Token(TkOPASGN, $1).set_text(op)
712
+ end
713
+
714
+ @OP.def_rule("+@", proc { @lex_state == EXPR_FNAME }) do |op, _io|
715
+ Token(TkUPLUS).set_text(op)
716
+ end
717
+
718
+ @OP.def_rule("-@", proc { @lex_state == EXPR_FNAME }) do |op, _io|
719
+ Token(TkUMINUS).set_text(op)
720
+ end
721
+
722
+ @OP.def_rules("+", "-") do |op, _io|
723
+ catch(:RET) do
724
+ if @lex_state == EXPR_ARG
725
+ if @space_seen && peek(0) =~ /[0-9]/
726
+ throw :RET, identify_number(op)
727
+ else
728
+ @lex_state = EXPR_BEG
729
+ end
730
+ elsif @lex_state != EXPR_END && peek(0) =~ /[0-9]/
731
+ throw :RET, identify_number(op)
732
+ else
733
+ @lex_state = EXPR_BEG
734
+ end
735
+ Token(op).set_text(op)
736
+ end
737
+ end
738
+
739
+ @OP.def_rule(".") do
740
+ @lex_state = EXPR_BEG
741
+ if peek(0) =~ /[0-9]/
742
+ ungetc
743
+ identify_number("")
744
+ else
745
+ # for obj.if
746
+ @lex_state = EXPR_DOT
747
+ Token(TkDOT).set_text(".")
748
+ end
749
+ end
750
+
751
+ @OP.def_rules("..", "...") do |op, _io|
752
+ @lex_state = EXPR_BEG
753
+ Token(op).set_text(op)
754
+ end
755
+
756
+ lex_int2
757
+ end
758
+
759
+ def lex_int2
760
+ @OP.def_rules("]", "}", ")") do |op, _io|
761
+ @lex_state = EXPR_END
762
+ @indent -= 1
763
+ Token(op).set_text(op)
764
+ end
765
+
766
+ @OP.def_rule(":") do
767
+ if (@colonblock_seen && @lex_state != EXPR_BEG) || peek(0) =~ /\s/
768
+ @lex_state = EXPR_BEG
769
+ tk = Token(TkCOLON)
770
+ else
771
+ @lex_state = EXPR_FNAME
772
+ tk = Token(TkSYMBEG)
773
+ end
774
+ tk.set_text(":")
775
+ end
776
+
777
+ @OP.def_rule("::") do
778
+ # p @lex_state.id2name, @space_seen
779
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_ARG && @space_seen
780
+ @lex_state = EXPR_BEG
781
+ tk = Token(TkCOLON3)
782
+ else
783
+ @lex_state = EXPR_DOT
784
+ tk = Token(TkCOLON2)
785
+ end
786
+ tk.set_text("::")
787
+ end
788
+
789
+ @OP.def_rule("/") do |op, _io|
790
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
791
+ identify_string(op)
792
+ elsif peek(0) == '='
793
+ getc
794
+ @lex_state = EXPR_BEG
795
+ Token(TkOPASGN, :/).set_text("/=") #")
796
+ elsif @lex_state == EXPR_ARG && @space_seen && peek(0) !~ /\s/
797
+ identify_string(op)
798
+ else
799
+ @lex_state = EXPR_BEG
800
+ Token("/").set_text(op)
801
+ end
802
+ end
803
+
804
+ @OP.def_rules("^") do
805
+ @lex_state = EXPR_BEG
806
+ Token("^").set_text("^")
807
+ end
808
+
809
+ # @OP.def_rules("^=") do
810
+ # @lex_state = EXPR_BEG
811
+ # Token(TkOPASGN, :^)
812
+ # end
813
+
814
+ @OP.def_rules(",", ";") do |op, _io|
815
+ @colonblock_seen = false
816
+ @lex_state = EXPR_BEG
817
+ Token(op).set_text(op)
818
+ end
819
+
820
+ @OP.def_rule("~") do
821
+ @lex_state = EXPR_BEG
822
+ Token("~").set_text("~")
823
+ end
824
+
825
+ @OP.def_rule("~@", proc { @lex_state = EXPR_FNAME }) do
826
+ @lex_state = EXPR_BEG
827
+ Token("~").set_text("~@")
828
+ end
829
+
830
+ @OP.def_rule("(") do
831
+ @indent += 1
832
+ # if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
833
+ # @lex_state = EXPR_BEG
834
+ # tk = Token(TkfLPAREN)
835
+ # else
836
+ @lex_state = EXPR_BEG
837
+ tk = Token(TkLPAREN)
838
+ # end
839
+ tk.set_text("(")
840
+ end
841
+
842
+ @OP.def_rule("[]", proc { @lex_state == EXPR_FNAME }) do
843
+ Token("[]").set_text("[]")
844
+ end
845
+
846
+ @OP.def_rule("[]=", proc { @lex_state == EXPR_FNAME }) do
847
+ Token("[]=").set_text("[]=")
848
+ end
849
+
850
+ @OP.def_rule("[") do
851
+ @indent += 1
852
+ # if @lex_state == EXPR_FNAME
853
+ # t = Token(TkfLBRACK)
854
+ # else
855
+ # if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
856
+ # t = Token(TkLBRACK)
857
+ # elsif @lex_state == EXPR_ARG && @space_seen
858
+ # else
859
+ # t = Token(TkfLBRACK)
860
+ # end
861
+ # end
862
+ t = Token(TkLBRACK)
863
+ @lex_state = EXPR_BEG
864
+ t.set_text("[")
865
+ end
866
+
867
+ @OP.def_rule("{") do
868
+ @indent += 1
869
+ # if @lex_state != EXPR_END && @lex_state != EXPR_ARG
870
+ # t = Token(TkLBRACE)
871
+ # else
872
+ # t = Token(TkfLBRACE)
873
+ # end
874
+ t = Token(TkLBRACE)
875
+ @lex_state = EXPR_BEG
876
+ t.set_text("{")
877
+ end
878
+
879
+ @OP.def_rule('\\') do #'
880
+ if getc == "\n"
881
+ @space_seen = true
882
+ @continue = true
883
+ Token(TkSPACE).set_text("\\\n")
884
+ else
885
+ ungetc
886
+ Token("\\").set_text("\\") #"
887
+ end
888
+ end
889
+
890
+ @OP.def_rule('%') do |_op, _io|
891
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
892
+ identify_quotation('%')
893
+ elsif peek(0) == '='
894
+ getc
895
+ Token(TkOPASGN, "%").set_text("%=")
896
+ elsif @lex_state == EXPR_ARG && @space_seen && peek(0) !~ /\s/
897
+ identify_quotation('%')
898
+ else
899
+ @lex_state = EXPR_BEG
900
+ Token("%").set_text("%")
901
+ end
902
+ end
903
+
904
+ @OP.def_rule('$') do #'
905
+ identify_gvar
906
+ end
907
+
908
+ @OP.def_rule('@') do
909
+ if peek(0) =~ /[@\w]/
910
+ ungetc
911
+ identify_identifier
912
+ else
913
+ Token("@").set_text("@")
914
+ end
915
+ end
916
+
917
+ # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
918
+ # |op, io|
919
+ # @indent += 1
920
+ # @lex_state = EXPR_FNAME
921
+ # # @lex_state = EXPR_END
922
+ # # until @rests[0] == "\n" or @rests[0] == ";"
923
+ # # rests.shift
924
+ # # end
925
+ # end
926
+
927
+ @OP.def_rule("__END__", proc { @prev_char_no == 0 && peek(0) =~ /[\r\n]/ }) do
928
+ throw :eof
929
+ end
930
+
931
+ @OP.def_rule("") do |op, io|
932
+ printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
933
+ if peek(0) =~ /[0-9]/
934
+ t = identify_number("")
935
+ elsif peek(0) =~ /[\w]/
936
+ t = identify_identifier
937
+ end
938
+ printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
939
+ t
940
+ end
941
+
942
+ p @OP if RubyLex.debug?
943
+ end
944
+
945
+ def identify_gvar
946
+ @lex_state = EXPR_END
947
+ str = String.new("$")
948
+
949
+ tk = case ch = getc
950
+ when %r{[~_*$?!@/\\;,=:<>".]}
951
+ str << ch
952
+ Token(TkGVAR, str)
953
+
954
+ when "-"
955
+ str << "-" << getc
956
+ Token(TkGVAR, str)
957
+
958
+ when "&", "`", "'", "+"
959
+ str << ch
960
+ Token(TkBACK_REF, str)
961
+
962
+ when /[1-9]/
963
+ str << ch
964
+ while (ch = getc) =~ /[0-9]/
965
+ str << ch
966
+ end
967
+ ungetc
968
+ Token(TkNTH_REF)
969
+ when /\w/
970
+ ungetc
971
+ ungetc
972
+ return identify_identifier
973
+ else
974
+ ungetc
975
+ Token("$")
976
+ end
977
+ tk.set_text(str)
978
+ end
979
+
980
+ def identify_identifier
981
+ token = ""
982
+ token.concat getc if peek(0) =~ /[$@]/
983
+ token.concat getc if peek(0) == "@"
984
+
985
+ while (ch = getc) =~ /\w|_/
986
+ print ":", ch, ":" if RubyLex.debug?
987
+ token.concat ch
988
+ end
989
+ ungetc
990
+
991
+ if ch == "!" || ch == "?"
992
+ token.concat getc
993
+ end
994
+ # fix token
995
+
996
+ # $stderr.puts "identifier - #{token}, state = #@lex_state"
997
+
998
+ case token
999
+ when /^\$/
1000
+ return Token(TkGVAR, token).set_text(token)
1001
+ when /^\@/
1002
+ @lex_state = EXPR_END
1003
+ return Token(TkIVAR, token).set_text(token)
1004
+ end
1005
+
1006
+ if @lex_state != EXPR_DOT
1007
+ print token, "\n" if RubyLex.debug?
1008
+
1009
+ token_c, *trans = TkReading2Token[token]
1010
+ if token_c
1011
+ # reserved word?
1012
+
1013
+ if @lex_state != EXPR_BEG &&
1014
+ @lex_state != EXPR_FNAME &&
1015
+ trans[1]
1016
+ # modifiers
1017
+ token_c = TkSymbol2Token[trans[1]]
1018
+ @lex_state = trans[0]
1019
+ else
1020
+ if @lex_state != EXPR_FNAME
1021
+ if ENINDENT_CLAUSE.include?(token)
1022
+ @indent += 1
1023
+
1024
+ if ACCEPTS_COLON.include?(token)
1025
+ @colonblock_seen = true
1026
+ else
1027
+ @colonblock_seen = false
1028
+ end
1029
+ elsif DEINDENT_CLAUSE.include?(token)
1030
+ @indent -= 1
1031
+ @colonblock_seen = false
1032
+ end
1033
+ @lex_state = trans[0]
1034
+ else
1035
+ @lex_state = EXPR_END
1036
+ end
1037
+ end
1038
+ return Token(token_c, token).set_text(token)
1039
+ end
1040
+ end
1041
+
1042
+ if @lex_state == EXPR_FNAME
1043
+ @lex_state = EXPR_END
1044
+ if peek(0) == '='
1045
+ token.concat getc
1046
+ end
1047
+ elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
1048
+ @lex_state = EXPR_ARG
1049
+ else
1050
+ @lex_state = EXPR_END
1051
+ end
1052
+
1053
+ if token[0, 1] =~ /[A-Z]/
1054
+ return Token(TkCONSTANT, token).set_text(token)
1055
+ elsif token[token.size - 1, 1] =~ /[!?]/
1056
+ return Token(TkFID, token).set_text(token)
1057
+ else
1058
+ return Token(TkIDENTIFIER, token).set_text(token)
1059
+ end
1060
+ end
1061
+
1062
+ def identify_here_document
1063
+ ch = getc
1064
+ if ch == "-"
1065
+ ch = getc
1066
+ indent = true
1067
+ end
1068
+ if /['"`]/ =~ ch # '
1069
+ lt = ch
1070
+ quoted = ""
1071
+ while (c = getc) && c != lt
1072
+ quoted.concat c
1073
+ end
1074
+ else
1075
+ lt = '"'
1076
+ quoted = ch.dup
1077
+ while (c = getc) && c =~ /\w/
1078
+ quoted.concat c
1079
+ end
1080
+ ungetc
1081
+ end
1082
+
1083
+ ltback, @ltype = @ltype, lt
1084
+ reserve = String.new
1085
+
1086
+ while ch = getc
1087
+ reserve << ch
1088
+ if ch == "\\" #"
1089
+ ch = getc
1090
+ reserve << ch
1091
+ elsif ch == "\n"
1092
+ break
1093
+ end
1094
+ end
1095
+
1096
+ str = String.new
1097
+ while (l = gets)
1098
+ l.chomp!
1099
+ l.strip! if indent
1100
+ break if l == quoted
1101
+ str << l.chomp << "\n"
1102
+ end
1103
+
1104
+ @reader.divert_read_from(reserve)
1105
+
1106
+ @ltype = ltback
1107
+ @lex_state = EXPR_END
1108
+ Token(Ltype2Token[lt], str).set_text(str.dump)
1109
+ end
1110
+
1111
+ def identify_quotation(initial_char)
1112
+ ch = getc
1113
+ if lt = PERCENT_LTYPE[ch]
1114
+ initial_char += ch
1115
+ ch = getc
1116
+ elsif ch =~ /\W/
1117
+ lt = "\""
1118
+ else
1119
+ # RubyLex.fail SyntaxError, "unknown type of %string ('#{ch}')"
1120
+ end
1121
+ # if ch !~ /\W/
1122
+ # ungetc
1123
+ # next
1124
+ # end
1125
+ # @ltype = lt
1126
+ @quoted = ch unless @quoted = PERCENT_PAREN[ch]
1127
+ identify_string(lt, @quoted, ch, initial_char) if lt
1128
+ end
1129
+
1130
+ def identify_number(start)
1131
+ str = start.dup
1132
+
1133
+ if start == "+" || start == "-" || start == ""
1134
+ start = getc
1135
+ str << start
1136
+ end
1137
+
1138
+ @lex_state = EXPR_END
1139
+
1140
+ if start == "0"
1141
+ if peek(0) == "x"
1142
+ ch = getc
1143
+ str << ch
1144
+ match = /[0-9a-f_]/
1145
+ else
1146
+ match = /[0-7_]/
1147
+ end
1148
+ while ch = getc
1149
+ if ch !~ match
1150
+ ungetc
1151
+ break
1152
+ else
1153
+ str << ch
1154
+ end
1155
+ end
1156
+ return Token(TkINTEGER).set_text(str)
1157
+ end
1158
+
1159
+ type = TkINTEGER
1160
+ allow_point = true
1161
+ allow_e = true
1162
+ while ch = getc
1163
+ case ch
1164
+ when /[0-9_]/
1165
+ str << ch
1166
+
1167
+ when allow_point && "."
1168
+ type = TkFLOAT
1169
+ if peek(0) !~ /[0-9]/
1170
+ ungetc
1171
+ break
1172
+ end
1173
+ str << ch
1174
+ allow_point = false
1175
+
1176
+ when allow_e && "e", allow_e && "E"
1177
+ str << ch
1178
+ type = TkFLOAT
1179
+ if peek(0) =~ /[+-]/
1180
+ str << getc
1181
+ end
1182
+ allow_e = false
1183
+ allow_point = false
1184
+ else
1185
+ ungetc
1186
+ break
1187
+ end
1188
+ end
1189
+ Token(type).set_text(str)
1190
+ end
1191
+
1192
+ def identify_string(ltype, quoted = ltype, opener = nil, initial_char = nil)
1193
+ @ltype = ltype
1194
+ @quoted = quoted
1195
+ subtype = nil
1196
+
1197
+ str = String.new
1198
+ str << initial_char if initial_char
1199
+ str << (opener || quoted)
1200
+
1201
+ nest = 0
1202
+ begin
1203
+ while ch = getc
1204
+ str << ch
1205
+ if @quoted == ch
1206
+ if nest == 0
1207
+ break
1208
+ else
1209
+ nest -= 1
1210
+ end
1211
+ elsif opener == ch
1212
+ nest += 1
1213
+ elsif @ltype != "'" && @ltype != "]" && ch == "#"
1214
+ ch = getc
1215
+ if ch == "{"
1216
+ subtype = true
1217
+ str << ch << skip_inner_expression
1218
+ else
1219
+ ungetc(ch)
1220
+ end
1221
+ elsif ch == '\\' #'
1222
+ str << read_escape
1223
+ end
1224
+ end
1225
+ if @ltype == "/"
1226
+ if peek(0) =~ /i|o|n|e|s/
1227
+ str << getc
1228
+ end
1229
+ end
1230
+ if subtype
1231
+ Token(DLtype2Token[ltype], str)
1232
+ else
1233
+ Token(Ltype2Token[ltype], str)
1234
+ end.set_text(str)
1235
+ ensure
1236
+ @ltype = nil
1237
+ @quoted = nil
1238
+ @lex_state = EXPR_END
1239
+ end
1240
+ end
1241
+
1242
+ def skip_inner_expression
1243
+ res = String.new
1244
+ nest = 0
1245
+ while (ch = getc)
1246
+ res << ch
1247
+ if ch == '}'
1248
+ break if nest == 0
1249
+ nest -= 1
1250
+ elsif ch == '{'
1251
+ nest += 1
1252
+ end
1253
+ end
1254
+ res
1255
+ end
1256
+
1257
+ def identify_comment
1258
+ @ltype = "#"
1259
+ comment = String.new("#")
1260
+ while ch = getc
1261
+ if ch == "\\"
1262
+ ch = getc
1263
+ if ch == "\n"
1264
+ ch = " "
1265
+ else
1266
+ comment << "\\"
1267
+ end
1268
+ else
1269
+ if ch == "\n"
1270
+ @ltype = nil
1271
+ ungetc
1272
+ break
1273
+ end
1274
+ end
1275
+ comment << ch
1276
+ end
1277
+ Token(TkCOMMENT).set_text(comment)
1278
+ end
1279
+
1280
+ def read_escape
1281
+ res = String.new
1282
+ case ch = getc
1283
+ when /[0-7]/
1284
+ ungetc ch
1285
+ 3.times do
1286
+ case ch = getc
1287
+ when /[0-7]/
1288
+ when nil
1289
+ break
1290
+ else
1291
+ ungetc
1292
+ break
1293
+ end
1294
+ res << ch
1295
+ end
1296
+
1297
+ when "x"
1298
+ res << ch
1299
+ 2.times do
1300
+ case ch = getc
1301
+ when /[0-9a-fA-F]/
1302
+ when nil
1303
+ break
1304
+ else
1305
+ ungetc
1306
+ break
1307
+ end
1308
+ res << ch
1309
+ end
1310
+
1311
+ when "M"
1312
+ res << ch
1313
+ if (ch = getc) != '-'
1314
+ ungetc
1315
+ else
1316
+ res << ch
1317
+ if (ch = getc) == "\\" #"
1318
+ res << ch
1319
+ res << read_escape
1320
+ else
1321
+ res << ch
1322
+ end
1323
+ end
1324
+
1325
+ when "C", "c" #, "^"
1326
+ res << ch
1327
+ if ch == "C" && (ch = getc) != "-"
1328
+ ungetc
1329
+ else
1330
+ res << ch
1331
+ if (ch = getc) == "\\" #"
1332
+ res << ch
1333
+ res << read_escape
1334
+ else
1335
+ res << ch
1336
+ end
1337
+ end
1338
+ else
1339
+ res << ch
1340
+ end
1341
+ res
1342
+ end
1343
+ end
1344
+ end
1345
+ end