nishidayuya-rd2odt 0.0.1.20090403.01 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS +13 -0
- data/Rakefile +3 -1
- data/lib/rd2odt/compat/ruby-1.8.6.rb +86 -0
- data/lib/rd2odt/rdtool/NOTICE.rd2odt +8 -0
- data/lib/rd2odt/rdtool/README.rd +50 -0
- data/lib/rd2odt/rdtool/README.rd.ja +53 -0
- data/lib/rd2odt/rdtool/rd/block-element.rb +114 -0
- data/lib/rd2odt/rdtool/rd/complex-list-item.rb +65 -0
- data/lib/rd2odt/rdtool/rd/desclist.rb +55 -0
- data/lib/rd2odt/rdtool/rd/document-struct.rb +46 -0
- data/lib/rd2odt/rdtool/rd/element.rb +160 -0
- data/lib/rd2odt/rdtool/rd/filter.rb +255 -0
- data/lib/rd2odt/rdtool/rd/inline-element.rb +233 -0
- data/lib/rd2odt/rdtool/rd/labeled-element.rb +14 -0
- data/lib/rd2odt/rdtool/rd/list.rb +57 -0
- data/lib/rd2odt/rdtool/rd/loose-struct.rb +11 -0
- data/lib/rd2odt/rdtool/rd/methodlist.rb +57 -0
- data/lib/rd2odt/rdtool/rd/output-format-visitor.rb +28 -0
- data/lib/rd2odt/rdtool/rd/package.rb +4 -0
- data/lib/rd2odt/rdtool/rd/parser-util.rb +14 -0
- data/lib/rd2odt/rdtool/rd/rbl-file.rb +69 -0
- data/lib/rd2odt/rdtool/rd/rbl-suite.rb +37 -0
- data/lib/rd2odt/rdtool/rd/rd-struct.rb +86 -0
- data/lib/rd2odt/rdtool/rd/rd2html-lib.rb +490 -0
- data/lib/rd2odt/rdtool/rd/rd2html-opt.rb +67 -0
- data/lib/rd2odt/rdtool/rd/rd2man-lib.rb +241 -0
- data/lib/rd2odt/rdtool/rd/rd2rdo-lib.rb +19 -0
- data/lib/rd2odt/rdtool/rd/rd2rmi-lib.rb +32 -0
- data/lib/rd2odt/rdtool/rd/rdblockparser.tab.rb +1050 -0
- data/lib/rd2odt/rdtool/rd/rdfmt.rb +15 -0
- data/lib/rd2odt/rdtool/rd/rdinlineparser.tab.rb +1243 -0
- data/lib/rd2odt/rdtool/rd/rdvisitor.rb +214 -0
- data/lib/rd2odt/rdtool/rd/reference-resolver.rb +114 -0
- data/lib/rd2odt/rdtool/rd/search-file.rb +14 -0
- data/lib/rd2odt/rdtool/rd/tree.rb +103 -0
- data/lib/rd2odt/rdtool/rd/version.rb +39 -0
- data/lib/rd2odt/rdtool/rd/visitor.rb +86 -0
- data/lib/rd2odt.rb +12 -17
- data/rd2odt.gemspec +39 -4
- data/test/test-helper.rb +86 -1
- data/test/unit/rd2odt-spec.rb +13 -11
- metadata +39 -4
data/NEWS
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
= version 0.1.1 2009-07-01
|
2
|
+
|
3
|
+
== a little feature
|
4
|
+
|
5
|
+
* Supported Ruby version 1.8.6.
|
6
|
+
|
7
|
+
= version 0.1.0 2009-05-16
|
8
|
+
|
9
|
+
== a feature
|
10
|
+
|
11
|
+
* Distributed under the RubyGems package.
|
12
|
+
* rd2odt includes RDtool.
|
13
|
+
|
1
14
|
= version 0.0.1 2009-04-01
|
2
15
|
|
3
16
|
== a little features
|
data/Rakefile
CHANGED
@@ -15,6 +15,8 @@ end
|
|
15
15
|
Spec::Rake::SpecTask.new do |t|
|
16
16
|
t.spec_files = FileList["test/**/*-spec.rb"]
|
17
17
|
t.libs << "lib"
|
18
|
+
t.libs << "lib/rd2odt/rdtool"
|
19
|
+
t.spec_opts << "--colour"
|
18
20
|
end
|
19
21
|
|
20
22
|
Rake::RDocTask.new do |t|
|
@@ -33,7 +35,7 @@ task :init_gem_spec do
|
|
33
35
|
s = File.read("rd2odt.gemspec").untaint
|
34
36
|
spec = nil
|
35
37
|
Thread.start {
|
36
|
-
$SAFE =
|
38
|
+
$SAFE = 3
|
37
39
|
spec = Module.new.module_eval(s)
|
38
40
|
}.join
|
39
41
|
Rake::GemPackageTask.new(spec) do |pkg|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# This part is from Ruby 1.8.7's tmpdir.rb.
|
2
|
+
|
3
|
+
class Dir
|
4
|
+
# Dir.mktmpdir creates a temporary directory.
|
5
|
+
#
|
6
|
+
# The directory is created with 0700 permission.
|
7
|
+
#
|
8
|
+
# The prefix and suffix of the name of the directory is specified by
|
9
|
+
# the optional first argument, <i>prefix_suffix</i>.
|
10
|
+
# - If it is not specified or nil, "d" is used as the prefix and no suffix is used.
|
11
|
+
# - If it is a string, it is used as the prefix and no suffix is used.
|
12
|
+
# - If it is an array, first element is used as the prefix and second element is used as a suffix.
|
13
|
+
#
|
14
|
+
# Dir.mktmpdir {|dir| dir is ".../d..." }
|
15
|
+
# Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
|
16
|
+
# Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }
|
17
|
+
#
|
18
|
+
# The directory is created under Dir.tmpdir or
|
19
|
+
# the optional second argument <i>tmpdir</i> if non-nil value is given.
|
20
|
+
#
|
21
|
+
# Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
|
22
|
+
# Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }
|
23
|
+
#
|
24
|
+
# If a block is given,
|
25
|
+
# it is yielded with the path of the directory.
|
26
|
+
# The directory and its contents are removed
|
27
|
+
# using FileUtils.remove_entry_secure before Dir.mktmpdir returns.
|
28
|
+
# The value of the block is returned.
|
29
|
+
#
|
30
|
+
# Dir.mktmpdir {|dir|
|
31
|
+
# # use the directory...
|
32
|
+
# open("#{dir}/foo", "w") { ... }
|
33
|
+
# }
|
34
|
+
#
|
35
|
+
# If a block is not given,
|
36
|
+
# The path of the directory is returned.
|
37
|
+
# In this case, Dir.mktmpdir doesn't remove the directory.
|
38
|
+
#
|
39
|
+
# dir = Dir.mktmpdir
|
40
|
+
# begin
|
41
|
+
# # use the directory...
|
42
|
+
# open("#{dir}/foo", "w") { ... }
|
43
|
+
# ensure
|
44
|
+
# # remove the directory.
|
45
|
+
# FileUtils.remove_entry_secure dir
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil)
|
49
|
+
case prefix_suffix
|
50
|
+
when nil
|
51
|
+
prefix = "d"
|
52
|
+
suffix = ""
|
53
|
+
when String
|
54
|
+
prefix = prefix_suffix
|
55
|
+
suffix = ""
|
56
|
+
when Array
|
57
|
+
prefix = prefix_suffix[0]
|
58
|
+
suffix = prefix_suffix[1]
|
59
|
+
else
|
60
|
+
raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
|
61
|
+
end
|
62
|
+
tmpdir ||= Dir.tmpdir
|
63
|
+
t = Time.now.strftime("%Y%m%d")
|
64
|
+
n = nil
|
65
|
+
begin
|
66
|
+
path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
|
67
|
+
path << "-#{n}" if n
|
68
|
+
path << suffix
|
69
|
+
Dir.mkdir(path, 0700)
|
70
|
+
rescue Errno::EEXIST
|
71
|
+
n ||= 0
|
72
|
+
n += 1
|
73
|
+
retry
|
74
|
+
end
|
75
|
+
|
76
|
+
if block_given?
|
77
|
+
begin
|
78
|
+
yield path
|
79
|
+
ensure
|
80
|
+
FileUtils.remove_entry_secure path
|
81
|
+
end
|
82
|
+
else
|
83
|
+
path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
=begin
|
2
|
+
= RDtool 0.6.21
|
3
|
+
== What is RDtool
|
4
|
+
|
5
|
+
RD is Ruby's POD. RDtool is formatter for RD.
|
6
|
+
|
7
|
+
== What is Changed
|
8
|
+
|
9
|
+
See HISTORY.
|
10
|
+
|
11
|
+
== How to Install
|
12
|
+
|
13
|
+
(1)((%su%)) if you install into public directories.
|
14
|
+
(2)((%ruby setup.rb%))
|
15
|
+
(3)If you want to use , utils/rd-mode.el, install it ((*by hand*)).
|
16
|
+
|
17
|
+
== How to use
|
18
|
+
|
19
|
+
Simply,
|
20
|
+
% rd2 rdfile.rd > outputfile
|
21
|
+
|
22
|
+
If you want to indicate format-library, do
|
23
|
+
% rd2 -r library rdfile.rd > outputfile
|
24
|
+
|
25
|
+
Use ((% rd2 --help %)) for more options.
|
26
|
+
|
27
|
+
For options depend on format-library, enter ((%--help%)) after
|
28
|
+
the indication of format-library. For example,
|
29
|
+
|
30
|
+
% rd2 -r rd/rd2html-lib.rb --help
|
31
|
+
|
32
|
+
rd2 load "${HOME}/.rd2rc" when it runs.
|
33
|
+
|
34
|
+
== How to write RD?
|
35
|
+
|
36
|
+
Please read doc/rd-draft.rd.
|
37
|
+
|
38
|
+
== About bug report
|
39
|
+
|
40
|
+
If you find a bug in RDtool, please E-mail me
|
41
|
+
((<URL:mailto:moonwolf@moonwolf.com>)).
|
42
|
+
|
43
|
+
== License
|
44
|
+
|
45
|
+
You can use/re-distribute/change RDtool under Ruby's License or GPL.
|
46
|
+
This distribution of RDtool include files that are copyrighted by
|
47
|
+
somebody else, and these files can be re-distributed under those own license.
|
48
|
+
These files include the condition of those licenses in themselves.
|
49
|
+
|
50
|
+
=end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
=begin
|
2
|
+
= RDtool 0.6.21
|
3
|
+
== RDってなに?
|
4
|
+
|
5
|
+
RDはRubyにおけるPOD(Plain Old Documentation)のようなものです。
|
6
|
+
RDtoolはRDのフォーマッタであり、RDをHTMLなどに変換できます。
|
7
|
+
|
8
|
+
== 何が変わった?
|
9
|
+
|
10
|
+
HISTORYを見てください。
|
11
|
+
|
12
|
+
== インストールの方法
|
13
|
+
|
14
|
+
(1)必要なら、((%su%))
|
15
|
+
(2)((%ruby setup.rb%))
|
16
|
+
(3)utils/rd-mode.elを使いたいならば
|
17
|
+
それらを((*手で*))インストールします。
|
18
|
+
|
19
|
+
== どうやって使うか。
|
20
|
+
|
21
|
+
基本的には、こんな感じ。
|
22
|
+
% rd2 rdfile.rd > outputfile
|
23
|
+
|
24
|
+
フォーマットライブラリを指定したい時は、こう。
|
25
|
+
% rd2 -r library rdfile.rd > outputfile
|
26
|
+
|
27
|
+
((% rd2 --help %))でオプションの詳細がでます。
|
28
|
+
|
29
|
+
フォーマットライブラリ依存のオプションは先にフォーマットライブラリの
|
30
|
+
指定をしてから((%--help%))。例えば、
|
31
|
+
|
32
|
+
% rd2 -r rd/rd2html-lib.rb --help
|
33
|
+
|
34
|
+
rd2はホームディレクトリにある".rd2rc"というファイルを読み込みます。
|
35
|
+
これはRubyスクリプトです。
|
36
|
+
|
37
|
+
== RDの書き方
|
38
|
+
|
39
|
+
doc/rd-draft.rdを読んでください。
|
40
|
+
|
41
|
+
== バグ報告
|
42
|
+
|
43
|
+
バグを見付けた時は、次のアドレスまでメールしてください。
|
44
|
+
((<URL:mailto:moonwolf@moonwolf.com>))
|
45
|
+
|
46
|
+
== ライセンス
|
47
|
+
|
48
|
+
RDtoolはRuby's LicenseかGPLの下で使用/配布/改造してください。
|
49
|
+
RDtoolのパッケージにはTosh以外の人が著作権を持つファイルが含まれています。
|
50
|
+
それらのファイルについての配布条件はファイル自体に書かれたライセンスの下で
|
51
|
+
行ってください。
|
52
|
+
|
53
|
+
=end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'rd/element'
|
2
|
+
require 'rd/labeled-element'
|
3
|
+
|
4
|
+
module RD
|
5
|
+
# Block-level Element of document tree. abstruct class.
|
6
|
+
class BlockElement < Element
|
7
|
+
end
|
8
|
+
|
9
|
+
class Headline < BlockElement
|
10
|
+
include NonterminalElement
|
11
|
+
include LabeledElement
|
12
|
+
|
13
|
+
MARK2LEVEL = {
|
14
|
+
"=" => 1,
|
15
|
+
"==" => 2,
|
16
|
+
"===" => 3,
|
17
|
+
"====" => 4,
|
18
|
+
"+" => 5,
|
19
|
+
"++" => 6
|
20
|
+
}
|
21
|
+
|
22
|
+
attr_accessor :level
|
23
|
+
attr_reader :title
|
24
|
+
|
25
|
+
def initialize(level_num)
|
26
|
+
super()
|
27
|
+
@level = level_num
|
28
|
+
@title = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def accept(visitor)
|
32
|
+
visitor.visit_Headline(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def calculate_label
|
36
|
+
ret = ""
|
37
|
+
@title.each do |i|
|
38
|
+
ret << i.to_label
|
39
|
+
end
|
40
|
+
ret
|
41
|
+
end
|
42
|
+
private :calculate_label
|
43
|
+
|
44
|
+
def Headline.mark_to_level(mark_str)
|
45
|
+
MARK2LEVEL[mark_str] or
|
46
|
+
raise ArgumentError, "#{mark_str} is irregular for Headline mark."
|
47
|
+
end
|
48
|
+
|
49
|
+
def children
|
50
|
+
@title
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Include < BlockElement
|
55
|
+
include TerminalElement
|
56
|
+
|
57
|
+
attr_accessor :filename
|
58
|
+
|
59
|
+
def initialize(filename)
|
60
|
+
super()
|
61
|
+
@filename = filename
|
62
|
+
end
|
63
|
+
|
64
|
+
def accept(visitor)
|
65
|
+
visitor.visit_Include(self)
|
66
|
+
end
|
67
|
+
end # Include
|
68
|
+
|
69
|
+
class TextBlock < BlockElement
|
70
|
+
include NonterminalElement
|
71
|
+
|
72
|
+
attr_accessor :content
|
73
|
+
|
74
|
+
def initialize()
|
75
|
+
super()
|
76
|
+
@content = []
|
77
|
+
end
|
78
|
+
|
79
|
+
def accept(visitor)
|
80
|
+
visitor.visit_TextBlock(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
def children
|
84
|
+
@content
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Verbatim < BlockElement
|
89
|
+
include TerminalElement
|
90
|
+
|
91
|
+
attr_reader :content
|
92
|
+
|
93
|
+
def initialize(content_strings = [])
|
94
|
+
super()
|
95
|
+
@content = content_strings # Array of String
|
96
|
+
end
|
97
|
+
|
98
|
+
def accept(visitor)
|
99
|
+
visitor.visit_Verbatim(self)
|
100
|
+
end
|
101
|
+
|
102
|
+
def each_line
|
103
|
+
if @content.respond_to?(:each_line)
|
104
|
+
@content.each_line {|i|
|
105
|
+
yield i
|
106
|
+
}
|
107
|
+
else
|
108
|
+
@content.each {|i|
|
109
|
+
yield i
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module RD
|
4
|
+
# abstruct class for ListItem which have term part additionaly.
|
5
|
+
# (i.e. DescListItem and MethodListItem)
|
6
|
+
module ComplexListItem
|
7
|
+
def set_term(term)
|
8
|
+
set_term_under_document_struct(term, tree.document_struct)
|
9
|
+
end
|
10
|
+
alias term= set_term
|
11
|
+
|
12
|
+
def set_term_under_document_struct(term, document_struct)
|
13
|
+
raise ArgumentError unless document_struct.is_valid?(self, term)
|
14
|
+
assign_term(term)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_term_without_document_struct(term)
|
18
|
+
assign_term(term)
|
19
|
+
end
|
20
|
+
|
21
|
+
def assign_term(term)
|
22
|
+
@term = term
|
23
|
+
term.parent = self
|
24
|
+
end
|
25
|
+
|
26
|
+
def make_term(*args_of_new, &block)
|
27
|
+
child = self.class::Term.new(*args_of_new)
|
28
|
+
set_term(child)
|
29
|
+
child.build(&block) if block_given?
|
30
|
+
child
|
31
|
+
end
|
32
|
+
|
33
|
+
def each_element(&block)
|
34
|
+
yield(self)
|
35
|
+
@term.each_element(&block)
|
36
|
+
@description.each do |i|
|
37
|
+
i.each_element(&block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias each each_element
|
41
|
+
|
42
|
+
def each_block_in_description
|
43
|
+
@description.each do |i|
|
44
|
+
yield(i)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
alias each_block each_block_in_description
|
48
|
+
|
49
|
+
def children
|
50
|
+
@description
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_label
|
54
|
+
@term.to_label
|
55
|
+
end
|
56
|
+
alias label to_label
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
t = indent2(term.inspect) if term
|
60
|
+
c = children.collect{|i| indent2(i.inspect)}.join("\n")
|
61
|
+
"<#{self.class.name}>" + (term ? "\n" : "") + t.to_s +
|
62
|
+
(c.empty? ? "" : "\n") + c
|
63
|
+
end
|
64
|
+
end # ComplexListItem
|
65
|
+
end # RD
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rd/element'
|
2
|
+
require 'rd/list'
|
3
|
+
require 'rd/complex-list-item'
|
4
|
+
require 'rd/labeled-element'
|
5
|
+
|
6
|
+
module RD
|
7
|
+
class DescList < List
|
8
|
+
def accept(visitor)
|
9
|
+
visitor.visit_DescList(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DescListItem < ListItem
|
14
|
+
include ComplexListItem
|
15
|
+
|
16
|
+
attr_reader :term
|
17
|
+
attr_reader :description
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@term = nil
|
21
|
+
@description = []
|
22
|
+
@label = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def accept(visitor)
|
26
|
+
visitor.visit_DescListItem(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
class Term < Element
|
30
|
+
include NonterminalElement
|
31
|
+
include LabeledElement
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@content = []
|
35
|
+
end
|
36
|
+
|
37
|
+
def calculate_label
|
38
|
+
ret = ""
|
39
|
+
children.each do |i|
|
40
|
+
ret.concat(i.to_label)
|
41
|
+
end
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
private :calculate_label
|
45
|
+
|
46
|
+
def accept(visitor)
|
47
|
+
visitor.visit_DescListItemTerm(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
def children
|
51
|
+
@content
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end # DescListItem
|
55
|
+
end # RD
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module RD
|
3
|
+
# DocumentStructure defines and restricts structure of document tree.
|
4
|
+
# it consists of ElementRelationship
|
5
|
+
class DocumentStructure
|
6
|
+
def initialize
|
7
|
+
@relationships = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_relationships(*relations)
|
11
|
+
@relationships += relations
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_relationship(parent, child)
|
15
|
+
add_relationships(ElementRelationship.new(parent, child))
|
16
|
+
end
|
17
|
+
|
18
|
+
def each_relationship
|
19
|
+
@relationships.each do |i|
|
20
|
+
yield(i)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_valid?(parent, child)
|
25
|
+
each_relationship do |i|
|
26
|
+
return true if i.match?(parent, child)
|
27
|
+
end
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# ElementRelationship is knowledge about parent-children relationship
|
33
|
+
# between Elements.
|
34
|
+
class ElementRelationship
|
35
|
+
attr_reader(:parent, :child)
|
36
|
+
|
37
|
+
def initialize(parent, child)
|
38
|
+
@parent = parent
|
39
|
+
@child = child
|
40
|
+
end
|
41
|
+
|
42
|
+
def match?(parent, child)
|
43
|
+
parent.is_a? @parent and child.is_a? @child
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
|
2
|
+
module RD
|
3
|
+
|
4
|
+
# abstruct class of node of document tree
|
5
|
+
class Element
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_accessor :parent
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@parent = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def tree
|
15
|
+
raise RuntimeError, "#{self} doesn't have a parent." unless @parent
|
16
|
+
@parent.tree
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
c = children.collect{|i| indent2(i.inspect)}.join("\n")
|
21
|
+
"<#{self.class.name}>" + (c.empty? ? "" : "\n") + c
|
22
|
+
end
|
23
|
+
end # Element
|
24
|
+
|
25
|
+
# element which don't have children.
|
26
|
+
module TerminalElement
|
27
|
+
def children
|
28
|
+
[]
|
29
|
+
end
|
30
|
+
|
31
|
+
def each_element
|
32
|
+
yield(self)
|
33
|
+
end
|
34
|
+
alias each each_element
|
35
|
+
end
|
36
|
+
|
37
|
+
# element which have children.
|
38
|
+
module NonterminalElement
|
39
|
+
def initialize(*arg)
|
40
|
+
@temporary_document_structure = nil
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def children
|
45
|
+
raise NotImplimentedError, "need #{self}#children."
|
46
|
+
end
|
47
|
+
|
48
|
+
def each_child
|
49
|
+
children.each do |i|
|
50
|
+
yield(i)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def each_element(&block)
|
55
|
+
yield(self)
|
56
|
+
children.each do |i|
|
57
|
+
i.each_element(&block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
alias each each_element
|
61
|
+
|
62
|
+
def add_child(child)
|
63
|
+
add_child_under_document_struct(child, tree.document_struct)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_child_under_document_struct(child, document_struct)
|
67
|
+
if document_struct.is_valid?(self, child)
|
68
|
+
push_to_children(child)
|
69
|
+
else
|
70
|
+
raise ArgumentError,
|
71
|
+
"mismatched document structure, #{self} <-/- #{child}."
|
72
|
+
end
|
73
|
+
return self
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_children(children)
|
77
|
+
add_children_under_document_struct(children, tree.document_struct)
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_children_under_document_struct(children, document_struct)
|
81
|
+
children.each do |i|
|
82
|
+
add_child_under_document_struct(i, document_struct)
|
83
|
+
end
|
84
|
+
return self
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_children_without_document_struct(new_children)
|
88
|
+
new_children.each do |i|
|
89
|
+
push_to_children(i)
|
90
|
+
end
|
91
|
+
return self
|
92
|
+
end
|
93
|
+
|
94
|
+
def push_to_children(child)
|
95
|
+
children.push(child)
|
96
|
+
child.parent = self
|
97
|
+
end
|
98
|
+
|
99
|
+
attr_accessor :temporary_document_structure
|
100
|
+
|
101
|
+
def build(document_struct = tree.document_struct, &block)
|
102
|
+
under_temporary_document_structure(document_struct) do
|
103
|
+
self.instance_eval(&block)
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def make_child(child_class, *args_of_new, &block)
|
109
|
+
child = child_class.new(*args_of_new)
|
110
|
+
if self.temporary_document_structure
|
111
|
+
self.add_child_under_document_struct(child,
|
112
|
+
self.temporary_document_structure)
|
113
|
+
child.build(self.temporary_document_structure, &block) if block_given?
|
114
|
+
else
|
115
|
+
self.add_child(child)
|
116
|
+
child.build(&block) if block_given?
|
117
|
+
end
|
118
|
+
child
|
119
|
+
end
|
120
|
+
alias new make_child
|
121
|
+
private :new
|
122
|
+
# NonterminalElement#new, not NonterminalElement.new
|
123
|
+
|
124
|
+
def under_temporary_document_structure(document_struct)
|
125
|
+
begin
|
126
|
+
self.temporary_document_structure = document_struct
|
127
|
+
yield
|
128
|
+
ensure
|
129
|
+
self.temporary_document_structure = nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def indent2(str)
|
134
|
+
buf = ''
|
135
|
+
str.each_line{|i| buf << " " << i }
|
136
|
+
buf
|
137
|
+
end
|
138
|
+
private :indent2
|
139
|
+
end
|
140
|
+
|
141
|
+
# root node of document tree
|
142
|
+
class DocumentElement < Element
|
143
|
+
include NonterminalElement
|
144
|
+
attr_reader :blocks
|
145
|
+
|
146
|
+
def initialize()
|
147
|
+
@blocks = []
|
148
|
+
end
|
149
|
+
|
150
|
+
def accept(visitor)
|
151
|
+
visitor.visit_DocumentElement(self)
|
152
|
+
end
|
153
|
+
|
154
|
+
alias each_block each_child
|
155
|
+
|
156
|
+
def children
|
157
|
+
@blocks
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|