kwaff 1.0.0

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.
Files changed (85) hide show
  1. data/COPYING +340 -0
  2. data/ChangeLog.txt +118 -0
  3. data/README.txt +96 -0
  4. data/bin/kwaff +131 -0
  5. data/doc/docstyle.css +307 -0
  6. data/doc/examples.html +1283 -0
  7. data/doc/users-guide.html +395 -0
  8. data/examples/Makefile +17 -0
  9. data/examples/ant/Makefile +7 -0
  10. data/examples/ant/build.kwaff +57 -0
  11. data/examples/hibernate/AuctionItem.hbm.kwaff +45 -0
  12. data/examples/hibernate/Bid.hbm.kwaff +42 -0
  13. data/examples/hibernate/Makefile +9 -0
  14. data/examples/hibernate/User.hbm.kwaff +65 -0
  15. data/examples/hibernate/hibernate.cfg.kwaff +17 -0
  16. data/examples/seasar2/Makefile +9 -0
  17. data/examples/seasar2/seasar2.kwaff +62 -0
  18. data/examples/servlet/Makefile +9 -0
  19. data/examples/servlet/web.kwaff +37 -0
  20. data/examples/spring/Makefile +9 -0
  21. data/examples/spring/applicationContext.kwaff +147 -0
  22. data/examples/xhtml/Makefile +9 -0
  23. data/examples/xhtml/README.kwaff +84 -0
  24. data/examples/xi/Makefile +9 -0
  25. data/examples/xi/bbs.kwaff +58 -0
  26. data/lib/kwaff.rb +85 -0
  27. data/lib/kwaff/doctype.rb +124 -0
  28. data/lib/kwaff/doctypes.yaml +138 -0
  29. data/lib/kwaff/errors.rb +26 -0
  30. data/lib/kwaff/node.rb +101 -0
  31. data/lib/kwaff/optparse.rb +101 -0
  32. data/lib/kwaff/orderedhash.rb +56 -0
  33. data/lib/kwaff/parser.rb +342 -0
  34. data/lib/kwaff/rexml.rb +394 -0
  35. data/lib/kwaff/translator.rb +275 -0
  36. data/setup.rb +1331 -0
  37. data/test/ex101.exp +10 -0
  38. data/test/ex101.in +8 -0
  39. data/test/ex102.exp +14 -0
  40. data/test/ex102.in +16 -0
  41. data/test/ex103.exp +13 -0
  42. data/test/ex103.in +13 -0
  43. data/test/ex104.exp +24 -0
  44. data/test/ex104.in +24 -0
  45. data/test/ex105.exp +12 -0
  46. data/test/ex105.in +18 -0
  47. data/test/ex106.exp +22 -0
  48. data/test/ex106.in +21 -0
  49. data/test/ex107.exp +14 -0
  50. data/test/ex107.in +14 -0
  51. data/test/ex111.exp +7 -0
  52. data/test/ex111.in +13 -0
  53. data/test/ex112.exp +15 -0
  54. data/test/ex112.in +16 -0
  55. data/test/ex113.exp +23 -0
  56. data/test/ex113.in +22 -0
  57. data/test/ex114.exp +12 -0
  58. data/test/ex114.in +17 -0
  59. data/test/ex115.exp +9 -0
  60. data/test/ex115.in +12 -0
  61. data/test/ex121.exp +10 -0
  62. data/test/ex121.in +8 -0
  63. data/test/ex122.exp +10 -0
  64. data/test/ex122.in +8 -0
  65. data/test/ex301.exp +13 -0
  66. data/test/ex301.in +14 -0
  67. data/test/ex302.exp +15 -0
  68. data/test/ex302.in +18 -0
  69. data/test/ex303.exp +15 -0
  70. data/test/ex303.in +16 -0
  71. data/test/ex304.exp +17 -0
  72. data/test/ex304.in +15 -0
  73. data/test/ex311.exp +18 -0
  74. data/test/ex311.in +32 -0
  75. data/test/ex312.exp +21 -0
  76. data/test/ex312.in +18 -0
  77. data/test/ex313.exp +20 -0
  78. data/test/ex313.in +33 -0
  79. data/test/ex314.exp +34 -0
  80. data/test/ex314.in +24 -0
  81. data/test/ex801.exp +16 -0
  82. data/test/ex801.in +15 -0
  83. data/test/test.rb +273 -0
  84. data/todo.txt +1 -0
  85. metadata +132 -0
@@ -0,0 +1,26 @@
1
+ ##
2
+ ## errors and assertions
3
+ ##
4
+ ## $Id: errors.rb 7 2005-05-18 14:33:37Z kwatch $
5
+ ## $Release: 1.0.0 $
6
+ ## copyright(c) 2005 kuwata-lab.com all rights reserved
7
+ ##
8
+
9
+ module Kwaff
10
+ class KwaffError < StandardError
11
+ end
12
+
13
+ class NotImplementedError < KwaffError
14
+ end
15
+
16
+ class AssertionError < KwaffError
17
+ def initialize(linenum, msg=nil)
18
+ super("assertion error: #{linenum}" + (msg ? ": msg=#{msg};" : ""))
19
+ end
20
+ end
21
+
22
+ def self.assert(message=nil)
23
+ linenum = caller()[0]
24
+ AssertionError.new(linenum, message)
25
+ end
26
+ end
@@ -0,0 +1,101 @@
1
+ ##
2
+ ## definitions of node, element and document
3
+ ##
4
+ ## $Id: node.rb 7 2005-05-18 14:33:37Z kwatch $
5
+ ## $Release: 1.0.0 $
6
+ ## copyright(c) 2005 kuwata-lab.com all rights reserved
7
+ ##
8
+
9
+ require 'kwaff/errors'
10
+ require 'kwaff/orderedhash'
11
+
12
+ module Kwaff
13
+
14
+ ## abstract class
15
+ class Node
16
+ ## abstract method
17
+ def accept(translator, level=0)
18
+ raise NotImplementedError.new("#{self.class.name}#accept() is not implemented.")
19
+ end
20
+
21
+ def to_xml(toppings={})
22
+ translator = XmlTranslator.new(toppings)
23
+ return translator ? translator.translate(self) : nil
24
+ end
25
+
26
+ def initialize()
27
+ @empty_lines = 0
28
+ end
29
+
30
+ attr_accessor :empty_lines
31
+ end
32
+
33
+
34
+ class Element < Node
35
+ def accept(translator, level=0)
36
+ return translator.translate_element(self, level)
37
+ end
38
+ def initialize(tag, children=[], attrs=OrderedHash.new)
39
+ @tag = tag
40
+ @children = children
41
+ @attrs = attrs ## Hash or OrderedHash
42
+ end
43
+ attr_reader :children, :attrs
44
+ attr_accessor :tag
45
+
46
+ def text
47
+ if @children.length > 0 && @children[0].is_a?(Text)
48
+ text = children[0]
49
+ return text.str
50
+ end
51
+ return nil
52
+ end
53
+
54
+ def text=(str, flag_escape=true)
55
+ children[0] = Text.new(str, flag_escape)
56
+ end
57
+ end
58
+
59
+
60
+ class Document < Node
61
+ def accept(translator, level=0)
62
+ return translator.translate_document(self, level)
63
+ end
64
+ def initialize(headers=OrderedHash.new, root=nil)
65
+ @headers = headers
66
+ @root = root
67
+ end
68
+ attr_reader :headers
69
+ attr_accessor :root
70
+ end
71
+
72
+
73
+ class Comment < Node
74
+ def accept(translator, level=0)
75
+ return translator.translate_comment(self, level)
76
+ end
77
+ def initialize(str)
78
+ @str = str
79
+ end
80
+ attr_reader :str
81
+ end
82
+
83
+
84
+ class Text < Node
85
+ def accept(translator, level=0)
86
+ return translator.translate_text(self, level)
87
+ end
88
+ def initialize(str, flag_escape=true)
89
+ @str = str
90
+ @escape = flag_escape
91
+ end
92
+ attr_accessor :str, :escape
93
+ #def str
94
+ # return @escape ? Kwaff::escape(@str) : @str
95
+ #end
96
+ def escape?
97
+ return @escape
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,101 @@
1
+ ##
2
+ ## required only from 'bin/kwaff' script
3
+ ##
4
+ ## $Id: optparse.rb 11 2005-06-09 12:32:33Z kwatch $
5
+ ## $Release: 1.0.0 $
6
+ ## copyright(c) 2005 kuwata-lab.com all rights reserved
7
+ ##
8
+
9
+ require 'kwaff/errors'
10
+
11
+ module Kwaff
12
+
13
+ class CommandOptionError < KwaffError
14
+ end
15
+
16
+ class CommandOptionParser
17
+
18
+ def initialize(noarg_opts='', argneed_opts='', argoptional_opts='', flag_str2value=true)
19
+ @noarg_opts = noarg_opts
20
+ @argneed_opts = argneed_opts
21
+ @argoptional_opts = argoptional_opts
22
+ @flag_str2value = flag_str2value
23
+ @options = nil
24
+ @properties = nil
25
+ end
26
+ attr_reader :options, :properites
27
+
28
+
29
+ def parse(argv=ARGV)
30
+ options = {}
31
+ properties = {}
32
+
33
+ while !argv.empty? && argv[0][0] == ?-
34
+ opt = argv.shift
35
+ if opt[1] == ?- ## properteis
36
+ propstr = opt.sub(/^--/, '')
37
+ unless propstr =~ /^([-\w]+)(?:=(.*))?$/
38
+ raise CommandOptionError.new("--#{optstr}: invalid property.")
39
+ end
40
+ name = $1
41
+ value = $2
42
+ name.gsub!(/-/, '_')
43
+ if !value
44
+ value = true
45
+ elsif flag_str2value
46
+ value = self.to_value(value)
47
+ end
48
+ properties[name.intern] = value
49
+
50
+ else ## options
51
+ optstr = opt.sub(/^-/, '')
52
+ while optstr && !optstr.empty?
53
+ optchar = optstr[0]
54
+ optstr = optstr[1, optstr.length-1]
55
+ if @noarg_opts.include?(optchar)
56
+ options[optchar] = true
57
+ elsif @argneed_opts.include?(optchar)
58
+ arg = optstr
59
+ optstr = nil
60
+ arg = argv.shift if !arg || arg.empty?
61
+ unless arg
62
+ raise CommandOptionError.new("-#{optchar.chr}: argument required.")
63
+ end
64
+ options[optchar] = arg
65
+ elsif @argoptional_opts.include?(optchar)
66
+ arg = optstr && !optstr.empty? ? optstr : true
67
+ optstr = nil
68
+ options[optchar] = arg
69
+ else
70
+ raise CommandOptionError.new("-#{optchar.chr}: invalid option.")
71
+ end
72
+ end
73
+
74
+ end # if
75
+
76
+ end # while
77
+
78
+ @options = options
79
+ @properties = properties
80
+ return options, properties
81
+ end
82
+
83
+
84
+ def to_value(str)
85
+ case str
86
+ when 'true', 'yes' ; return true
87
+ when 'false', 'no' ; return false
88
+ when 'null', 'nil' ; return nil
89
+ when /\A\d+\z/ ; return str.to_i
90
+ when /\A\d+\.\d+\z/ ; return str.to_f
91
+ when /\A\/(.*)\/\z/ ; return Regexp.new($1)
92
+ when /\A'.*'\z/ ; return eval(str)
93
+ when /\A".*"\z/ ; return eval(str)
94
+ else
95
+ return str
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ end
@@ -0,0 +1,56 @@
1
+ ##
2
+ ## hash which keeps order of keys added into itself
3
+ ##
4
+ ## $Id: orderedhash.rb 7 2005-05-18 14:33:37Z kwatch $
5
+ ## $Release: 1.0.0 $
6
+ ## copyright(c) 2005 kuwata-lab.com all rights reserved
7
+ ##
8
+
9
+ module Kwaff
10
+
11
+ class OrderedHash
12
+ include Enumerable
13
+
14
+ def initialize
15
+ @keys = []
16
+ @hash = {}
17
+ end
18
+
19
+ attr_reader :keys, :hash
20
+
21
+ def each(&block)
22
+ keys.each do |key|
23
+ value = @hash[key]
24
+ yield(key, value)
25
+ end
26
+ end
27
+
28
+ def [](key)
29
+ return @hash[key]
30
+ end
31
+
32
+ def []=(key, value)
33
+ @keys << key unless @hash.key?(key)
34
+ @hash[key] = value
35
+ end
36
+
37
+ def delete(key)
38
+ @keys.delete(key)
39
+ @hash.delete(key)
40
+ end
41
+
42
+ def default
43
+ return @hash.default
44
+ end
45
+
46
+ def default=(value)
47
+ @hash.default = value
48
+ end
49
+
50
+ def key?(key)
51
+ return @hash.key?(key)
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,342 @@
1
+ ##
2
+ ## parse Kwaff document
3
+ ##
4
+ ## $Id: parser.rb 14 2005-06-10 09:01:18Z kwatch $
5
+ ## $Release: 1.0.0 $
6
+ ## copyright(c) 2005 kuwata-lab.com all rights reserved
7
+ ##
8
+
9
+ require 'kwaff/errors'
10
+ require 'kwaff/orderedhash'
11
+ require 'kwaff/node'
12
+ require 'kwaff/doctype'
13
+
14
+ module Kwaff
15
+
16
+ class ParseError < KwaffError
17
+ def initialize(msg, parser)
18
+ super(msg)
19
+ @parser = parser
20
+ end
21
+
22
+ def to_s
23
+ index = @parser.index
24
+ line = @parser.lines[index]
25
+ super() + " - (line #{index + 1}: #{line.inspect})\n"
26
+ end
27
+ end
28
+
29
+ ## parse Kwaff string and create Kwaff::Document.
30
+ ##
31
+ ## ex.
32
+ ## kwaff_str = File.open('file.kwaff') { |f| f.read }
33
+ ## parser = Kwaff::Parser.new(kwaff_str)
34
+ ## kwaff_doc = parser.parse_document()
35
+ ## translator = Kwaff::XmlTranslator.new()
36
+ ## xml_str = translator.translate(kwaff_doc)
37
+ ##
38
+ ## if you want to get REXML::Document instead of Kwaff::Document,
39
+ ## use Kwaff::Rexml::Parser instead of Kwaff::Parser.
40
+ ##
41
+ class Parser
42
+ def initialize(str, toppings={})
43
+ reset(str)
44
+ @toppings = toppings
45
+ @_s_cache = {} # for spclen()
46
+ @indent_width = toppings[:indent_width] || 2
47
+ end
48
+ attr_reader :lines, :index, :newline
49
+
50
+
51
+ def reset(str)
52
+ @str = str
53
+ idx = str.index(?\n)
54
+ @newline = (idx && str[idx-1] == ?\r) ? "\r\n" : "\n"
55
+ @lines = str.split(@newline, -1)
56
+ @lines.pop() # remove the last line
57
+ @index = 0
58
+ @limit = @lines.length
59
+ end
60
+
61
+
62
+ def _read_line
63
+ return nil if @index >= @limit
64
+ @index += 1
65
+ return @lines[@index]
66
+ end
67
+ private :_read_line
68
+
69
+ def _current_line
70
+ return @lines[@index]
71
+ end
72
+ private :_current_line
73
+
74
+
75
+ ## space length, with tab expanding
76
+ def spclen(str)
77
+ return 0 unless str
78
+ len = (@_s_cache[str] ||= (str.gsub(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")}).length)
79
+ return len
80
+ end
81
+
82
+
83
+ ## factory method
84
+ def create_document(headers, root)
85
+ return Document.new(headers, root)
86
+ end
87
+
88
+ ## factory method
89
+ def create_element(tag, children, attrs)
90
+ return Element.new(tag, children, attrs)
91
+ end
92
+
93
+ ## factory method
94
+ def create_comment(str)
95
+ return Comment.new(str)
96
+ end
97
+
98
+ ## factory method
99
+ def create_text(str, flag_escape=true)
100
+ return Text.new(str, flag_escape)
101
+ end
102
+
103
+ ##
104
+ def set_node_option(node, name, value)
105
+ node.empty_lines = value if name == :empty_lines
106
+ end
107
+
108
+ ##
109
+ def parse_document(str=nil)
110
+ reset(str) if str
111
+ headers = OrderedHash.new
112
+ line = _current_line()
113
+ while line
114
+ if line =~ /^\?[ \t]*([-:\w]+)[ \t]*[:=][ \t]*(.*)/ ## *pattern*
115
+ headers[$1.intern] = $2.strip
116
+ elsif line =~ /^\s*$/
117
+ # ignore empty line
118
+ elsif line =~ /^\s*\/\// ## *pattern*
119
+ # ignore comment line
120
+ else
121
+ break
122
+ end
123
+ line = _read_line()
124
+ end
125
+ if headers[:doctype] =~ /\A@[-:\w]+\z/
126
+ nickname = headers[:doctype]
127
+ doctype = DocType.get(nickname)
128
+ unless doctype
129
+ raise ParseError.new("doctype `#{headers[:doctype]}' not registered.", self)
130
+ end
131
+ headers[:doctype] = doctype
132
+ end
133
+ root_elem = parse_element()
134
+ doc = create_document(headers, root_elem)
135
+ set_node_option(doc, :empty_lines, @empty_lines)
136
+ return doc
137
+ end
138
+
139
+
140
+ def parse_node_list(level=0)
141
+ list = []
142
+ str = nil
143
+ line = _current_line()
144
+ while line
145
+ if line =~ /^(\s*)([*\#!.\~])/ # node ## *pattern*
146
+ curr_level = spclen($1)
147
+ ch = $2
148
+ if str
149
+ list << create_text(str)
150
+ str = nil
151
+ end
152
+ if curr_level == level # sibling node
153
+ empty_lines = @empty_lines || 0
154
+ @empty_lines = 0
155
+ case ch
156
+ when '*' ## *pattern*
157
+ node = parse_element(level)
158
+ when '#', '!' ## *pattern*
159
+ node = parse_comment(level)
160
+ when '.' ## *pattern*
161
+ node = parse_text(level)
162
+ when '~' ## *pattern*
163
+ node = parse_cdata(level)
164
+ else
165
+ raise ParseError.new("internal error", self)
166
+ end
167
+ set_node_option(node, :empty_lines, empty_lines)
168
+ list << node
169
+ line = _current_line()
170
+ next
171
+ elsif curr_level < level # parent node
172
+ break
173
+ else # child node
174
+ raise ParseError.new("illegal indentation.", self) # or internal error
175
+ end
176
+ elsif line =~ /^\s*$/ # empty lines
177
+ @empty_lines ||= 0
178
+ @empty_lines += 1
179
+ line = _read_line()
180
+ elsif line =~ /^\s*\/\// # line-comment # *pattern*
181
+ line = _read_line()
182
+ else
183
+ #raise ParseError.new("invalid line.", self)
184
+ str ||= ''
185
+ str << line
186
+ line = _read_line()
187
+ end
188
+ end
189
+ list << create_text(str) if str
190
+ return list
191
+ end
192
+
193
+
194
+ def _parse_heredoc(terminator, flag_join=false)
195
+ s = ""
196
+ while line = _read_line()
197
+ break if terminator === line.strip
198
+ s << @newline unless flag_join || s.empty?
199
+ s << line
200
+ end
201
+ raise ParseError.new("'<<#{terminator.to_s}' is not ended.", self) unless line
202
+ if line =~ /\A\s*/
203
+ space = $&
204
+ s.gsub!(/^#{space}/, '')
205
+ end
206
+ return s
207
+ end
208
+ private :_parse_heredoc
209
+
210
+
211
+ def parse_element(level=0)
212
+ ## tag and text
213
+ line = _current_line()
214
+ line =~ /^([ \t]*)\*[ \t]*([-:\w]+)([ \t]*=[ \t]*(.*))?/ ## *pattern*
215
+ Kwaff::assert() unless level == spclen($1)
216
+ tag = $2 || ''
217
+ value = $4
218
+ tag.strip!
219
+ if tag.empty?
220
+ raise ParseError.new("tag is missing.", self)
221
+ end
222
+ flag_escape = true
223
+ if value =~ /^<<<?('?\w+'?)$/
224
+ terminator = $1
225
+ if terminator =~ /\A'(.*)'\z/
226
+ terminator = $1
227
+ flag_escape = false
228
+ end
229
+ value = _parse_heredoc(terminator)
230
+ end
231
+
232
+ ## text
233
+ text = value ? create_text(value, flag_escape) : nil
234
+
235
+ ## attrs
236
+ attrs = OrderedHash.new
237
+ line = _read_line()
238
+ while line
239
+ if line =~ /^\s*\/\/$/ # line comment ## *pattern*
240
+ # nothing
241
+ #elsif line =~ /^\s*$/ # empty line
242
+ # @empty_lines += 1
243
+ elsif line =~ /^\s*\-/ # attribute ## *pattern*
244
+ unless line =~ /\A([ \t]*)\-[ \t]+([-:\w]+)[ \t]*=[ \t]*(.*)/ ## *pattern*
245
+ raise ParseError.new("invalid attribute format.", self)
246
+ end
247
+ attr_level = spclen($1)
248
+ attr_name = $2
249
+ attr_value = $3
250
+ unless attr_level == level + @indent_width ## *indent*
251
+ raise ParseError.new("attr indent width is not #{@indent_width}.", self)
252
+ end
253
+ if attr_value =~ /^<<([_A-Z]+)$/
254
+ terminator = $1
255
+ attr_value = _parse_heredoc(terminator)
256
+ end
257
+ attrs[attr_name] = attr_value
258
+ else
259
+ break
260
+ end
261
+ line = _read_line()
262
+ end
263
+
264
+ ## empty lines
265
+ @empty_lines = 0
266
+ while line && line =~ /\A\s*\z/
267
+ @empty_lines += 1
268
+ line = _read_line()
269
+ end
270
+
271
+ ## children
272
+ if line && line =~ /^(\s*)[*\#!.\~]/ && spclen($1) > level ## *pattern*
273
+ #children = parse_node_list(spclen($1))
274
+ unless spclen($1) == level + @indent_width ## *indent*
275
+ raise ParseError.new("indent width is not #{@indent_width}.", self)
276
+ end
277
+ children = parse_node_list(level+@indent_width)
278
+ else
279
+ children = []
280
+ end
281
+ children.unshift(text) if text
282
+
283
+ ## element
284
+ return create_element(tag, children, attrs)
285
+ end
286
+
287
+
288
+ def parse_comment(level=0)
289
+ line = _current_line()
290
+ line =~ /^([ \t]*)[\#\!][ \t]*(.*)$/ # *pattern*
291
+ Kwaff::assert() unless level == spclen($1)
292
+ str = $2
293
+ comment = create_comment(str)
294
+ line = _read_line()
295
+ return comment
296
+ end
297
+
298
+
299
+ def parse_text(level=0)
300
+ return _parse_textline(/^([ \t]*)\. ?(.*)$/, true, level) # *pattern*
301
+ end
302
+
303
+ def parse_cdata(level=0)
304
+ return _parse_textline(/^([ \t]*)\~ ?(.*)$/, false, level) # *pattern*
305
+ end
306
+
307
+ def _parse_textline(pattern, flag_escape, level=0)
308
+ line = _current_line()
309
+ str = ''
310
+ while line
311
+ break unless line =~ pattern
312
+ curr_level = spclen($1)
313
+ value = $2
314
+ if curr_level == level
315
+ str << @newline unless str.empty?
316
+ str << value
317
+ line = _read_line()
318
+ elsif curr_level < level
319
+ break
320
+ else
321
+ raise Parser.new("invalid indentaton.", self)
322
+ end
323
+ end
324
+ text = create_text(str, flag_escape)
325
+ return text
326
+ end
327
+ private :_parse_textline
328
+
329
+ end
330
+
331
+
332
+ ##
333
+ ## ex.
334
+ ## kwaff_str = File.open('file.kwaff') { |f| f.read }
335
+ ## kwaff_document = Kwaff::parse_document(kwaff_str)
336
+ ## xml_str = kwaff_document.to_xml
337
+ ##
338
+ def self.parse_document(input, toppings={})
339
+ return Parser.new(input, toppings).parse_document()
340
+ end
341
+
342
+ end