yard 0.9.16 → 0.9.17

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 (566) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +26 -26
  3. data/CHANGELOG.md +728 -728
  4. data/LEGAL +66 -66
  5. data/LICENSE +22 -22
  6. data/README.md +328 -328
  7. data/Rakefile +53 -47
  8. data/benchmarks/builtins_vs_eval.rb +24 -24
  9. data/benchmarks/concat_vs_join.rb +13 -13
  10. data/benchmarks/erb_vs_erubis.rb +54 -54
  11. data/benchmarks/format_args.rb +47 -47
  12. data/benchmarks/generation.rb +38 -38
  13. data/benchmarks/marshal_vs_dbm.rb +64 -64
  14. data/benchmarks/parsing.rb +46 -46
  15. data/benchmarks/pathname_vs_string.rb +50 -50
  16. data/benchmarks/rdoc_vs_yardoc.rb +11 -11
  17. data/benchmarks/registry_store_types.rb +49 -49
  18. data/benchmarks/ri_vs_yri.rb +19 -19
  19. data/benchmarks/ripper_parser.rb +13 -13
  20. data/benchmarks/splat_vs_flatten.rb +13 -13
  21. data/benchmarks/template_erb.rb +23 -23
  22. data/benchmarks/template_format.rb +7 -7
  23. data/benchmarks/template_profile.rb +18 -18
  24. data/benchmarks/yri_cache.rb +20 -20
  25. data/bin/yard +13 -13
  26. data/bin/yardoc +13 -13
  27. data/bin/yri +13 -13
  28. data/docs/CodeObjects.md +115 -115
  29. data/docs/GettingStarted.md +679 -679
  30. data/docs/Handlers.md +152 -152
  31. data/docs/Overview.md +61 -61
  32. data/docs/Parser.md +191 -191
  33. data/docs/Tags.md +283 -283
  34. data/docs/TagsArch.md +123 -123
  35. data/docs/Templates.md +496 -496
  36. data/docs/WhatsNew.md +1245 -1245
  37. data/docs/templates/default/fulldoc/html/full_list_tag.erb +8 -8
  38. data/docs/templates/default/fulldoc/html/setup.rb +6 -6
  39. data/docs/templates/default/layout/html/setup.rb +9 -9
  40. data/docs/templates/default/layout/html/tag_list.erb +11 -11
  41. data/docs/templates/default/yard_tags/html/list.erb +18 -18
  42. data/docs/templates/default/yard_tags/html/setup.rb +26 -26
  43. data/docs/templates/plugin.rb +70 -70
  44. data/lib/rubygems_plugin.rb +9 -9
  45. data/lib/yard.rb +69 -69
  46. data/lib/yard/autoload.rb +303 -303
  47. data/lib/yard/cli/command.rb +85 -85
  48. data/lib/yard/cli/command_parser.rb +93 -93
  49. data/lib/yard/cli/config.rb +198 -198
  50. data/lib/yard/cli/diff.rb +270 -270
  51. data/lib/yard/cli/display.rb +69 -69
  52. data/lib/yard/cli/gems.rb +84 -84
  53. data/lib/yard/cli/graph.rb +125 -125
  54. data/lib/yard/cli/help.rb +20 -20
  55. data/lib/yard/cli/i18n.rb +70 -70
  56. data/lib/yard/cli/list.rb +23 -23
  57. data/lib/yard/cli/markup_types.rb +32 -32
  58. data/lib/yard/cli/server.rb +257 -257
  59. data/lib/yard/cli/stats.rb +231 -231
  60. data/lib/yard/cli/yardoc.rb +788 -788
  61. data/lib/yard/cli/yardopts_command.rb +110 -110
  62. data/lib/yard/cli/yri.rb +215 -215
  63. data/lib/yard/code_objects/base.rb +615 -610
  64. data/lib/yard/code_objects/class_object.rb +146 -146
  65. data/lib/yard/code_objects/class_variable_object.rb +11 -11
  66. data/lib/yard/code_objects/constant_object.rb +16 -16
  67. data/lib/yard/code_objects/extended_method_object.rb +24 -24
  68. data/lib/yard/code_objects/extra_file_object.rb +131 -131
  69. data/lib/yard/code_objects/macro_object.rb +172 -172
  70. data/lib/yard/code_objects/method_object.rb +196 -196
  71. data/lib/yard/code_objects/module_object.rb +21 -21
  72. data/lib/yard/code_objects/namespace_mapper.rb +114 -114
  73. data/lib/yard/code_objects/namespace_object.rb +200 -200
  74. data/lib/yard/code_objects/proxy.rb +240 -240
  75. data/lib/yard/code_objects/root_object.rb +19 -19
  76. data/lib/yard/config.rb +270 -270
  77. data/lib/yard/core_ext/array.rb +16 -16
  78. data/lib/yard/core_ext/file.rb +69 -69
  79. data/lib/yard/core_ext/hash.rb +16 -16
  80. data/lib/yard/core_ext/insertion.rb +63 -63
  81. data/lib/yard/core_ext/module.rb +20 -20
  82. data/lib/yard/core_ext/string.rb +68 -68
  83. data/lib/yard/core_ext/symbol_hash.rb +75 -75
  84. data/lib/yard/docstring.rb +386 -378
  85. data/lib/yard/docstring_parser.rb +345 -345
  86. data/lib/yard/gem_index.rb +29 -29
  87. data/lib/yard/globals.rb +22 -22
  88. data/lib/yard/handlers/base.rb +595 -595
  89. data/lib/yard/handlers/c/alias_handler.rb +16 -16
  90. data/lib/yard/handlers/c/attribute_handler.rb +13 -13
  91. data/lib/yard/handlers/c/base.rb +129 -129
  92. data/lib/yard/handlers/c/class_handler.rb +27 -27
  93. data/lib/yard/handlers/c/constant_handler.rb +13 -13
  94. data/lib/yard/handlers/c/handler_methods.rb +211 -211
  95. data/lib/yard/handlers/c/init_handler.rb +20 -20
  96. data/lib/yard/handlers/c/method_handler.rb +45 -36
  97. data/lib/yard/handlers/c/mixin_handler.rb +21 -21
  98. data/lib/yard/handlers/c/module_handler.rb +17 -17
  99. data/lib/yard/handlers/c/override_comment_handler.rb +31 -31
  100. data/lib/yard/handlers/c/path_handler.rb +11 -11
  101. data/lib/yard/handlers/c/struct_handler.rb +13 -13
  102. data/lib/yard/handlers/c/symbol_handler.rb +8 -8
  103. data/lib/yard/handlers/processor.rb +200 -200
  104. data/lib/yard/handlers/ruby/alias_handler.rb +44 -44
  105. data/lib/yard/handlers/ruby/attribute_handler.rb +87 -87
  106. data/lib/yard/handlers/ruby/base.rb +165 -165
  107. data/lib/yard/handlers/ruby/class_condition_handler.rb +92 -92
  108. data/lib/yard/handlers/ruby/class_handler.rb +119 -119
  109. data/lib/yard/handlers/ruby/class_variable_handler.rb +17 -17
  110. data/lib/yard/handlers/ruby/comment_handler.rb +10 -10
  111. data/lib/yard/handlers/ruby/constant_handler.rb +59 -59
  112. data/lib/yard/handlers/ruby/decorator_handler_methods.rb +123 -123
  113. data/lib/yard/handlers/ruby/dsl_handler.rb +15 -15
  114. data/lib/yard/handlers/ruby/dsl_handler_methods.rb +96 -95
  115. data/lib/yard/handlers/ruby/exception_handler.rb +27 -27
  116. data/lib/yard/handlers/ruby/extend_handler.rb +22 -22
  117. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +37 -37
  118. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +65 -65
  119. data/lib/yard/handlers/ruby/legacy/base.rb +245 -245
  120. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +83 -83
  121. data/lib/yard/handlers/ruby/legacy/class_handler.rb +113 -113
  122. data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +15 -15
  123. data/lib/yard/handlers/ruby/legacy/comment_handler.rb +10 -10
  124. data/lib/yard/handlers/ruby/legacy/constant_handler.rb +29 -29
  125. data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +17 -17
  126. data/lib/yard/handlers/ruby/legacy/exception_handler.rb +13 -13
  127. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +21 -21
  128. data/lib/yard/handlers/ruby/legacy/method_handler.rb +90 -90
  129. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +39 -39
  130. data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +19 -19
  131. data/lib/yard/handlers/ruby/legacy/module_handler.rb +12 -12
  132. data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +22 -22
  133. data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +22 -22
  134. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +17 -17
  135. data/lib/yard/handlers/ruby/legacy/yield_handler.rb +29 -29
  136. data/lib/yard/handlers/ruby/method_condition_handler.rb +9 -9
  137. data/lib/yard/handlers/ruby/method_handler.rb +118 -118
  138. data/lib/yard/handlers/ruby/mixin_handler.rb +37 -37
  139. data/lib/yard/handlers/ruby/module_function_handler.rb +27 -27
  140. data/lib/yard/handlers/ruby/module_handler.rb +12 -12
  141. data/lib/yard/handlers/ruby/private_class_method_handler.rb +14 -14
  142. data/lib/yard/handlers/ruby/private_constant_handler.rb +43 -43
  143. data/lib/yard/handlers/ruby/public_class_method_handler.rb +14 -14
  144. data/lib/yard/handlers/ruby/struct_handler_methods.rb +143 -143
  145. data/lib/yard/handlers/ruby/visibility_handler.rb +22 -22
  146. data/lib/yard/handlers/ruby/yield_handler.rb +31 -31
  147. data/lib/yard/i18n/locale.rb +67 -67
  148. data/lib/yard/i18n/message.rb +57 -57
  149. data/lib/yard/i18n/messages.rb +56 -56
  150. data/lib/yard/i18n/po_parser.rb +61 -61
  151. data/lib/yard/i18n/pot_generator.rb +290 -290
  152. data/lib/yard/i18n/text.rb +173 -173
  153. data/lib/yard/logging.rb +205 -205
  154. data/lib/yard/options.rb +217 -217
  155. data/lib/yard/parser/base.rb +57 -57
  156. data/lib/yard/parser/c/c_parser.rb +235 -235
  157. data/lib/yard/parser/c/comment_parser.rb +134 -134
  158. data/lib/yard/parser/c/statement.rb +64 -64
  159. data/lib/yard/parser/ruby/ast_node.rb +540 -540
  160. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1354 -1354
  161. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +32 -32
  162. data/lib/yard/parser/ruby/legacy/statement.rb +66 -66
  163. data/lib/yard/parser/ruby/legacy/statement_list.rb +394 -394
  164. data/lib/yard/parser/ruby/legacy/token_list.rb +74 -74
  165. data/lib/yard/parser/ruby/ruby_parser.rb +687 -687
  166. data/lib/yard/parser/ruby/token_resolver.rb +156 -156
  167. data/lib/yard/parser/source_parser.rb +526 -526
  168. data/lib/yard/rake/yardoc_task.rb +81 -81
  169. data/lib/yard/registry.rb +439 -439
  170. data/lib/yard/registry_resolver.rb +189 -189
  171. data/lib/yard/registry_store.rb +337 -337
  172. data/lib/yard/rubygems/backports.rb +10 -10
  173. data/lib/yard/rubygems/backports/LICENSE.txt +57 -57
  174. data/lib/yard/rubygems/backports/MIT.txt +20 -20
  175. data/lib/yard/rubygems/backports/gem.rb +10 -10
  176. data/lib/yard/rubygems/backports/source_index.rb +365 -365
  177. data/lib/yard/rubygems/doc_manager.rb +90 -90
  178. data/lib/yard/rubygems/hook.rb +197 -197
  179. data/lib/yard/rubygems/specification.rb +50 -50
  180. data/lib/yard/serializers/base.rb +83 -83
  181. data/lib/yard/serializers/file_system_serializer.rb +123 -123
  182. data/lib/yard/serializers/process_serializer.rb +24 -24
  183. data/lib/yard/serializers/stdout_serializer.rb +34 -34
  184. data/lib/yard/serializers/yardoc_serializer.rb +152 -152
  185. data/lib/yard/server.rb +13 -13
  186. data/lib/yard/server/adapter.rb +100 -100
  187. data/lib/yard/server/commands/base.rb +209 -209
  188. data/lib/yard/server/commands/display_file_command.rb +29 -29
  189. data/lib/yard/server/commands/display_object_command.rb +65 -65
  190. data/lib/yard/server/commands/frames_command.rb +16 -16
  191. data/lib/yard/server/commands/library_command.rb +187 -187
  192. data/lib/yard/server/commands/library_index_command.rb +28 -28
  193. data/lib/yard/server/commands/list_command.rb +25 -25
  194. data/lib/yard/server/commands/root_request_command.rb +15 -15
  195. data/lib/yard/server/commands/search_command.rb +79 -79
  196. data/lib/yard/server/commands/static_file_command.rb +23 -23
  197. data/lib/yard/server/commands/static_file_helpers.rb +62 -62
  198. data/lib/yard/server/doc_server_helper.rb +91 -91
  199. data/lib/yard/server/doc_server_serializer.rb +39 -39
  200. data/lib/yard/server/library_version.rb +277 -277
  201. data/lib/yard/server/rack_adapter.rb +89 -89
  202. data/lib/yard/server/router.rb +187 -187
  203. data/lib/yard/server/static_caching.rb +46 -46
  204. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +127 -127
  205. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +11 -11
  206. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +37 -37
  207. data/lib/yard/server/templates/default/layout/html/script_setup.erb +7 -7
  208. data/lib/yard/server/templates/default/layout/html/setup.rb +8 -8
  209. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -4
  210. data/lib/yard/server/templates/default/method_details/html/setup.rb +5 -5
  211. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +8 -8
  212. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +14 -14
  213. data/lib/yard/server/templates/doc_server/library_list/html/listing.erb +13 -13
  214. data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +6 -6
  215. data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -2
  216. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +52 -52
  217. data/lib/yard/server/templates/doc_server/processing/html/setup.rb +4 -4
  218. data/lib/yard/server/templates/doc_server/search/html/search.erb +18 -18
  219. data/lib/yard/server/templates/doc_server/search/html/setup.rb +9 -9
  220. data/lib/yard/server/webrick_adapter.rb +45 -45
  221. data/lib/yard/tags/default_factory.rb +191 -191
  222. data/lib/yard/tags/default_tag.rb +13 -13
  223. data/lib/yard/tags/directives.rb +616 -616
  224. data/lib/yard/tags/library.rb +633 -633
  225. data/lib/yard/tags/option_tag.rb +13 -13
  226. data/lib/yard/tags/overload_tag.rb +71 -71
  227. data/lib/yard/tags/ref_tag.rb +8 -8
  228. data/lib/yard/tags/ref_tag_list.rb +28 -28
  229. data/lib/yard/tags/tag.rb +71 -71
  230. data/lib/yard/tags/tag_format_error.rb +7 -7
  231. data/lib/yard/tags/types_explainer.rb +162 -162
  232. data/lib/yard/templates/engine.rb +186 -186
  233. data/lib/yard/templates/erb_cache.rb +23 -23
  234. data/lib/yard/templates/helpers/base_helper.rb +215 -215
  235. data/lib/yard/templates/helpers/filter_helper.rb +27 -27
  236. data/lib/yard/templates/helpers/html_helper.rb +646 -642
  237. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +78 -78
  238. data/lib/yard/templates/helpers/markup/rdoc_markdown.rb +23 -23
  239. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +109 -109
  240. data/lib/yard/templates/helpers/markup_helper.rb +172 -172
  241. data/lib/yard/templates/helpers/method_helper.rb +75 -75
  242. data/lib/yard/templates/helpers/module_helper.rb +21 -21
  243. data/lib/yard/templates/helpers/text_helper.rb +112 -112
  244. data/lib/yard/templates/helpers/uml_helper.rb +47 -47
  245. data/lib/yard/templates/section.rb +105 -105
  246. data/lib/yard/templates/template.rb +418 -418
  247. data/lib/yard/templates/template_options.rb +92 -92
  248. data/lib/yard/verifier.rb +151 -151
  249. data/lib/yard/version.rb +3 -1
  250. data/spec/cli/command_parser_spec.rb +43 -43
  251. data/spec/cli/command_spec.rb +36 -36
  252. data/spec/cli/config_spec.rb +148 -148
  253. data/spec/cli/diff_spec.rb +254 -254
  254. data/spec/cli/display_spec.rb +30 -30
  255. data/spec/cli/gems_spec.rb +81 -81
  256. data/spec/cli/graph_spec.rb +18 -18
  257. data/spec/cli/help_spec.rb +22 -22
  258. data/spec/cli/i18n_spec.rb +107 -107
  259. data/spec/cli/list_spec.rb +8 -8
  260. data/spec/cli/markup_types_spec.rb +22 -22
  261. data/spec/cli/server_spec.rb +324 -324
  262. data/spec/cli/stats_spec.rb +96 -96
  263. data/spec/cli/yard_on_yard_spec.rb +38 -38
  264. data/spec/cli/yardoc_spec.rb +862 -849
  265. data/spec/cli/yri_spec.rb +101 -101
  266. data/spec/code_objects/base_spec.rb +470 -460
  267. data/spec/code_objects/class_object_spec.rb +226 -226
  268. data/spec/code_objects/code_object_list_spec.rb +36 -36
  269. data/spec/code_objects/constants_spec.rb +116 -116
  270. data/spec/code_objects/extra_file_object_spec.rb +160 -160
  271. data/spec/code_objects/macro_object_spec.rb +150 -150
  272. data/spec/code_objects/method_object_spec.rb +184 -184
  273. data/spec/code_objects/module_object_spec.rb +142 -142
  274. data/spec/code_objects/namespace_object_spec.rb +171 -171
  275. data/spec/code_objects/proxy_spec.rb +141 -141
  276. data/spec/code_objects/spec_helper.rb +3 -3
  277. data/spec/config_spec.rb +171 -171
  278. data/spec/core_ext/array_spec.rb +13 -13
  279. data/spec/core_ext/file_spec.rb +72 -72
  280. data/spec/core_ext/hash_spec.rb +14 -14
  281. data/spec/core_ext/insertion_spec.rb +37 -37
  282. data/spec/core_ext/module_spec.rb +15 -15
  283. data/spec/core_ext/string_spec.rb +42 -42
  284. data/spec/core_ext/symbol_hash_spec.rb +89 -89
  285. data/spec/docstring_parser_spec.rb +280 -262
  286. data/spec/docstring_spec.rb +373 -364
  287. data/spec/examples.txt +1875 -1871
  288. data/spec/handlers/alias_handler_spec.rb +82 -82
  289. data/spec/handlers/attribute_handler_spec.rb +96 -96
  290. data/spec/handlers/base_spec.rb +216 -216
  291. data/spec/handlers/c/alias_handler_spec.rb +34 -34
  292. data/spec/handlers/c/attribute_handler_spec.rb +41 -41
  293. data/spec/handlers/c/class_handler_spec.rb +78 -78
  294. data/spec/handlers/c/constant_handler_spec.rb +71 -71
  295. data/spec/handlers/c/init_handler_spec.rb +48 -48
  296. data/spec/handlers/c/method_handler_spec.rb +325 -325
  297. data/spec/handlers/c/mixin_handler_spec.rb +44 -44
  298. data/spec/handlers/c/module_handler_spec.rb +71 -71
  299. data/spec/handlers/c/override_comment_handler_spec.rb +47 -47
  300. data/spec/handlers/c/path_handler_spec.rb +36 -36
  301. data/spec/handlers/c/spec_helper.rb +23 -23
  302. data/spec/handlers/c/struct_handler_spec.rb +16 -16
  303. data/spec/handlers/class_condition_handler_spec.rb +87 -87
  304. data/spec/handlers/class_handler_spec.rb +247 -247
  305. data/spec/handlers/class_method_handler_shared_examples.rb +133 -133
  306. data/spec/handlers/class_variable_handler_spec.rb +12 -12
  307. data/spec/handlers/constant_handler_spec.rb +112 -112
  308. data/spec/handlers/decorator_handler_methods_spec.rb +393 -393
  309. data/spec/handlers/dsl_handler_spec.rb +219 -219
  310. data/spec/handlers/examples/alias_handler_001.rb.txt +45 -45
  311. data/spec/handlers/examples/attribute_handler_001.rb.txt +31 -31
  312. data/spec/handlers/examples/class_condition_handler_001.rb.txt +68 -68
  313. data/spec/handlers/examples/class_handler_001.rb.txt +120 -120
  314. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -9
  315. data/spec/handlers/examples/constant_handler_001.rb.txt +35 -35
  316. data/spec/handlers/examples/dsl_handler_001.rb.txt +154 -154
  317. data/spec/handlers/examples/exception_handler_001.rb.txt +58 -58
  318. data/spec/handlers/examples/extend_handler_001.rb.txt +15 -15
  319. data/spec/handlers/examples/method_condition_handler_001.rb.txt +9 -9
  320. data/spec/handlers/examples/method_handler_001.rb.txt +128 -128
  321. data/spec/handlers/examples/mixin_handler_001.rb.txt +37 -37
  322. data/spec/handlers/examples/module_handler_001.rb.txt +29 -29
  323. data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -8
  324. data/spec/handlers/examples/process_handler_001.rb.txt +11 -11
  325. data/spec/handlers/examples/visibility_handler_001.rb.txt +35 -35
  326. data/spec/handlers/examples/yield_handler_001.rb.txt +54 -54
  327. data/spec/handlers/exception_handler_spec.rb +49 -49
  328. data/spec/handlers/extend_handler_spec.rb +24 -24
  329. data/spec/handlers/legacy_base_spec.rb +128 -128
  330. data/spec/handlers/method_condition_handler_spec.rb +15 -15
  331. data/spec/handlers/method_handler_spec.rb +190 -190
  332. data/spec/handlers/mixin_handler_spec.rb +56 -56
  333. data/spec/handlers/module_function_handler_spec.rb +106 -106
  334. data/spec/handlers/module_handler_spec.rb +35 -35
  335. data/spec/handlers/private_class_method_handler_spec.rb +11 -11
  336. data/spec/handlers/private_constant_handler_spec.rb +25 -25
  337. data/spec/handlers/processor_spec.rb +35 -35
  338. data/spec/handlers/public_class_method_handler_spec.rb +11 -11
  339. data/spec/handlers/ruby/base_spec.rb +95 -95
  340. data/spec/handlers/ruby/legacy/base_spec.rb +84 -84
  341. data/spec/handlers/spec_helper.rb +33 -33
  342. data/spec/handlers/visibility_handler_spec.rb +44 -44
  343. data/spec/handlers/yield_handler_spec.rb +52 -52
  344. data/spec/i18n/locale_spec.rb +81 -81
  345. data/spec/i18n/message_spec.rb +52 -52
  346. data/spec/i18n/messages_spec.rb +67 -67
  347. data/spec/i18n/pot_generator_spec.rb +295 -295
  348. data/spec/i18n/text_spec.rb +184 -184
  349. data/spec/logging_spec.rb +44 -44
  350. data/spec/options_spec.rb +171 -171
  351. data/spec/parser/base_spec.rb +24 -24
  352. data/spec/parser/c_parser_spec.rb +236 -223
  353. data/spec/parser/examples/array.c.txt +6267 -6267
  354. data/spec/parser/examples/example1.rb.txt +7 -7
  355. data/spec/parser/examples/extrafile.c.txt +8 -8
  356. data/spec/parser/examples/file.c.txt +28 -0
  357. data/spec/parser/examples/multifile.c.txt +22 -22
  358. data/spec/parser/examples/namespace.cpp.txt +68 -68
  359. data/spec/parser/examples/override.c.txt +424 -424
  360. data/spec/parser/examples/parse_in_order_001.rb.txt +2 -2
  361. data/spec/parser/examples/parse_in_order_002.rb.txt +1 -1
  362. data/spec/parser/examples/tag_handler_001.rb.txt +7 -7
  363. data/spec/parser/ruby/ast_node_spec.rb +33 -33
  364. data/spec/parser/ruby/legacy/statement_list_spec.rb +299 -299
  365. data/spec/parser/ruby/legacy/token_list_spec.rb +79 -79
  366. data/spec/parser/ruby/ruby_parser_spec.rb +508 -508
  367. data/spec/parser/ruby/token_resolver_spec.rb +165 -165
  368. data/spec/parser/source_parser_spec.rb +727 -727
  369. data/spec/parser/tag_parsing_spec.rb +17 -17
  370. data/spec/rake/yardoc_task_spec.rb +118 -118
  371. data/spec/registry_spec.rb +463 -463
  372. data/spec/registry_store_spec.rb +316 -316
  373. data/spec/rubygems/doc_manager_spec.rb +112 -112
  374. data/spec/serializers/data/serialized_yardoc/checksums +1 -1
  375. data/spec/serializers/file_system_serializer_spec.rb +145 -145
  376. data/spec/serializers/spec_helper.rb +2 -2
  377. data/spec/serializers/yardoc_serializer_spec.rb +78 -78
  378. data/spec/server/adapter_spec.rb +39 -39
  379. data/spec/server/commands/base_spec.rb +91 -91
  380. data/spec/server/commands/library_command_spec.rb +39 -39
  381. data/spec/server/doc_server_helper_spec.rb +72 -72
  382. data/spec/server/doc_server_serializer_spec.rb +60 -60
  383. data/spec/server/rack_adapter_spec.rb +21 -21
  384. data/spec/server/router_spec.rb +123 -123
  385. data/spec/server/spec_helper.rb +22 -22
  386. data/spec/server/static_caching_spec.rb +47 -47
  387. data/spec/server/webrick_servlet_spec.rb +20 -20
  388. data/spec/server_spec.rb +19 -19
  389. data/spec/spec_helper.rb +212 -212
  390. data/spec/tags/default_factory_spec.rb +168 -168
  391. data/spec/tags/default_tag_spec.rb +11 -11
  392. data/spec/tags/directives_spec.rb +463 -463
  393. data/spec/tags/library_spec.rb +48 -48
  394. data/spec/tags/overload_tag_spec.rb +53 -53
  395. data/spec/tags/ref_tag_list_spec.rb +53 -53
  396. data/spec/tags/types_explainer_spec.rb +203 -203
  397. data/spec/templates/class_spec.rb +45 -45
  398. data/spec/templates/constant_spec.rb +41 -41
  399. data/spec/templates/engine_spec.rb +131 -131
  400. data/spec/templates/examples/class001.html +308 -308
  401. data/spec/templates/examples/class001.txt +36 -36
  402. data/spec/templates/examples/class002.html +39 -39
  403. data/spec/templates/examples/constant001.txt +24 -24
  404. data/spec/templates/examples/constant002.txt +6 -6
  405. data/spec/templates/examples/constant003.txt +10 -10
  406. data/spec/templates/examples/method001.html +137 -137
  407. data/spec/templates/examples/method001.txt +35 -35
  408. data/spec/templates/examples/method002.html +91 -91
  409. data/spec/templates/examples/method002.txt +20 -20
  410. data/spec/templates/examples/method003.html +165 -165
  411. data/spec/templates/examples/method003.txt +45 -45
  412. data/spec/templates/examples/method004.html +48 -48
  413. data/spec/templates/examples/method004.txt +10 -10
  414. data/spec/templates/examples/method005.html +105 -105
  415. data/spec/templates/examples/method005.txt +33 -33
  416. data/spec/templates/examples/method006.html +107 -107
  417. data/spec/templates/examples/method006.txt +20 -20
  418. data/spec/templates/examples/module001.dot +33 -33
  419. data/spec/templates/examples/module001.html +833 -833
  420. data/spec/templates/examples/module001.txt +33 -33
  421. data/spec/templates/examples/module002.html +341 -341
  422. data/spec/templates/examples/module003.html +202 -202
  423. data/spec/templates/examples/module004.html +394 -394
  424. data/spec/templates/examples/module005.html +81 -81
  425. data/spec/templates/examples/tag001.txt +82 -82
  426. data/spec/templates/helpers/base_helper_spec.rb +171 -171
  427. data/spec/templates/helpers/html_helper_spec.rb +668 -653
  428. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +65 -65
  429. data/spec/templates/helpers/markup/rdoc_markup_spec.rb +84 -84
  430. data/spec/templates/helpers/markup_helper_spec.rb +136 -136
  431. data/spec/templates/helpers/method_helper_spec.rb +107 -107
  432. data/spec/templates/helpers/module_helper_spec.rb +35 -35
  433. data/spec/templates/helpers/shared_signature_examples.rb +126 -126
  434. data/spec/templates/helpers/text_helper_spec.rb +65 -65
  435. data/spec/templates/method_spec.rb +118 -118
  436. data/spec/templates/module_spec.rb +203 -203
  437. data/spec/templates/onefile_spec.rb +66 -66
  438. data/spec/templates/section_spec.rb +144 -144
  439. data/spec/templates/spec_helper.rb +76 -76
  440. data/spec/templates/tag_spec.rb +52 -52
  441. data/spec/templates/template_spec.rb +410 -410
  442. data/spec/verifier_spec.rb +106 -106
  443. data/templates/default/class/dot/setup.rb +7 -7
  444. data/templates/default/class/dot/superklass.erb +2 -2
  445. data/templates/default/class/html/constructor_details.erb +8 -8
  446. data/templates/default/class/html/setup.rb +2 -2
  447. data/templates/default/class/html/subclasses.erb +4 -4
  448. data/templates/default/class/setup.rb +36 -36
  449. data/templates/default/class/text/setup.rb +12 -12
  450. data/templates/default/class/text/subclasses.erb +5 -5
  451. data/templates/default/constant/text/header.erb +11 -11
  452. data/templates/default/constant/text/setup.rb +4 -4
  453. data/templates/default/docstring/html/abstract.erb +4 -4
  454. data/templates/default/docstring/html/deprecated.erb +1 -1
  455. data/templates/default/docstring/html/index.erb +5 -5
  456. data/templates/default/docstring/html/note.erb +6 -6
  457. data/templates/default/docstring/html/private.erb +4 -4
  458. data/templates/default/docstring/html/text.erb +1 -1
  459. data/templates/default/docstring/html/todo.erb +6 -6
  460. data/templates/default/docstring/setup.rb +52 -52
  461. data/templates/default/docstring/text/abstract.erb +2 -2
  462. data/templates/default/docstring/text/deprecated.erb +2 -2
  463. data/templates/default/docstring/text/index.erb +2 -2
  464. data/templates/default/docstring/text/note.erb +3 -3
  465. data/templates/default/docstring/text/private.erb +2 -2
  466. data/templates/default/docstring/text/text.erb +1 -1
  467. data/templates/default/docstring/text/todo.erb +3 -3
  468. data/templates/default/fulldoc/html/css/full_list.css +58 -58
  469. data/templates/default/fulldoc/html/css/style.css +496 -496
  470. data/templates/default/fulldoc/html/frames.erb +17 -17
  471. data/templates/default/fulldoc/html/full_list.erb +37 -37
  472. data/templates/default/fulldoc/html/full_list_class.erb +2 -2
  473. data/templates/default/fulldoc/html/full_list_file.erb +7 -7
  474. data/templates/default/fulldoc/html/full_list_method.erb +10 -10
  475. data/templates/default/fulldoc/html/js/app.js +292 -292
  476. data/templates/default/fulldoc/html/js/full_list.js +216 -216
  477. data/templates/default/fulldoc/html/js/jquery.js +3 -3
  478. data/templates/default/fulldoc/html/setup.rb +241 -241
  479. data/templates/default/layout/dot/header.erb +5 -5
  480. data/templates/default/layout/dot/setup.rb +15 -15
  481. data/templates/default/layout/html/breadcrumb.erb +11 -11
  482. data/templates/default/layout/html/files.erb +11 -11
  483. data/templates/default/layout/html/footer.erb +5 -5
  484. data/templates/default/layout/html/headers.erb +15 -15
  485. data/templates/default/layout/html/index.erb +2 -2
  486. data/templates/default/layout/html/layout.erb +23 -23
  487. data/templates/default/layout/html/listing.erb +4 -4
  488. data/templates/default/layout/html/objects.erb +32 -32
  489. data/templates/default/layout/html/script_setup.erb +4 -4
  490. data/templates/default/layout/html/search.erb +12 -12
  491. data/templates/default/layout/html/setup.rb +89 -89
  492. data/templates/default/method/html/header.erb +16 -16
  493. data/templates/default/method/setup.rb +4 -4
  494. data/templates/default/method_details/html/header.erb +2 -2
  495. data/templates/default/method_details/html/method_signature.erb +24 -24
  496. data/templates/default/method_details/html/source.erb +9 -9
  497. data/templates/default/method_details/setup.rb +11 -11
  498. data/templates/default/method_details/text/header.erb +10 -10
  499. data/templates/default/method_details/text/method_signature.erb +12 -12
  500. data/templates/default/method_details/text/setup.rb +11 -11
  501. data/templates/default/module/dot/child.erb +1 -1
  502. data/templates/default/module/dot/dependencies.erb +2 -2
  503. data/templates/default/module/dot/header.erb +6 -6
  504. data/templates/default/module/dot/info.erb +13 -13
  505. data/templates/default/module/dot/setup.rb +15 -15
  506. data/templates/default/module/html/attribute_details.erb +10 -10
  507. data/templates/default/module/html/attribute_summary.erb +8 -8
  508. data/templates/default/module/html/box_info.erb +43 -43
  509. data/templates/default/module/html/children.erb +8 -8
  510. data/templates/default/module/html/constant_summary.erb +17 -17
  511. data/templates/default/module/html/defines.erb +2 -2
  512. data/templates/default/module/html/header.erb +5 -5
  513. data/templates/default/module/html/inherited_attributes.erb +14 -14
  514. data/templates/default/module/html/inherited_constants.erb +8 -8
  515. data/templates/default/module/html/inherited_methods.erb +18 -18
  516. data/templates/default/module/html/item_summary.erb +40 -40
  517. data/templates/default/module/html/method_details_list.erb +9 -9
  518. data/templates/default/module/html/method_summary.erb +13 -13
  519. data/templates/default/module/html/methodmissing.erb +12 -12
  520. data/templates/default/module/setup.rb +167 -167
  521. data/templates/default/module/text/children.erb +9 -9
  522. data/templates/default/module/text/class_meths_list.erb +7 -7
  523. data/templates/default/module/text/extends.erb +7 -7
  524. data/templates/default/module/text/header.erb +7 -7
  525. data/templates/default/module/text/includes.erb +7 -7
  526. data/templates/default/module/text/instance_meths_list.erb +7 -7
  527. data/templates/default/module/text/setup.rb +13 -13
  528. data/templates/default/onefile/html/files.erb +4 -4
  529. data/templates/default/onefile/html/headers.erb +6 -6
  530. data/templates/default/onefile/html/layout.erb +17 -17
  531. data/templates/default/onefile/html/readme.erb +2 -2
  532. data/templates/default/onefile/html/setup.rb +62 -62
  533. data/templates/default/root/dot/child.erb +2 -2
  534. data/templates/default/root/dot/setup.rb +6 -6
  535. data/templates/default/root/html/setup.rb +2 -2
  536. data/templates/default/tags/html/example.erb +10 -10
  537. data/templates/default/tags/html/index.erb +2 -2
  538. data/templates/default/tags/html/option.erb +24 -24
  539. data/templates/default/tags/html/overload.erb +13 -13
  540. data/templates/default/tags/html/see.erb +7 -7
  541. data/templates/default/tags/html/tag.erb +20 -20
  542. data/templates/default/tags/setup.rb +57 -57
  543. data/templates/default/tags/text/example.erb +12 -12
  544. data/templates/default/tags/text/index.erb +1 -1
  545. data/templates/default/tags/text/option.erb +20 -20
  546. data/templates/default/tags/text/overload.erb +19 -19
  547. data/templates/default/tags/text/see.erb +11 -11
  548. data/templates/default/tags/text/tag.erb +13 -13
  549. data/templates/guide/class/html/setup.rb +2 -2
  550. data/templates/guide/docstring/html/setup.rb +2 -2
  551. data/templates/guide/fulldoc/html/css/style.css +108 -108
  552. data/templates/guide/fulldoc/html/js/app.js +33 -33
  553. data/templates/guide/fulldoc/html/setup.rb +74 -74
  554. data/templates/guide/layout/html/layout.erb +81 -81
  555. data/templates/guide/layout/html/setup.rb +25 -25
  556. data/templates/guide/method/html/header.erb +17 -17
  557. data/templates/guide/method/html/setup.rb +22 -22
  558. data/templates/guide/module/html/header.erb +6 -6
  559. data/templates/guide/module/html/method_list.erb +4 -4
  560. data/templates/guide/module/html/setup.rb +27 -27
  561. data/templates/guide/onefile/html/files.erb +4 -4
  562. data/templates/guide/onefile/html/setup.rb +6 -6
  563. data/templates/guide/onefile/html/toc.erb +3 -3
  564. data/templates/guide/tags/html/setup.rb +9 -9
  565. data/yard.gemspec +43 -43
  566. metadata +4 -4
@@ -1,1354 +1,1354 @@
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 "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