gitlab-rdoc 6.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.rdoc +220 -0
- data/CVE-2013-0256.rdoc +49 -0
- data/ExampleMarkdown.md +37 -0
- data/ExampleRDoc.rdoc +208 -0
- data/Gemfile +12 -0
- data/History.rdoc +1666 -0
- data/LEGAL.rdoc +50 -0
- data/LICENSE.rdoc +57 -0
- data/README.rdoc +133 -0
- data/RI.rdoc +57 -0
- data/Rakefile +101 -0
- data/TODO.rdoc +59 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/exe/rdoc +44 -0
- data/exe/ri +12 -0
- data/lib/rdoc/alias.rb +112 -0
- data/lib/rdoc/anon_class.rb +11 -0
- data/lib/rdoc/any_method.rb +361 -0
- data/lib/rdoc/attr.rb +176 -0
- data/lib/rdoc/class_module.rb +802 -0
- data/lib/rdoc/code_object.rb +421 -0
- data/lib/rdoc/code_objects.rb +6 -0
- data/lib/rdoc/comment.rb +250 -0
- data/lib/rdoc/constant.rb +187 -0
- data/lib/rdoc/context/section.rb +232 -0
- data/lib/rdoc/context.rb +1266 -0
- data/lib/rdoc/cross_reference.rb +202 -0
- data/lib/rdoc/encoding.rb +136 -0
- data/lib/rdoc/erb_partial.rb +19 -0
- data/lib/rdoc/erbio.rb +42 -0
- data/lib/rdoc/extend.rb +10 -0
- data/lib/rdoc/generator/darkfish.rb +790 -0
- data/lib/rdoc/generator/json_index.rb +300 -0
- data/lib/rdoc/generator/markup.rb +160 -0
- data/lib/rdoc/generator/pot/message_extractor.rb +68 -0
- data/lib/rdoc/generator/pot/po.rb +84 -0
- data/lib/rdoc/generator/pot/po_entry.rb +141 -0
- data/lib/rdoc/generator/pot.rb +98 -0
- data/lib/rdoc/generator/ri.rb +31 -0
- data/lib/rdoc/generator/template/darkfish/.document +0 -0
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +5 -0
- data/lib/rdoc/generator/template/darkfish/_head.rhtml +22 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +19 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +9 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +15 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +9 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +15 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +15 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +12 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml +11 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +12 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +11 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +14 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +11 -0
- data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +18 -0
- data/lib/rdoc/generator/template/darkfish/class.rhtml +172 -0
- data/lib/rdoc/generator/template/darkfish/css/fonts.css +167 -0
- data/lib/rdoc/generator/template/darkfish/css/rdoc.css +639 -0
- data/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
- data/lib/rdoc/generator/template/darkfish/images/add.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/arrow_up.png +0 -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/bug.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/delete.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif +0 -0
- data/lib/rdoc/generator/template/darkfish/images/macFFBgHack.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_blue.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
- data/lib/rdoc/generator/template/darkfish/images/transparent.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 +22 -0
- data/lib/rdoc/generator/template/darkfish/js/darkfish.js +84 -0
- data/lib/rdoc/generator/template/darkfish/js/search.js +110 -0
- data/lib/rdoc/generator/template/darkfish/page.rhtml +18 -0
- data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +18 -0
- data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +62 -0
- data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +58 -0
- data/lib/rdoc/generator/template/json_index/.document +1 -0
- data/lib/rdoc/generator/template/json_index/js/navigation.js +105 -0
- data/lib/rdoc/generator/template/json_index/js/searcher.js +229 -0
- data/lib/rdoc/generator.rb +51 -0
- data/lib/rdoc/ghost_method.rb +7 -0
- data/lib/rdoc/i18n/locale.rb +102 -0
- data/lib/rdoc/i18n/text.rb +126 -0
- data/lib/rdoc/i18n.rb +10 -0
- data/lib/rdoc/include.rb +10 -0
- data/lib/rdoc/known_classes.rb +73 -0
- data/lib/rdoc/markdown/entities.rb +2132 -0
- data/lib/rdoc/markdown/literals.kpeg +23 -0
- data/lib/rdoc/markdown/literals.rb +417 -0
- data/lib/rdoc/markdown.kpeg +1237 -0
- data/lib/rdoc/markdown.rb +16685 -0
- data/lib/rdoc/markup/attr_changer.rb +23 -0
- data/lib/rdoc/markup/attr_span.rb +36 -0
- data/lib/rdoc/markup/attribute_manager.rb +409 -0
- data/lib/rdoc/markup/attributes.rb +71 -0
- data/lib/rdoc/markup/blank_line.rb +28 -0
- data/lib/rdoc/markup/block_quote.rb +15 -0
- data/lib/rdoc/markup/document.rb +165 -0
- data/lib/rdoc/markup/formatter.rb +266 -0
- data/lib/rdoc/markup/hard_break.rb +32 -0
- data/lib/rdoc/markup/heading.rb +79 -0
- data/lib/rdoc/markup/include.rb +43 -0
- data/lib/rdoc/markup/indented_paragraph.rb +48 -0
- data/lib/rdoc/markup/list.rb +102 -0
- data/lib/rdoc/markup/list_item.rb +100 -0
- data/lib/rdoc/markup/paragraph.rb +29 -0
- data/lib/rdoc/markup/parser.rb +575 -0
- data/lib/rdoc/markup/pre_process.rb +296 -0
- data/lib/rdoc/markup/raw.rb +70 -0
- data/lib/rdoc/markup/regexp_handling.rb +41 -0
- data/lib/rdoc/markup/rule.rb +21 -0
- data/lib/rdoc/markup/table.rb +47 -0
- data/lib/rdoc/markup/to_ansi.rb +94 -0
- data/lib/rdoc/markup/to_bs.rb +77 -0
- data/lib/rdoc/markup/to_html.rb +444 -0
- data/lib/rdoc/markup/to_html_crossref.rb +176 -0
- data/lib/rdoc/markup/to_html_snippet.rb +285 -0
- data/lib/rdoc/markup/to_joined_paragraph.rb +47 -0
- data/lib/rdoc/markup/to_label.rb +75 -0
- data/lib/rdoc/markup/to_markdown.rb +192 -0
- data/lib/rdoc/markup/to_rdoc.rb +362 -0
- data/lib/rdoc/markup/to_table_of_contents.rb +89 -0
- data/lib/rdoc/markup/to_test.rb +70 -0
- data/lib/rdoc/markup/to_tt_only.rb +121 -0
- data/lib/rdoc/markup/verbatim.rb +84 -0
- data/lib/rdoc/markup.rb +867 -0
- data/lib/rdoc/meta_method.rb +7 -0
- data/lib/rdoc/method_attr.rb +419 -0
- data/lib/rdoc/mixin.rb +121 -0
- data/lib/rdoc/normal_class.rb +93 -0
- data/lib/rdoc/normal_module.rb +74 -0
- data/lib/rdoc/options.rb +1285 -0
- data/lib/rdoc/parser/c.rb +1225 -0
- data/lib/rdoc/parser/changelog.rb +335 -0
- data/lib/rdoc/parser/markdown.rb +24 -0
- data/lib/rdoc/parser/rd.rb +23 -0
- data/lib/rdoc/parser/ripper_state_lex.rb +590 -0
- data/lib/rdoc/parser/ruby.rb +2327 -0
- data/lib/rdoc/parser/ruby_tools.rb +167 -0
- data/lib/rdoc/parser/simple.rb +61 -0
- data/lib/rdoc/parser/text.rb +12 -0
- data/lib/rdoc/parser.rb +277 -0
- data/lib/rdoc/rd/block_parser.rb +1056 -0
- data/lib/rdoc/rd/block_parser.ry +639 -0
- data/lib/rdoc/rd/inline.rb +72 -0
- data/lib/rdoc/rd/inline_parser.rb +1208 -0
- data/lib/rdoc/rd/inline_parser.ry +593 -0
- data/lib/rdoc/rd.rb +100 -0
- data/lib/rdoc/rdoc.rb +579 -0
- data/lib/rdoc/require.rb +52 -0
- data/lib/rdoc/ri/driver.rb +1572 -0
- data/lib/rdoc/ri/formatter.rb +6 -0
- data/lib/rdoc/ri/paths.rb +171 -0
- data/lib/rdoc/ri/store.rb +7 -0
- data/lib/rdoc/ri/task.rb +71 -0
- data/lib/rdoc/ri.rb +21 -0
- data/lib/rdoc/rubygems_hook.rb +246 -0
- data/lib/rdoc/servlet.rb +451 -0
- data/lib/rdoc/single_class.rb +26 -0
- data/lib/rdoc/stats/normal.rb +58 -0
- data/lib/rdoc/stats/quiet.rb +60 -0
- data/lib/rdoc/stats/verbose.rb +46 -0
- data/lib/rdoc/stats.rb +462 -0
- data/lib/rdoc/store.rb +979 -0
- data/lib/rdoc/task.rb +329 -0
- data/lib/rdoc/text.rb +304 -0
- data/lib/rdoc/token_stream.rb +119 -0
- data/lib/rdoc/tom_doc.rb +263 -0
- data/lib/rdoc/top_level.rb +289 -0
- data/lib/rdoc/version.rb +8 -0
- data/lib/rdoc.rb +201 -0
- data/man/ri.1 +247 -0
- data/rdoc.gemspec +249 -0
- metadata +279 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# A hard-break in the middle of a paragraph.
|
4
|
+
|
5
|
+
class RDoc::Markup::HardBreak
|
6
|
+
|
7
|
+
@instance = new
|
8
|
+
|
9
|
+
##
|
10
|
+
# RDoc::Markup::HardBreak is a singleton
|
11
|
+
|
12
|
+
def self.new
|
13
|
+
@instance
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Calls #accept_hard_break on +visitor+
|
18
|
+
|
19
|
+
def accept visitor
|
20
|
+
visitor.accept_hard_break self
|
21
|
+
end
|
22
|
+
|
23
|
+
def == other # :nodoc:
|
24
|
+
self.class === other
|
25
|
+
end
|
26
|
+
|
27
|
+
def pretty_print q # :nodoc:
|
28
|
+
q.text "[break]"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# A heading with a level (1-6) and text
|
4
|
+
|
5
|
+
RDoc::Markup::Heading =
|
6
|
+
Struct.new :level, :text do
|
7
|
+
|
8
|
+
@to_html = nil
|
9
|
+
@to_label = nil
|
10
|
+
|
11
|
+
##
|
12
|
+
# A singleton RDoc::Markup::ToLabel formatter for headings.
|
13
|
+
|
14
|
+
def self.to_label
|
15
|
+
@to_label ||= RDoc::Markup::ToLabel.new
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# A singleton plain HTML formatter for headings. Used for creating labels
|
20
|
+
# for the Table of Contents
|
21
|
+
|
22
|
+
def self.to_html
|
23
|
+
return @to_html if @to_html
|
24
|
+
|
25
|
+
markup = RDoc::Markup.new
|
26
|
+
markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
|
27
|
+
|
28
|
+
@to_html = RDoc::Markup::ToHtml.new nil
|
29
|
+
|
30
|
+
def @to_html.handle_regexp_CROSSREF target
|
31
|
+
target.text.sub(/^\\/, '')
|
32
|
+
end
|
33
|
+
|
34
|
+
@to_html
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Calls #accept_heading on +visitor+
|
39
|
+
|
40
|
+
def accept visitor
|
41
|
+
visitor.accept_heading self
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# An HTML-safe anchor reference for this header.
|
46
|
+
|
47
|
+
def aref
|
48
|
+
"label-#{self.class.to_label.convert text.dup}"
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Creates a fully-qualified label which will include the label from
|
53
|
+
# +context+. This helps keep ids unique in HTML.
|
54
|
+
|
55
|
+
def label context = nil
|
56
|
+
label = aref
|
57
|
+
|
58
|
+
label = [context.aref, label].compact.join '-' if
|
59
|
+
context and context.respond_to? :aref
|
60
|
+
|
61
|
+
label
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# HTML markup of the text of this label without the surrounding header
|
66
|
+
# element.
|
67
|
+
|
68
|
+
def plain_html
|
69
|
+
self.class.to_html.to_html(text.dup)
|
70
|
+
end
|
71
|
+
|
72
|
+
def pretty_print q # :nodoc:
|
73
|
+
q.group 2, "[head: #{level} ", ']' do
|
74
|
+
q.pp text
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# A file included at generation time. Objects of this class are created by
|
4
|
+
# RDoc::RD for an extension-less include.
|
5
|
+
#
|
6
|
+
# This implementation in incomplete.
|
7
|
+
|
8
|
+
class RDoc::Markup::Include
|
9
|
+
|
10
|
+
##
|
11
|
+
# The filename to be included, without extension
|
12
|
+
|
13
|
+
attr_reader :file
|
14
|
+
|
15
|
+
##
|
16
|
+
# Directories to search for #file
|
17
|
+
|
18
|
+
attr_reader :include_path
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates a new include that will import +file+ from +include_path+
|
22
|
+
|
23
|
+
def initialize file, include_path
|
24
|
+
@file = file
|
25
|
+
@include_path = include_path
|
26
|
+
end
|
27
|
+
|
28
|
+
def == other # :nodoc:
|
29
|
+
self.class === other and
|
30
|
+
@file == other.file and @include_path == other.include_path
|
31
|
+
end
|
32
|
+
|
33
|
+
def pretty_print q # :nodoc:
|
34
|
+
q.group 2, '[incl ', ']' do
|
35
|
+
q.text file
|
36
|
+
q.breakable
|
37
|
+
q.text 'from '
|
38
|
+
q.pp include_path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# An Indented Paragraph of text
|
4
|
+
|
5
|
+
class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw
|
6
|
+
|
7
|
+
##
|
8
|
+
# The indent in number of spaces
|
9
|
+
|
10
|
+
attr_reader :indent
|
11
|
+
|
12
|
+
##
|
13
|
+
# Creates a new IndentedParagraph containing +parts+ indented with +indent+
|
14
|
+
# spaces
|
15
|
+
|
16
|
+
def initialize indent, *parts
|
17
|
+
@indent = indent
|
18
|
+
|
19
|
+
super(*parts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def == other # :nodoc:
|
23
|
+
super and indent == other.indent
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Calls #accept_indented_paragraph on +visitor+
|
28
|
+
|
29
|
+
def accept visitor
|
30
|
+
visitor.accept_indented_paragraph self
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Joins the raw paragraph text and converts inline HardBreaks to the
|
35
|
+
# +hard_break+ text followed by the indent.
|
36
|
+
|
37
|
+
def text hard_break = nil
|
38
|
+
@parts.map do |part|
|
39
|
+
if RDoc::Markup::HardBreak === part then
|
40
|
+
'%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break
|
41
|
+
else
|
42
|
+
part
|
43
|
+
end
|
44
|
+
end.join
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# A List is a homogeneous set of ListItems.
|
4
|
+
#
|
5
|
+
# The supported list types include:
|
6
|
+
#
|
7
|
+
# :BULLET::
|
8
|
+
# An unordered list
|
9
|
+
# :LABEL::
|
10
|
+
# An unordered definition list, but using an alternate RDoc::Markup syntax
|
11
|
+
# :LALPHA::
|
12
|
+
# An ordered list using increasing lowercase English letters
|
13
|
+
# :NOTE::
|
14
|
+
# An unordered definition list
|
15
|
+
# :NUMBER::
|
16
|
+
# An ordered list using increasing Arabic numerals
|
17
|
+
# :UALPHA::
|
18
|
+
# An ordered list using increasing uppercase English letters
|
19
|
+
#
|
20
|
+
# Definition lists behave like HTML definition lists. Each list item can
|
21
|
+
# describe multiple terms. See RDoc::Markup::ListItem for how labels and
|
22
|
+
# definition are stored as list items.
|
23
|
+
|
24
|
+
class RDoc::Markup::List
|
25
|
+
|
26
|
+
##
|
27
|
+
# The list's type
|
28
|
+
|
29
|
+
attr_accessor :type
|
30
|
+
|
31
|
+
##
|
32
|
+
# Items in the list
|
33
|
+
|
34
|
+
attr_reader :items
|
35
|
+
|
36
|
+
##
|
37
|
+
# Creates a new list of +type+ with +items+. Valid list types are:
|
38
|
+
# +:BULLET+, +:LABEL+, +:LALPHA+, +:NOTE+, +:NUMBER+, +:UALPHA+
|
39
|
+
|
40
|
+
def initialize type = nil, *items
|
41
|
+
@type = type
|
42
|
+
@items = []
|
43
|
+
@items.concat items
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Appends +item+ to the list
|
48
|
+
|
49
|
+
def << item
|
50
|
+
@items << item
|
51
|
+
end
|
52
|
+
|
53
|
+
def == other # :nodoc:
|
54
|
+
self.class == other.class and
|
55
|
+
@type == other.type and
|
56
|
+
@items == other.items
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Runs this list and all its #items through +visitor+
|
61
|
+
|
62
|
+
def accept visitor
|
63
|
+
visitor.accept_list_start self
|
64
|
+
|
65
|
+
@items.each do |item|
|
66
|
+
item.accept visitor
|
67
|
+
end
|
68
|
+
|
69
|
+
visitor.accept_list_end self
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Is the list empty?
|
74
|
+
|
75
|
+
def empty?
|
76
|
+
@items.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Returns the last item in the list
|
81
|
+
|
82
|
+
def last
|
83
|
+
@items.last
|
84
|
+
end
|
85
|
+
|
86
|
+
def pretty_print q # :nodoc:
|
87
|
+
q.group 2, "[list: #{@type} ", ']' do
|
88
|
+
q.seplist @items do |item|
|
89
|
+
q.pp item
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Appends +items+ to the list
|
96
|
+
|
97
|
+
def push *items
|
98
|
+
@items.concat items
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# An item within a List that contains paragraphs, headings, etc.
|
4
|
+
#
|
5
|
+
# For BULLET, NUMBER, LALPHA and UALPHA lists, the label will always be nil.
|
6
|
+
# For NOTE and LABEL lists, the list label may contain:
|
7
|
+
#
|
8
|
+
# * a single String for a single label
|
9
|
+
# * an Array of Strings for a list item with multiple terms
|
10
|
+
# * nil for an extra description attached to a previously labeled list item
|
11
|
+
|
12
|
+
class RDoc::Markup::ListItem
|
13
|
+
|
14
|
+
##
|
15
|
+
# The label for the ListItem
|
16
|
+
|
17
|
+
attr_accessor :label
|
18
|
+
|
19
|
+
##
|
20
|
+
# Parts of the ListItem
|
21
|
+
|
22
|
+
attr_reader :parts
|
23
|
+
|
24
|
+
##
|
25
|
+
# Creates a new ListItem with an optional +label+ containing +parts+
|
26
|
+
|
27
|
+
def initialize label = nil, *parts
|
28
|
+
@label = label
|
29
|
+
@parts = []
|
30
|
+
@parts.concat parts
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Appends +part+ to the ListItem
|
35
|
+
|
36
|
+
def << part
|
37
|
+
@parts << part
|
38
|
+
end
|
39
|
+
|
40
|
+
def == other # :nodoc:
|
41
|
+
self.class == other.class and
|
42
|
+
@label == other.label and
|
43
|
+
@parts == other.parts
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Runs this list item and all its #parts through +visitor+
|
48
|
+
|
49
|
+
def accept visitor
|
50
|
+
visitor.accept_list_item_start self
|
51
|
+
|
52
|
+
@parts.each do |part|
|
53
|
+
part.accept visitor
|
54
|
+
end
|
55
|
+
|
56
|
+
visitor.accept_list_item_end self
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Is the ListItem empty?
|
61
|
+
|
62
|
+
def empty?
|
63
|
+
@parts.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Length of parts in the ListItem
|
68
|
+
|
69
|
+
def length
|
70
|
+
@parts.length
|
71
|
+
end
|
72
|
+
|
73
|
+
def pretty_print q # :nodoc:
|
74
|
+
q.group 2, '[item: ', ']' do
|
75
|
+
case @label
|
76
|
+
when Array then
|
77
|
+
q.pp @label
|
78
|
+
q.text ';'
|
79
|
+
q.breakable
|
80
|
+
when String then
|
81
|
+
q.pp @label
|
82
|
+
q.text ';'
|
83
|
+
q.breakable
|
84
|
+
end
|
85
|
+
|
86
|
+
q.seplist @parts do |part|
|
87
|
+
q.pp part
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Adds +parts+ to the ListItem
|
94
|
+
|
95
|
+
def push *parts
|
96
|
+
@parts.concat parts
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
##
|
3
|
+
# A Paragraph of text
|
4
|
+
|
5
|
+
class RDoc::Markup::Paragraph < RDoc::Markup::Raw
|
6
|
+
|
7
|
+
##
|
8
|
+
# Calls #accept_paragraph on +visitor+
|
9
|
+
|
10
|
+
def accept visitor
|
11
|
+
visitor.accept_paragraph self
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Joins the raw paragraph text and converts inline HardBreaks to the
|
16
|
+
# +hard_break+ text.
|
17
|
+
|
18
|
+
def text hard_break = ''
|
19
|
+
@parts.map do |part|
|
20
|
+
if RDoc::Markup::HardBreak === part then
|
21
|
+
hard_break
|
22
|
+
else
|
23
|
+
part
|
24
|
+
end
|
25
|
+
end.join
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,575 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'strscan'
|
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, Rule and BlockQuote.
|
13
|
+
# Inline markup such as <tt>\+blah\+</tt> is handled separately by
|
14
|
+
# RDoc::Markup::AttributeManager.
|
15
|
+
#
|
16
|
+
# To see what markup the Parser implements read RDoc. To see how to use
|
17
|
+
# RDoc markup to format text in your program read RDoc::Markup.
|
18
|
+
|
19
|
+
class RDoc::Markup::Parser
|
20
|
+
|
21
|
+
include RDoc::Text
|
22
|
+
|
23
|
+
##
|
24
|
+
# List token types
|
25
|
+
|
26
|
+
LIST_TOKENS = [
|
27
|
+
:BULLET,
|
28
|
+
:LABEL,
|
29
|
+
:LALPHA,
|
30
|
+
:NOTE,
|
31
|
+
:NUMBER,
|
32
|
+
:UALPHA,
|
33
|
+
]
|
34
|
+
|
35
|
+
##
|
36
|
+
# Parser error subclass
|
37
|
+
|
38
|
+
class Error < RuntimeError; end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Raised when the parser is unable to handle the given markup
|
42
|
+
|
43
|
+
class ParseError < Error; end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Enables display of debugging information
|
47
|
+
|
48
|
+
attr_accessor :debug
|
49
|
+
|
50
|
+
##
|
51
|
+
# Token accessor
|
52
|
+
|
53
|
+
attr_reader :tokens
|
54
|
+
|
55
|
+
##
|
56
|
+
# Parses +str+ into a Document.
|
57
|
+
#
|
58
|
+
# Use RDoc::Markup#parse instead of this method.
|
59
|
+
|
60
|
+
def self.parse str
|
61
|
+
parser = new
|
62
|
+
parser.tokenize str
|
63
|
+
doc = RDoc::Markup::Document.new
|
64
|
+
parser.parse doc
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Returns a token stream for +str+, for testing
|
69
|
+
|
70
|
+
def self.tokenize str
|
71
|
+
parser = new
|
72
|
+
parser.tokenize str
|
73
|
+
parser.tokens
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Creates a new Parser. See also ::parse
|
78
|
+
|
79
|
+
def initialize
|
80
|
+
@binary_input = nil
|
81
|
+
@current_token = nil
|
82
|
+
@debug = false
|
83
|
+
@s = nil
|
84
|
+
@tokens = []
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Builds a Heading of +level+
|
89
|
+
|
90
|
+
def build_heading level
|
91
|
+
type, text, = get
|
92
|
+
|
93
|
+
text = case type
|
94
|
+
when :TEXT then
|
95
|
+
skip :NEWLINE
|
96
|
+
text
|
97
|
+
else
|
98
|
+
unget
|
99
|
+
''
|
100
|
+
end
|
101
|
+
|
102
|
+
RDoc::Markup::Heading.new level, text
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Builds a List flush to +margin+
|
107
|
+
|
108
|
+
def build_list margin
|
109
|
+
p :list_start => margin if @debug
|
110
|
+
|
111
|
+
list = RDoc::Markup::List.new
|
112
|
+
label = nil
|
113
|
+
|
114
|
+
until @tokens.empty? do
|
115
|
+
type, data, column, = get
|
116
|
+
|
117
|
+
case type
|
118
|
+
when *LIST_TOKENS then
|
119
|
+
if column < margin || (list.type && list.type != type) then
|
120
|
+
unget
|
121
|
+
break
|
122
|
+
end
|
123
|
+
|
124
|
+
list.type = type
|
125
|
+
peek_type, _, column, = peek_token
|
126
|
+
|
127
|
+
case type
|
128
|
+
when :NOTE, :LABEL then
|
129
|
+
label = [] unless label
|
130
|
+
|
131
|
+
if peek_type == :NEWLINE then
|
132
|
+
# description not on the same line as LABEL/NOTE
|
133
|
+
# skip the trailing newline & any blank lines below
|
134
|
+
while peek_type == :NEWLINE
|
135
|
+
get
|
136
|
+
peek_type, _, column, = peek_token
|
137
|
+
end
|
138
|
+
|
139
|
+
# we may be:
|
140
|
+
# - at end of stream
|
141
|
+
# - at a column < margin:
|
142
|
+
# [text]
|
143
|
+
# blah blah blah
|
144
|
+
# - at the same column, but with a different type of list item
|
145
|
+
# [text]
|
146
|
+
# * blah blah
|
147
|
+
# - at the same column, with the same type of list item
|
148
|
+
# [one]
|
149
|
+
# [two]
|
150
|
+
# In all cases, we have an empty description.
|
151
|
+
# In the last case only, we continue.
|
152
|
+
if peek_type.nil? || column < margin then
|
153
|
+
empty = true
|
154
|
+
elsif column == margin then
|
155
|
+
case peek_type
|
156
|
+
when type
|
157
|
+
empty = :continue
|
158
|
+
when *LIST_TOKENS
|
159
|
+
empty = true
|
160
|
+
else
|
161
|
+
empty = false
|
162
|
+
end
|
163
|
+
else
|
164
|
+
empty = false
|
165
|
+
end
|
166
|
+
|
167
|
+
if empty then
|
168
|
+
label << data
|
169
|
+
next if empty == :continue
|
170
|
+
break
|
171
|
+
end
|
172
|
+
end
|
173
|
+
else
|
174
|
+
data = nil
|
175
|
+
end
|
176
|
+
|
177
|
+
if label then
|
178
|
+
data = label << data
|
179
|
+
label = nil
|
180
|
+
end
|
181
|
+
|
182
|
+
list_item = RDoc::Markup::ListItem.new data
|
183
|
+
parse list_item, column
|
184
|
+
list << list_item
|
185
|
+
|
186
|
+
else
|
187
|
+
unget
|
188
|
+
break
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
p :list_end => margin if @debug
|
193
|
+
|
194
|
+
if list.empty? then
|
195
|
+
return nil unless label
|
196
|
+
return nil unless [:LABEL, :NOTE].include? list.type
|
197
|
+
|
198
|
+
list_item = RDoc::Markup::ListItem.new label, RDoc::Markup::BlankLine.new
|
199
|
+
list << list_item
|
200
|
+
end
|
201
|
+
|
202
|
+
list
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Builds a Paragraph that is flush to +margin+
|
207
|
+
|
208
|
+
def build_paragraph margin
|
209
|
+
p :paragraph_start => margin if @debug
|
210
|
+
|
211
|
+
paragraph = RDoc::Markup::Paragraph.new
|
212
|
+
|
213
|
+
until @tokens.empty? do
|
214
|
+
type, data, column, = get
|
215
|
+
|
216
|
+
if type == :TEXT and column == margin then
|
217
|
+
paragraph << data
|
218
|
+
|
219
|
+
break if peek_token.first == :BREAK
|
220
|
+
|
221
|
+
data << ' ' if skip :NEWLINE
|
222
|
+
else
|
223
|
+
unget
|
224
|
+
break
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
paragraph.parts.last.sub!(/ \z/, '') # cleanup
|
229
|
+
|
230
|
+
p :paragraph_end => margin if @debug
|
231
|
+
|
232
|
+
paragraph
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# Builds a Verbatim that is indented from +margin+.
|
237
|
+
#
|
238
|
+
# The verbatim block is shifted left (the least indented lines start in
|
239
|
+
# column 0). Each part of the verbatim is one line of text, always
|
240
|
+
# terminated by a newline. Blank lines always consist of a single newline
|
241
|
+
# character, and there is never a single newline at the end of the verbatim.
|
242
|
+
|
243
|
+
def build_verbatim margin
|
244
|
+
p :verbatim_begin => margin if @debug
|
245
|
+
verbatim = RDoc::Markup::Verbatim.new
|
246
|
+
|
247
|
+
min_indent = nil
|
248
|
+
generate_leading_spaces = true
|
249
|
+
line = ''.dup
|
250
|
+
|
251
|
+
until @tokens.empty? do
|
252
|
+
type, data, column, = get
|
253
|
+
|
254
|
+
if type == :NEWLINE then
|
255
|
+
line << data
|
256
|
+
verbatim << line
|
257
|
+
line = ''.dup
|
258
|
+
generate_leading_spaces = true
|
259
|
+
next
|
260
|
+
end
|
261
|
+
|
262
|
+
if column <= margin
|
263
|
+
unget
|
264
|
+
break
|
265
|
+
end
|
266
|
+
|
267
|
+
if generate_leading_spaces then
|
268
|
+
indent = column - margin
|
269
|
+
line << ' ' * indent
|
270
|
+
min_indent = indent if min_indent.nil? || indent < min_indent
|
271
|
+
generate_leading_spaces = false
|
272
|
+
end
|
273
|
+
|
274
|
+
case type
|
275
|
+
when :HEADER then
|
276
|
+
line << '=' * data
|
277
|
+
_, _, peek_column, = peek_token
|
278
|
+
peek_column ||= column + data
|
279
|
+
indent = peek_column - column - data
|
280
|
+
line << ' ' * indent
|
281
|
+
when :RULE then
|
282
|
+
width = 2 + data
|
283
|
+
line << '-' * width
|
284
|
+
_, _, peek_column, = peek_token
|
285
|
+
peek_column ||= column + width
|
286
|
+
indent = peek_column - column - width
|
287
|
+
line << ' ' * indent
|
288
|
+
when :BREAK, :TEXT then
|
289
|
+
line << data
|
290
|
+
else # *LIST_TOKENS
|
291
|
+
list_marker = case type
|
292
|
+
when :BULLET then data
|
293
|
+
when :LABEL then "[#{data}]"
|
294
|
+
when :NOTE then "#{data}::"
|
295
|
+
else # :LALPHA, :NUMBER, :UALPHA
|
296
|
+
"#{data}."
|
297
|
+
end
|
298
|
+
line << list_marker
|
299
|
+
peek_type, _, peek_column = peek_token
|
300
|
+
unless peek_type == :NEWLINE then
|
301
|
+
peek_column ||= column + list_marker.length
|
302
|
+
indent = peek_column - column - list_marker.length
|
303
|
+
line << ' ' * indent
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
verbatim << line << "\n" unless line.empty?
|
310
|
+
verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0
|
311
|
+
verbatim.normalize
|
312
|
+
|
313
|
+
p :verbatim_end => margin if @debug
|
314
|
+
|
315
|
+
verbatim
|
316
|
+
end
|
317
|
+
|
318
|
+
##
|
319
|
+
# Pulls the next token from the stream.
|
320
|
+
|
321
|
+
def get
|
322
|
+
@current_token = @tokens.shift
|
323
|
+
p :get => @current_token if @debug
|
324
|
+
@current_token
|
325
|
+
end
|
326
|
+
|
327
|
+
##
|
328
|
+
# Parses the tokens into an array of RDoc::Markup::XXX objects,
|
329
|
+
# and appends them to the passed +parent+ RDoc::Markup::YYY object.
|
330
|
+
#
|
331
|
+
# Exits at the end of the token stream, or when it encounters a token
|
332
|
+
# in a column less than +indent+ (unless it is a NEWLINE).
|
333
|
+
#
|
334
|
+
# Returns +parent+.
|
335
|
+
|
336
|
+
def parse parent, indent = 0
|
337
|
+
p :parse_start => indent if @debug
|
338
|
+
|
339
|
+
until @tokens.empty? do
|
340
|
+
type, data, column, = get
|
341
|
+
|
342
|
+
case type
|
343
|
+
when :BREAK then
|
344
|
+
parent << RDoc::Markup::BlankLine.new
|
345
|
+
skip :NEWLINE, false
|
346
|
+
next
|
347
|
+
when :NEWLINE then
|
348
|
+
# trailing newlines are skipped below, so this is a blank line
|
349
|
+
parent << RDoc::Markup::BlankLine.new
|
350
|
+
skip :NEWLINE, false
|
351
|
+
next
|
352
|
+
end
|
353
|
+
|
354
|
+
# indentation change: break or verbatim
|
355
|
+
if column < indent then
|
356
|
+
unget
|
357
|
+
break
|
358
|
+
elsif column > indent then
|
359
|
+
unget
|
360
|
+
parent << build_verbatim(indent)
|
361
|
+
next
|
362
|
+
end
|
363
|
+
|
364
|
+
# indentation is the same
|
365
|
+
case type
|
366
|
+
when :HEADER then
|
367
|
+
parent << build_heading(data)
|
368
|
+
when :RULE then
|
369
|
+
parent << RDoc::Markup::Rule.new(data)
|
370
|
+
skip :NEWLINE
|
371
|
+
when :TEXT then
|
372
|
+
unget
|
373
|
+
parse_text parent, indent
|
374
|
+
when :BLOCKQUOTE then
|
375
|
+
type, _, column = get
|
376
|
+
if type == :NEWLINE
|
377
|
+
type, _, column = get
|
378
|
+
end
|
379
|
+
unget if type
|
380
|
+
bq = RDoc::Markup::BlockQuote.new
|
381
|
+
p :blockquote_start => [data, column] if @debug
|
382
|
+
parse bq, column
|
383
|
+
p :blockquote_end => indent if @debug
|
384
|
+
parent << bq
|
385
|
+
when *LIST_TOKENS then
|
386
|
+
unget
|
387
|
+
parent << build_list(indent)
|
388
|
+
else
|
389
|
+
type, data, column, line = @current_token
|
390
|
+
raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
p :parse_end => indent if @debug
|
395
|
+
|
396
|
+
parent
|
397
|
+
|
398
|
+
end
|
399
|
+
|
400
|
+
##
|
401
|
+
# Small hook that is overridden by RDoc::TomDoc
|
402
|
+
|
403
|
+
def parse_text parent, indent # :nodoc:
|
404
|
+
parent << build_paragraph(indent)
|
405
|
+
end
|
406
|
+
|
407
|
+
##
|
408
|
+
# Returns the next token on the stream without modifying the stream
|
409
|
+
|
410
|
+
def peek_token
|
411
|
+
token = @tokens.first || []
|
412
|
+
p :peek => token if @debug
|
413
|
+
token
|
414
|
+
end
|
415
|
+
|
416
|
+
##
|
417
|
+
# A simple wrapper of StringScanner that is aware of the current column and lineno
|
418
|
+
|
419
|
+
class MyStringScanner
|
420
|
+
def initialize(input)
|
421
|
+
@line = @column = 0
|
422
|
+
@s = StringScanner.new input
|
423
|
+
end
|
424
|
+
|
425
|
+
def scan(re)
|
426
|
+
ret = @s.scan(re)
|
427
|
+
@column += ret.length if ret
|
428
|
+
ret
|
429
|
+
end
|
430
|
+
|
431
|
+
def unscan(s)
|
432
|
+
@s.pos -= s.bytesize
|
433
|
+
@column -= s.length
|
434
|
+
end
|
435
|
+
|
436
|
+
def pos
|
437
|
+
[@column, @line]
|
438
|
+
end
|
439
|
+
|
440
|
+
def newline!
|
441
|
+
@column = 0
|
442
|
+
@line += 1
|
443
|
+
end
|
444
|
+
|
445
|
+
def eos?
|
446
|
+
@s.eos?
|
447
|
+
end
|
448
|
+
|
449
|
+
def matched
|
450
|
+
@s.matched
|
451
|
+
end
|
452
|
+
|
453
|
+
def [](i)
|
454
|
+
@s[i]
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
##
|
459
|
+
# Creates the StringScanner
|
460
|
+
|
461
|
+
def setup_scanner input
|
462
|
+
@s = MyStringScanner.new input
|
463
|
+
end
|
464
|
+
|
465
|
+
##
|
466
|
+
# Skips the next token if its type is +token_type+.
|
467
|
+
#
|
468
|
+
# Optionally raises an error if the next token is not of the expected type.
|
469
|
+
|
470
|
+
def skip token_type, error = true
|
471
|
+
type, = get
|
472
|
+
return unless type # end of stream
|
473
|
+
return @current_token if token_type == type
|
474
|
+
unget
|
475
|
+
raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error
|
476
|
+
end
|
477
|
+
|
478
|
+
##
|
479
|
+
# Turns text +input+ into a stream of tokens
|
480
|
+
|
481
|
+
def tokenize input
|
482
|
+
setup_scanner input
|
483
|
+
|
484
|
+
until @s.eos? do
|
485
|
+
pos = @s.pos
|
486
|
+
|
487
|
+
# leading spaces will be reflected by the column of the next token
|
488
|
+
# the only thing we loose are trailing spaces at the end of the file
|
489
|
+
next if @s.scan(/ +/)
|
490
|
+
|
491
|
+
# note: after BULLET, LABEL, etc.,
|
492
|
+
# indent will be the column of the next non-newline token
|
493
|
+
|
494
|
+
@tokens << case
|
495
|
+
# [CR]LF => :NEWLINE
|
496
|
+
when @s.scan(/\r?\n/) then
|
497
|
+
token = [:NEWLINE, @s.matched, *pos]
|
498
|
+
@s.newline!
|
499
|
+
token
|
500
|
+
# === text => :HEADER then :TEXT
|
501
|
+
when @s.scan(/(=+)(\s*)/) then
|
502
|
+
level = @s[1].length
|
503
|
+
header = [:HEADER, level, *pos]
|
504
|
+
|
505
|
+
if @s[2] =~ /^\r?\n/ then
|
506
|
+
@s.unscan(@s[2])
|
507
|
+
header
|
508
|
+
else
|
509
|
+
pos = @s.pos
|
510
|
+
@s.scan(/.*/)
|
511
|
+
@tokens << header
|
512
|
+
[:TEXT, @s.matched.sub(/\r$/, ''), *pos]
|
513
|
+
end
|
514
|
+
# --- (at least 3) and nothing else on the line => :RULE
|
515
|
+
when @s.scan(/(-{3,}) *\r?$/) then
|
516
|
+
[:RULE, @s[1].length - 2, *pos]
|
517
|
+
# * or - followed by white space and text => :BULLET
|
518
|
+
when @s.scan(/([*-]) +(\S)/) then
|
519
|
+
@s.unscan(@s[2])
|
520
|
+
[:BULLET, @s[1], *pos]
|
521
|
+
# A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER
|
522
|
+
when @s.scan(/([a-z]|\d+)\. +(\S)/i) then
|
523
|
+
# FIXME if tab(s), the column will be wrong
|
524
|
+
# either support tabs everywhere by first expanding them to
|
525
|
+
# spaces, or assume that they will have been replaced
|
526
|
+
# before (and provide a check for that at least in debug
|
527
|
+
# mode)
|
528
|
+
list_label = @s[1]
|
529
|
+
@s.unscan(@s[2])
|
530
|
+
list_type =
|
531
|
+
case list_label
|
532
|
+
when /[a-z]/ then :LALPHA
|
533
|
+
when /[A-Z]/ then :UALPHA
|
534
|
+
when /\d/ then :NUMBER
|
535
|
+
else
|
536
|
+
raise ParseError, "BUG token #{list_label}"
|
537
|
+
end
|
538
|
+
[list_type, list_label, *pos]
|
539
|
+
# [text] followed by spaces or end of line => :LABEL
|
540
|
+
when @s.scan(/\[(.*?)\]( +|\r?$)/) then
|
541
|
+
[:LABEL, @s[1], *pos]
|
542
|
+
# text:: followed by spaces or end of line => :NOTE
|
543
|
+
when @s.scan(/(.*?)::( +|\r?$)/) then
|
544
|
+
[:NOTE, @s[1], *pos]
|
545
|
+
# >>> followed by end of line => :BLOCKQUOTE
|
546
|
+
when @s.scan(/>>> *(\w+)?$/) then
|
547
|
+
[:BLOCKQUOTE, @s[1], *pos]
|
548
|
+
# anything else: :TEXT
|
549
|
+
else
|
550
|
+
@s.scan(/(.*?)( )?\r?$/)
|
551
|
+
token = [:TEXT, @s[1], *pos]
|
552
|
+
|
553
|
+
if @s[2] then
|
554
|
+
@tokens << token
|
555
|
+
[:BREAK, @s[2], pos[0] + @s[1].length, pos[1]]
|
556
|
+
else
|
557
|
+
token
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
self
|
563
|
+
end
|
564
|
+
|
565
|
+
##
|
566
|
+
# Returns the current token to the token stream
|
567
|
+
|
568
|
+
def unget
|
569
|
+
token = @current_token
|
570
|
+
p :unget => token if @debug
|
571
|
+
raise Error, 'too many #ungets' if token == @tokens.first
|
572
|
+
@tokens.unshift token if token
|
573
|
+
end
|
574
|
+
|
575
|
+
end
|