review-peg 0.1.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 (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +605 -0
  5. data/.travis.yml +18 -0
  6. data/COPYING +515 -0
  7. data/ChangeLog +2449 -0
  8. data/Dockerfile +22 -0
  9. data/Gemfile +6 -0
  10. data/README.rdoc +81 -0
  11. data/Rakefile +51 -0
  12. data/bin/review-catalog-converter-peg +129 -0
  13. data/bin/review-check-peg +169 -0
  14. data/bin/review-checkdep-peg +63 -0
  15. data/bin/review-compile-peg +202 -0
  16. data/bin/review-epubmaker-legacy-peg +1024 -0
  17. data/bin/review-epubmaker-peg +44 -0
  18. data/bin/review-index-peg +110 -0
  19. data/bin/review-init-peg +151 -0
  20. data/bin/review-pdfmaker-peg +18 -0
  21. data/bin/review-preproc-peg +131 -0
  22. data/bin/review-validate-peg +51 -0
  23. data/bin/review-vol-peg +100 -0
  24. data/debian/README.Debian +12 -0
  25. data/debian/README.source +5 -0
  26. data/debian/changelog +5 -0
  27. data/debian/compat +1 -0
  28. data/debian/control +22 -0
  29. data/debian/copyright +62 -0
  30. data/debian/docs +6 -0
  31. data/debian/manpage.1.ex +59 -0
  32. data/debian/patches/path.diff +91 -0
  33. data/debian/patches/series +1 -0
  34. data/debian/review.install +13 -0
  35. data/debian/review.links +4 -0
  36. data/debian/rules +13 -0
  37. data/debian/source/format +1 -0
  38. data/doc/NEWS.ja.md +350 -0
  39. data/doc/NEWS.md +354 -0
  40. data/doc/catalog.ja.md +53 -0
  41. data/doc/catalog.md +52 -0
  42. data/doc/format.ja.md +734 -0
  43. data/doc/format.md +746 -0
  44. data/doc/format_idg.ja.md +203 -0
  45. data/doc/quickstart.ja.md +222 -0
  46. data/doc/quickstart.md +252 -0
  47. data/doc/ruby-uuid/README +11 -0
  48. data/doc/ruby-uuid/README.ja +34 -0
  49. data/doc/sample.css +108 -0
  50. data/doc/sample.yml +238 -0
  51. data/lib/epubmaker.rb +24 -0
  52. data/lib/epubmaker/content.rb +93 -0
  53. data/lib/epubmaker/epubcommon.rb +424 -0
  54. data/lib/epubmaker/epubv2.rb +139 -0
  55. data/lib/epubmaker/epubv3.rb +222 -0
  56. data/lib/epubmaker/producer.rb +330 -0
  57. data/lib/lineinput.rb +107 -0
  58. data/lib/review.rb +3 -0
  59. data/lib/review/book.rb +43 -0
  60. data/lib/review/book/base.rb +401 -0
  61. data/lib/review/book/chapter.rb +100 -0
  62. data/lib/review/book/compilable.rb +184 -0
  63. data/lib/review/book/image_finder.rb +71 -0
  64. data/lib/review/book/index.rb +413 -0
  65. data/lib/review/book/page_metric.rb +47 -0
  66. data/lib/review/book/part.rb +54 -0
  67. data/lib/review/book/volume.rb +67 -0
  68. data/lib/review/builder.rb +452 -0
  69. data/lib/review/catalog.rb +52 -0
  70. data/lib/review/compiler.rb +5183 -0
  71. data/lib/review/compiler/literals_1_9.kpeg +22 -0
  72. data/lib/review/compiler/literals_1_9.rb +435 -0
  73. data/lib/review/configure.rb +64 -0
  74. data/lib/review/epubbuilder.rb +18 -0
  75. data/lib/review/epubmaker.rb +480 -0
  76. data/lib/review/ewbbuilder.rb +381 -0
  77. data/lib/review/exception.rb +21 -0
  78. data/lib/review/extentions.rb +4 -0
  79. data/lib/review/extentions/array.rb +25 -0
  80. data/lib/review/extentions/object.rb +9 -0
  81. data/lib/review/extentions/string.rb +33 -0
  82. data/lib/review/htmlbuilder.rb +1166 -0
  83. data/lib/review/htmllayout.rb +41 -0
  84. data/lib/review/htmltoc.rb +45 -0
  85. data/lib/review/htmlutils.rb +90 -0
  86. data/lib/review/i18n.rb +96 -0
  87. data/lib/review/i18n.yml +169 -0
  88. data/lib/review/idgxmlbuilder.rb +1233 -0
  89. data/lib/review/inaobuilder.rb +357 -0
  90. data/lib/review/latexbuilder.rb +941 -0
  91. data/lib/review/latexindex.rb +35 -0
  92. data/lib/review/latexutils.rb +95 -0
  93. data/lib/review/layout.tex.erb +340 -0
  94. data/lib/review/lineinput.rb +17 -0
  95. data/lib/review/location.rb +24 -0
  96. data/lib/review/makerhelper.rb +67 -0
  97. data/lib/review/markdownbuilder.rb +339 -0
  98. data/lib/review/node.rb +288 -0
  99. data/lib/review/pdfmaker.rb +332 -0
  100. data/lib/review/preprocessor.rb +530 -0
  101. data/lib/review/review.kpeg +745 -0
  102. data/lib/review/sec_counter.rb +69 -0
  103. data/lib/review/template.rb +21 -0
  104. data/lib/review/textbuilder.rb +17 -0
  105. data/lib/review/textutils.rb +16 -0
  106. data/lib/review/tocparser.rb +348 -0
  107. data/lib/review/tocprinter.rb +205 -0
  108. data/lib/review/topbuilder.rb +796 -0
  109. data/lib/review/unfold.rb +138 -0
  110. data/lib/review/version.rb +3 -0
  111. data/lib/uuid.rb +312 -0
  112. data/review.gemspec +32 -0
  113. data/templates/html/layout-html5.html.erb +17 -0
  114. data/templates/html/layout-xhtml1.html.erb +20 -0
  115. data/templates/ncx/epubv2.ncx.erb +11 -0
  116. data/templates/opf/epubv2.opf.erb +21 -0
  117. data/templates/opf/epubv3.opf.erb +18 -0
  118. data/templates/xml/container.xml.erb +6 -0
  119. data/test/CHAPS +2 -0
  120. data/test/assets/test.xml.erb +3 -0
  121. data/test/assets/test_template.tex +255 -0
  122. data/test/assets/test_template_backmatter.tex +32 -0
  123. data/test/bib.re +13 -0
  124. data/test/book_test_helper.rb +35 -0
  125. data/test/sample-book/README.md +7 -0
  126. data/test/sample-book/src/Rakefile +58 -0
  127. data/test/sample-book/src/_cover.html +3 -0
  128. data/test/sample-book/src/catalog.yml +10 -0
  129. data/test/sample-book/src/ch01.re +71 -0
  130. data/test/sample-book/src/ch02.re +3 -0
  131. data/test/sample-book/src/config.yml +186 -0
  132. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  133. data/test/sample-book/src/images/cover.jpg +0 -0
  134. data/test/sample-book/src/preface.re +15 -0
  135. data/test/sample-book/src/sty/jumoline.sty +310 -0
  136. data/test/sample-book/src/sty/reviewmacro.sty +39 -0
  137. data/test/sample-book/src/style.css +251 -0
  138. data/test/sample-book/src/vendor/jumoline/README +29 -0
  139. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  140. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  141. data/test/test.re +43 -0
  142. data/test/test_book.rb +556 -0
  143. data/test/test_book_chapter.rb +280 -0
  144. data/test/test_book_part.rb +54 -0
  145. data/test/test_builder.rb +80 -0
  146. data/test/test_catalog.rb +119 -0
  147. data/test/test_catalog_converter_cmd.rb +73 -0
  148. data/test/test_compiler.rb +92 -0
  149. data/test/test_configure.rb +50 -0
  150. data/test/test_epub3maker.rb +529 -0
  151. data/test/test_epubmaker.rb +569 -0
  152. data/test/test_epubmaker_cmd.rb +40 -0
  153. data/test/test_helper.rb +92 -0
  154. data/test/test_htmlbuilder.rb +1114 -0
  155. data/test/test_htmltoc.rb +32 -0
  156. data/test/test_htmlutils.rb +50 -0
  157. data/test/test_i18n.rb +180 -0
  158. data/test/test_idgxmlbuilder.rb +608 -0
  159. data/test/test_image_finder.rb +82 -0
  160. data/test/test_inaobuilder.rb +245 -0
  161. data/test/test_index.rb +174 -0
  162. data/test/test_latexbuilder.rb +732 -0
  163. data/test/test_lineinput.rb +182 -0
  164. data/test/test_makerhelper.rb +66 -0
  165. data/test/test_markdownbuilder.rb +125 -0
  166. data/test/test_pdfmaker.rb +171 -0
  167. data/test/test_pdfmaker_cmd.rb +40 -0
  168. data/test/test_preprocessor.rb +23 -0
  169. data/test/test_review_ext.rb +31 -0
  170. data/test/test_template.rb +26 -0
  171. data/test/test_textutils.rb +32 -0
  172. data/test/test_topbuilder.rb +291 -0
  173. data/test/test_uuid.rb +157 -0
  174. metadata +357 -0
@@ -0,0 +1,745 @@
1
+ %% name = ReVIEW::Compiler
2
+
3
+ %% {
4
+ class Error; end
5
+ class Position
6
+ attr_accessor :pos, :line, :col
7
+ def initialize(compiler)
8
+ @pos = compiler.pos
9
+ @line = compiler.current_line
10
+ @col = compiler.current_column
11
+ end
12
+ end
13
+
14
+ # rubocop:disable all
15
+ require 'review/location'
16
+ require 'review/extentions'
17
+ require 'review/preprocessor'
18
+ require 'review/exception'
19
+ require 'review/node'
20
+ require 'lineinput'
21
+ require 'review/compiler/literals_1_9'
22
+ # require 'review/compiler/literals_1_8'
23
+
24
+ ## redifine Compiler.new
25
+ def initialize(strategy)
26
+ @strategy = strategy
27
+ @current_column = nil
28
+ @chapter = nil
29
+ end
30
+
31
+ attr_accessor :strategy
32
+
33
+ def compile(chap)
34
+ @chapter = chap
35
+ do_compile
36
+ @strategy.result
37
+ end
38
+
39
+ def do_compile
40
+ @strategy.bind self, @chapter, ReVIEW::Location.new(@chapter.basename, self)
41
+ setup_parser(@chapter.content)
42
+ parse()
43
+ convert_ast
44
+ end
45
+
46
+ def convert_ast
47
+ ast = @strategy.ast
48
+ convert_column(ast)
49
+ if $DEBUG
50
+ File.open("review-dump.json","w") do |f|
51
+ f.write(ast.to_json)
52
+ end
53
+ end
54
+ @strategy.output << ast.to_doc
55
+ end
56
+
57
+ def flush_column(new_content)
58
+ if @current_column
59
+ new_content << @current_column
60
+ @current_column = nil
61
+ end
62
+ end
63
+
64
+ def convert_column(ast)
65
+ @column_stack = []
66
+ content = ast.content
67
+ new_content = []
68
+ @current_content = new_content
69
+ content.each do |elem|
70
+ if elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc == "column"
71
+ flush_column(new_content)
72
+ @current_content = []
73
+ @current_column = ReVIEW::ColumnNode.new(elem.compiler, elem.position, elem.level,
74
+ elem.label, elem.content, @current_content)
75
+ next
76
+ elsif elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc =~ %r|^/|
77
+ cmd_name = elem.cmd.to_doc[1..-1]
78
+ if cmd_name != "column"
79
+ raise ReVIEW::CompileError, "#{cmd_name} is not opened."
80
+ end
81
+ flush_column(new_content)
82
+ @current_content = new_content
83
+ next
84
+ elsif elem.kind_of?(ReVIEW::HeadlineNode) && @current_column && elem.level <= @current_column.level
85
+ flush_column(new_content)
86
+ @current_content = new_content
87
+ end
88
+ @current_content << elem
89
+ end
90
+ flush_column(new_content)
91
+ ast.content = new_content
92
+ ast
93
+ end
94
+
95
+ def compile_text(text)
96
+ @strategy.nofunc_text(text)
97
+ end
98
+
99
+ class SyntaxElement
100
+ def initialize(name, type, argc, esc, &block)
101
+ @name = name
102
+ @type = type
103
+ @argc_spec = argc
104
+ @esc_patterns = esc
105
+ @checker = block
106
+ end
107
+
108
+ attr_reader :name
109
+
110
+ def check_args(args)
111
+ unless @argc_spec === args.size
112
+ raise ReVIEW::CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})"
113
+ end
114
+ @checker.call(*args) if @checker
115
+ end
116
+
117
+ def min_argc
118
+ case @argc_spec
119
+ when Range then @argc_spec.begin
120
+ when Integer then @argc_spec
121
+ else
122
+ raise TypeError, "argc_spec is not Range/Integer: #{inspect()}"
123
+ end
124
+ end
125
+
126
+ def parse_args(args)
127
+ if @esc_patterns
128
+ args.map.with_index do |pattern, i|
129
+ if @esc_patterns[i]
130
+ args[i].__send__("to_#{@esc_patterns[i]}")
131
+ else
132
+ args[i].to_doc
133
+ end
134
+ end
135
+ else
136
+ args.map(&:to_doc)
137
+ end
138
+ end
139
+
140
+ def block_required?
141
+ @type == :block or @type == :code_block
142
+ end
143
+
144
+ def block_allowed?
145
+ @type == :block or @type == :code_block or @type == :optional or @type == :optional_code_block
146
+ end
147
+
148
+ def code_block?
149
+ @type == :code_block or @type == :optional_code_block
150
+ end
151
+ end
152
+
153
+ SYNTAX = {}
154
+
155
+ def self.defblock(name, argc, optional = false, esc = nil, &block)
156
+ defsyntax(name, (optional ? :optional : :block), argc, esc, &block)
157
+ end
158
+
159
+ def self.defcodeblock(name, argc, optional = false, esc = nil, &block)
160
+ defsyntax(name, (optional ? :optional_code_block : :code_block), argc, esc, &block)
161
+ end
162
+
163
+ def self.defsingle(name, argc, esc = nil, &block)
164
+ defsyntax name, :line, argc, esc, &block
165
+ end
166
+
167
+ def self.defsyntax(name, type, argc, esc = nil, &block)
168
+ SYNTAX[name] = SyntaxElement.new(name, type, argc, esc, &block)
169
+ end
170
+
171
+ def syntax_defined?(name)
172
+ SYNTAX.key?(name.to_sym)
173
+ end
174
+
175
+ def syntax_descriptor(name)
176
+ SYNTAX[name.to_sym]
177
+ end
178
+
179
+ class InlineSyntaxElement
180
+ def initialize(name)
181
+ @name = name
182
+ end
183
+
184
+ attr_reader :name
185
+ end
186
+
187
+ INLINE = {}
188
+ COMPLEX_INLINE = {}
189
+
190
+ def self.definline(name)
191
+ INLINE[name] = InlineSyntaxElement.new(name)
192
+ end
193
+
194
+ def self.defcomplexinline(name)
195
+ COMPLEX_INLINE[name] = InlineSyntaxElement.new(name)
196
+ end
197
+
198
+ def inline_defined?(name)
199
+ INLINE.key?(name.to_sym) || COMPLEX_INLINE.key?(name.to_sym)
200
+ end
201
+
202
+ defblock :read, 0
203
+ defblock :lead, 0
204
+ defblock :quote, 0
205
+ defblock :bibpaper, 2..3, true, [:raw, :doc, :doc]
206
+ defblock :doorquote, 1, false, [:doc]
207
+ defblock :talk, 0
208
+ defblock :graph, 1..3, false, [:raw, :raw, :doc]
209
+
210
+ defcodeblock :emlist, 0..2, false, [:doc, :raw]
211
+ defcodeblock :cmd, 0..1, false, [:doc]
212
+ defcodeblock :source, 0..2, false, [:doc, :raw]
213
+ defcodeblock :list, 2..4, false, [:raw, :doc, :raw, :raw]
214
+ defcodeblock :listnum, 2..3, false, [:raw, :doc, :raw]
215
+ defcodeblock :emlistnum, 0..2, false, [:doc, :raw]
216
+ defcodeblock :texequation, 0, false
217
+ defcodeblock :table, 0..2, false, [:raw, :doc]
218
+ defcodeblock :image, 2..3, true, [:raw,:doc,:raw]
219
+ defcodeblock :box, 0..1, false, [:doc]
220
+
221
+ defblock :address, 0
222
+ defblock :blockquote, 0
223
+ defblock :bpo, 0
224
+ defblock :flushright, 0
225
+ defblock :centering, 0
226
+ defblock :note, 0..1
227
+ defblock :comment, 0..1, true
228
+
229
+ defsingle :footnote, 2, [:raw, :doc]
230
+ defsingle :noindent, 0
231
+ defsingle :linebreak, 0
232
+ defsingle :pagebreak, 0
233
+ defsingle :indepimage, 1..3, [:raw, :doc, :raw]
234
+ defsingle :numberlessimage, 1..3, [:raw, :doc, :raw]
235
+ defsingle :hr, 0
236
+ defsingle :parasep, 0
237
+ defsingle :label, 1, [:raw]
238
+ defsingle :raw, 1, [:raw]
239
+ defsingle :tsize, 1, [:raw]
240
+ defsingle :include, 1, [:raw]
241
+ defsingle :olnum, 1, [:raw]
242
+
243
+ definline :chapref
244
+ definline :chap
245
+ definline :title
246
+ definline :img
247
+ definline :imgref
248
+ definline :icon
249
+ definline :list
250
+ definline :table
251
+ definline :fn
252
+ definline :bou
253
+ definline :ami
254
+ definline :b
255
+ definline :dtp
256
+ definline :code
257
+ definline :bib
258
+ definline :hd
259
+ definline :recipe
260
+ definline :column
261
+
262
+ definline :abbr
263
+ definline :acronym
264
+ definline :cite
265
+ definline :dfn
266
+ definline :em
267
+ definline :kbd
268
+ definline :q
269
+ definline :samp
270
+ definline :strong
271
+ definline :var
272
+ definline :big
273
+ definline :small
274
+ definline :del
275
+ definline :ins
276
+ definline :sup
277
+ definline :sub
278
+ definline :tt
279
+ definline :i
280
+ definline :tti
281
+ definline :ttb
282
+ definline :u
283
+ definline :raw
284
+ definline :br
285
+ definline :m
286
+ definline :uchar
287
+ definline :idx
288
+ definline :hidx
289
+ definline :comment
290
+ definline :include
291
+
292
+ defcomplexinline :kw
293
+ defcomplexinline :ruby
294
+ defcomplexinline :href
295
+
296
+ def compile_column(level, label, caption, content)
297
+ buf = ""
298
+ buf << @strategy.__send__("column_begin", level, label, caption)
299
+ buf << content.to_doc
300
+ buf << @strategy.__send__("column_end", level)
301
+ buf
302
+ end
303
+
304
+ def compile_command(name, args, lines, node)
305
+ syntax = syntax_descriptor(name)
306
+ if !syntax || (!@strategy.respond_to?(syntax.name) && !@strategy.respond_to?("node_#{syntax.name}"))
307
+ error "strategy does not support command: //#{name}"
308
+ compile_unknown_command args, lines
309
+ return
310
+ end
311
+ begin
312
+ syntax.check_args args
313
+ rescue ReVIEW::CompileError => err
314
+ error err.message
315
+ args = ['(NoArgument)'] * syntax.min_argc
316
+ end
317
+ if syntax.block_allowed?
318
+ compile_block(syntax, args, lines, node)
319
+ else
320
+ if lines
321
+ error "block is not allowed for command //#{syntax.name}; ignore"
322
+ end
323
+ compile_single(syntax, args, node)
324
+ end
325
+ end
326
+
327
+ def compile_headline(level, tag, label, caption)
328
+ buf = ""
329
+ @headline_indexs ||= [0] ## XXX
330
+ caption ||= ""
331
+ caption.strip!
332
+ index = level - 1
333
+ if @headline_indexs.size > (index + 1)
334
+ @headline_indexs = @headline_indexs[0..index]
335
+ end
336
+ @headline_indexs[index] = 0 if @headline_indexs[index].nil?
337
+ @headline_indexs[index] += 1
338
+ buf << @strategy.headline(level, label, caption)
339
+ buf
340
+ end
341
+
342
+ def comment(text)
343
+ @strategy.comment(text)
344
+ end
345
+
346
+ def compile_ulist(content)
347
+ buf0 = ""
348
+ level = 0
349
+ content.each do |element|
350
+ current_level = element.level
351
+ buf = element.to_doc
352
+ if level == current_level
353
+ buf0 << @strategy.ul_item_end
354
+ # body
355
+ buf0 << @strategy.ul_item_begin([buf])
356
+ elsif level < current_level # down
357
+ level_diff = current_level - level
358
+ level = current_level
359
+ (1..(level_diff - 1)).to_a.reverse_each do |i|
360
+ buf0 << @strategy.ul_begin{i}
361
+ buf0 << @strategy.ul_item_begin([])
362
+ end
363
+ buf0 << @strategy.ul_begin{level}
364
+ buf0 << @strategy.ul_item_begin([buf])
365
+ elsif level > current_level # up
366
+ level_diff = level - current_level
367
+ level = current_level
368
+ (1..level_diff).to_a.reverse_each do |i|
369
+ buf0 << @strategy.ul_item_end
370
+ buf0 << @strategy.ul_end{level + i}
371
+ end
372
+ buf0 << @strategy.ul_item_end
373
+ # body
374
+ buf0 <<@strategy.ul_item_begin([buf])
375
+ end
376
+ end
377
+
378
+ (1..level).to_a.reverse_each do |i|
379
+ buf0 << @strategy.ul_item_end
380
+ buf0 << @strategy.ul_end{i}
381
+ end
382
+ buf0
383
+ end
384
+
385
+ def compile_olist(content)
386
+ buf0 = ""
387
+ buf0 << @strategy.ol_begin
388
+ content.each do |element|
389
+ ## XXX 1st arg should be String, not Array
390
+ buf0 << @strategy.ol_item(element.to_doc.split(/\n/), element.num)
391
+ end
392
+ buf0 << @strategy.ol_end
393
+ buf0
394
+ end
395
+
396
+ def compile_dlist(content)
397
+ buf = ""
398
+ buf << @strategy.dl_begin
399
+ content.each do |element|
400
+ buf << @strategy.dt(element.text.to_doc)
401
+ buf << @strategy.dd(element.content.map{|s| s.to_doc})
402
+ end
403
+ buf << @strategy.dl_end
404
+ buf
405
+ end
406
+
407
+
408
+ def compile_unknown_command(args, lines)
409
+ @strategy.unknown_command(args, lines)
410
+ end
411
+
412
+ def compile_block(syntax, args, lines, node)
413
+ node_name = "node_#{syntax.name}".to_sym
414
+ if @strategy.respond_to?(node_name)
415
+ @strategy.__send__(node_name, node)
416
+ else
417
+ args_conv = syntax.parse_args(args)
418
+ @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args_conv)
419
+ end
420
+ end
421
+
422
+ def default_block(syntax)
423
+ if syntax.block_required?
424
+ error "block is required for //#{syntax.name}; use empty block"
425
+ end
426
+ []
427
+ end
428
+
429
+ def compile_single(syntax, args, node)
430
+ node_name = "node_#{syntax.name}".to_sym
431
+ if @strategy.respond_to?(node_name)
432
+ @strategy.__send__(node_name, node)
433
+ else
434
+ args_conv = syntax.parse_args(args)
435
+ @strategy.__send__(syntax.name, *args_conv)
436
+ end
437
+ end
438
+
439
+
440
+ def compile_inline(op, args)
441
+ unless inline_defined?(op)
442
+ raise ReVIEW::CompileError, "no such inline op: #{op}"
443
+ end
444
+ if @strategy.respond_to?("node_inline_#{op}")
445
+ return @strategy.__send__("node_inline_#{op}", args)
446
+ end
447
+ unless @strategy.respond_to?("inline_#{op}")
448
+ raise "strategy does not support inline op: @<#{op}>"
449
+ end
450
+ if !args
451
+ @strategy.__send__("inline_#{op}", "")
452
+ else
453
+ @strategy.__send__("inline_#{op}", *(args.map(&:to_doc)))
454
+ end
455
+ # rescue => err
456
+ # error err.message
457
+ end
458
+
459
+ def compile_paragraph(buf)
460
+ @strategy.paragraph buf
461
+ end
462
+
463
+ def compile_raw(builders, content)
464
+ c = @strategy.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
465
+ if !builders || builders.include?(c)
466
+ content.gsub("\\n", "\n")
467
+ else
468
+ ""
469
+ end
470
+ end
471
+
472
+ def warn(msg)
473
+ @strategy.warn msg
474
+ end
475
+
476
+ def error(msg)
477
+ @strategy.error msg
478
+ end
479
+
480
+ def check_indent(s)
481
+ s.size >= @list_stack.last.size
482
+ end
483
+
484
+ def check_nested_indent(s)
485
+ s.size >= @list_stack.last.size + 2
486
+ end
487
+
488
+ def check_inline_element_symbol(name)
489
+ INLINE.key?(name.to_sym)
490
+ end
491
+
492
+ def check_complex_inline_element_symbol(name)
493
+ COMPLEX_INLINE.key?(name.to_sym)
494
+ end
495
+
496
+ def position
497
+ Position.new(self)
498
+ end
499
+
500
+
501
+ }
502
+
503
+ %% ast-location = ::ReVIEW
504
+ %% headline = ast HeadlineNode(compiler, position, level, cmd, label, content)
505
+ %% paragraph = ast ParagraphNode(compiler, position, content)
506
+ %% block_element = ast BlockElementNode(compiler, position, name, args, content)
507
+ %% code_block_element = ast CodeBlockElementNode(compiler, position, name, args, content)
508
+ %% inline_element = ast InlineElementNode(compiler, position, symbol, content)
509
+ %% inline_element_content = ast InlineElementContentNode(compiler, position, content)
510
+ %% complex_inline_element = ast ComplexInlineElementNode(compiler, position, symbol, content)
511
+ %% complex_inline_element_content = ast ComplexInlineElementContentNode(compiler, position, content)
512
+ %% text = ast TextNode(compiler, position, content)
513
+ %% raw = ast RawNode(compiler, builder, position, content)
514
+ %% brace = ast BraceNode(compiler, position, content)
515
+ %% singleline_content = ast SinglelineContentNode(compiler, position, content)
516
+ %% singleline_comment = ast SinglelineCommentNode(compiler, position, content)
517
+ %% ulist = ast UlistNode(compiler, position, content)
518
+ %% ulist_element = ast UlistElementNode(compiler, position, level, content)
519
+ %% olist = ast OlistNode(compiler, position, content)
520
+ %% olist_element = ast OlistElementNode(compiler, position, num, content)
521
+ %% dlist = ast DlistNode(compiler, position, content)
522
+ %% dlist_element = ast DlistElementNode(compiler, position, text, content)
523
+ %% bracket_arg = ast BracketArgNode(compiler, position, content)
524
+ %% document = ast DocumentNode(compiler, position, content)
525
+ %% column = ast ColumnNode(compiler, position, level, label, caption, content)
526
+ %% newline = ast NewLineNode(compiler, position, content)
527
+
528
+ # %% dummy
529
+
530
+ root = Start
531
+
532
+ Start = &. { @list_stack = Array.new } Document:c { @strategy.ast = c }
533
+
534
+ ## a Document is a set of Blocks
535
+ Document = BOM? Block*:c ~document(self, position, c)
536
+
537
+ ## ignore leading blank lines
538
+ Block = BlankLine*:c { c }
539
+ ( SinglelineComment:c
540
+ | Headline:c
541
+ | BlockElement:c
542
+ | Ulist:c
543
+ | Olist:c
544
+ | Dlist:c
545
+ | Paragraph:c
546
+ ) { c }
547
+
548
+ BlankLine = Newline
549
+
550
+ SinglelineComment = ("#@" < NonNewline+ > EOL) ~singleline_comment(self, position, text)
551
+
552
+ Headline = HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent?:caption EOL ~headline(self, position, level, cmd, label, caption)
553
+
554
+ HeadlinePrefix = < /={1,5}/ > { text.length }
555
+
556
+ Paragraph = ParagraphLine+:c ~paragraph(self, position, c.flatten)
557
+
558
+ ParagraphLine = !Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }
559
+
560
+ # There are 3 types of Block Element: raw Block, Code Block, and Normal Block
561
+ BlockElement = ( "//raw[" RawBlockBuilderSelect?:b RawBlockElementArg*:r1 "]" Space* EOL
562
+ ~raw(self, b, position, r1)
563
+ | !"//raw" "//" ElementName:symbol &{ syntax = syntax_descriptor(symbol); syntax && syntax.code_block? } BracketArg*:args "{" Space* Newline CodeBlockElementContents?:contents "//}" Space* EOL
564
+ ~code_block_element(self, position, symbol, args, contents)
565
+ | !"//raw" "//" ElementName:symbol BracketArg*:args "{" Space* Newline BlockElementContents?:contents "//}" Space* EOL
566
+ ~block_element(self, position, symbol, args, contents)
567
+ | !"//raw" "//" ElementName:symbol BracketArg*:args Space* EOL ~block_element(self, position, symbol, args, nil)
568
+ )
569
+
570
+ RawBlockBuilderSelect = "|" Space* RawBlockBuilderSelectSub:c Space* "|" { c }
571
+
572
+ RawBlockBuilderSelectSub = ( < AlphanumericAscii+ >:c1 Space* "," Space* RawBlockBuilderSelectSub:c2
573
+ { [text] + c2 }
574
+ | < AlphanumericAscii+ >:c1
575
+ { [text] }
576
+ )
577
+
578
+ RawBlockElementArg = !"]" ( "\\]" { "]" }
579
+ | "\\n" { "\n" }
580
+ | < NonNewline > { text }
581
+ )
582
+
583
+ BracketArg = "[" BracketArgInline*:content "]" ~bracket_arg(self, position, content)
584
+
585
+ ## XXX '\' (excpet '\]' and '\\' ) => '\' is ???
586
+ BracketArgInline = ( InlineElement:c { c }
587
+ | "\\]" ~text(self, position, "]")
588
+ | "\\\\" ~text(self, position, "\\")
589
+ | < /[^\r\n\]]/ > ~text(self, position, text)
590
+ )
591
+
592
+ BraceArg = "{" < /([^\r\n}\\]|\\[^\r\n])*/ > "}" { text }
593
+
594
+ ## Standard BlockElement has nested blocks. Texts in content of block are parsed as Paragraph.
595
+ BlockElementContents = BlockElementContent+:c { c }
596
+
597
+ ### Headline is prohibited.
598
+ ### Note: do not allow "//}" at front of Paragraph.
599
+ BlockElementContent = ( SinglelineComment:c { c }
600
+ | BlockElement:c { c }
601
+ | Ulist:c
602
+ | Dlist:c
603
+ | Olist:c
604
+ | BlankLine:c { c }
605
+ | BlockElementParagraph:c { c }
606
+ )
607
+
608
+ ## it's like Paragraph, but it's in a block, so do not allow '//}\n'
609
+ BlockElementParagraph = BlockElementParagraphLine+:c ~paragraph(self, position, c.flatten)
610
+ BlockElementParagraphLine = !"//}" !BlankLine !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }
611
+
612
+ ## In CodeBlockElementContents, newline should no be ingored. So we use TextNode instead of NewLineNode.
613
+ CodeBlockElementContents = CodeBlockElementContent+:c { c }
614
+ CodeBlockElementContent = ( SinglelineComment:c { c }
615
+ | BlankLine:c { ::ReVIEW::TextNode.new(self, position, "\n") }
616
+ | !"//}" SinglelineContent:c Newline { [c, ::ReVIEW::TextNode.new(self, position, "\n")] }
617
+ )
618
+
619
+ ## Ulist and Olist
620
+
621
+ Bullet = "*"
622
+ Enumerator = < /[0-9]+/ > { num = text } "." { num.to_i }
623
+
624
+ Ulist = Indent+:s Bullet+:b Space+ { @list_stack.push(s) } UlistItemBlock:item
625
+ { if b.size > 1 then item.level = b.size end }
626
+ (UlistItem | UlistItemMore | NestedList)*:items &{ s == @list_stack.pop }
627
+ ~ulist(self, position, items.unshift(item))
628
+
629
+ Olist = Indent+:s Enumerator:e Space+ { @list_stack.push(s) } OlistItemBlock:item
630
+ { item.num = e }
631
+ (OlistItem | NestedList)*:items &{ s == @list_stack.pop }
632
+ ~olist(self, position, items.unshift(item))
633
+
634
+ UlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~ulist_element(self, position, @list_stack.size, d.unshift(c))
635
+ OlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~olist_element(self, position, 0, d.unshift(c))
636
+
637
+ ListItemFirstLine = SinglelineContent:c Newline { c }
638
+ ListItemLine = Indent+:s !Bullet !Enumerator !Space SinglelineContent:c &{ check_indent(s) } Newline { c }
639
+
640
+ UlistItemMore = Indent+:s Bullet Bullet+:b Space+ &{ check_indent(s) } UlistItemBlock:item { item.level = b.size+1; item }
641
+
642
+ UlistItem = Indent+:s Bullet Space+ &{ check_indent(s) } UlistItemBlock:item { item }
643
+ OlistItem = Indent+:s Enumerator:e Space+ &{ check_indent(s) } OlistItemBlock:item { item.num = e; item }
644
+
645
+ ## NestedList is markdown-like indented syntax.
646
+ ## You can write nested Ulist and Olist with this syntax.
647
+
648
+ NestedList = (NestedUlist | NestedOlist)
649
+
650
+ NestedUlist = Indent+:s Bullet Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } UlistItemBlock:item
651
+ (UlistItem | NestedList)*:items &{ s == @list_stack.pop }
652
+ ~ulist(self, position, items.unshift(item))
653
+ NestedOlist = Indent+:s Enumerator:e Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } OlistItemBlock:item
654
+ { item.num = e }
655
+ (OlistItem | NestedList)*:items &{ s == @list_stack.pop }
656
+ ~olist(self, position, items.unshift(item))
657
+
658
+ # Dlist
659
+ Dlist = (DlistElement | SinglelineComment)+:content ~dlist(self, position, content)
660
+
661
+ DlistElement = Indent* ":" Space+ SinglelineContent:text Newline DlistElementContent+:content ~dlist_element(self, position, text, content)
662
+
663
+ DlistElementContent = (SinglelineComment:c { c }
664
+ |Space+ SinglelineContent:c Newline { c }
665
+ )
666
+
667
+ SinglelineContent = Inline+:c ~singleline_content(self, position, c)
668
+
669
+
670
+ # Inline Element and Non Inline Element
671
+
672
+ Inline = ( InlineElement | NonInlineElement)
673
+
674
+ NonInlineElement = !InlineElement < NonNewline > ~text(self, position, text)
675
+
676
+ InlineElement = ( RawInlineElement:c { c }
677
+ | !RawInlineElement "@<" InlineElementSymbol:symbol ">" "{" InlineElementContents?:contents "}" ~inline_element(self, position, symbol,contents)
678
+ | !RawInlineElement "@<" ComplexInlineElementSymbol:symbol ">" "{" ComplexInlineElementContents?:contents "}" ~complex_inline_element(self, position, symbol,contents)
679
+ )
680
+
681
+ RawInlineElement = "@<raw>{" RawBlockBuilderSelect?:builders RawInlineElementContent+:c "}" ~raw(self, builders, position, c)
682
+
683
+ RawInlineElementContent = ( "\\}" { "}" }
684
+ | < /[^\r\n\}]/ > { text }
685
+ )
686
+
687
+ InlineElementSymbol = < AlphanumericAscii+ >:s &{ check_inline_element_symbol(text) } { text }
688
+
689
+ InlineElementContents = !"}" InlineElementContentsSub:c { c }
690
+
691
+ InlineElementContentsSub = !"}" Space* InlineElementContent:c1 Space* { [c1] }
692
+
693
+ ComplexInlineElementSymbol = < AlphanumericAscii+ > &{ check_complex_inline_element_symbol(text) } { text }
694
+
695
+ ComplexInlineElementContents = !"}" ComplexInlineElementContentsSub:c { c }
696
+
697
+ ComplexInlineElementContentsSub = !"}" ( Space* InlineElementContent:c1 Space* "," ComplexInlineElementContentsSub:c2 { [c1]+c2 }
698
+ | Space* InlineElementContent:c1 Space* { [c1] }
699
+ )
700
+
701
+
702
+ InlineElementContent = InlineElementContentSub+:d { d }
703
+
704
+ InlineElementContentSub = ( InlineElement:c { c }
705
+ | !InlineElement QuotedInlineText:content ~inline_element_content(self, position, content)
706
+ | !InlineElement InlineElementContentText+:content ~inline_element_content(self, position, content)
707
+ )
708
+
709
+ ## Quoted Inline Text is "..."
710
+ ## In Quoted Inline Text, "\\" is "\", "\'" is "'", other characters are kept as is.
711
+ QuotedInlineText = "\""
712
+ ( "\\\"" { "\"" }
713
+ | "\\\\" { "\\" }
714
+ | < /[^"\r\n\\]/ > { text }
715
+ )+:str "\"" ~text(self, position, str.join(""))
716
+
717
+ ## XXX '\' (excpet '\}' and '\,' and '\\' ) => '\' is OK?
718
+ InlineElementContentText = ( "\\}" ~text(self, position, "}")
719
+ | "\\," ~text(self, position, ",")
720
+ | "\\\\" ~text(self, position, "\\" )
721
+ | "\\" ~text(self, position, "\\" )
722
+ | !InlineElement < /[^\r\n\\},]/> ~text(self, position, text)
723
+ )
724
+
725
+ NonNewline = /[^\r\n]/
726
+
727
+ Space = /[ \t]/
728
+
729
+ Indent = " "
730
+
731
+ EOL = (Newline|EOF)
732
+
733
+ EOF = !.
734
+
735
+ ElementName = < LowerAlphabetAscii+ > { text }
736
+
737
+ %literals = ReVIEW::Compiler::Literals
738
+ Alphanumeric = %literals.Alphanumeric
739
+ AlphanumericAscii = %literals.AlphanumericAscii
740
+ LowerAlphabetAscii = %literals.LowerAlphabetAscii
741
+ Digit = %literals.Digit
742
+ BOM = %literals.BOM
743
+ Newline = %literals.Newline:n ~newline(self, position, "\n")
744
+ NonAlphanumeric = %literals.NonAlphanumeric
745
+ Spacechar = %literals.Spacechar