review-peg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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