rdoc 2.4.3 → 2.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rdoc might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/.autotest +3 -1
- data/History.txt +68 -0
- data/LICENSE.txt +57 -0
- data/Manifest.txt +37 -19
- data/README.txt +2 -12
- data/Rakefile +12 -12
- data/bin/rdoc +4 -4
- data/lib/rdoc.rb +32 -9
- data/lib/rdoc/alias.rb +2 -2
- data/lib/rdoc/any_method.rb +108 -16
- data/lib/rdoc/attr.rb +87 -1
- data/lib/rdoc/class_module.rb +131 -5
- data/lib/rdoc/code_object.rb +28 -5
- data/lib/rdoc/constant.rb +22 -0
- data/lib/rdoc/context.rb +80 -37
- data/lib/rdoc/gauntlet.rb +48 -0
- data/lib/rdoc/generator/darkfish.rb +25 -23
- data/lib/rdoc/generator/markup.rb +6 -29
- data/lib/rdoc/generator/ri.rb +39 -189
- data/lib/rdoc/generator/template/darkfish/classpage.rhtml +17 -1
- data/lib/rdoc/generator/template/darkfish/filepage.rhtml +10 -0
- data/lib/rdoc/generator/template/darkfish/images/brick.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/brick_link.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/bullet_black.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/date.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/package.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/page_green.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/page_white_text.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/page_white_width.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/plugin.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/ruby.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/wrench.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/wrench_orange.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/zoom.png +0 -0
- data/lib/rdoc/generator/template/darkfish/index.rhtml +2 -2
- data/lib/rdoc/generator/template/darkfish/rdoc.css +38 -33
- data/lib/rdoc/include.rb +22 -0
- data/lib/rdoc/markup.rb +10 -262
- data/lib/rdoc/markup/attribute_manager.rb +57 -50
- data/lib/rdoc/markup/blank_line.rb +19 -0
- data/lib/rdoc/markup/document.rb +72 -0
- data/lib/rdoc/markup/formatter.rb +118 -0
- data/lib/rdoc/markup/formatter_test_case.rb +341 -0
- data/lib/rdoc/markup/heading.rb +17 -0
- data/lib/rdoc/markup/inline.rb +6 -5
- data/lib/rdoc/markup/list.rb +78 -0
- data/lib/rdoc/markup/list_item.rb +83 -0
- data/lib/rdoc/markup/paragraph.rb +66 -0
- data/lib/rdoc/markup/parser.rb +528 -0
- data/lib/rdoc/markup/rule.rb +17 -0
- data/lib/rdoc/markup/to_ansi.rb +72 -0
- data/lib/rdoc/markup/to_bs.rb +74 -0
- data/lib/rdoc/markup/to_html.rb +106 -172
- data/lib/rdoc/markup/to_html_crossref.rb +10 -4
- data/lib/rdoc/markup/to_rdoc.rb +243 -0
- data/lib/rdoc/markup/to_test.rb +27 -16
- data/lib/rdoc/markup/verbatim.rb +42 -0
- data/lib/rdoc/normal_class.rb +38 -1
- data/lib/rdoc/normal_module.rb +38 -8
- data/lib/rdoc/options.rb +39 -151
- data/lib/rdoc/parser.rb +36 -18
- data/lib/rdoc/parser/c.rb +102 -109
- data/lib/rdoc/parser/ruby.rb +359 -1662
- data/lib/rdoc/parser/ruby_tools.rb +157 -0
- data/lib/rdoc/parser/simple.rb +0 -2
- data/lib/rdoc/rdoc.rb +142 -82
- data/lib/rdoc/ri.rb +10 -0
- data/lib/rdoc/ri/driver.rb +674 -444
- data/lib/rdoc/ri/formatter.rb +2 -651
- data/lib/rdoc/ri/paths.rb +70 -45
- data/lib/rdoc/ri/store.rb +248 -0
- data/lib/rdoc/ruby_lex.rb +1284 -0
- data/lib/rdoc/ruby_token.rb +416 -0
- data/lib/rdoc/single_class.rb +5 -0
- data/lib/rdoc/stats.rb +152 -83
- data/lib/rdoc/task.rb +27 -49
- data/lib/rdoc/text.rb +130 -0
- data/lib/rdoc/tokenstream.rb +28 -9
- data/lib/rdoc/top_level.rb +49 -43
- data/test/hidden.zip.txt +1 -0
- data/test/test_attribute_manager.rb +9 -16
- data/test/test_rdoc_any_method.rb +23 -0
- data/test/test_rdoc_attr.rb +40 -0
- data/test/test_rdoc_class_module.rb +100 -0
- data/test/test_rdoc_code_object.rb +18 -2
- data/test/test_rdoc_context.rb +41 -0
- data/test/test_rdoc_generator_ri.rb +56 -0
- data/test/test_rdoc_markup.rb +21 -610
- data/test/test_rdoc_markup_attribute_manager.rb +14 -17
- data/test/test_rdoc_markup_document.rb +51 -0
- data/test/test_rdoc_markup_paragraph.rb +27 -0
- data/test/test_rdoc_markup_parser.rb +1327 -0
- data/test/test_rdoc_markup_to_ansi.rb +426 -0
- data/test/test_rdoc_markup_to_bs.rb +443 -0
- data/test/test_rdoc_markup_to_html.rb +183 -18
- data/test/test_rdoc_markup_to_html_crossref.rb +1 -3
- data/test/test_rdoc_markup_to_rdoc.rb +426 -0
- data/test/test_rdoc_normal_class.rb +17 -0
- data/test/test_rdoc_normal_module.rb +6 -6
- data/test/test_rdoc_options.rb +41 -0
- data/test/test_rdoc_parser.rb +66 -13
- data/test/test_rdoc_parser_c.rb +93 -38
- data/test/test_rdoc_parser_perl.rb +2 -3
- data/test/test_rdoc_parser_ruby.rb +291 -28
- data/test/test_rdoc_parser_simple.rb +48 -0
- data/test/test_rdoc_rdoc.rb +66 -0
- data/test/test_rdoc_ri_driver.rb +752 -38
- data/test/test_rdoc_ri_paths.rb +39 -0
- data/test/test_rdoc_ri_store.rb +309 -0
- data/test/test_rdoc_text.rb +157 -0
- data/test/test_rdoc_top_level.rb +35 -9
- data/test/xref_data.rb +9 -1
- data/test/xref_test_case.rb +8 -3
- metadata +110 -38
- metadata.gz.sig +0 -0
- data/lib/rdoc/cache.rb +0 -41
- data/lib/rdoc/diagram.rb +0 -340
- data/lib/rdoc/dot.rb +0 -249
- data/lib/rdoc/markup/fragments.rb +0 -377
- data/lib/rdoc/markup/lines.rb +0 -156
- data/lib/rdoc/markup/to_flow.rb +0 -211
- data/lib/rdoc/markup/to_latex.rb +0 -328
- data/lib/rdoc/markup/to_texinfo.rb +0 -73
- data/lib/rdoc/ri/cache.rb +0 -187
- data/lib/rdoc/ri/descriptions.rb +0 -156
- data/lib/rdoc/ri/display.rb +0 -340
- data/lib/rdoc/ri/reader.rb +0 -106
- data/lib/rdoc/ri/util.rb +0 -79
- data/lib/rdoc/ri/writer.rb +0 -68
- data/test/test_rdoc_ri_attribute_formatter.rb +0 -44
- data/test/test_rdoc_ri_default_display.rb +0 -302
- data/test/test_rdoc_ri_formatter.rb +0 -320
- data/test/test_rdoc_ri_html_formatter.rb +0 -141
- data/test/test_rdoc_ri_overstrike_formatter.rb +0 -71
data/lib/rdoc/parser/ruby.rb
CHANGED
@@ -7,1339 +7,16 @@
|
|
7
7
|
# by Keiju ISHITSUKA (Nippon Rational Inc.)
|
8
8
|
#
|
9
9
|
|
10
|
-
require '
|
11
|
-
require '
|
10
|
+
require 'rdoc/ruby_token'
|
11
|
+
require 'rdoc/ruby_lex'
|
12
12
|
|
13
13
|
require 'rdoc/code_objects'
|
14
14
|
require 'rdoc/tokenstream'
|
15
15
|
require 'rdoc/markup/preprocess'
|
16
16
|
require 'rdoc/parser'
|
17
|
+
require 'rdoc/parser/ruby_tools'
|
17
18
|
|
18
19
|
$TOKEN_DEBUG ||= nil
|
19
|
-
#$TOKEN_DEBUG = $DEBUG_RDOC
|
20
|
-
|
21
|
-
##
|
22
|
-
# Definitions of all tokens involved in the lexical analysis
|
23
|
-
|
24
|
-
module RDoc::RubyToken
|
25
|
-
|
26
|
-
EXPR_BEG = :EXPR_BEG
|
27
|
-
EXPR_MID = :EXPR_MID
|
28
|
-
EXPR_END = :EXPR_END
|
29
|
-
EXPR_ARG = :EXPR_ARG
|
30
|
-
EXPR_FNAME = :EXPR_FNAME
|
31
|
-
EXPR_DOT = :EXPR_DOT
|
32
|
-
EXPR_CLASS = :EXPR_CLASS
|
33
|
-
|
34
|
-
class Token
|
35
|
-
NO_TEXT = "??".freeze
|
36
|
-
|
37
|
-
attr_accessor :text
|
38
|
-
attr_reader :line_no
|
39
|
-
attr_reader :char_no
|
40
|
-
|
41
|
-
def initialize(line_no, char_no)
|
42
|
-
@line_no = line_no
|
43
|
-
@char_no = char_no
|
44
|
-
@text = NO_TEXT
|
45
|
-
end
|
46
|
-
|
47
|
-
def ==(other)
|
48
|
-
self.class == other.class and
|
49
|
-
other.line_no == @line_no and
|
50
|
-
other.char_no == @char_no and
|
51
|
-
other.text == @text
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# Because we're used in contexts that expect to return a token, we set the
|
56
|
-
# text string and then return ourselves
|
57
|
-
|
58
|
-
def set_text(text)
|
59
|
-
@text = text
|
60
|
-
self
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
class TkNode < Token
|
66
|
-
attr :node
|
67
|
-
end
|
68
|
-
|
69
|
-
class TkId < Token
|
70
|
-
def initialize(line_no, char_no, name)
|
71
|
-
super(line_no, char_no)
|
72
|
-
@name = name
|
73
|
-
end
|
74
|
-
attr :name
|
75
|
-
end
|
76
|
-
|
77
|
-
class TkKW < TkId
|
78
|
-
end
|
79
|
-
|
80
|
-
class TkVal < Token
|
81
|
-
def initialize(line_no, char_no, value = nil)
|
82
|
-
super(line_no, char_no)
|
83
|
-
set_text(value)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class TkOp < Token
|
88
|
-
def name
|
89
|
-
self.class.op_name
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
class TkOPASGN < TkOp
|
94
|
-
def initialize(line_no, char_no, op)
|
95
|
-
super(line_no, char_no)
|
96
|
-
op = TkReading2Token[op] unless Symbol === op
|
97
|
-
@op = op
|
98
|
-
end
|
99
|
-
attr :op
|
100
|
-
end
|
101
|
-
|
102
|
-
class TkUnknownChar < Token
|
103
|
-
def initialize(line_no, char_no, id)
|
104
|
-
super(line_no, char_no)
|
105
|
-
@name = char_no.chr
|
106
|
-
end
|
107
|
-
attr :name
|
108
|
-
end
|
109
|
-
|
110
|
-
class TkError < Token
|
111
|
-
end
|
112
|
-
|
113
|
-
def set_token_position(line, char)
|
114
|
-
@prev_line_no = line
|
115
|
-
@prev_char_no = char
|
116
|
-
end
|
117
|
-
|
118
|
-
def Token(token, value = nil)
|
119
|
-
tk = nil
|
120
|
-
case token
|
121
|
-
when String, Symbol
|
122
|
-
source = String === token ? TkReading2Token : TkSymbol2Token
|
123
|
-
raise TkReading2TokenNoKey, token if (tk = source[token]).nil?
|
124
|
-
tk = Token(tk[0], value)
|
125
|
-
else
|
126
|
-
tk = if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
|
127
|
-
token.new(@prev_line_no, @prev_char_no)
|
128
|
-
else
|
129
|
-
token.new(@prev_line_no, @prev_char_no, value)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
tk
|
133
|
-
end
|
134
|
-
|
135
|
-
TokenDefinitions = [
|
136
|
-
[:TkCLASS, TkKW, "class", EXPR_CLASS],
|
137
|
-
[:TkMODULE, TkKW, "module", EXPR_CLASS],
|
138
|
-
[:TkDEF, TkKW, "def", EXPR_FNAME],
|
139
|
-
[:TkUNDEF, TkKW, "undef", EXPR_FNAME],
|
140
|
-
[:TkBEGIN, TkKW, "begin", EXPR_BEG],
|
141
|
-
[:TkRESCUE, TkKW, "rescue", EXPR_MID],
|
142
|
-
[:TkENSURE, TkKW, "ensure", EXPR_BEG],
|
143
|
-
[:TkEND, TkKW, "end", EXPR_END],
|
144
|
-
[:TkIF, TkKW, "if", EXPR_BEG, :TkIF_MOD],
|
145
|
-
[:TkUNLESS, TkKW, "unless", EXPR_BEG, :TkUNLESS_MOD],
|
146
|
-
[:TkTHEN, TkKW, "then", EXPR_BEG],
|
147
|
-
[:TkELSIF, TkKW, "elsif", EXPR_BEG],
|
148
|
-
[:TkELSE, TkKW, "else", EXPR_BEG],
|
149
|
-
[:TkCASE, TkKW, "case", EXPR_BEG],
|
150
|
-
[:TkWHEN, TkKW, "when", EXPR_BEG],
|
151
|
-
[:TkWHILE, TkKW, "while", EXPR_BEG, :TkWHILE_MOD],
|
152
|
-
[:TkUNTIL, TkKW, "until", EXPR_BEG, :TkUNTIL_MOD],
|
153
|
-
[:TkFOR, TkKW, "for", EXPR_BEG],
|
154
|
-
[:TkBREAK, TkKW, "break", EXPR_END],
|
155
|
-
[:TkNEXT, TkKW, "next", EXPR_END],
|
156
|
-
[:TkREDO, TkKW, "redo", EXPR_END],
|
157
|
-
[:TkRETRY, TkKW, "retry", EXPR_END],
|
158
|
-
[:TkIN, TkKW, "in", EXPR_BEG],
|
159
|
-
[:TkDO, TkKW, "do", EXPR_BEG],
|
160
|
-
[:TkRETURN, TkKW, "return", EXPR_MID],
|
161
|
-
[:TkYIELD, TkKW, "yield", EXPR_END],
|
162
|
-
[:TkSUPER, TkKW, "super", EXPR_END],
|
163
|
-
[:TkSELF, TkKW, "self", EXPR_END],
|
164
|
-
[:TkNIL, TkKW, "nil", EXPR_END],
|
165
|
-
[:TkTRUE, TkKW, "true", EXPR_END],
|
166
|
-
[:TkFALSE, TkKW, "false", EXPR_END],
|
167
|
-
[:TkAND, TkKW, "and", EXPR_BEG],
|
168
|
-
[:TkOR, TkKW, "or", EXPR_BEG],
|
169
|
-
[:TkNOT, TkKW, "not", EXPR_BEG],
|
170
|
-
[:TkIF_MOD, TkKW],
|
171
|
-
[:TkUNLESS_MOD, TkKW],
|
172
|
-
[:TkWHILE_MOD, TkKW],
|
173
|
-
[:TkUNTIL_MOD, TkKW],
|
174
|
-
[:TkALIAS, TkKW, "alias", EXPR_FNAME],
|
175
|
-
[:TkDEFINED, TkKW, "defined?", EXPR_END],
|
176
|
-
[:TklBEGIN, TkKW, "BEGIN", EXPR_END],
|
177
|
-
[:TklEND, TkKW, "END", EXPR_END],
|
178
|
-
[:Tk__LINE__, TkKW, "__LINE__", EXPR_END],
|
179
|
-
[:Tk__FILE__, TkKW, "__FILE__", EXPR_END],
|
180
|
-
|
181
|
-
[:TkIDENTIFIER, TkId],
|
182
|
-
[:TkFID, TkId],
|
183
|
-
[:TkGVAR, TkId],
|
184
|
-
[:TkIVAR, TkId],
|
185
|
-
[:TkCONSTANT, TkId],
|
186
|
-
|
187
|
-
[:TkINTEGER, TkVal],
|
188
|
-
[:TkFLOAT, TkVal],
|
189
|
-
[:TkSTRING, TkVal],
|
190
|
-
[:TkXSTRING, TkVal],
|
191
|
-
[:TkREGEXP, TkVal],
|
192
|
-
[:TkCOMMENT, TkVal],
|
193
|
-
|
194
|
-
[:TkDSTRING, TkNode],
|
195
|
-
[:TkDXSTRING, TkNode],
|
196
|
-
[:TkDREGEXP, TkNode],
|
197
|
-
[:TkNTH_REF, TkId],
|
198
|
-
[:TkBACK_REF, TkId],
|
199
|
-
|
200
|
-
[:TkUPLUS, TkOp, "+@"],
|
201
|
-
[:TkUMINUS, TkOp, "-@"],
|
202
|
-
[:TkPOW, TkOp, "**"],
|
203
|
-
[:TkCMP, TkOp, "<=>"],
|
204
|
-
[:TkEQ, TkOp, "=="],
|
205
|
-
[:TkEQQ, TkOp, "==="],
|
206
|
-
[:TkNEQ, TkOp, "!="],
|
207
|
-
[:TkGEQ, TkOp, ">="],
|
208
|
-
[:TkLEQ, TkOp, "<="],
|
209
|
-
[:TkANDOP, TkOp, "&&"],
|
210
|
-
[:TkOROP, TkOp, "||"],
|
211
|
-
[:TkMATCH, TkOp, "=~"],
|
212
|
-
[:TkNMATCH, TkOp, "!~"],
|
213
|
-
[:TkDOT2, TkOp, ".."],
|
214
|
-
[:TkDOT3, TkOp, "..."],
|
215
|
-
[:TkAREF, TkOp, "[]"],
|
216
|
-
[:TkASET, TkOp, "[]="],
|
217
|
-
[:TkLSHFT, TkOp, "<<"],
|
218
|
-
[:TkRSHFT, TkOp, ">>"],
|
219
|
-
[:TkCOLON2, TkOp],
|
220
|
-
[:TkCOLON3, TkOp],
|
221
|
-
# [:OPASGN, TkOp], # +=, -= etc. #
|
222
|
-
[:TkASSOC, TkOp, "=>"],
|
223
|
-
[:TkQUESTION, TkOp, "?"], #?
|
224
|
-
[:TkCOLON, TkOp, ":"], #:
|
225
|
-
|
226
|
-
[:TkfLPAREN], # func( #
|
227
|
-
[:TkfLBRACK], # func[ #
|
228
|
-
[:TkfLBRACE], # func{ #
|
229
|
-
[:TkSTAR], # *arg
|
230
|
-
[:TkAMPER], # &arg #
|
231
|
-
[:TkSYMBOL, TkId], # :SYMBOL
|
232
|
-
[:TkSYMBEG, TkId],
|
233
|
-
[:TkGT, TkOp, ">"],
|
234
|
-
[:TkLT, TkOp, "<"],
|
235
|
-
[:TkPLUS, TkOp, "+"],
|
236
|
-
[:TkMINUS, TkOp, "-"],
|
237
|
-
[:TkMULT, TkOp, "*"],
|
238
|
-
[:TkDIV, TkOp, "/"],
|
239
|
-
[:TkMOD, TkOp, "%"],
|
240
|
-
[:TkBITOR, TkOp, "|"],
|
241
|
-
[:TkBITXOR, TkOp, "^"],
|
242
|
-
[:TkBITAND, TkOp, "&"],
|
243
|
-
[:TkBITNOT, TkOp, "~"],
|
244
|
-
[:TkNOTOP, TkOp, "!"],
|
245
|
-
|
246
|
-
[:TkBACKQUOTE, TkOp, "`"],
|
247
|
-
|
248
|
-
[:TkASSIGN, Token, "="],
|
249
|
-
[:TkDOT, Token, "."],
|
250
|
-
[:TkLPAREN, Token, "("], #(exp)
|
251
|
-
[:TkLBRACK, Token, "["], #[arry]
|
252
|
-
[:TkLBRACE, Token, "{"], #{hash}
|
253
|
-
[:TkRPAREN, Token, ")"],
|
254
|
-
[:TkRBRACK, Token, "]"],
|
255
|
-
[:TkRBRACE, Token, "}"],
|
256
|
-
[:TkCOMMA, Token, ","],
|
257
|
-
[:TkSEMICOLON, Token, ";"],
|
258
|
-
|
259
|
-
[:TkRD_COMMENT],
|
260
|
-
[:TkSPACE],
|
261
|
-
[:TkNL],
|
262
|
-
[:TkEND_OF_SCRIPT],
|
263
|
-
|
264
|
-
[:TkBACKSLASH, TkUnknownChar, "\\"],
|
265
|
-
[:TkAT, TkUnknownChar, "@"],
|
266
|
-
[:TkDOLLAR, TkUnknownChar, "\$"], #"
|
267
|
-
]
|
268
|
-
|
269
|
-
# {reading => token_class}
|
270
|
-
# {reading => [token_class, *opt]}
|
271
|
-
TkReading2Token = {}
|
272
|
-
TkSymbol2Token = {}
|
273
|
-
|
274
|
-
def self.def_token(token_n, super_token = Token, reading = nil, *opts)
|
275
|
-
token_n = token_n.id2name unless String === token_n
|
276
|
-
|
277
|
-
fail AlreadyDefinedToken, token_n if const_defined?(token_n)
|
278
|
-
|
279
|
-
token_c = Class.new super_token
|
280
|
-
const_set token_n, token_c
|
281
|
-
# token_c.inspect
|
282
|
-
|
283
|
-
if reading
|
284
|
-
if TkReading2Token[reading]
|
285
|
-
fail TkReading2TokenDuplicateError, token_n, reading
|
286
|
-
end
|
287
|
-
if opts.empty?
|
288
|
-
TkReading2Token[reading] = [token_c]
|
289
|
-
else
|
290
|
-
TkReading2Token[reading] = [token_c].concat(opts)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
TkSymbol2Token[token_n.intern] = token_c
|
294
|
-
|
295
|
-
if token_c <= TkOp
|
296
|
-
token_c.class_eval %{
|
297
|
-
def self.op_name; "#{reading}"; end
|
298
|
-
}
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
for defs in TokenDefinitions
|
303
|
-
def_token(*defs)
|
304
|
-
end
|
305
|
-
|
306
|
-
NEWLINE_TOKEN = TkNL.new(0,0)
|
307
|
-
NEWLINE_TOKEN.set_text("\n")
|
308
|
-
|
309
|
-
end
|
310
|
-
|
311
|
-
##
|
312
|
-
# Lexical analyzer for Ruby source
|
313
|
-
|
314
|
-
class RDoc::RubyLex
|
315
|
-
|
316
|
-
##
|
317
|
-
# Read an input stream character by character. We allow for unlimited
|
318
|
-
# ungetting of characters just read.
|
319
|
-
#
|
320
|
-
# We simplify the implementation greatly by reading the entire input
|
321
|
-
# into a buffer initially, and then simply traversing it using
|
322
|
-
# pointers.
|
323
|
-
#
|
324
|
-
# We also have to allow for the <i>here document diversion</i>. This
|
325
|
-
# little gem comes about when the lexer encounters a here
|
326
|
-
# document. At this point we effectively need to split the input
|
327
|
-
# stream into two parts: one to read the body of the here document,
|
328
|
-
# the other to read the rest of the input line where the here
|
329
|
-
# document was initially encountered. For example, we might have
|
330
|
-
#
|
331
|
-
# do_something(<<-A, <<-B)
|
332
|
-
# stuff
|
333
|
-
# for
|
334
|
-
# A
|
335
|
-
# stuff
|
336
|
-
# for
|
337
|
-
# B
|
338
|
-
#
|
339
|
-
# When the lexer encounters the <<A, it reads until the end of the
|
340
|
-
# line, and keeps it around for later. It then reads the body of the
|
341
|
-
# here document. Once complete, it needs to read the rest of the
|
342
|
-
# original line, but then skip the here document body.
|
343
|
-
#
|
344
|
-
|
345
|
-
class BufferedReader
|
346
|
-
|
347
|
-
attr_reader :line_num
|
348
|
-
|
349
|
-
def initialize(content, options)
|
350
|
-
@options = options
|
351
|
-
|
352
|
-
if /\t/ =~ content
|
353
|
-
tab_width = @options.tab_width
|
354
|
-
content = content.split(/\n/).map do |line|
|
355
|
-
1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)} && $~ #`
|
356
|
-
line
|
357
|
-
end .join("\n")
|
358
|
-
end
|
359
|
-
@content = content
|
360
|
-
@content << "\n" unless @content[-1,1] == "\n"
|
361
|
-
@size = @content.size
|
362
|
-
@offset = 0
|
363
|
-
@hwm = 0
|
364
|
-
@line_num = 1
|
365
|
-
@read_back_offset = 0
|
366
|
-
@last_newline = 0
|
367
|
-
@newline_pending = false
|
368
|
-
end
|
369
|
-
|
370
|
-
def column
|
371
|
-
@offset - @last_newline
|
372
|
-
end
|
373
|
-
|
374
|
-
def getc
|
375
|
-
return nil if @offset >= @size
|
376
|
-
ch = @content[@offset, 1]
|
377
|
-
|
378
|
-
@offset += 1
|
379
|
-
@hwm = @offset if @hwm < @offset
|
380
|
-
|
381
|
-
if @newline_pending
|
382
|
-
@line_num += 1
|
383
|
-
@last_newline = @offset - 1
|
384
|
-
@newline_pending = false
|
385
|
-
end
|
386
|
-
|
387
|
-
if ch == "\n"
|
388
|
-
@newline_pending = true
|
389
|
-
end
|
390
|
-
ch
|
391
|
-
end
|
392
|
-
|
393
|
-
def getc_already_read
|
394
|
-
getc
|
395
|
-
end
|
396
|
-
|
397
|
-
def ungetc(ch)
|
398
|
-
raise "unget past beginning of file" if @offset <= 0
|
399
|
-
@offset -= 1
|
400
|
-
if @content[@offset] == ?\n
|
401
|
-
@newline_pending = false
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
def get_read
|
406
|
-
res = @content[@read_back_offset...@offset]
|
407
|
-
@read_back_offset = @offset
|
408
|
-
res
|
409
|
-
end
|
410
|
-
|
411
|
-
def peek(at)
|
412
|
-
pos = @offset + at
|
413
|
-
if pos >= @size
|
414
|
-
nil
|
415
|
-
else
|
416
|
-
@content[pos, 1]
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def peek_equal(str)
|
421
|
-
@content[@offset, str.length] == str
|
422
|
-
end
|
423
|
-
|
424
|
-
def divert_read_from(reserve)
|
425
|
-
@content[@offset, 0] = reserve
|
426
|
-
@size = @content.size
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
# end of nested class BufferedReader
|
431
|
-
|
432
|
-
extend Exception2MessageMapper
|
433
|
-
def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
|
434
|
-
def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
|
435
|
-
def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
|
436
|
-
def_exception(:TkReading2TokenDuplicateError,
|
437
|
-
"key duplicate(token_n='%s', key='%s')")
|
438
|
-
def_exception(:SyntaxError, "%s")
|
439
|
-
|
440
|
-
include RDoc::RubyToken
|
441
|
-
include IRB
|
442
|
-
|
443
|
-
attr_reader :continue
|
444
|
-
attr_reader :lex_state
|
445
|
-
|
446
|
-
def self.debug?
|
447
|
-
false
|
448
|
-
end
|
449
|
-
|
450
|
-
def initialize(content, options)
|
451
|
-
lex_init
|
452
|
-
|
453
|
-
@options = options
|
454
|
-
|
455
|
-
@reader = BufferedReader.new content, @options
|
456
|
-
|
457
|
-
@exp_line_no = @line_no = 1
|
458
|
-
@base_char_no = 0
|
459
|
-
@indent = 0
|
460
|
-
|
461
|
-
@ltype = nil
|
462
|
-
@quoted = nil
|
463
|
-
@lex_state = EXPR_BEG
|
464
|
-
@space_seen = false
|
465
|
-
|
466
|
-
@continue = false
|
467
|
-
@line = ""
|
468
|
-
|
469
|
-
@skip_space = false
|
470
|
-
@read_auto_clean_up = false
|
471
|
-
@exception_on_syntax_error = true
|
472
|
-
end
|
473
|
-
|
474
|
-
attr_accessor :skip_space
|
475
|
-
attr_accessor :read_auto_clean_up
|
476
|
-
attr_accessor :exception_on_syntax_error
|
477
|
-
attr_reader :indent
|
478
|
-
|
479
|
-
# io functions
|
480
|
-
def line_no
|
481
|
-
@reader.line_num
|
482
|
-
end
|
483
|
-
|
484
|
-
def char_no
|
485
|
-
@reader.column
|
486
|
-
end
|
487
|
-
|
488
|
-
def get_read
|
489
|
-
@reader.get_read
|
490
|
-
end
|
491
|
-
|
492
|
-
def getc
|
493
|
-
@reader.getc
|
494
|
-
end
|
495
|
-
|
496
|
-
def getc_of_rests
|
497
|
-
@reader.getc_already_read
|
498
|
-
end
|
499
|
-
|
500
|
-
def gets
|
501
|
-
c = getc or return
|
502
|
-
l = ""
|
503
|
-
begin
|
504
|
-
l.concat c unless c == "\r"
|
505
|
-
break if c == "\n"
|
506
|
-
end while c = getc
|
507
|
-
l
|
508
|
-
end
|
509
|
-
|
510
|
-
|
511
|
-
def ungetc(c = nil)
|
512
|
-
@reader.ungetc(c)
|
513
|
-
end
|
514
|
-
|
515
|
-
def peek_equal?(str)
|
516
|
-
@reader.peek_equal(str)
|
517
|
-
end
|
518
|
-
|
519
|
-
def peek(i = 0)
|
520
|
-
@reader.peek(i)
|
521
|
-
end
|
522
|
-
|
523
|
-
def lex
|
524
|
-
until (TkNL === (tk = token) or TkEND_OF_SCRIPT === tk) and
|
525
|
-
not @continue or tk.nil?
|
526
|
-
end
|
527
|
-
|
528
|
-
line = get_read
|
529
|
-
|
530
|
-
if line == "" and TkEND_OF_SCRIPT === tk or tk.nil? then
|
531
|
-
nil
|
532
|
-
else
|
533
|
-
line
|
534
|
-
end
|
535
|
-
end
|
536
|
-
|
537
|
-
def token
|
538
|
-
set_token_position(line_no, char_no)
|
539
|
-
begin
|
540
|
-
begin
|
541
|
-
tk = @OP.match(self)
|
542
|
-
@space_seen = TkSPACE === tk
|
543
|
-
rescue SyntaxError => e
|
544
|
-
raise RDoc::Error, "syntax error: #{e.message}" if
|
545
|
-
@exception_on_syntax_error
|
546
|
-
|
547
|
-
tk = TkError.new(line_no, char_no)
|
548
|
-
end
|
549
|
-
end while @skip_space and TkSPACE === tk
|
550
|
-
if @read_auto_clean_up
|
551
|
-
get_read
|
552
|
-
end
|
553
|
-
# throw :eof unless tk
|
554
|
-
tk
|
555
|
-
end
|
556
|
-
|
557
|
-
ENINDENT_CLAUSE = [
|
558
|
-
"case", "class", "def", "do", "for", "if",
|
559
|
-
"module", "unless", "until", "while", "begin" #, "when"
|
560
|
-
]
|
561
|
-
DEINDENT_CLAUSE = ["end" #, "when"
|
562
|
-
]
|
563
|
-
|
564
|
-
PERCENT_LTYPE = {
|
565
|
-
"q" => "\'",
|
566
|
-
"Q" => "\"",
|
567
|
-
"x" => "\`",
|
568
|
-
"r" => "/",
|
569
|
-
"w" => "]"
|
570
|
-
}
|
571
|
-
|
572
|
-
PERCENT_PAREN = {
|
573
|
-
"{" => "}",
|
574
|
-
"[" => "]",
|
575
|
-
"<" => ">",
|
576
|
-
"(" => ")"
|
577
|
-
}
|
578
|
-
|
579
|
-
Ltype2Token = {
|
580
|
-
"\'" => TkSTRING,
|
581
|
-
"\"" => TkSTRING,
|
582
|
-
"\`" => TkXSTRING,
|
583
|
-
"/" => TkREGEXP,
|
584
|
-
"]" => TkDSTRING
|
585
|
-
}
|
586
|
-
Ltype2Token.default = TkSTRING
|
587
|
-
|
588
|
-
DLtype2Token = {
|
589
|
-
"\"" => TkDSTRING,
|
590
|
-
"\`" => TkDXSTRING,
|
591
|
-
"/" => TkDREGEXP,
|
592
|
-
}
|
593
|
-
|
594
|
-
def lex_init()
|
595
|
-
@OP = IRB::SLex.new
|
596
|
-
@OP.def_rules("\0", "\004", "\032") do |chars, io|
|
597
|
-
Token(TkEND_OF_SCRIPT).set_text(chars)
|
598
|
-
end
|
599
|
-
|
600
|
-
@OP.def_rules(" ", "\t", "\f", "\r", "\13") do |chars, io|
|
601
|
-
@space_seen = TRUE
|
602
|
-
while (ch = getc) =~ /[ \t\f\r\13]/
|
603
|
-
chars << ch
|
604
|
-
end
|
605
|
-
ungetc
|
606
|
-
Token(TkSPACE).set_text(chars)
|
607
|
-
end
|
608
|
-
|
609
|
-
@OP.def_rule("#") do
|
610
|
-
|op, io|
|
611
|
-
identify_comment
|
612
|
-
end
|
613
|
-
|
614
|
-
@OP.def_rule("=begin", proc{@prev_char_no == 0 && peek(0) =~ /\s/}) do
|
615
|
-
|op, io|
|
616
|
-
str = op
|
617
|
-
@ltype = "="
|
618
|
-
|
619
|
-
|
620
|
-
begin
|
621
|
-
line = ""
|
622
|
-
begin
|
623
|
-
ch = getc
|
624
|
-
line << ch
|
625
|
-
end until ch == "\n"
|
626
|
-
str << line
|
627
|
-
end until line =~ /^=end/
|
628
|
-
|
629
|
-
ungetc
|
630
|
-
|
631
|
-
@ltype = nil
|
632
|
-
|
633
|
-
if str =~ /\A=begin\s+rdoc/i
|
634
|
-
str.sub!(/\A=begin.*\n/, '')
|
635
|
-
str.sub!(/^=end.*/m, '')
|
636
|
-
Token(TkCOMMENT).set_text(str)
|
637
|
-
else
|
638
|
-
Token(TkRD_COMMENT)#.set_text(str)
|
639
|
-
end
|
640
|
-
end
|
641
|
-
|
642
|
-
@OP.def_rule("\n") do
|
643
|
-
print "\\n\n" if RDoc::RubyLex.debug?
|
644
|
-
case @lex_state
|
645
|
-
when EXPR_BEG, EXPR_FNAME, EXPR_DOT
|
646
|
-
@continue = TRUE
|
647
|
-
else
|
648
|
-
@continue = FALSE
|
649
|
-
@lex_state = EXPR_BEG
|
650
|
-
end
|
651
|
-
Token(TkNL).set_text("\n")
|
652
|
-
end
|
653
|
-
|
654
|
-
@OP.def_rules("*", "**",
|
655
|
-
"!", "!=", "!~",
|
656
|
-
"=", "==", "===",
|
657
|
-
"=~", "<=>",
|
658
|
-
"<", "<=",
|
659
|
-
">", ">=", ">>") do
|
660
|
-
|op, io|
|
661
|
-
@lex_state = EXPR_BEG
|
662
|
-
Token(op).set_text(op)
|
663
|
-
end
|
664
|
-
|
665
|
-
@OP.def_rules("<<") do
|
666
|
-
|op, io|
|
667
|
-
tk = nil
|
668
|
-
if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
|
669
|
-
(@lex_state != EXPR_ARG || @space_seen)
|
670
|
-
c = peek(0)
|
671
|
-
if /[-\w_\"\'\`]/ =~ c
|
672
|
-
tk = identify_here_document
|
673
|
-
end
|
674
|
-
end
|
675
|
-
if !tk
|
676
|
-
@lex_state = EXPR_BEG
|
677
|
-
tk = Token(op).set_text(op)
|
678
|
-
end
|
679
|
-
tk
|
680
|
-
end
|
681
|
-
|
682
|
-
@OP.def_rules("'", '"') do
|
683
|
-
|op, io|
|
684
|
-
identify_string(op)
|
685
|
-
end
|
686
|
-
|
687
|
-
@OP.def_rules("`") do
|
688
|
-
|op, io|
|
689
|
-
if @lex_state == EXPR_FNAME
|
690
|
-
Token(op).set_text(op)
|
691
|
-
else
|
692
|
-
identify_string(op)
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
@OP.def_rules('?') do
|
697
|
-
|op, io|
|
698
|
-
if @lex_state == EXPR_END
|
699
|
-
@lex_state = EXPR_BEG
|
700
|
-
Token(TkQUESTION).set_text(op)
|
701
|
-
else
|
702
|
-
ch = getc
|
703
|
-
if @lex_state == EXPR_ARG && ch !~ /\s/
|
704
|
-
ungetc
|
705
|
-
@lex_state = EXPR_BEG
|
706
|
-
Token(TkQUESTION).set_text(op)
|
707
|
-
else
|
708
|
-
str = op
|
709
|
-
str << ch
|
710
|
-
if (ch == '\\') #'
|
711
|
-
str << read_escape
|
712
|
-
end
|
713
|
-
@lex_state = EXPR_END
|
714
|
-
Token(TkINTEGER).set_text(str)
|
715
|
-
end
|
716
|
-
end
|
717
|
-
end
|
718
|
-
|
719
|
-
@OP.def_rules("&", "&&", "|", "||") do
|
720
|
-
|op, io|
|
721
|
-
@lex_state = EXPR_BEG
|
722
|
-
Token(op).set_text(op)
|
723
|
-
end
|
724
|
-
|
725
|
-
@OP.def_rules("+=", "-=", "*=", "**=",
|
726
|
-
"&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
|
727
|
-
|op, io|
|
728
|
-
@lex_state = EXPR_BEG
|
729
|
-
op =~ /^(.*)=$/
|
730
|
-
Token(TkOPASGN, $1).set_text(op)
|
731
|
-
end
|
732
|
-
|
733
|
-
@OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) do |op, io|
|
734
|
-
Token(TkUPLUS).set_text(op)
|
735
|
-
end
|
736
|
-
|
737
|
-
@OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) do |op, io|
|
738
|
-
Token(TkUMINUS).set_text(op)
|
739
|
-
end
|
740
|
-
|
741
|
-
@OP.def_rules("+", "-") do
|
742
|
-
|op, io|
|
743
|
-
catch(:RET) do
|
744
|
-
if @lex_state == EXPR_ARG
|
745
|
-
if @space_seen and peek(0) =~ /[0-9]/
|
746
|
-
throw :RET, identify_number(op)
|
747
|
-
else
|
748
|
-
@lex_state = EXPR_BEG
|
749
|
-
end
|
750
|
-
elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
|
751
|
-
throw :RET, identify_number(op)
|
752
|
-
else
|
753
|
-
@lex_state = EXPR_BEG
|
754
|
-
end
|
755
|
-
Token(op).set_text(op)
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
@OP.def_rule(".") do
|
760
|
-
@lex_state = EXPR_BEG
|
761
|
-
if peek(0) =~ /[0-9]/
|
762
|
-
ungetc
|
763
|
-
identify_number("")
|
764
|
-
else
|
765
|
-
# for obj.if
|
766
|
-
@lex_state = EXPR_DOT
|
767
|
-
Token(TkDOT).set_text(".")
|
768
|
-
end
|
769
|
-
end
|
770
|
-
|
771
|
-
@OP.def_rules("..", "...") do
|
772
|
-
|op, io|
|
773
|
-
@lex_state = EXPR_BEG
|
774
|
-
Token(op).set_text(op)
|
775
|
-
end
|
776
|
-
|
777
|
-
lex_int2
|
778
|
-
end
|
779
|
-
|
780
|
-
def lex_int2
|
781
|
-
@OP.def_rules("]", "}", ")") do
|
782
|
-
|op, io|
|
783
|
-
@lex_state = EXPR_END
|
784
|
-
@indent -= 1
|
785
|
-
Token(op).set_text(op)
|
786
|
-
end
|
787
|
-
|
788
|
-
@OP.def_rule(":") do
|
789
|
-
if @lex_state == EXPR_END || peek(0) =~ /\s/
|
790
|
-
@lex_state = EXPR_BEG
|
791
|
-
tk = Token(TkCOLON)
|
792
|
-
else
|
793
|
-
@lex_state = EXPR_FNAME
|
794
|
-
tk = Token(TkSYMBEG)
|
795
|
-
end
|
796
|
-
tk.set_text(":")
|
797
|
-
end
|
798
|
-
|
799
|
-
@OP.def_rule("::") do
|
800
|
-
if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
|
801
|
-
@lex_state = EXPR_BEG
|
802
|
-
tk = Token(TkCOLON3)
|
803
|
-
else
|
804
|
-
@lex_state = EXPR_DOT
|
805
|
-
tk = Token(TkCOLON2)
|
806
|
-
end
|
807
|
-
tk.set_text("::")
|
808
|
-
end
|
809
|
-
|
810
|
-
@OP.def_rule("/") do
|
811
|
-
|op, io|
|
812
|
-
if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
|
813
|
-
identify_string(op)
|
814
|
-
elsif peek(0) == '='
|
815
|
-
getc
|
816
|
-
@lex_state = EXPR_BEG
|
817
|
-
Token(TkOPASGN, :/).set_text("/=") #")
|
818
|
-
elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
|
819
|
-
identify_string(op)
|
820
|
-
else
|
821
|
-
@lex_state = EXPR_BEG
|
822
|
-
Token("/").set_text(op)
|
823
|
-
end
|
824
|
-
end
|
825
|
-
|
826
|
-
@OP.def_rules("^") do
|
827
|
-
@lex_state = EXPR_BEG
|
828
|
-
Token("^").set_text("^")
|
829
|
-
end
|
830
|
-
|
831
|
-
@OP.def_rules(",", ";") do
|
832
|
-
|op, io|
|
833
|
-
@lex_state = EXPR_BEG
|
834
|
-
Token(op).set_text(op)
|
835
|
-
end
|
836
|
-
|
837
|
-
@OP.def_rule("~") do
|
838
|
-
@lex_state = EXPR_BEG
|
839
|
-
Token("~").set_text("~")
|
840
|
-
end
|
841
|
-
|
842
|
-
@OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) do
|
843
|
-
@lex_state = EXPR_BEG
|
844
|
-
Token("~").set_text("~@")
|
845
|
-
end
|
846
|
-
|
847
|
-
@OP.def_rule("(") do
|
848
|
-
@indent += 1
|
849
|
-
if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
|
850
|
-
@lex_state = EXPR_BEG
|
851
|
-
tk = Token(TkfLPAREN)
|
852
|
-
else
|
853
|
-
@lex_state = EXPR_BEG
|
854
|
-
tk = Token(TkLPAREN)
|
855
|
-
end
|
856
|
-
tk.set_text("(")
|
857
|
-
end
|
858
|
-
|
859
|
-
@OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) do
|
860
|
-
Token("[]").set_text("[]")
|
861
|
-
end
|
862
|
-
|
863
|
-
@OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) do
|
864
|
-
Token("[]=").set_text("[]=")
|
865
|
-
end
|
866
|
-
|
867
|
-
@OP.def_rule("[") do
|
868
|
-
@indent += 1
|
869
|
-
if @lex_state == EXPR_FNAME
|
870
|
-
t = Token(TkfLBRACK)
|
871
|
-
else
|
872
|
-
if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
|
873
|
-
t = Token(TkLBRACK)
|
874
|
-
elsif @lex_state == EXPR_ARG && @space_seen
|
875
|
-
t = Token(TkLBRACK)
|
876
|
-
else
|
877
|
-
t = Token(TkfLBRACK)
|
878
|
-
end
|
879
|
-
@lex_state = EXPR_BEG
|
880
|
-
end
|
881
|
-
t.set_text("[")
|
882
|
-
end
|
883
|
-
|
884
|
-
@OP.def_rule("{") do
|
885
|
-
@indent += 1
|
886
|
-
if @lex_state != EXPR_END && @lex_state != EXPR_ARG
|
887
|
-
t = Token(TkLBRACE)
|
888
|
-
else
|
889
|
-
t = Token(TkfLBRACE)
|
890
|
-
end
|
891
|
-
@lex_state = EXPR_BEG
|
892
|
-
t.set_text("{")
|
893
|
-
end
|
894
|
-
|
895
|
-
@OP.def_rule('\\') do #'
|
896
|
-
if getc == "\n"
|
897
|
-
@space_seen = true
|
898
|
-
@continue = true
|
899
|
-
Token(TkSPACE).set_text("\\\n")
|
900
|
-
else
|
901
|
-
ungetc
|
902
|
-
Token("\\").set_text("\\") #"
|
903
|
-
end
|
904
|
-
end
|
905
|
-
|
906
|
-
@OP.def_rule('%') do
|
907
|
-
|op, io|
|
908
|
-
if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
|
909
|
-
identify_quotation('%')
|
910
|
-
elsif peek(0) == '='
|
911
|
-
getc
|
912
|
-
Token(TkOPASGN, "%").set_text("%=")
|
913
|
-
elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
|
914
|
-
identify_quotation('%')
|
915
|
-
else
|
916
|
-
@lex_state = EXPR_BEG
|
917
|
-
Token("%").set_text("%")
|
918
|
-
end
|
919
|
-
end
|
920
|
-
|
921
|
-
@OP.def_rule('$') do #'
|
922
|
-
identify_gvar
|
923
|
-
end
|
924
|
-
|
925
|
-
@OP.def_rule('@') do
|
926
|
-
if peek(0) =~ /[@\w_]/
|
927
|
-
ungetc
|
928
|
-
identify_identifier
|
929
|
-
else
|
930
|
-
Token("@").set_text("@")
|
931
|
-
end
|
932
|
-
end
|
933
|
-
|
934
|
-
@OP.def_rule("__END__", proc{@prev_char_no == 0 && peek(0) =~ /[\r\n]/}) do
|
935
|
-
throw :eof
|
936
|
-
end
|
937
|
-
|
938
|
-
@OP.def_rule("") do
|
939
|
-
|op, io|
|
940
|
-
printf "MATCH: start %s: %s\n", op, io.inspect if RDoc::RubyLex.debug?
|
941
|
-
if peek(0) =~ /[0-9]/
|
942
|
-
t = identify_number("")
|
943
|
-
elsif peek(0) =~ /[\w_]/
|
944
|
-
t = identify_identifier
|
945
|
-
end
|
946
|
-
printf "MATCH: end %s: %s\n", op, io.inspect if RDoc::RubyLex.debug?
|
947
|
-
t
|
948
|
-
end
|
949
|
-
end
|
950
|
-
|
951
|
-
def identify_gvar
|
952
|
-
@lex_state = EXPR_END
|
953
|
-
str = "$"
|
954
|
-
|
955
|
-
tk = case ch = getc
|
956
|
-
when /[~_*$?!@\/\\;,=:<>".]/ #"
|
957
|
-
str << ch
|
958
|
-
Token(TkGVAR, str)
|
959
|
-
|
960
|
-
when "-"
|
961
|
-
str << "-" << getc
|
962
|
-
Token(TkGVAR, str)
|
963
|
-
|
964
|
-
when "&", "`", "'", "+"
|
965
|
-
str << ch
|
966
|
-
Token(TkBACK_REF, str)
|
967
|
-
|
968
|
-
when /[1-9]/
|
969
|
-
str << ch
|
970
|
-
while (ch = getc) =~ /[0-9]/
|
971
|
-
str << ch
|
972
|
-
end
|
973
|
-
ungetc
|
974
|
-
Token(TkNTH_REF)
|
975
|
-
when /\w/
|
976
|
-
ungetc
|
977
|
-
ungetc
|
978
|
-
return identify_identifier
|
979
|
-
else
|
980
|
-
ungetc
|
981
|
-
Token("$")
|
982
|
-
end
|
983
|
-
tk.set_text(str)
|
984
|
-
end
|
985
|
-
|
986
|
-
def identify_identifier
|
987
|
-
token = ""
|
988
|
-
token.concat getc if peek(0) =~ /[$@]/
|
989
|
-
token.concat getc if peek(0) == "@"
|
990
|
-
|
991
|
-
while (ch = getc) =~ /\w|_/
|
992
|
-
print ":", ch, ":" if RDoc::RubyLex.debug?
|
993
|
-
token.concat ch
|
994
|
-
end
|
995
|
-
ungetc
|
996
|
-
|
997
|
-
if ch == "!" or ch == "?"
|
998
|
-
token.concat getc
|
999
|
-
end
|
1000
|
-
# fix token
|
1001
|
-
|
1002
|
-
# $stderr.puts "identifier - #{token}, state = #@lex_state"
|
1003
|
-
|
1004
|
-
case token
|
1005
|
-
when /^\$/
|
1006
|
-
return Token(TkGVAR, token).set_text(token)
|
1007
|
-
when /^\@/
|
1008
|
-
@lex_state = EXPR_END
|
1009
|
-
return Token(TkIVAR, token).set_text(token)
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
if @lex_state != EXPR_DOT
|
1013
|
-
print token, "\n" if RDoc::RubyLex.debug?
|
1014
|
-
|
1015
|
-
token_c, *trans = TkReading2Token[token]
|
1016
|
-
if token_c
|
1017
|
-
# reserved word?
|
1018
|
-
|
1019
|
-
if (@lex_state != EXPR_BEG &&
|
1020
|
-
@lex_state != EXPR_FNAME &&
|
1021
|
-
trans[1])
|
1022
|
-
# modifiers
|
1023
|
-
token_c = TkSymbol2Token[trans[1]]
|
1024
|
-
@lex_state = trans[0]
|
1025
|
-
else
|
1026
|
-
if @lex_state != EXPR_FNAME
|
1027
|
-
if ENINDENT_CLAUSE.include?(token)
|
1028
|
-
@indent += 1
|
1029
|
-
elsif DEINDENT_CLAUSE.include?(token)
|
1030
|
-
@indent -= 1
|
1031
|
-
end
|
1032
|
-
@lex_state = trans[0]
|
1033
|
-
else
|
1034
|
-
@lex_state = EXPR_END
|
1035
|
-
end
|
1036
|
-
end
|
1037
|
-
return Token(token_c, token).set_text(token)
|
1038
|
-
end
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
if @lex_state == EXPR_FNAME
|
1042
|
-
@lex_state = EXPR_END
|
1043
|
-
if peek(0) == '='
|
1044
|
-
token.concat getc
|
1045
|
-
end
|
1046
|
-
elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
|
1047
|
-
@lex_state = EXPR_ARG
|
1048
|
-
else
|
1049
|
-
@lex_state = EXPR_END
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
if token[0, 1] =~ /[A-Z]/
|
1053
|
-
return Token(TkCONSTANT, token).set_text(token)
|
1054
|
-
elsif token[token.size - 1, 1] =~ /[!?]/
|
1055
|
-
return Token(TkFID, token).set_text(token)
|
1056
|
-
else
|
1057
|
-
return Token(TkIDENTIFIER, token).set_text(token)
|
1058
|
-
end
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
def identify_here_document
|
1062
|
-
ch = getc
|
1063
|
-
if ch == "-"
|
1064
|
-
ch = getc
|
1065
|
-
indent = true
|
1066
|
-
end
|
1067
|
-
if /['"`]/ =~ ch # '
|
1068
|
-
lt = ch
|
1069
|
-
quoted = ""
|
1070
|
-
while (c = getc) && c != lt
|
1071
|
-
quoted.concat c
|
1072
|
-
end
|
1073
|
-
else
|
1074
|
-
lt = '"'
|
1075
|
-
quoted = ch.dup
|
1076
|
-
while (c = getc) && c =~ /\w/
|
1077
|
-
quoted.concat c
|
1078
|
-
end
|
1079
|
-
ungetc
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
ltback, @ltype = @ltype, lt
|
1083
|
-
reserve = ""
|
1084
|
-
|
1085
|
-
while ch = getc
|
1086
|
-
reserve << ch
|
1087
|
-
if ch == "\\" #"
|
1088
|
-
ch = getc
|
1089
|
-
reserve << ch
|
1090
|
-
elsif ch == "\n"
|
1091
|
-
break
|
1092
|
-
end
|
1093
|
-
end
|
1094
|
-
|
1095
|
-
str = ""
|
1096
|
-
while (l = gets)
|
1097
|
-
l.chomp!
|
1098
|
-
l.strip! if indent
|
1099
|
-
break if l == quoted
|
1100
|
-
str << l.chomp << "\n"
|
1101
|
-
end
|
1102
|
-
|
1103
|
-
@reader.divert_read_from(reserve)
|
1104
|
-
|
1105
|
-
@ltype = ltback
|
1106
|
-
@lex_state = EXPR_END
|
1107
|
-
Token(Ltype2Token[lt], str).set_text(str.dump)
|
1108
|
-
end
|
1109
|
-
|
1110
|
-
def identify_quotation(initial_char)
|
1111
|
-
ch = getc
|
1112
|
-
if lt = PERCENT_LTYPE[ch]
|
1113
|
-
initial_char += ch
|
1114
|
-
ch = getc
|
1115
|
-
elsif ch =~ /\W/
|
1116
|
-
lt = "\""
|
1117
|
-
else
|
1118
|
-
fail SyntaxError, "unknown type of %string ('#{ch}')"
|
1119
|
-
end
|
1120
|
-
# if ch !~ /\W/
|
1121
|
-
# ungetc
|
1122
|
-
# next
|
1123
|
-
# end
|
1124
|
-
#@ltype = lt
|
1125
|
-
@quoted = ch unless @quoted = PERCENT_PAREN[ch]
|
1126
|
-
identify_string(lt, @quoted, ch, initial_char)
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
def identify_number(start)
|
1130
|
-
str = start.dup
|
1131
|
-
|
1132
|
-
if start == "+" or start == "-" or start == ""
|
1133
|
-
start = getc
|
1134
|
-
str << start
|
1135
|
-
end
|
1136
|
-
|
1137
|
-
@lex_state = EXPR_END
|
1138
|
-
|
1139
|
-
if start == "0"
|
1140
|
-
if peek(0) == "x"
|
1141
|
-
ch = getc
|
1142
|
-
str << ch
|
1143
|
-
match = /[0-9a-f_]/
|
1144
|
-
else
|
1145
|
-
match = /[0-7_]/
|
1146
|
-
end
|
1147
|
-
while ch = getc
|
1148
|
-
if ch !~ match
|
1149
|
-
ungetc
|
1150
|
-
break
|
1151
|
-
else
|
1152
|
-
str << ch
|
1153
|
-
end
|
1154
|
-
end
|
1155
|
-
return Token(TkINTEGER).set_text(str)
|
1156
|
-
end
|
1157
|
-
|
1158
|
-
type = TkINTEGER
|
1159
|
-
allow_point = TRUE
|
1160
|
-
allow_e = TRUE
|
1161
|
-
while ch = getc
|
1162
|
-
case ch
|
1163
|
-
when /[0-9_]/
|
1164
|
-
str << ch
|
1165
|
-
|
1166
|
-
when allow_point && "."
|
1167
|
-
type = TkFLOAT
|
1168
|
-
if peek(0) !~ /[0-9]/
|
1169
|
-
ungetc
|
1170
|
-
break
|
1171
|
-
end
|
1172
|
-
str << ch
|
1173
|
-
allow_point = false
|
1174
|
-
|
1175
|
-
when allow_e && "e", allow_e && "E"
|
1176
|
-
str << ch
|
1177
|
-
type = TkFLOAT
|
1178
|
-
if peek(0) =~ /[+-]/
|
1179
|
-
str << getc
|
1180
|
-
end
|
1181
|
-
allow_e = false
|
1182
|
-
allow_point = false
|
1183
|
-
else
|
1184
|
-
ungetc
|
1185
|
-
break
|
1186
|
-
end
|
1187
|
-
end
|
1188
|
-
Token(type).set_text(str)
|
1189
|
-
end
|
1190
|
-
|
1191
|
-
def identify_string(ltype, quoted = ltype, opener=nil, initial_char = nil)
|
1192
|
-
@ltype = ltype
|
1193
|
-
@quoted = quoted
|
1194
|
-
subtype = nil
|
1195
|
-
|
1196
|
-
str = ""
|
1197
|
-
str << initial_char if initial_char
|
1198
|
-
str << (opener||quoted)
|
1199
|
-
|
1200
|
-
nest = 0
|
1201
|
-
begin
|
1202
|
-
while ch = getc
|
1203
|
-
str << ch
|
1204
|
-
if @quoted == ch
|
1205
|
-
if nest == 0
|
1206
|
-
break
|
1207
|
-
else
|
1208
|
-
nest -= 1
|
1209
|
-
end
|
1210
|
-
elsif opener == ch
|
1211
|
-
nest += 1
|
1212
|
-
elsif @ltype != "'" && @ltype != "]" and ch == "#"
|
1213
|
-
ch = getc
|
1214
|
-
if ch == "{"
|
1215
|
-
subtype = true
|
1216
|
-
str << ch << skip_inner_expression
|
1217
|
-
else
|
1218
|
-
ungetc(ch)
|
1219
|
-
end
|
1220
|
-
elsif ch == '\\' #'
|
1221
|
-
str << read_escape
|
1222
|
-
end
|
1223
|
-
end
|
1224
|
-
if @ltype == "/"
|
1225
|
-
if peek(0) =~ /i|o|n|e|s/
|
1226
|
-
str << getc
|
1227
|
-
end
|
1228
|
-
end
|
1229
|
-
if subtype
|
1230
|
-
Token(DLtype2Token[ltype], str)
|
1231
|
-
else
|
1232
|
-
Token(Ltype2Token[ltype], str)
|
1233
|
-
end.set_text(str)
|
1234
|
-
ensure
|
1235
|
-
@ltype = nil
|
1236
|
-
@quoted = nil
|
1237
|
-
@lex_state = EXPR_END
|
1238
|
-
end
|
1239
|
-
end
|
1240
|
-
|
1241
|
-
def skip_inner_expression
|
1242
|
-
res = ""
|
1243
|
-
nest = 0
|
1244
|
-
while (ch = getc)
|
1245
|
-
res << ch
|
1246
|
-
if ch == '}'
|
1247
|
-
break if nest.zero?
|
1248
|
-
nest -= 1
|
1249
|
-
elsif ch == '{'
|
1250
|
-
nest += 1
|
1251
|
-
end
|
1252
|
-
end
|
1253
|
-
res
|
1254
|
-
end
|
1255
|
-
|
1256
|
-
def identify_comment
|
1257
|
-
@ltype = "#"
|
1258
|
-
comment = "#"
|
1259
|
-
while ch = getc
|
1260
|
-
if ch == "\\"
|
1261
|
-
ch = getc
|
1262
|
-
if ch == "\n"
|
1263
|
-
ch = " "
|
1264
|
-
else
|
1265
|
-
comment << "\\"
|
1266
|
-
end
|
1267
|
-
else
|
1268
|
-
if ch == "\n"
|
1269
|
-
@ltype = nil
|
1270
|
-
ungetc
|
1271
|
-
break
|
1272
|
-
end
|
1273
|
-
end
|
1274
|
-
comment << ch
|
1275
|
-
end
|
1276
|
-
return Token(TkCOMMENT).set_text(comment)
|
1277
|
-
end
|
1278
|
-
|
1279
|
-
def read_escape
|
1280
|
-
res = ""
|
1281
|
-
case ch = getc
|
1282
|
-
when /[0-7]/
|
1283
|
-
ungetc ch
|
1284
|
-
3.times do
|
1285
|
-
case ch = getc
|
1286
|
-
when /[0-7]/
|
1287
|
-
when nil
|
1288
|
-
break
|
1289
|
-
else
|
1290
|
-
ungetc
|
1291
|
-
break
|
1292
|
-
end
|
1293
|
-
res << ch
|
1294
|
-
end
|
1295
|
-
|
1296
|
-
when "x"
|
1297
|
-
res << ch
|
1298
|
-
2.times do
|
1299
|
-
case ch = getc
|
1300
|
-
when /[0-9a-fA-F]/
|
1301
|
-
when nil
|
1302
|
-
break
|
1303
|
-
else
|
1304
|
-
ungetc
|
1305
|
-
break
|
1306
|
-
end
|
1307
|
-
res << ch
|
1308
|
-
end
|
1309
|
-
|
1310
|
-
when "M"
|
1311
|
-
res << ch
|
1312
|
-
if (ch = getc) != '-'
|
1313
|
-
ungetc
|
1314
|
-
else
|
1315
|
-
res << ch
|
1316
|
-
if (ch = getc) == "\\" #"
|
1317
|
-
res << ch
|
1318
|
-
res << read_escape
|
1319
|
-
else
|
1320
|
-
res << ch
|
1321
|
-
end
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
when "C", "c" #, "^"
|
1325
|
-
res << ch
|
1326
|
-
if ch == "C" and (ch = getc) != "-"
|
1327
|
-
ungetc
|
1328
|
-
else
|
1329
|
-
res << ch
|
1330
|
-
if (ch = getc) == "\\" #"
|
1331
|
-
res << ch
|
1332
|
-
res << read_escape
|
1333
|
-
else
|
1334
|
-
res << ch
|
1335
|
-
end
|
1336
|
-
end
|
1337
|
-
else
|
1338
|
-
res << ch
|
1339
|
-
end
|
1340
|
-
res
|
1341
|
-
end
|
1342
|
-
end
|
1343
20
|
|
1344
21
|
##
|
1345
22
|
# Extracts code elements from a source file returning a TopLevel object
|
@@ -1473,8 +150,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1473
150
|
|
1474
151
|
include RDoc::RubyToken
|
1475
152
|
include RDoc::TokenStream
|
153
|
+
include RDoc::Parser::RubyTools
|
154
|
+
|
155
|
+
##
|
156
|
+
# RDoc::NormalClass type
|
1476
157
|
|
1477
158
|
NORMAL = "::"
|
159
|
+
|
160
|
+
##
|
161
|
+
# RDoc::SingleClass type
|
162
|
+
|
1478
163
|
SINGLE = "<<"
|
1479
164
|
|
1480
165
|
def initialize(top_level, file_name, content, options, stats)
|
@@ -1484,21 +169,17 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1484
169
|
@token_listeners = nil
|
1485
170
|
@scanner = RDoc::RubyLex.new content, @options
|
1486
171
|
@scanner.exception_on_syntax_error = false
|
172
|
+
@prev_seek = nil
|
1487
173
|
|
1488
174
|
reset
|
1489
175
|
end
|
1490
176
|
|
1491
|
-
def add_token_listener(obj)
|
1492
|
-
@token_listeners ||= []
|
1493
|
-
@token_listeners << obj
|
1494
|
-
end
|
1495
|
-
|
1496
177
|
##
|
1497
178
|
# Look for the first comment in a file that isn't a shebang line.
|
1498
179
|
|
1499
180
|
def collect_first_comment
|
1500
181
|
skip_tkspace
|
1501
|
-
|
182
|
+
comment = ''
|
1502
183
|
first_line = true
|
1503
184
|
|
1504
185
|
tk = get_tk
|
@@ -1513,7 +194,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1513
194
|
tk = get_tk
|
1514
195
|
else
|
1515
196
|
first_line = false
|
1516
|
-
|
197
|
+
comment << tk.text << "\n"
|
1517
198
|
tk = get_tk
|
1518
199
|
|
1519
200
|
if TkNL === tk then
|
@@ -1525,7 +206,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1525
206
|
|
1526
207
|
unget_tk tk
|
1527
208
|
|
1528
|
-
|
209
|
+
comment
|
1529
210
|
end
|
1530
211
|
|
1531
212
|
def error(msg)
|
@@ -1571,24 +252,24 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1571
252
|
name_t = get_tk
|
1572
253
|
|
1573
254
|
# class ::A -> A is in the top level
|
1574
|
-
|
255
|
+
case name_t
|
256
|
+
when TkCOLON2, TkCOLON3 then # bug
|
1575
257
|
name_t = get_tk
|
1576
258
|
container = @top_level
|
1577
259
|
end
|
1578
260
|
|
1579
|
-
skip_tkspace
|
261
|
+
skip_tkspace false
|
1580
262
|
|
1581
263
|
while TkCOLON2 === peek_tk do
|
1582
264
|
prev_container = container
|
1583
|
-
container = container.find_module_named
|
1584
|
-
|
1585
|
-
# warn("Couldn't find module #{name_t.name}")
|
265
|
+
container = container.find_module_named name_t.name
|
266
|
+
unless container then
|
1586
267
|
container = prev_container.add_module RDoc::NormalModule, name_t.name
|
1587
268
|
end
|
1588
269
|
get_tk
|
1589
270
|
name_t = get_tk
|
1590
271
|
end
|
1591
|
-
skip_tkspace
|
272
|
+
skip_tkspace false
|
1592
273
|
return [container, name_t]
|
1593
274
|
end
|
1594
275
|
|
@@ -1601,12 +282,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1601
282
|
|
1602
283
|
res = ""
|
1603
284
|
while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
|
1604
|
-
res += tk.
|
285
|
+
res += tk.name
|
1605
286
|
tk = get_tk
|
1606
287
|
end
|
1607
288
|
|
1608
289
|
unget_tk(tk)
|
1609
|
-
skip_tkspace
|
290
|
+
skip_tkspace false
|
1610
291
|
|
1611
292
|
get_tkread # empty out read buffer
|
1612
293
|
|
@@ -1628,11 +309,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1628
309
|
|
1629
310
|
def get_constant
|
1630
311
|
res = ""
|
1631
|
-
skip_tkspace
|
312
|
+
skip_tkspace false
|
1632
313
|
tk = get_tk
|
1633
314
|
|
1634
315
|
while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
|
1635
|
-
res += tk.
|
316
|
+
res += tk.name
|
1636
317
|
tk = get_tk
|
1637
318
|
end
|
1638
319
|
|
@@ -1647,88 +328,51 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1647
328
|
# Get a constant that may be surrounded by parens
|
1648
329
|
|
1649
330
|
def get_constant_with_optional_parens
|
1650
|
-
skip_tkspace
|
331
|
+
skip_tkspace false
|
1651
332
|
nest = 0
|
1652
333
|
while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do
|
1653
334
|
get_tk
|
1654
|
-
skip_tkspace
|
335
|
+
skip_tkspace
|
1655
336
|
nest += 1
|
1656
337
|
end
|
1657
338
|
|
1658
339
|
name = get_constant
|
1659
340
|
|
1660
341
|
while nest > 0
|
1661
|
-
skip_tkspace
|
342
|
+
skip_tkspace
|
1662
343
|
tk = get_tk
|
1663
344
|
nest -= 1 if TkRPAREN === tk
|
1664
345
|
end
|
346
|
+
|
1665
347
|
name
|
1666
348
|
end
|
1667
349
|
|
1668
350
|
def get_symbol_or_name
|
1669
351
|
tk = get_tk
|
1670
352
|
case tk
|
1671
|
-
when
|
1672
|
-
tk.text.sub(/^:/, '')
|
1673
|
-
|
353
|
+
when TkSYMBOL then
|
354
|
+
text = tk.text.sub(/^:/, '')
|
355
|
+
|
356
|
+
if TkASSIGN === peek_tk then
|
357
|
+
get_tk
|
358
|
+
text << '='
|
359
|
+
end
|
360
|
+
|
361
|
+
text
|
362
|
+
when TkId, TkOp then
|
1674
363
|
tk.name
|
1675
|
-
when TkSTRING
|
364
|
+
when TkSTRING, TkDSTRING then
|
1676
365
|
tk.text
|
1677
366
|
else
|
1678
|
-
raise "Name or symbol expected (got #{tk})"
|
1679
|
-
end
|
1680
|
-
end
|
1681
|
-
|
1682
|
-
def get_tk
|
1683
|
-
tk = nil
|
1684
|
-
if @tokens.empty?
|
1685
|
-
tk = @scanner.token
|
1686
|
-
@read.push @scanner.get_read
|
1687
|
-
puts "get_tk1 => #{tk.inspect}" if $TOKEN_DEBUG
|
1688
|
-
else
|
1689
|
-
@read.push @unget_read.shift
|
1690
|
-
tk = @tokens.shift
|
1691
|
-
puts "get_tk2 => #{tk.inspect}" if $TOKEN_DEBUG
|
1692
|
-
end
|
1693
|
-
|
1694
|
-
if TkSYMBEG === tk then
|
1695
|
-
set_token_position(tk.line_no, tk.char_no)
|
1696
|
-
tk1 = get_tk
|
1697
|
-
if TkId === tk1 or TkOp === tk1 or TkSTRING === tk1 or TkDSTRING === tk1 then
|
1698
|
-
if tk1.respond_to?(:name)
|
1699
|
-
tk = Token(TkSYMBOL).set_text(":" + tk1.name)
|
1700
|
-
else
|
1701
|
-
tk = Token(TkSYMBOL).set_text(":" + tk1.text)
|
1702
|
-
end
|
1703
|
-
# remove the identifier we just read (we're about to
|
1704
|
-
# replace it with a symbol)
|
1705
|
-
@token_listeners.each do |obj|
|
1706
|
-
obj.pop_token
|
1707
|
-
end if @token_listeners
|
1708
|
-
else
|
1709
|
-
warn("':' not followed by identifier or operator")
|
1710
|
-
tk = tk1
|
1711
|
-
end
|
367
|
+
raise RDoc::Error, "Name or symbol expected (got #{tk})"
|
1712
368
|
end
|
1713
|
-
|
1714
|
-
# inform any listeners of our shiny new token
|
1715
|
-
@token_listeners.each do |obj|
|
1716
|
-
obj.add_token(tk)
|
1717
|
-
end if @token_listeners
|
1718
|
-
|
1719
|
-
tk
|
1720
|
-
end
|
1721
|
-
|
1722
|
-
def get_tkread
|
1723
|
-
read = @read.join("")
|
1724
|
-
@read = []
|
1725
|
-
read
|
1726
369
|
end
|
1727
370
|
|
1728
371
|
##
|
1729
372
|
# Look for directives in a normal comment block:
|
1730
373
|
#
|
1731
|
-
#
|
374
|
+
# # :stopdoc:
|
375
|
+
# # Don't display comment from this point forward
|
1732
376
|
#
|
1733
377
|
# This routine modifies it's parameter
|
1734
378
|
|
@@ -1743,8 +387,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1743
387
|
when 'main' then
|
1744
388
|
@options.main_page = param
|
1745
389
|
''
|
1746
|
-
when 'method', 'singleton-method'
|
1747
|
-
|
390
|
+
when 'method', 'singleton-method',
|
391
|
+
'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
|
392
|
+
false # handled elsewhere
|
1748
393
|
when 'section' then
|
1749
394
|
context.set_current_section(param, comment)
|
1750
395
|
comment.replace ''
|
@@ -1765,15 +410,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1765
410
|
end
|
1766
411
|
end
|
1767
412
|
|
1768
|
-
remove_private_comments
|
413
|
+
remove_private_comments comment
|
1769
414
|
end
|
1770
415
|
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
416
|
+
##
|
417
|
+
# Adds useful info about the parser to +message+
|
418
|
+
|
419
|
+
def make_message message
|
420
|
+
prefix = "\n#{@file_name}:"
|
421
|
+
|
422
|
+
prefix << "#{@scanner.line_no}:#{@scanner.char_no}:" if @scanner
|
423
|
+
|
424
|
+
"#{prefix} #{message}"
|
1777
425
|
end
|
1778
426
|
|
1779
427
|
##
|
@@ -1785,7 +433,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1785
433
|
if args.size > 0
|
1786
434
|
name = args[0]
|
1787
435
|
rw = "R"
|
1788
|
-
skip_tkspace
|
436
|
+
skip_tkspace false
|
1789
437
|
tk = get_tk
|
1790
438
|
if TkCOMMA === tk then
|
1791
439
|
rw = "RW" if get_bool
|
@@ -1838,19 +486,24 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1838
486
|
skip_tkspace
|
1839
487
|
end
|
1840
488
|
new_name = get_symbol_or_name
|
1841
|
-
|
489
|
+
|
490
|
+
@scanner.instance_eval { @lex_state = EXPR_FNAME }
|
491
|
+
|
1842
492
|
skip_tkspace
|
1843
493
|
if TkCOMMA === peek_tk then
|
1844
494
|
get_tk
|
1845
495
|
skip_tkspace
|
1846
496
|
end
|
1847
|
-
|
497
|
+
|
498
|
+
begin
|
499
|
+
old_name = get_symbol_or_name
|
500
|
+
rescue RDoc::Error
|
501
|
+
return
|
502
|
+
end
|
1848
503
|
|
1849
504
|
al = RDoc::Alias.new get_tkread, old_name, new_name, comment
|
1850
505
|
read_documentation_modifiers al, RDoc::ATTR_MODIFIERS
|
1851
|
-
if al.document_self
|
1852
|
-
context.add_alias(al)
|
1853
|
-
end
|
506
|
+
context.add_alias al if al.document_self
|
1854
507
|
end
|
1855
508
|
|
1856
509
|
def parse_call_parameters(tk)
|
@@ -1865,23 +518,25 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1865
518
|
nest = 0
|
1866
519
|
|
1867
520
|
loop do
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
end
|
1880
|
-
when TkCOMMENT
|
1881
|
-
unget_tk(tk)
|
1882
|
-
break
|
521
|
+
case tk
|
522
|
+
when TkSEMICOLON
|
523
|
+
break
|
524
|
+
when TkLPAREN, TkfLPAREN
|
525
|
+
nest += 1
|
526
|
+
when end_token
|
527
|
+
if end_token == TkRPAREN
|
528
|
+
nest -= 1
|
529
|
+
break if @scanner.lex_state == EXPR_END and nest <= 0
|
530
|
+
else
|
531
|
+
break unless @scanner.continue
|
1883
532
|
end
|
1884
|
-
|
533
|
+
when TkCOMMENT
|
534
|
+
unget_tk(tk)
|
535
|
+
break
|
536
|
+
when nil then
|
537
|
+
break
|
538
|
+
end
|
539
|
+
tk = get_tk
|
1885
540
|
end
|
1886
541
|
res = get_tkread.tr("\n", " ").strip
|
1887
542
|
res = "" if res == ";"
|
@@ -1898,7 +553,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1898
553
|
|
1899
554
|
if TkLT === peek_tk then
|
1900
555
|
get_tk
|
1901
|
-
skip_tkspace
|
556
|
+
skip_tkspace
|
1902
557
|
superclass = get_class_specification
|
1903
558
|
superclass = "<unknown>" if superclass.empty?
|
1904
559
|
end
|
@@ -1906,25 +561,24 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1906
561
|
cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
|
1907
562
|
cls = container.add_class cls_type, name, superclass
|
1908
563
|
|
1909
|
-
@stats.add_class cls
|
1910
|
-
|
1911
564
|
read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
|
1912
565
|
cls.record_location @top_level
|
1913
|
-
|
1914
|
-
parse_statements cls
|
1915
566
|
cls.comment = comment
|
1916
567
|
|
568
|
+
@stats.add_class cls
|
569
|
+
|
570
|
+
parse_statements cls
|
1917
571
|
when TkLSHFT
|
1918
572
|
case name = get_class_specification
|
1919
573
|
when "self", container.name
|
1920
|
-
parse_statements
|
574
|
+
parse_statements container, SINGLE
|
1921
575
|
else
|
1922
|
-
other = RDoc::TopLevel.find_class_named
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
other =
|
576
|
+
other = RDoc::TopLevel.find_class_named name
|
577
|
+
|
578
|
+
unless other then
|
579
|
+
other = container.add_module RDoc::NormalModule, name
|
580
|
+
other.record_location @top_level
|
581
|
+
other.comment = comment
|
1928
582
|
end
|
1929
583
|
|
1930
584
|
@stats.add_class other
|
@@ -1938,13 +592,13 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1938
592
|
end
|
1939
593
|
end
|
1940
594
|
|
1941
|
-
def parse_constant(container,
|
595
|
+
def parse_constant(container, tk, comment)
|
1942
596
|
name = tk.name
|
1943
|
-
skip_tkspace
|
597
|
+
skip_tkspace false
|
1944
598
|
eq_tk = get_tk
|
1945
599
|
|
1946
600
|
unless TkASSIGN === eq_tk then
|
1947
|
-
unget_tk
|
601
|
+
unget_tk eq_tk
|
1948
602
|
return
|
1949
603
|
end
|
1950
604
|
|
@@ -1952,12 +606,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1952
606
|
get_tkread
|
1953
607
|
|
1954
608
|
tk = get_tk
|
609
|
+
|
1955
610
|
if TkGT === tk then
|
1956
|
-
unget_tk
|
1957
|
-
unget_tk
|
611
|
+
unget_tk tk
|
612
|
+
unget_tk eq_tk
|
1958
613
|
return
|
1959
614
|
end
|
1960
615
|
|
616
|
+
rhs_name = ''
|
617
|
+
|
1961
618
|
loop do
|
1962
619
|
case tk
|
1963
620
|
when TkSEMICOLON then
|
@@ -1972,12 +629,30 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1972
629
|
unget_tk tk
|
1973
630
|
break
|
1974
631
|
end
|
632
|
+
when TkCONSTANT then
|
633
|
+
rhs_name << tk.name
|
634
|
+
|
635
|
+
if nest <= 0 and TkNL === peek_tk then
|
636
|
+
mod = if rhs_name =~ /^::/ then
|
637
|
+
RDoc::TopLevel.find_class_or_module rhs_name
|
638
|
+
else
|
639
|
+
container.find_module_named rhs_name
|
640
|
+
end
|
641
|
+
|
642
|
+
container.add_module_alias mod, name if mod
|
643
|
+
get_tk # TkNL
|
644
|
+
break
|
645
|
+
end
|
1975
646
|
when TkNL then
|
1976
647
|
if nest <= 0 &&
|
1977
648
|
(@scanner.lex_state == EXPR_END || !@scanner.continue) then
|
1978
649
|
unget_tk tk
|
1979
650
|
break
|
1980
651
|
end
|
652
|
+
when TkCOLON2, TkCOLON3 then
|
653
|
+
rhs_name << '::'
|
654
|
+
when nil then
|
655
|
+
break
|
1981
656
|
end
|
1982
657
|
tk = get_tk
|
1983
658
|
end
|
@@ -1988,6 +663,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
1988
663
|
con = RDoc::Constant.new name, res, comment
|
1989
664
|
read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
|
1990
665
|
|
666
|
+
@stats.add_constant con
|
1991
667
|
container.add_constant con if con.document_self
|
1992
668
|
end
|
1993
669
|
|
@@ -2008,22 +684,25 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2008
684
|
meth = RDoc::GhostMethod.new get_tkread, name
|
2009
685
|
meth.singleton = singleton
|
2010
686
|
|
2011
|
-
@stats.add_method meth
|
2012
|
-
|
2013
687
|
meth.start_collecting_tokens
|
2014
|
-
indent = TkSPACE.new 1, 1
|
688
|
+
indent = TkSPACE.new nil, 1, 1
|
2015
689
|
indent.set_text " " * column
|
2016
690
|
|
2017
|
-
position_comment = TkCOMMENT.new
|
691
|
+
position_comment = TkCOMMENT.new nil, line_no, 1
|
692
|
+
position_comment.set_text "# File #{@top_level.absolute_name}, line #{line_no}"
|
2018
693
|
meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
|
2019
694
|
|
2020
695
|
meth.params = ''
|
2021
696
|
|
2022
697
|
extract_call_seq comment, meth
|
2023
698
|
|
699
|
+
return unless meth.name
|
700
|
+
|
2024
701
|
container.add_method meth if meth.document_self
|
2025
702
|
|
2026
703
|
meth.comment = comment
|
704
|
+
|
705
|
+
@stats.add_method meth
|
2027
706
|
elsif comment.sub!(/# +:?(attr(_reader|_writer|_accessor)?:) *(\S*).*?\n/i, '') then
|
2028
707
|
rw = case $1
|
2029
708
|
when 'attr_reader' then 'R'
|
@@ -2035,6 +714,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2035
714
|
|
2036
715
|
att = RDoc::Attr.new get_tkread, name, rw, comment
|
2037
716
|
container.add_attribute att
|
717
|
+
|
718
|
+
@stats.add_method att
|
2038
719
|
end
|
2039
720
|
end
|
2040
721
|
|
@@ -2050,6 +731,35 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2050
731
|
end
|
2051
732
|
end
|
2052
733
|
|
734
|
+
##
|
735
|
+
# Parses a meta-programmed attribute and creates an RDoc::Attr.
|
736
|
+
#
|
737
|
+
# To create foo and bar attributes on class C with comment "My attributes":
|
738
|
+
#
|
739
|
+
# class C
|
740
|
+
#
|
741
|
+
# ##
|
742
|
+
# # :attr:
|
743
|
+
# #
|
744
|
+
# # My attributes
|
745
|
+
#
|
746
|
+
# my_attr :foo, :bar
|
747
|
+
#
|
748
|
+
# end
|
749
|
+
#
|
750
|
+
# To create a foo attribute on class C with comment "My attribute":
|
751
|
+
#
|
752
|
+
# class C
|
753
|
+
#
|
754
|
+
# ##
|
755
|
+
# # :attr: foo
|
756
|
+
# #
|
757
|
+
# # My attribute
|
758
|
+
#
|
759
|
+
# my_attr :foo, :bar
|
760
|
+
#
|
761
|
+
# end
|
762
|
+
|
2053
763
|
def parse_meta_attr(context, single, tk, comment)
|
2054
764
|
args = parse_symbol_arg
|
2055
765
|
read = get_tkread
|
@@ -2070,9 +780,14 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2070
780
|
name = $3 unless $3.empty?
|
2071
781
|
end
|
2072
782
|
|
2073
|
-
|
783
|
+
if name then
|
2074
784
|
att = RDoc::Attr.new get_tkread, name, rw, comment
|
2075
785
|
context.add_attribute att
|
786
|
+
else
|
787
|
+
args.each do |attr_name|
|
788
|
+
att = RDoc::Attr.new get_tkread, attr_name, rw, comment
|
789
|
+
context.add_attribute att
|
790
|
+
end
|
2076
791
|
end
|
2077
792
|
end
|
2078
793
|
|
@@ -2101,7 +816,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2101
816
|
when TkSYMBOL then
|
2102
817
|
name = name_t.text[1..-1]
|
2103
818
|
when TkSTRING then
|
2104
|
-
name = name_t.
|
819
|
+
name = name_t.value[1..-2]
|
2105
820
|
when TkASSIGN then # ignore
|
2106
821
|
remove_token_listener self
|
2107
822
|
return
|
@@ -2114,173 +829,183 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2114
829
|
meth = RDoc::MetaMethod.new get_tkread, name
|
2115
830
|
meth.singleton = singleton
|
2116
831
|
|
2117
|
-
@stats.add_method meth
|
2118
|
-
|
2119
832
|
remove_token_listener self
|
2120
833
|
|
2121
834
|
meth.start_collecting_tokens
|
2122
|
-
indent = TkSPACE.new 1, 1
|
835
|
+
indent = TkSPACE.new nil, 1, 1
|
2123
836
|
indent.set_text " " * column
|
2124
837
|
|
2125
|
-
position_comment = TkCOMMENT.new
|
838
|
+
position_comment = TkCOMMENT.new nil, line_no, 1
|
839
|
+
position_comment.value = "# File #{@top_level.absolute_name}, line #{line_no}"
|
2126
840
|
meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
|
2127
841
|
meth.add_tokens @token_stream
|
2128
842
|
|
2129
|
-
|
2130
|
-
|
2131
|
-
meth.params = ''
|
843
|
+
token_listener meth do
|
844
|
+
meth.params = ''
|
2132
845
|
|
2133
|
-
|
846
|
+
extract_call_seq comment, meth
|
2134
847
|
|
2135
|
-
|
848
|
+
container.add_method meth if meth.document_self
|
2136
849
|
|
2137
|
-
|
850
|
+
last_tk = tk
|
2138
851
|
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
852
|
+
while tk = get_tk do
|
853
|
+
case tk
|
854
|
+
when TkSEMICOLON then
|
855
|
+
break
|
856
|
+
when TkNL then
|
857
|
+
break unless last_tk and TkCOMMA === last_tk
|
858
|
+
when TkSPACE then
|
859
|
+
# expression continues
|
860
|
+
else
|
861
|
+
last_tk = tk
|
862
|
+
end
|
2149
863
|
end
|
2150
864
|
end
|
2151
865
|
|
2152
|
-
remove_token_listener meth
|
2153
|
-
|
2154
866
|
meth.comment = comment
|
867
|
+
|
868
|
+
@stats.add_method meth
|
2155
869
|
end
|
2156
870
|
|
2157
871
|
##
|
2158
|
-
# Parses a method
|
872
|
+
# Parses a normal method defined by +def+
|
2159
873
|
|
2160
874
|
def parse_method(container, single, tk, comment)
|
875
|
+
added_container = nil
|
876
|
+
meth = nil
|
877
|
+
name = nil
|
2161
878
|
line_no = tk.line_no
|
2162
879
|
column = tk.char_no
|
2163
880
|
|
2164
881
|
start_collecting_tokens
|
2165
|
-
add_token
|
2166
|
-
add_token_listener(self)
|
882
|
+
add_token tk
|
2167
883
|
|
2168
|
-
|
884
|
+
token_listener self do
|
885
|
+
@scanner.instance_eval do @lex_state = EXPR_FNAME end
|
2169
886
|
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
887
|
+
skip_tkspace false
|
888
|
+
name_t = get_tk
|
889
|
+
back_tk = skip_tkspace
|
890
|
+
meth = nil
|
891
|
+
added_container = false
|
2175
892
|
|
2176
|
-
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
|
893
|
+
dot = get_tk
|
894
|
+
if TkDOT === dot or TkCOLON2 === dot then
|
895
|
+
@scanner.instance_eval do @lex_state = EXPR_FNAME end
|
896
|
+
skip_tkspace
|
897
|
+
name_t2 = get_tk
|
898
|
+
|
899
|
+
case name_t
|
900
|
+
when TkSELF, TkMOD then
|
901
|
+
name = name_t2.name
|
902
|
+
when TkCONSTANT then
|
903
|
+
name = name_t2.name
|
904
|
+
prev_container = container
|
905
|
+
container = container.find_module_named(name_t.name)
|
906
|
+
unless container then
|
907
|
+
added_container = true
|
908
|
+
obj = name_t.name.split("::").inject(Object) do |state, item|
|
909
|
+
state.const_get(item)
|
910
|
+
end rescue nil
|
911
|
+
|
912
|
+
type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
|
913
|
+
|
914
|
+
unless [Class, Module].include?(obj.class) then
|
915
|
+
warn("Couldn't find #{name_t.name}. Assuming it's a module")
|
916
|
+
end
|
2181
917
|
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2185
|
-
|
2186
|
-
|
2187
|
-
|
2188
|
-
container = container.find_module_named(name_t.name)
|
2189
|
-
unless container then
|
2190
|
-
added_container = true
|
2191
|
-
obj = name_t.name.split("::").inject(Object) do |state, item|
|
2192
|
-
state.const_get(item)
|
2193
|
-
end rescue nil
|
2194
|
-
|
2195
|
-
type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
|
2196
|
-
|
2197
|
-
unless [Class, Module].include?(obj.class) then
|
2198
|
-
warn("Couldn't find #{name_t.name}. Assuming it's a module")
|
2199
|
-
end
|
918
|
+
if type == RDoc::NormalClass then
|
919
|
+
sclass = obj.superclass ? obj.superclass.name : nil
|
920
|
+
container = prev_container.add_class type, name_t.name, sclass
|
921
|
+
else
|
922
|
+
container = prev_container.add_module type, name_t.name
|
923
|
+
end
|
2200
924
|
|
2201
|
-
|
2202
|
-
container = prev_container.add_class(type, name_t.name, obj.superclass.name)
|
2203
|
-
else
|
2204
|
-
container = prev_container.add_module(type, name_t.name)
|
925
|
+
container.record_location @top_level
|
2205
926
|
end
|
2206
|
-
|
2207
|
-
|
927
|
+
when TkIDENTIFIER, TkIVAR then
|
928
|
+
dummy = RDoc::Context.new
|
929
|
+
dummy.parent = container
|
930
|
+
skip_method dummy
|
931
|
+
return
|
932
|
+
else
|
933
|
+
warn "unexpected method name token #{name_t.inspect}"
|
934
|
+
# break
|
935
|
+
skip_method container
|
936
|
+
return
|
2208
937
|
end
|
938
|
+
|
939
|
+
meth = RDoc::AnyMethod.new(get_tkread, name)
|
940
|
+
meth.singleton = true
|
2209
941
|
else
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
end
|
942
|
+
unget_tk dot
|
943
|
+
back_tk.reverse_each do |token|
|
944
|
+
unget_tk token
|
945
|
+
end
|
2215
946
|
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
|
947
|
+
name = case name_t
|
948
|
+
when TkSTAR, TkAMPER then
|
949
|
+
name_t.text
|
950
|
+
else
|
951
|
+
unless name_t.respond_to? :name then
|
952
|
+
warn "expected method name token, . or ::, got #{name_t.inspect}"
|
953
|
+
skip_method container
|
954
|
+
return
|
955
|
+
end
|
956
|
+
name_t.name
|
957
|
+
end
|
2223
958
|
|
2224
|
-
|
2225
|
-
|
2226
|
-
skip_method container
|
2227
|
-
return
|
959
|
+
meth = RDoc::AnyMethod.new get_tkread, name
|
960
|
+
meth.singleton = (single == SINGLE)
|
2228
961
|
end
|
2229
|
-
|
2230
|
-
name = name_t.name
|
2231
|
-
|
2232
|
-
meth = RDoc::AnyMethod.new get_tkread, name
|
2233
|
-
meth.singleton = (single == SINGLE)
|
2234
962
|
end
|
2235
963
|
|
2236
|
-
@stats.add_method meth
|
2237
|
-
|
2238
|
-
remove_token_listener self
|
2239
|
-
|
2240
964
|
meth.start_collecting_tokens
|
2241
|
-
indent = TkSPACE.new 1, 1
|
965
|
+
indent = TkSPACE.new nil, 1, 1
|
2242
966
|
indent.set_text " " * column
|
2243
967
|
|
2244
|
-
token = TkCOMMENT.new
|
968
|
+
token = TkCOMMENT.new nil, line_no, 1
|
969
|
+
token.set_text "# File #{@top_level.absolute_name}, line #{line_no}"
|
2245
970
|
meth.add_tokens [token, NEWLINE_TOKEN, indent]
|
2246
971
|
meth.add_tokens @token_stream
|
2247
972
|
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
parse_method_parameters meth
|
973
|
+
token_listener meth do
|
974
|
+
@scanner.instance_eval do @continue = false end
|
975
|
+
parse_method_parameters meth
|
2252
976
|
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
977
|
+
if meth.document_self then
|
978
|
+
container.add_method meth
|
979
|
+
elsif added_container then
|
980
|
+
container.document_self = false
|
981
|
+
end
|
2258
982
|
|
2259
|
-
|
2260
|
-
|
983
|
+
# Having now read the method parameters and documentation modifiers, we
|
984
|
+
# now know whether we have to rename #initialize to ::new
|
2261
985
|
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
986
|
+
if name == "initialize" && !meth.singleton then
|
987
|
+
if meth.dont_rename_initialize then
|
988
|
+
meth.visibility = :protected
|
989
|
+
else
|
990
|
+
meth.singleton = true
|
991
|
+
meth.name = "new"
|
992
|
+
meth.visibility = :public
|
993
|
+
end
|
2269
994
|
end
|
2270
|
-
end
|
2271
995
|
|
2272
|
-
|
2273
|
-
|
2274
|
-
remove_token_listener(meth)
|
996
|
+
parse_statements container, single, meth
|
997
|
+
end
|
2275
998
|
|
2276
999
|
extract_call_seq comment, meth
|
2277
1000
|
|
2278
1001
|
meth.comment = comment
|
1002
|
+
|
1003
|
+
@stats.add_method meth
|
2279
1004
|
end
|
2280
1005
|
|
2281
1006
|
def parse_method_or_yield_parameters(method = nil,
|
2282
1007
|
modifiers = RDoc::METHOD_MODIFIERS)
|
2283
|
-
skip_tkspace
|
1008
|
+
skip_tkspace false
|
2284
1009
|
tk = get_tk
|
2285
1010
|
|
2286
1011
|
# Little hack going on here. In the statement
|
@@ -2324,6 +1049,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2324
1049
|
@read.pop
|
2325
1050
|
when TkCOMMENT then
|
2326
1051
|
@read.pop
|
1052
|
+
when nil then
|
1053
|
+
break
|
2327
1054
|
end
|
2328
1055
|
tk = get_tk
|
2329
1056
|
end
|
@@ -2348,52 +1075,47 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2348
1075
|
method.params = res unless method.params
|
2349
1076
|
|
2350
1077
|
if method.block_params.nil? then
|
2351
|
-
skip_tkspace
|
1078
|
+
skip_tkspace false
|
2352
1079
|
read_documentation_modifiers method, RDoc::METHOD_MODIFIERS
|
2353
1080
|
end
|
2354
1081
|
end
|
2355
1082
|
|
2356
1083
|
def parse_module(container, single, tk, comment)
|
2357
|
-
container, name_t = get_class_or_module
|
1084
|
+
container, name_t = get_class_or_module container
|
2358
1085
|
|
2359
1086
|
name = name_t.name
|
2360
1087
|
|
2361
1088
|
mod = container.add_module RDoc::NormalModule, name
|
2362
1089
|
mod.record_location @top_level
|
2363
1090
|
|
2364
|
-
@stats.add_module mod
|
2365
|
-
|
2366
1091
|
read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
|
2367
1092
|
parse_statements(mod)
|
2368
1093
|
mod.comment = comment
|
1094
|
+
|
1095
|
+
@stats.add_module mod
|
2369
1096
|
end
|
2370
1097
|
|
2371
1098
|
def parse_require(context, comment)
|
2372
1099
|
skip_tkspace_comment
|
2373
1100
|
tk = get_tk
|
1101
|
+
|
2374
1102
|
if TkLPAREN === tk then
|
2375
1103
|
skip_tkspace_comment
|
2376
1104
|
tk = get_tk
|
2377
1105
|
end
|
2378
1106
|
|
2379
|
-
name =
|
2380
|
-
|
2381
|
-
|
2382
|
-
name = tk.text
|
2383
|
-
# when TkCONSTANT, TkIDENTIFIER, TkIVAR, TkGVAR
|
2384
|
-
# name = tk.name
|
2385
|
-
when TkDSTRING
|
2386
|
-
warn "Skipping require of dynamic string: #{tk.text}"
|
2387
|
-
# else
|
2388
|
-
# warn "'require' used as variable"
|
2389
|
-
end
|
2390
|
-
if name
|
1107
|
+
name = tk.text if TkSTRING === tk
|
1108
|
+
|
1109
|
+
if name then
|
2391
1110
|
context.add_require RDoc::Require.new(name, comment)
|
2392
1111
|
else
|
2393
|
-
unget_tk
|
1112
|
+
unget_tk tk
|
2394
1113
|
end
|
2395
1114
|
end
|
2396
1115
|
|
1116
|
+
##
|
1117
|
+
# The core of the ruby parser.
|
1118
|
+
|
2397
1119
|
def parse_statements(container, single = NORMAL, current_method = nil,
|
2398
1120
|
comment = '')
|
2399
1121
|
nest = 1
|
@@ -2408,7 +1130,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2408
1130
|
|
2409
1131
|
case tk
|
2410
1132
|
when TkNL then
|
2411
|
-
skip_tkspace
|
1133
|
+
skip_tkspace
|
2412
1134
|
tk = get_tk
|
2413
1135
|
|
2414
1136
|
if TkCOMMENT === tk then
|
@@ -2422,8 +1144,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2422
1144
|
|
2423
1145
|
while TkCOMMENT === tk do
|
2424
1146
|
comment << tk.text << "\n"
|
2425
|
-
|
2426
|
-
|
1147
|
+
|
1148
|
+
tk = get_tk # this is the newline
|
1149
|
+
skip_tkspace false # leading spaces
|
2427
1150
|
tk = get_tk
|
2428
1151
|
end
|
2429
1152
|
|
@@ -2466,11 +1189,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2466
1189
|
|
2467
1190
|
when TkCONSTANT then
|
2468
1191
|
if container.document_self then
|
2469
|
-
parse_constant container,
|
1192
|
+
parse_constant container, tk, comment
|
2470
1193
|
end
|
2471
1194
|
|
2472
1195
|
when TkALIAS then
|
2473
|
-
if container.document_self then
|
1196
|
+
if container.document_self and not current_method then
|
2474
1197
|
parse_alias container, single, tk, comment
|
2475
1198
|
end
|
2476
1199
|
|
@@ -2510,12 +1233,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2510
1233
|
when /^attr_(reader|writer|accessor)$/ then
|
2511
1234
|
parse_attr_accessor container, single, tk, comment
|
2512
1235
|
when 'alias_method' then
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
1236
|
+
parse_alias container, single, tk, comment if
|
1237
|
+
container.document_self
|
1238
|
+
when 'require', 'include' then
|
1239
|
+
# ignore
|
2516
1240
|
else
|
2517
1241
|
if container.document_self and comment =~ /\A#\#$/ then
|
2518
|
-
|
1242
|
+
case comment
|
1243
|
+
when /^# +:?attr(_reader|_writer|_accessor)?:/ then
|
1244
|
+
parse_meta_attr container, single, tk, comment
|
1245
|
+
else
|
1246
|
+
parse_meta_method container, single, tk, comment
|
1247
|
+
end
|
2519
1248
|
end
|
2520
1249
|
end
|
2521
1250
|
end
|
@@ -2532,16 +1261,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2532
1261
|
if nest == 0 then
|
2533
1262
|
read_documentation_modifiers container, RDoc::CLASS_MODIFIERS
|
2534
1263
|
container.ongoing_visibility = save_visibility
|
1264
|
+
|
1265
|
+
parse_comment container, tk, comment unless comment.empty?
|
1266
|
+
|
2535
1267
|
return
|
2536
1268
|
end
|
2537
|
-
|
2538
1269
|
end
|
2539
1270
|
|
2540
1271
|
comment = '' unless keep_comment
|
2541
1272
|
|
2542
1273
|
begin
|
2543
1274
|
get_tkread
|
2544
|
-
skip_tkspace
|
1275
|
+
skip_tkspace false
|
2545
1276
|
end while peek_tk == TkNL
|
2546
1277
|
end
|
2547
1278
|
end
|
@@ -2576,7 +1307,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2576
1307
|
end
|
2577
1308
|
|
2578
1309
|
loop do
|
2579
|
-
skip_tkspace
|
1310
|
+
skip_tkspace false
|
2580
1311
|
|
2581
1312
|
tk1 = get_tk
|
2582
1313
|
unless TkCOMMA === tk1 then
|
@@ -2632,7 +1363,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2632
1363
|
singleton = true
|
2633
1364
|
:public
|
2634
1365
|
else
|
2635
|
-
raise "Invalid visibility: #{tk.name}"
|
1366
|
+
raise RDoc::Error, "Invalid visibility: #{tk.name}"
|
2636
1367
|
end
|
2637
1368
|
|
2638
1369
|
skip_tkspace_comment false
|
@@ -2686,18 +1417,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2686
1417
|
end
|
2687
1418
|
end
|
2688
1419
|
|
2689
|
-
def peek_read
|
2690
|
-
@read.join('')
|
2691
|
-
end
|
2692
|
-
|
2693
|
-
##
|
2694
|
-
# Peek at the next token, but don't remove it from the stream
|
2695
|
-
|
2696
|
-
def peek_tk
|
2697
|
-
unget_tk(tk = get_tk)
|
2698
|
-
tk
|
2699
|
-
end
|
2700
|
-
|
2701
1420
|
##
|
2702
1421
|
# Directives are modifier comments that can appear after class, module, or
|
2703
1422
|
# method names. For example:
|
@@ -2762,40 +1481,40 @@ class RDoc::Parser::Ruby < RDoc::Parser
|
|
2762
1481
|
comment.sub!(/^#--\n.*/m, '')
|
2763
1482
|
end
|
2764
1483
|
|
2765
|
-
def remove_token_listener(obj)
|
2766
|
-
@token_listeners.delete(obj)
|
2767
|
-
end
|
2768
|
-
|
2769
|
-
def reset
|
2770
|
-
@tokens = []
|
2771
|
-
@unget_read = []
|
2772
|
-
@read = []
|
2773
|
-
end
|
2774
|
-
|
2775
1484
|
def scan
|
2776
1485
|
reset
|
2777
1486
|
|
2778
|
-
catch
|
2779
|
-
catch
|
1487
|
+
catch :eof do
|
1488
|
+
catch :enddoc do
|
2780
1489
|
begin
|
2781
|
-
parse_top_level_statements
|
2782
|
-
rescue
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
1490
|
+
parse_top_level_statements @top_level
|
1491
|
+
rescue StandardError => e
|
1492
|
+
bytes = ''
|
1493
|
+
|
1494
|
+
20.times do @scanner.ungetc end
|
1495
|
+
count = 0
|
1496
|
+
60.times do |i|
|
1497
|
+
count = i
|
1498
|
+
byte = @scanner.getc
|
1499
|
+
break unless byte
|
1500
|
+
bytes << byte
|
1501
|
+
end
|
1502
|
+
count -= 20
|
1503
|
+
count.times do @scanner.ungetc end
|
2788
1504
|
|
2789
|
-
|
2790
|
-
compiles cleanly--RDoc is not a full Ruby parser, and gets confused easily if
|
2791
|
-
fed invalid programs.
|
1505
|
+
$stderr.puts <<-EOF
|
2792
1506
|
|
2793
|
-
|
1507
|
+
#{self.class} failure around line #{@scanner.line_no} of
|
1508
|
+
#{@file_name}
|
2794
1509
|
|
2795
1510
|
EOF
|
2796
1511
|
|
2797
|
-
|
2798
|
-
|
1512
|
+
unless bytes.empty? then
|
1513
|
+
$stderr.puts
|
1514
|
+
$stderr.puts bytes.inspect
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
raise e
|
2799
1518
|
end
|
2800
1519
|
end
|
2801
1520
|
end
|
@@ -2807,7 +1526,7 @@ The internal error was:
|
|
2807
1526
|
# while, until, and for have an optional do
|
2808
1527
|
|
2809
1528
|
def skip_optional_do_after_expression
|
2810
|
-
skip_tkspace
|
1529
|
+
skip_tkspace false
|
2811
1530
|
tk = get_tk
|
2812
1531
|
case tk
|
2813
1532
|
when TkLPAREN, TkfLPAREN
|
@@ -2834,10 +1553,12 @@ The internal error was:
|
|
2834
1553
|
else
|
2835
1554
|
break unless @scanner.continue
|
2836
1555
|
end
|
1556
|
+
when nil then
|
1557
|
+
break
|
2837
1558
|
end
|
2838
1559
|
tk = get_tk
|
2839
1560
|
end
|
2840
|
-
skip_tkspace
|
1561
|
+
skip_tkspace false
|
2841
1562
|
|
2842
1563
|
get_tk if TkDO === peek_tk
|
2843
1564
|
end
|
@@ -2846,31 +1567,17 @@ The internal error was:
|
|
2846
1567
|
# skip the var [in] part of a 'for' statement
|
2847
1568
|
|
2848
1569
|
def skip_for_variable
|
2849
|
-
skip_tkspace
|
1570
|
+
skip_tkspace false
|
2850
1571
|
tk = get_tk
|
2851
|
-
skip_tkspace
|
1572
|
+
skip_tkspace false
|
2852
1573
|
tk = get_tk
|
2853
1574
|
unget_tk(tk) unless TkIN === tk
|
2854
1575
|
end
|
2855
1576
|
|
2856
|
-
def skip_method
|
1577
|
+
def skip_method container
|
2857
1578
|
meth = RDoc::AnyMethod.new "", "anon"
|
2858
|
-
parse_method_parameters
|
2859
|
-
parse_statements
|
2860
|
-
end
|
2861
|
-
|
2862
|
-
##
|
2863
|
-
# Skip spaces
|
2864
|
-
|
2865
|
-
def skip_tkspace(skip_nl = true)
|
2866
|
-
tokens = []
|
2867
|
-
|
2868
|
-
while TkSPACE === (tk = get_tk) or (skip_nl and TkNL === tk) do
|
2869
|
-
tokens.push tk
|
2870
|
-
end
|
2871
|
-
|
2872
|
-
unget_tk(tk)
|
2873
|
-
tokens
|
1579
|
+
parse_method_parameters meth
|
1580
|
+
parse_statements container, false, meth
|
2874
1581
|
end
|
2875
1582
|
|
2876
1583
|
##
|
@@ -2878,22 +1585,12 @@ The internal error was:
|
|
2878
1585
|
|
2879
1586
|
def skip_tkspace_comment(skip_nl = true)
|
2880
1587
|
loop do
|
2881
|
-
skip_tkspace
|
1588
|
+
skip_tkspace skip_nl
|
2882
1589
|
return unless TkCOMMENT === peek_tk
|
2883
1590
|
get_tk
|
2884
1591
|
end
|
2885
1592
|
end
|
2886
1593
|
|
2887
|
-
def unget_tk(tk)
|
2888
|
-
@tokens.unshift tk
|
2889
|
-
@unget_read.unshift @read.pop
|
2890
|
-
|
2891
|
-
# Remove this token from any listeners
|
2892
|
-
@token_listeners.each do |obj|
|
2893
|
-
obj.pop_token
|
2894
|
-
end if @token_listeners
|
2895
|
-
end
|
2896
|
-
|
2897
1594
|
def warn(msg)
|
2898
1595
|
return if @options.quiet
|
2899
1596
|
msg = make_message msg
|