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.

Files changed (139) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +3 -1
  3. data/History.txt +68 -0
  4. data/LICENSE.txt +57 -0
  5. data/Manifest.txt +37 -19
  6. data/README.txt +2 -12
  7. data/Rakefile +12 -12
  8. data/bin/rdoc +4 -4
  9. data/lib/rdoc.rb +32 -9
  10. data/lib/rdoc/alias.rb +2 -2
  11. data/lib/rdoc/any_method.rb +108 -16
  12. data/lib/rdoc/attr.rb +87 -1
  13. data/lib/rdoc/class_module.rb +131 -5
  14. data/lib/rdoc/code_object.rb +28 -5
  15. data/lib/rdoc/constant.rb +22 -0
  16. data/lib/rdoc/context.rb +80 -37
  17. data/lib/rdoc/gauntlet.rb +48 -0
  18. data/lib/rdoc/generator/darkfish.rb +25 -23
  19. data/lib/rdoc/generator/markup.rb +6 -29
  20. data/lib/rdoc/generator/ri.rb +39 -189
  21. data/lib/rdoc/generator/template/darkfish/classpage.rhtml +17 -1
  22. data/lib/rdoc/generator/template/darkfish/filepage.rhtml +10 -0
  23. data/lib/rdoc/generator/template/darkfish/images/brick.png +0 -0
  24. data/lib/rdoc/generator/template/darkfish/images/brick_link.png +0 -0
  25. data/lib/rdoc/generator/template/darkfish/images/bullet_black.png +0 -0
  26. data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png +0 -0
  27. data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png +0 -0
  28. data/lib/rdoc/generator/template/darkfish/images/date.png +0 -0
  29. data/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
  30. data/lib/rdoc/generator/template/darkfish/images/package.png +0 -0
  31. data/lib/rdoc/generator/template/darkfish/images/page_green.png +0 -0
  32. data/lib/rdoc/generator/template/darkfish/images/page_white_text.png +0 -0
  33. data/lib/rdoc/generator/template/darkfish/images/page_white_width.png +0 -0
  34. data/lib/rdoc/generator/template/darkfish/images/plugin.png +0 -0
  35. data/lib/rdoc/generator/template/darkfish/images/ruby.png +0 -0
  36. data/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
  37. data/lib/rdoc/generator/template/darkfish/images/wrench.png +0 -0
  38. data/lib/rdoc/generator/template/darkfish/images/wrench_orange.png +0 -0
  39. data/lib/rdoc/generator/template/darkfish/images/zoom.png +0 -0
  40. data/lib/rdoc/generator/template/darkfish/index.rhtml +2 -2
  41. data/lib/rdoc/generator/template/darkfish/rdoc.css +38 -33
  42. data/lib/rdoc/include.rb +22 -0
  43. data/lib/rdoc/markup.rb +10 -262
  44. data/lib/rdoc/markup/attribute_manager.rb +57 -50
  45. data/lib/rdoc/markup/blank_line.rb +19 -0
  46. data/lib/rdoc/markup/document.rb +72 -0
  47. data/lib/rdoc/markup/formatter.rb +118 -0
  48. data/lib/rdoc/markup/formatter_test_case.rb +341 -0
  49. data/lib/rdoc/markup/heading.rb +17 -0
  50. data/lib/rdoc/markup/inline.rb +6 -5
  51. data/lib/rdoc/markup/list.rb +78 -0
  52. data/lib/rdoc/markup/list_item.rb +83 -0
  53. data/lib/rdoc/markup/paragraph.rb +66 -0
  54. data/lib/rdoc/markup/parser.rb +528 -0
  55. data/lib/rdoc/markup/rule.rb +17 -0
  56. data/lib/rdoc/markup/to_ansi.rb +72 -0
  57. data/lib/rdoc/markup/to_bs.rb +74 -0
  58. data/lib/rdoc/markup/to_html.rb +106 -172
  59. data/lib/rdoc/markup/to_html_crossref.rb +10 -4
  60. data/lib/rdoc/markup/to_rdoc.rb +243 -0
  61. data/lib/rdoc/markup/to_test.rb +27 -16
  62. data/lib/rdoc/markup/verbatim.rb +42 -0
  63. data/lib/rdoc/normal_class.rb +38 -1
  64. data/lib/rdoc/normal_module.rb +38 -8
  65. data/lib/rdoc/options.rb +39 -151
  66. data/lib/rdoc/parser.rb +36 -18
  67. data/lib/rdoc/parser/c.rb +102 -109
  68. data/lib/rdoc/parser/ruby.rb +359 -1662
  69. data/lib/rdoc/parser/ruby_tools.rb +157 -0
  70. data/lib/rdoc/parser/simple.rb +0 -2
  71. data/lib/rdoc/rdoc.rb +142 -82
  72. data/lib/rdoc/ri.rb +10 -0
  73. data/lib/rdoc/ri/driver.rb +674 -444
  74. data/lib/rdoc/ri/formatter.rb +2 -651
  75. data/lib/rdoc/ri/paths.rb +70 -45
  76. data/lib/rdoc/ri/store.rb +248 -0
  77. data/lib/rdoc/ruby_lex.rb +1284 -0
  78. data/lib/rdoc/ruby_token.rb +416 -0
  79. data/lib/rdoc/single_class.rb +5 -0
  80. data/lib/rdoc/stats.rb +152 -83
  81. data/lib/rdoc/task.rb +27 -49
  82. data/lib/rdoc/text.rb +130 -0
  83. data/lib/rdoc/tokenstream.rb +28 -9
  84. data/lib/rdoc/top_level.rb +49 -43
  85. data/test/hidden.zip.txt +1 -0
  86. data/test/test_attribute_manager.rb +9 -16
  87. data/test/test_rdoc_any_method.rb +23 -0
  88. data/test/test_rdoc_attr.rb +40 -0
  89. data/test/test_rdoc_class_module.rb +100 -0
  90. data/test/test_rdoc_code_object.rb +18 -2
  91. data/test/test_rdoc_context.rb +41 -0
  92. data/test/test_rdoc_generator_ri.rb +56 -0
  93. data/test/test_rdoc_markup.rb +21 -610
  94. data/test/test_rdoc_markup_attribute_manager.rb +14 -17
  95. data/test/test_rdoc_markup_document.rb +51 -0
  96. data/test/test_rdoc_markup_paragraph.rb +27 -0
  97. data/test/test_rdoc_markup_parser.rb +1327 -0
  98. data/test/test_rdoc_markup_to_ansi.rb +426 -0
  99. data/test/test_rdoc_markup_to_bs.rb +443 -0
  100. data/test/test_rdoc_markup_to_html.rb +183 -18
  101. data/test/test_rdoc_markup_to_html_crossref.rb +1 -3
  102. data/test/test_rdoc_markup_to_rdoc.rb +426 -0
  103. data/test/test_rdoc_normal_class.rb +17 -0
  104. data/test/test_rdoc_normal_module.rb +6 -6
  105. data/test/test_rdoc_options.rb +41 -0
  106. data/test/test_rdoc_parser.rb +66 -13
  107. data/test/test_rdoc_parser_c.rb +93 -38
  108. data/test/test_rdoc_parser_perl.rb +2 -3
  109. data/test/test_rdoc_parser_ruby.rb +291 -28
  110. data/test/test_rdoc_parser_simple.rb +48 -0
  111. data/test/test_rdoc_rdoc.rb +66 -0
  112. data/test/test_rdoc_ri_driver.rb +752 -38
  113. data/test/test_rdoc_ri_paths.rb +39 -0
  114. data/test/test_rdoc_ri_store.rb +309 -0
  115. data/test/test_rdoc_text.rb +157 -0
  116. data/test/test_rdoc_top_level.rb +35 -9
  117. data/test/xref_data.rb +9 -1
  118. data/test/xref_test_case.rb +8 -3
  119. metadata +110 -38
  120. metadata.gz.sig +0 -0
  121. data/lib/rdoc/cache.rb +0 -41
  122. data/lib/rdoc/diagram.rb +0 -340
  123. data/lib/rdoc/dot.rb +0 -249
  124. data/lib/rdoc/markup/fragments.rb +0 -377
  125. data/lib/rdoc/markup/lines.rb +0 -156
  126. data/lib/rdoc/markup/to_flow.rb +0 -211
  127. data/lib/rdoc/markup/to_latex.rb +0 -328
  128. data/lib/rdoc/markup/to_texinfo.rb +0 -73
  129. data/lib/rdoc/ri/cache.rb +0 -187
  130. data/lib/rdoc/ri/descriptions.rb +0 -156
  131. data/lib/rdoc/ri/display.rb +0 -340
  132. data/lib/rdoc/ri/reader.rb +0 -106
  133. data/lib/rdoc/ri/util.rb +0 -79
  134. data/lib/rdoc/ri/writer.rb +0 -68
  135. data/test/test_rdoc_ri_attribute_formatter.rb +0 -44
  136. data/test/test_rdoc_ri_default_display.rb +0 -302
  137. data/test/test_rdoc_ri_formatter.rb +0 -320
  138. data/test/test_rdoc_ri_html_formatter.rb +0 -141
  139. data/test/test_rdoc_ri_overstrike_formatter.rb +0 -71
@@ -0,0 +1,17 @@
1
+ ##
2
+ # A heading with a level (1-6) and text
3
+
4
+ class RDoc::Markup::Heading < Struct.new :level, :text
5
+
6
+ def accept visitor
7
+ visitor.accept_heading self
8
+ end
9
+
10
+ def pretty_print q # :nodoc:
11
+ q.group 2, "[head: #{level} ", ']' do
12
+ q.pp text
13
+ end
14
+ end
15
+
16
+ end
17
+
@@ -1,5 +1,3 @@
1
- require 'rdoc/markup'
2
-
3
1
  class RDoc::Markup
4
2
 
5
3
  ##
@@ -7,6 +5,10 @@ class RDoc::Markup
7
5
  # value.
8
6
 
9
7
  class Attribute
8
+
9
+ ##
10
+ # Special attribute type. See RDoc::Markup#add_special
11
+
10
12
  SPECIAL = 1
11
13
 
12
14
  @@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
@@ -40,7 +42,7 @@ class RDoc::Markup
40
42
 
41
43
  end
42
44
 
43
- AttrChanger = Struct.new :turn_on, :turn_off
45
+ AttrChanger = Struct.new :turn_on, :turn_off # :nodoc:
44
46
 
45
47
  ##
46
48
  # An AttrChanger records a change in attributes. It contains a bitmap of the
@@ -48,7 +50,7 @@ class RDoc::Markup
48
50
 
49
51
  class AttrChanger
50
52
  def to_s # :nodoc:
51
- "Attr: +#{Attribute.as_string(turn_on)}/-#{Attribute.as_string(turn_on)}"
53
+ "Attr: +#{Attribute.as_string turn_on}/-#{Attribute.as_string turn_on}"
52
54
  end
53
55
  end
54
56
 
@@ -123,4 +125,3 @@ class RDoc::Markup
123
125
 
124
126
  end
125
127
 
126
- require 'rdoc/markup/attribute_manager'
@@ -0,0 +1,78 @@
1
+ ##
2
+ # A List of ListItems
3
+
4
+ class RDoc::Markup::List
5
+
6
+ ##
7
+ # The list's type
8
+
9
+ attr_accessor :type
10
+
11
+ ##
12
+ # Items in the list
13
+
14
+ attr_reader :items
15
+
16
+ ##
17
+ # Creates a new list of +type+ with +items+
18
+
19
+ def initialize type = nil, *items
20
+ @type = type
21
+ @items = []
22
+ @items.push(*items)
23
+ end
24
+
25
+ ##
26
+ # Appends +item+ to the list
27
+
28
+ def << item
29
+ @items << item
30
+ end
31
+
32
+ def == other # :nodoc:
33
+ self.class == other.class and
34
+ @type == other.type and
35
+ @items == other.items
36
+ end
37
+
38
+ def accept visitor
39
+ visitor.accept_list_start self
40
+
41
+ @items.each do |item|
42
+ item.accept visitor
43
+ end
44
+
45
+ visitor.accept_list_end self
46
+ end
47
+
48
+ ##
49
+ # Is the list empty?
50
+
51
+ def empty?
52
+ @items.empty?
53
+ end
54
+
55
+ ##
56
+ # Returns the last item in the list
57
+
58
+ def last
59
+ @items.last
60
+ end
61
+
62
+ def pretty_print q # :nodoc:
63
+ q.group 2, "[list: #{@type} ", ']' do
64
+ q.seplist @items do |item|
65
+ q.pp item
66
+ end
67
+ end
68
+ end
69
+
70
+ ##
71
+ # Appends +items+ to the list
72
+
73
+ def push *items
74
+ @items.push(*items)
75
+ end
76
+
77
+ end
78
+
@@ -0,0 +1,83 @@
1
+ ##
2
+ # An item within a List that contains paragraphs, headings, etc.
3
+
4
+ class RDoc::Markup::ListItem
5
+
6
+ ##
7
+ # The label for the ListItem
8
+
9
+ attr_accessor :label
10
+
11
+ ##
12
+ # Parts of the ListItem
13
+
14
+ attr_reader :parts
15
+
16
+ ##
17
+ # Creates a new ListItem with an optional +label+ containing +parts+
18
+
19
+ def initialize label = nil, *parts
20
+ @label = label
21
+ @parts = []
22
+ @parts.push(*parts)
23
+ end
24
+
25
+ ##
26
+ # Appends +part+ to the ListItem
27
+
28
+ def << part
29
+ @parts << part
30
+ end
31
+
32
+ def == other # :nodoc:
33
+ self.class == other.class and
34
+ @label == other.label and
35
+ @parts == other.parts
36
+ end
37
+
38
+ def accept visitor
39
+ visitor.accept_list_item_start self
40
+
41
+ @parts.each do |part|
42
+ part.accept visitor
43
+ end
44
+
45
+ visitor.accept_list_item_end self
46
+ end
47
+
48
+ ##
49
+ # Is the ListItem empty?
50
+
51
+ def empty?
52
+ @parts.empty?
53
+ end
54
+
55
+ ##
56
+ # Length of parts in the ListItem
57
+
58
+ def length
59
+ @parts.length
60
+ end
61
+
62
+ def pretty_print q # :nodoc:
63
+ q.group 2, '[item: ', ']' do
64
+ if @label then
65
+ q.text @label
66
+ q.breakable
67
+ end
68
+
69
+ q.seplist @parts do |part|
70
+ q.pp part
71
+ end
72
+ end
73
+ end
74
+
75
+ ##
76
+ # Adds +parts+ to the ListItem
77
+
78
+ def push *parts
79
+ @parts.push(*parts)
80
+ end
81
+
82
+ end
83
+
@@ -0,0 +1,66 @@
1
+ ##
2
+ # A Paragraph of text
3
+
4
+ class RDoc::Markup::Paragraph
5
+
6
+ ##
7
+ # The component parts of the list
8
+
9
+ attr_reader :parts
10
+
11
+ ##
12
+ # Creates a new Paragraph containing +parts+
13
+
14
+ def initialize *parts
15
+ @parts = []
16
+ @parts.push(*parts)
17
+ end
18
+
19
+ ##
20
+ # Appends +text+ to the Paragraph
21
+
22
+ def << text
23
+ @parts << text
24
+ end
25
+
26
+ def == other # :nodoc:
27
+ self.class == other.class and text == other.text
28
+ end
29
+
30
+ def accept visitor
31
+ visitor.accept_paragraph self
32
+ end
33
+
34
+ ##
35
+ # Appends +other+'s parts into this Paragraph
36
+
37
+ def merge other
38
+ @parts.push(*other.parts)
39
+ end
40
+
41
+ def pretty_print q # :nodoc:
42
+ self.class.name =~ /.*::(\w{4})/i
43
+
44
+ q.group 2, "[#{$1.downcase}: ", ']' do
45
+ q.seplist @parts do |part|
46
+ q.pp part
47
+ end
48
+ end
49
+ end
50
+
51
+ ##
52
+ # Appends +texts+ onto this Paragraph
53
+
54
+ def push *texts
55
+ self.parts.push(*texts)
56
+ end
57
+
58
+ ##
59
+ # The text of this paragraph
60
+
61
+ def text
62
+ @parts.join ' '
63
+ end
64
+
65
+ end
66
+
@@ -0,0 +1,528 @@
1
+ require 'strscan'
2
+ require 'rdoc/text'
3
+
4
+ ##
5
+ # A recursive-descent parser for RDoc markup.
6
+ #
7
+ # The parser tokenizes an input string then parses the tokens into a Document.
8
+ # Documents can be converted into output formats by writing a visitor like
9
+ # RDoc::Markup::ToHTML.
10
+ #
11
+ # The parser only handles the block-level constructs Paragraph, List,
12
+ # ListItem, Heading, Verbatim, BlankLine and Rule. Inline markup such as
13
+ # <tt>\+blah\+</tt> is handled separately by RDoc::Markup::AttributeManager.
14
+ #
15
+ # To see what markup the Parser implements read RDoc. To see how to use
16
+ # RDoc markup to format text in your program read RDoc::Markup.
17
+
18
+ class RDoc::Markup::Parser
19
+
20
+ include RDoc::Text
21
+
22
+ ##
23
+ # List token types
24
+
25
+ LIST_TOKENS = [
26
+ :BULLET,
27
+ :LABEL,
28
+ :LALPHA,
29
+ :NOTE,
30
+ :NUMBER,
31
+ :UALPHA,
32
+ ]
33
+
34
+ ##
35
+ # Parser error subclass
36
+
37
+ class Error < RuntimeError; end
38
+
39
+ ##
40
+ # Raised when the parser is unable to handle the given markup
41
+
42
+ class ParseError < Error; end
43
+
44
+ ##
45
+ # Enables display of debugging information
46
+
47
+ attr_accessor :debug
48
+
49
+ ##
50
+ # Token accessor
51
+
52
+ attr_reader :tokens
53
+
54
+ ##
55
+ # Parsers +str+ into a Document
56
+
57
+ def self.parse str
58
+ parser = new
59
+ #parser.debug = true
60
+ parser.tokenize str
61
+ RDoc::Markup::Document.new(*parser.parse)
62
+ end
63
+
64
+ ##
65
+ # Returns a token stream for +str+, for testing
66
+
67
+ def self.tokenize str
68
+ parser = new
69
+ parser.tokenize str
70
+ parser.tokens
71
+ end
72
+
73
+ ##
74
+ # Creates a new Parser. See also ::parse
75
+
76
+ def initialize
77
+ @tokens = []
78
+ @current_token = nil
79
+ @debug = false
80
+
81
+ @line = 0
82
+ @line_pos = 0
83
+ end
84
+
85
+ ##
86
+ # Builds a Heading of +level+
87
+
88
+ def build_heading level
89
+ heading = RDoc::Markup::Heading.new level, text
90
+ skip :NEWLINE
91
+
92
+ heading
93
+ end
94
+
95
+ ##
96
+ # Builds a List flush to +margin+
97
+
98
+ def build_list margin
99
+ p :list_start => margin if @debug
100
+
101
+ list = RDoc::Markup::List.new
102
+
103
+ until @tokens.empty? do
104
+ type, data, column, = get
105
+
106
+ case type
107
+ when :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA then
108
+ list_type = type
109
+
110
+ if column < margin then
111
+ unget
112
+ break
113
+ end
114
+
115
+ if list.type and list.type != list_type then
116
+ unget
117
+ break
118
+ end
119
+
120
+ list.type = list_type
121
+
122
+ case type
123
+ when :NOTE, :LABEL then
124
+ _, indent, = get # SPACE
125
+ if :NEWLINE == peek_token.first then
126
+ get
127
+ peek_type, new_indent, peek_column, = peek_token
128
+ indent = new_indent if
129
+ peek_type == :INDENT and peek_column >= column
130
+ unget
131
+ end
132
+ else
133
+ data = nil
134
+ _, indent, = get
135
+ end
136
+
137
+ list_item = build_list_item(margin + indent, data)
138
+
139
+ list << list_item if list_item
140
+ else
141
+ unget
142
+ break
143
+ end
144
+ end
145
+
146
+ p :list_end => margin if @debug
147
+
148
+ return nil if list.empty?
149
+
150
+ list
151
+ end
152
+
153
+ ##
154
+ # Builds a ListItem that is flush to +indent+ with type +item_type+
155
+
156
+ def build_list_item indent, item_type = nil
157
+ p :list_item_start => [indent, item_type] if @debug
158
+
159
+ list_item = RDoc::Markup::ListItem.new item_type
160
+
161
+ until @tokens.empty? do
162
+ type, data, column = get
163
+
164
+ if column < indent and
165
+ not type == :NEWLINE and
166
+ (type != :INDENT or data < indent) then
167
+ unget
168
+ break
169
+ end
170
+
171
+ case type
172
+ when :INDENT then
173
+ unget
174
+ list_item.push(*parse(indent))
175
+ when :TEXT then
176
+ unget
177
+ list_item << build_paragraph(indent)
178
+ when :HEADER then
179
+ list_item << build_heading(data)
180
+ when :NEWLINE then
181
+ list_item << RDoc::Markup::BlankLine.new
182
+ when *LIST_TOKENS then
183
+ unget
184
+ list_item << build_list(column)
185
+ else
186
+ raise ParseError, "Unhandled token #{@current_token.inspect}"
187
+ end
188
+ end
189
+
190
+ p :list_item_end => [indent, item_type] if @debug
191
+
192
+ return nil if list_item.empty?
193
+
194
+ list_item.parts.shift if
195
+ RDoc::Markup::BlankLine === list_item.parts.first and
196
+ list_item.length > 1
197
+
198
+ list_item
199
+ end
200
+
201
+ ##
202
+ # Builds a Paragraph that is flush to +margin+
203
+
204
+ def build_paragraph margin
205
+ p :paragraph_start => margin if @debug
206
+
207
+ paragraph = RDoc::Markup::Paragraph.new
208
+
209
+ until @tokens.empty? do
210
+ type, data, column, = get
211
+
212
+ case type
213
+ when :INDENT then
214
+ next if data == margin and peek_token[0] == :TEXT
215
+
216
+ unget
217
+ break
218
+ when :TEXT then
219
+ if column != margin then
220
+ unget
221
+ break
222
+ end
223
+
224
+ paragraph << data
225
+ skip :NEWLINE
226
+ else
227
+ unget
228
+ break
229
+ end
230
+ end
231
+
232
+ p :paragraph_end => margin if @debug
233
+
234
+ paragraph
235
+ end
236
+
237
+ ##
238
+ # Builds a Verbatim that is flush to +margin+
239
+
240
+ def build_verbatim margin
241
+ p :verbatim_begin => margin if @debug
242
+ verbatim = RDoc::Markup::Verbatim.new
243
+
244
+ until @tokens.empty? do
245
+ type, data, column, = get
246
+
247
+ case type
248
+ when :INDENT then
249
+ if margin >= data then
250
+ unget
251
+ break
252
+ end
253
+
254
+ indent = data - margin
255
+
256
+ verbatim << ' ' * indent
257
+ when :HEADER then
258
+ verbatim << '=' * data
259
+
260
+ _, _, peek_column, = peek_token
261
+ peek_column ||= column + data
262
+ verbatim << ' ' * (peek_column - column - data)
263
+ when :RULE then
264
+ width = 2 + data
265
+ verbatim << '-' * width
266
+
267
+ _, _, peek_column, = peek_token
268
+ peek_column ||= column + data + 2
269
+ verbatim << ' ' * (peek_column - column - width)
270
+ when :TEXT then
271
+ verbatim << data
272
+ when *LIST_TOKENS then
273
+ if column <= margin then
274
+ unget
275
+ break
276
+ end
277
+
278
+ list_marker = case type
279
+ when :BULLET then '*'
280
+ when :LABEL then "[#{data}]"
281
+ when :LALPHA, :NUMBER, :UALPHA then "#{data}."
282
+ when :NOTE then "#{data}::"
283
+ end
284
+
285
+ verbatim << list_marker
286
+
287
+ _, data, = get
288
+
289
+ verbatim << ' ' * (data - list_marker.length)
290
+ when :NEWLINE then
291
+ verbatim << data
292
+ break unless [:INDENT, :NEWLINE].include? peek_token[0]
293
+ else
294
+ unget
295
+ break
296
+ end
297
+ end
298
+
299
+ verbatim.normalize
300
+
301
+ p :verbatim_end => margin if @debug
302
+
303
+ verbatim
304
+ end
305
+
306
+ ##
307
+ # Pulls the next token from the stream.
308
+
309
+ def get
310
+ @current_token = @tokens.shift
311
+ p :get => @current_token if @debug
312
+ @current_token
313
+ end
314
+
315
+ ##
316
+ # Parses the tokens into a Document
317
+
318
+ def parse indent = 0
319
+ p :parse_start => indent if @debug
320
+
321
+ document = []
322
+
323
+ until @tokens.empty? do
324
+ type, data, column, = get
325
+
326
+ if type != :INDENT and column < indent then
327
+ unget
328
+ break
329
+ end
330
+
331
+ case type
332
+ when :HEADER then
333
+ document << build_heading(data)
334
+ when :INDENT then
335
+ if indent > data then
336
+ unget
337
+ break
338
+ elsif indent == data then
339
+ next
340
+ end
341
+
342
+ unget
343
+ document << build_verbatim(indent)
344
+ when :NEWLINE then
345
+ document << RDoc::Markup::BlankLine.new
346
+ skip :NEWLINE, false
347
+ when :RULE then
348
+ document << RDoc::Markup::Rule.new(data)
349
+ skip :NEWLINE
350
+ when :TEXT then
351
+ unget
352
+ document << build_paragraph(indent)
353
+
354
+ # we're done with this paragraph (indent mismatch)
355
+ break if peek_token[0] == :TEXT
356
+ when *LIST_TOKENS then
357
+ unget
358
+
359
+ list = build_list(indent)
360
+
361
+ document << list if list
362
+
363
+ # we're done with this list (indent mismatch)
364
+ break if LIST_TOKENS.include? peek_token.first and indent > 0
365
+ else
366
+ type, data, column, line = @current_token
367
+ raise ParseError,
368
+ "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
369
+ end
370
+ end
371
+
372
+ p :parse_end => indent if @debug
373
+
374
+ document
375
+ end
376
+
377
+ ##
378
+ # Returns the next token on the stream without modifying the stream
379
+
380
+ def peek_token
381
+ token = @tokens.first || []
382
+ p :peek => token if @debug
383
+ token
384
+ end
385
+
386
+ ##
387
+ # Skips a token of +token_type+, optionally raising an error.
388
+
389
+ def skip token_type, error = true
390
+ type, data, = get
391
+
392
+ return unless type # end of stream
393
+
394
+ return @current_token if token_type == type
395
+
396
+ unget
397
+
398
+ raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if
399
+ error
400
+ end
401
+
402
+ ##
403
+ # Consumes tokens until NEWLINE and turns them back into text
404
+
405
+ def text
406
+ text = ''
407
+
408
+ loop do
409
+ type, data, = get
410
+
411
+ text << case type
412
+ when :BULLET then
413
+ _, space, = get # SPACE
414
+ "*#{' ' * (space - 1)}"
415
+ when :LABEL then
416
+ _, space, = get # SPACE
417
+ "[#{data}]#{' ' * (space - data.length - 2)}"
418
+ when :LALPHA, :NUMBER, :UALPHA then
419
+ _, space, = get # SPACE
420
+ "#{data}.#{' ' * (space - 2)}"
421
+ when :NOTE then
422
+ _, space = get # SPACE
423
+ "#{data}::#{' ' * (space - data.length - 2)}"
424
+ when :TEXT then
425
+ data
426
+ when :NEWLINE then
427
+ unget
428
+ break
429
+ when nil then
430
+ break
431
+ else
432
+ raise ParseError, "unhandled token #{@current_token.inspect}"
433
+ end
434
+ end
435
+
436
+ text
437
+ end
438
+
439
+ ##
440
+ # Calculates the column and line of the current token based on +offset+.
441
+
442
+ def token_pos offset
443
+ [offset - @line_pos, @line]
444
+ end
445
+
446
+ ##
447
+ # Turns text +input+ into a stream of tokens
448
+
449
+ def tokenize input
450
+ s = StringScanner.new input
451
+
452
+ @line = 0
453
+ @line_pos = 0
454
+
455
+ until s.eos? do
456
+ pos = s.pos
457
+
458
+ @tokens << case
459
+ when s.scan(/\r?\n/) then
460
+ token = [:NEWLINE, s.matched, *token_pos(pos)]
461
+ @line_pos = s.pos
462
+ @line += 1
463
+ token
464
+ when s.scan(/ +/) then
465
+ [:INDENT, s.matched_size, *token_pos(pos)]
466
+ when s.scan(/(=+)\s+/) then
467
+ level = s[1].length
468
+ level = 6 if level > 6
469
+ @tokens << [:HEADER, level, *token_pos(pos)]
470
+
471
+ pos = s.pos
472
+ s.scan(/.*/)
473
+ [:TEXT, s.matched, *token_pos(pos)]
474
+ when s.scan(/^(-{3,}) *$/) then
475
+ [:RULE, s[1].length - 2, *token_pos(pos)]
476
+ when s.scan(/([*-])\s+/) then
477
+ @tokens << [:BULLET, :BULLET, *token_pos(pos)]
478
+ [:SPACE, s.matched_size, *token_pos(pos)]
479
+ when s.scan(/([a-z]|\d+)\.[ \t]+\S/i) then
480
+ list_label = s[1]
481
+ width = s.matched_size - 1
482
+
483
+ s.pos -= 1 # unget \S
484
+
485
+ list_type = case list_label
486
+ when /[a-z]/ then :LALPHA
487
+ when /[A-Z]/ then :UALPHA
488
+ when /\d/ then :NUMBER
489
+ else
490
+ raise ParseError, "BUG token #{list_label}"
491
+ end
492
+
493
+ @tokens << [list_type, list_label, *token_pos(pos)]
494
+ [:SPACE, width, *token_pos(pos)]
495
+ when s.scan(/\[(.*?)\]( +|$)/) then
496
+ @tokens << [:LABEL, s[1], *token_pos(pos)]
497
+ [:SPACE, s.matched_size, *token_pos(pos)]
498
+ when s.scan(/(.*?)::( +|$)/) then
499
+ @tokens << [:NOTE, s[1], *token_pos(pos)]
500
+ [:SPACE, s.matched_size, *token_pos(pos)]
501
+ else s.scan(/.*/)
502
+ [:TEXT, s.matched, *token_pos(pos)]
503
+ end
504
+ end
505
+
506
+ self
507
+ end
508
+
509
+ ##
510
+ # Returns the current token or +token+ to the token stream
511
+
512
+ def unget token = @current_token
513
+ p :unget => token if @debug
514
+ raise Error, 'too many #ungets' if token == @tokens.first
515
+ @tokens.unshift token if token
516
+ end
517
+
518
+ end
519
+
520
+ require 'rdoc/markup/blank_line'
521
+ require 'rdoc/markup/document'
522
+ require 'rdoc/markup/heading'
523
+ require 'rdoc/markup/list'
524
+ require 'rdoc/markup/list_item'
525
+ require 'rdoc/markup/paragraph'
526
+ require 'rdoc/markup/rule'
527
+ require 'rdoc/markup/verbatim'
528
+