maruku 0.3.0 → 0.4.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 (108) hide show
  1. data/bin/{maruku0.3 → marudown} +6 -14
  2. data/bin/maruku +1 -1
  3. data/bin/marutest +37 -9
  4. data/docs/TOFIX.html +22 -0
  5. data/docs/TOFIX.md +3 -0
  6. data/docs/changelog-0.2.13.html +30 -0
  7. data/docs/changelog-0.2.13.md +6 -0
  8. data/docs/changelog-0.3.html +19 -5
  9. data/docs/faq.html +51 -40
  10. data/docs/faq.md +3 -3
  11. data/docs/hidden_o_n_squared.md +10 -0
  12. data/docs/index.html +84 -396
  13. data/docs/markdown_syntax.html +139 -330
  14. data/docs/markdown_syntax.md +80 -93
  15. data/docs/maruku.html +84 -396
  16. data/docs/maruku.md +88 -158
  17. data/docs/proposal.html +13 -106
  18. data/docs/proposal.md +3 -3
  19. data/docs/todo.html +38 -28
  20. data/lib/maruku.rb +77 -11
  21. data/lib/maruku/attributes.rb +186 -0
  22. data/lib/maruku/defaults.rb +40 -0
  23. data/lib/maruku/errors_management.rb +55 -39
  24. data/lib/maruku/helpers.rb +156 -72
  25. data/lib/maruku/input/charsource.rb +319 -0
  26. data/lib/maruku/{html_helper.rb → input/html_helper.rb} +30 -9
  27. data/lib/maruku/input/linesource.rb +111 -0
  28. data/lib/maruku/input/parse_block.rb +562 -0
  29. data/lib/maruku/{parse_doc.rb → input/parse_doc.rb} +60 -28
  30. data/lib/maruku/{parse_span_better.rb → input/parse_span_better.rb} +226 -256
  31. data/lib/maruku/input/type_detection.rb +137 -0
  32. data/lib/maruku/maruku.rb +33 -0
  33. data/lib/maruku/{to_html.rb → output/to_html.rb} +151 -132
  34. data/lib/maruku/{to_latex.rb → output/to_latex.rb} +31 -35
  35. data/lib/maruku/{to_latex_entities.rb → output/to_latex_entities.rb} +25 -3
  36. data/lib/maruku/output/to_latex_strings.rb +64 -0
  37. data/lib/maruku/output/to_markdown.rb +164 -0
  38. data/lib/maruku/{to_s.rb → output/to_s.rb} +6 -0
  39. data/lib/maruku/string_utils.rb +12 -181
  40. data/lib/maruku/structures.rb +91 -67
  41. data/lib/maruku/structures_inspect.rb +78 -0
  42. data/lib/maruku/structures_iterators.rb +24 -2
  43. data/lib/maruku/tests/benchmark.rb +41 -9
  44. data/lib/maruku/tests/new_parser.rb +317 -286
  45. data/lib/maruku/tests/tests.rb +20 -0
  46. data/lib/maruku/toc.rb +64 -64
  47. data/lib/maruku/usage/example1.rb +33 -0
  48. data/lib/maruku/version.rb +8 -2
  49. data/tests/unittest/abbreviations.md +27 -16
  50. data/tests/unittest/attributes/attributes.md +89 -0
  51. data/tests/unittest/attributes/circular.md +51 -0
  52. data/tests/unittest/attributes/default.md +47 -0
  53. data/tests/unittest/blank.md +10 -6
  54. data/tests/unittest/blanks_in_code.md +26 -26
  55. data/tests/unittest/code.md +9 -9
  56. data/tests/unittest/code2.md +12 -13
  57. data/tests/unittest/code3.md +34 -34
  58. data/tests/unittest/easy.md +9 -7
  59. data/tests/unittest/email.md +9 -7
  60. data/tests/unittest/encoding/iso-8859-1.md +41 -4
  61. data/tests/unittest/encoding/utf-8.md +6 -5
  62. data/tests/unittest/entities.md +52 -80
  63. data/tests/unittest/escaping.md +47 -35
  64. data/tests/unittest/extra_dl.md +19 -29
  65. data/tests/unittest/extra_header_id.md +31 -24
  66. data/tests/unittest/extra_table1.md +14 -32
  67. data/tests/unittest/footnotes.md +58 -42
  68. data/tests/unittest/headers.md +11 -11
  69. data/tests/unittest/hrule.md +14 -24
  70. data/tests/unittest/images.md +41 -26
  71. data/tests/unittest/inline_html.md +104 -56
  72. data/tests/unittest/inline_html2.md +38 -0
  73. data/tests/unittest/links.md +74 -33
  74. data/tests/unittest/list1.md +18 -15
  75. data/tests/unittest/list2.md +31 -13
  76. data/tests/unittest/list3.md +29 -28
  77. data/tests/unittest/list4.md +103 -12
  78. data/tests/unittest/lists.md +86 -53
  79. data/tests/unittest/lists6.md +53 -0
  80. data/tests/unittest/lists7.md +31 -0
  81. data/tests/unittest/lists_after_paragraph.md +105 -71
  82. data/tests/unittest/lists_ol.md +149 -73
  83. data/tests/unittest/misc_sw.md +366 -326
  84. data/tests/unittest/notyet/escape.md +10 -10
  85. data/tests/unittest/notyet/header_after_par.md +20 -14
  86. data/tests/unittest/notyet/ticks.md +8 -35
  87. data/tests/unittest/notyet/triggering.md +72 -45
  88. data/tests/unittest/olist.md +78 -0
  89. data/tests/unittest/one.md +5 -3
  90. data/tests/unittest/paragraph.md +5 -3
  91. data/tests/unittest/paragraph_rules/dont_merge_ref.md +15 -9
  92. data/tests/unittest/paragraph_rules/tab_is_blank.md +9 -5
  93. data/tests/unittest/paragraphs.md +21 -26
  94. data/tests/unittest/recover/recover_links.md +6 -5
  95. data/tests/unittest/references/long_example.md +39 -30
  96. data/tests/unittest/references/spaces_and_numbers.md +2 -2
  97. data/tests/unittest/syntax_hl.md +33 -31
  98. data/tests/unittest/test.md +4 -6
  99. data/tests/unittest/wrapping.md +43 -26
  100. metadata +160 -139
  101. data/docs/markdown_extra2.html +0 -87
  102. data/docs/markdown_extra2.md +0 -83
  103. data/docs/markdown_syntax_2.html +0 -152
  104. data/lib/maruku/parse_block.rb +0 -564
  105. data/lib/maruku/parse_span.rb +0 -451
  106. data/lib/maruku/to_latex_strings.rb +0 -59
  107. data/lib/maruku/to_markdown.rb +0 -110
  108. data/lib/test.rb +0 -29
@@ -1,75 +1,91 @@
1
-
2
-
3
- # Any method that detects formatting error calls the
4
- # error() method.
5
- # if @meta[:on_error] ==
6
- #
7
- # - :warning write on the standard err (or @error_stream if defined),
8
- # then do your best.
9
- # - :ignore be shy and try to continue
10
- # - :raise raises a MarukuException
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
11
3
  #
12
- # default is :raise
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
13
21
 
14
- class MarukuException < RuntimeError
15
-
16
- end
17
22
 
23
+ #m Any method that detects formatting error calls the
24
+ #m maruku_error() method.
25
+ #m if @meta[:on_error] ==
26
+ #m
27
+ #m - :warning write on the standard err (or @error_stream if defined),
28
+ #m then do your best.
29
+ #m - :ignore be shy and try to continue
30
+ #m - :raise raises a MarukuException
31
+ #m
32
+ #m default is :raise
18
33
 
19
- module MarukuErrors
34
+ module MaRuKu
35
+
36
+ class Exception < RuntimeError
37
+ end
38
+
39
+ module Errors
20
40
  Default_on_error = :warning
21
41
 
22
42
  def maruku_error(s,src=nil,con=nil)
23
- policy = @doc ? (@doc.meta[:on_error] || Default_on_error) : :raise
43
+ policy = @doc ? (@doc.attributes[:on_error] || Default_on_error) : :raise
24
44
 
25
45
  case policy
26
46
  when :ignore
27
47
  when :raise
28
- raise_error describe_error(s,src,con)
48
+ raise_error create_frame(describe_error(s,src,con))
29
49
  when :warning
30
- tell_user describe_error(s,src,con)
50
+ tell_user create_frame(describe_error(s,src,con))
31
51
  end
32
52
  end
33
53
 
54
+ def maruku_recover(s,src=nil,con=nil)
55
+ tell_user create_frame(describe_error(s,src,con))
56
+ end
57
+
34
58
  alias error maruku_error
35
59
 
36
60
  def raise_error(s)
37
- raise MarukuException, s, caller
61
+ raise MaRuKu::Exception, s, caller
38
62
  end
39
63
 
40
64
  def tell_user(s)
65
+ error_stream = self.attributes[:error_stream] || $stderr
66
+ error_stream << s
67
+ end
68
+
69
+ def create_frame(s)
41
70
  n = 75
42
- (@error_stream || $stderr) <<
71
+ "\n" +
43
72
  " "+"_"*n << "\n"<<
44
- "| Maruku tells you (#{caller[0]})\n" <<
73
+ "| Maruku tells you:\n" <<
45
74
  "+"+"-"*n +"\n"+
46
75
  add_tabs(s,1,'| ') << "\n" <<
47
76
  "+" << "-"*n << "\n" <<
48
- add_tabs(caller.join("\n"),1,'!') << "\n" <<
77
+ add_tabs(caller[0, 5].join("\n"),1,'!') << "\n" <<
49
78
  "\\" << "_"*n << "\n"
50
79
  end
51
-
52
- def set_error_stream(os)
53
- @error_stream = os
54
- end
55
80
 
56
81
  def describe_error(s,src,con)
57
82
  t = s
58
- if src
59
- t += "\n#{src.describe}\n"
60
- end
61
- if con
62
- t += "\n#{con.describe}\n"
63
- end
83
+ src && (t += "\n#{src.describe}\n")
84
+ con && (t += "\n#{con.describe}\n")
64
85
  t
65
86
  end
66
87
 
67
- end
68
-
69
- class MDElement
70
- include MarukuErrors
71
- end
72
-
73
-
88
+ end # Errors
89
+ end # MaRuKu
74
90
 
75
91
 
@@ -1,160 +1,244 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+
23
+
24
+ # A series of helper functions for creating elements: they hide the
25
+ # particular internal representation.
26
+ #
27
+ # Please, always use these instead of creating MDElement.
28
+ #
29
+
30
+ module MaRuKu
31
+ module Helpers
1
32
 
33
+ def md_el(node_type, children=[], meta={}, al=nil)
34
+ e = MDElement.new(node_type, children, meta, al)
35
+ e.doc = self
36
+ return e
37
+ end
2
38
 
3
- # A series of helper functions for creating elements
39
+ def md_header(level, children, al=nil)
40
+ md_el(:header, children, {:level => level}, al)
41
+ end
42
+
43
+ # Inline code
44
+ def md_code(code, al=nil)
45
+ md_el(:inline_code, [], {:raw_code => code}, al)
46
+ end
4
47
 
5
- module Helpers
48
+ # Code block
49
+ def md_codeblock(source, al=nil)
50
+ md_el(:code, [], {:raw_code => source}, al)
51
+ end
6
52
 
7
- def md_el(node_type, children=[], meta={})
8
- e=MDElement.new(node_type, children, meta)
9
- e.doc = self
10
- e
53
+ def md_quote(children, al=nil)
54
+ md_el(:quote, children, {}, al)
55
+ end
56
+
57
+ def md_li(children, want_my_par, al=nil)
58
+ md_el(:li, children, {:want_my_paragraph=>want_my_par}, al)
11
59
  end
12
60
 
13
- def md_code(code)
14
- md_el(:inline_code, [], {:raw_code => code})
61
+ def md_footnote(footnote_id, children, al=nil)
62
+ md_el(:footnote, children, {:footnote_id=>footnote_id}, al)
15
63
  end
16
64
 
17
- def md_par(children, meta={})
18
- md_el(:paragraph, [], meta)
65
+ def md_abbr_def(abbr, text, al=nil)
66
+ md_el(:abbr_def, [], {:abbr=>abbr, :text=>text}, al)
67
+ end
68
+
69
+ def md_abbr(abbr, title)
70
+ md_el(:abbr, [abbr], {:title=>title})
19
71
  end
20
72
 
21
- def md_html(raw_html)
73
+ def md_html(raw_html, al=nil)
22
74
  e = md_el(:raw_html, [], {:raw_html=>raw_html})
23
75
  begin
24
76
  # remove newlines and whitespace at begin
25
77
  # end end of string, or else REXML gets confused
26
78
  raw_html = raw_html.gsub(/\A\s*</,'<').
27
79
  gsub(/>[\s\n]*\Z/,'>')
80
+
81
+ raw_html = "<marukuwrap>#{raw_html}</marukuwrap>"
28
82
  e.instance_variable_set :@parsed_html,
29
83
  REXML::Document.new(raw_html)
30
-
31
- rescue Exception => ex
32
- tell_user "Malformed block of HTML:\n"+
33
- add_tabs(raw_html,1,'|')
84
+ rescue
85
+ # tell_user "Malformed block of HTML:\n"+
86
+ # add_tabs(raw_html,1,'|')
34
87
  # " #{raw_html.inspect}\n\n"+ex.inspect
35
88
  end
36
89
  e
37
90
  end
38
91
 
39
- def md_link(children, ref_id)
40
- md_el(:link, children, {:ref_id=>ref_id.downcase})
92
+ def md_link(children, ref_id, al=nil)
93
+ md_el(:link, children, {:ref_id=>ref_id.downcase}, al)
41
94
  end
42
95
 
43
- def md_im_link(children, url, title=nil)
44
- md_el(:link, children, {:url=>url,:title=>title})
96
+ def md_im_link(children, url, title=nil, al=nil)
97
+ md_el(:im_link, children, {:url=>url,:title=>title}, al)
45
98
  end
46
99
 
47
-
48
- def md_image(children, ref_id)
49
- md_el(:image, children, {:ref_id=>ref_id})
100
+ def md_image(children, ref_id, al=nil)
101
+ md_el(:image, children, {:ref_id=>ref_id}, al)
50
102
  end
51
103
 
52
- def md_im_image(children, url, title=nil)
53
- md_el(:image, children, {:url=>url,:title=>title})
104
+ def md_im_image(children, url, title=nil, al=nil)
105
+ md_el(:im_image, children, {:url=>url,:title=>title},al)
54
106
  end
55
107
 
56
- def md_em(children)
57
- md_el(:emphasis, [children].flatten)
108
+ def md_em(children, al=nil)
109
+ md_el(:emphasis, [children].flatten, {}, al)
58
110
  end
59
111
 
60
- def md_strong(children)
61
- md_el(:strong, [children].flatten)
112
+ def md_br()
113
+ md_el(:linebreak, [], {}, nil)
62
114
  end
63
115
 
64
- def md_emstrong(children)
65
- md_strong(md_em(children))
116
+ def md_hrule()
117
+ md_el(:hrule, [], {}, nil)
118
+ end
119
+
120
+ def md_strong(children, al=nil)
121
+ md_el(:strong, [children].flatten, {}, al)
122
+ end
123
+
124
+ def md_emstrong(children, al=nil)
125
+ md_strong(md_em(children), al)
66
126
  end
67
127
 
68
128
  # <http://www.example.com/>
69
- def md_url(url)
70
- md_el(:immediate_link, [], {:url=>url})
129
+ def md_url(url, al=nil)
130
+ md_el(:immediate_link, [], {:url=>url}, al)
71
131
  end
72
132
 
73
133
  # <andrea@rubyforge.org>
74
134
  # <mailto:andrea@rubyforge.org>
75
- def md_email(email)
76
- md_el(:email_address, [], {:email=>email})
135
+ def md_email(email, al=nil)
136
+ md_el(:email_address, [], {:email=>email}, al)
77
137
  end
78
138
 
79
- def md_entity(entity_name)
80
- md_el(:entity, [], {:entity_name=>entity_name})
139
+ def md_entity(entity_name, al=nil)
140
+ md_el(:entity, [], {:entity_name=>entity_name}, al)
81
141
  end
82
142
 
83
143
  # Markdown extra
84
- def md_foot_ref(ref_id)
85
- md_el(:footnote_reference, [], {:footnote_id=>ref_id})
144
+ def md_foot_ref(ref_id, al=nil)
145
+ md_el(:footnote_reference, [], {:footnote_id=>ref_id}, al)
86
146
  end
87
147
 
88
- def md_par(children, meta={})
89
- md_el(:paragraph, children, meta)
148
+ def md_par(children, al=nil)
149
+ md_el(:paragraph, children, meta={}, al)
90
150
  end
91
151
 
92
152
  # [1]: http://url [properties]
93
- def md_ref_def(ref_id, url, title=nil, meta={})
153
+ def md_ref_def(ref_id, url, title=nil, meta={}, al=nil)
94
154
  meta[:url] = url
95
155
  meta[:ref_id] = ref_id
96
156
  meta[:title] = title if title
97
- md_el(:ref_definition, [], meta)
157
+ md_el(:ref_definition, [], meta, al)
158
+ end
159
+
160
+ # inline attribute list
161
+ def md_ial(al)
162
+ al = Maruku::AttributeList.new(al) if
163
+ not al.kind_of?Maruku::AttributeList
164
+ md_el(:ial, [], {:ial=>al})
165
+ end
166
+
167
+ # Attribute list definition
168
+ def md_ald(id, al)
169
+ md_el(:ald, [], {:ald_id=>id,:ald=>al})
170
+ end
171
+
172
+ # Server directive <? code ?>
173
+ def md_server(code)
174
+ md_el(:server, [], {:code=>code})
98
175
  end
99
176
  end
177
+ end
178
+
179
+ module MaRuKu
100
180
 
101
181
  class MDElement
102
- # outputs abbreviated form
182
+ # outputs abbreviated form (this should be eval()uable to get the document)
103
183
  def inspect2
184
+ s =
104
185
  case @node_type
105
186
  when :paragraph
106
187
  "md_par(%s)" % children_inspect
107
188
  when :footnote_reference
108
- "md_foot_ref(%s)" % @meta[:footnote_id].inspect
189
+ "md_foot_ref(%s)" % self.footnote_id.inspect
109
190
  when :entity
110
- "md_entity(%s)" % @meta[:entity_name].inspect
191
+ "md_entity(%s)" % self.entity_name.inspect
111
192
  when :email_address
112
- "md_email(%s)" % @meta[:email].inspect
193
+ "md_email(%s)" % self.email.inspect
113
194
  when :inline_code
114
- "md_code(%s)" % @meta[:raw_code].inspect
195
+ "md_code(%s)" % self.raw_code.inspect
115
196
  when :raw_html
116
- "md_html(%s)" % @meta[:raw_html].inspect
197
+ "md_html(%s)" % self.raw_html.inspect
117
198
  when :emphasis
118
199
  "md_em(%s)" % children_inspect
119
200
  when :strong
120
201
  "md_strong(%s)" % children_inspect
121
202
  when :immediate_link
122
- "md_url(%s)" % @meta[:url].inspect
203
+ "md_url(%s)" % self.url.inspect
123
204
  when :image
124
- if @meta[:ref_id]
125
- "md_image(%s,%s)" % [
126
- children_inspect, @meta[:ref_id].inspect]
127
- else
128
- "md_im_image(%s, %s %s)" % [
129
- children_inspect, @meta[:url].inspect,
130
- (title=@meta[:title]) ? (", "+ title.inspect) : ""
131
- ]
132
- end
205
+ "md_image(%s, %s)" % [
206
+ children_inspect,
207
+ self.ref_id.inspect]
208
+ when :im_image
209
+ "md_im_image(%s, %s, %s)" % [
210
+ children_inspect,
211
+ self.url.inspect,
212
+ self.title.inspect]
133
213
  when :link
134
- if @meta[:ref_id]
135
214
  "md_link(%s,%s)" % [
136
- children_inspect, @meta[:ref_id].inspect]
137
- else
138
- "md_im_link(%s, %s %s)" % [
139
- children_inspect, @meta[:url].inspect,
140
- (title=@meta[:title]) ? (", "+ title.inspect) : ""
215
+ children_inspect, self.ref_id.inspect]
216
+ when :im_link
217
+ "md_im_link(%s, %s, %s)" % [
218
+ children_inspect,
219
+ self.url.inspect,
220
+ self.title.inspect,
141
221
  ]
142
- end
143
222
  when :ref_definition
144
- "md_ref_def(%s, %s %s)" %
145
- [
146
- @meta[:ref_id].inspect,
147
- @meta[:url].inspect,
148
- @meta[:title] ? ","+@meta[:title].inspect : ""
223
+ "md_ref_def(%s, %s, %s)" % [
224
+ self.ref_id.inspect,
225
+ self.url.inspect,
226
+ self.title.inspect
149
227
  ]
228
+ when :ial
229
+ "md_ial(%s)" % self.ial.inspect
150
230
  else
151
- nil
231
+ return nil
232
+ end
233
+ if @al and not @al.empty? then
234
+ s = s.chop + ", #{@al.inspect})"
152
235
  end
236
+ s
153
237
  end
154
238
 
155
239
  end
156
240
 
157
-
241
+ end
158
242
 
159
243
 
160
244
 
@@ -0,0 +1,319 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+ module MaRuKu; module In; module Markdown; module SpanLevelParser
23
+
24
+ # a string scanner coded by me
25
+ class CharSourceManual; end
26
+
27
+ # a wrapper around StringScanner
28
+ class CharSourceStrscan; end
29
+
30
+ # A debug scanner that checks the correctness of both
31
+ # by comparing their output
32
+ class CharSourceDebug; end
33
+
34
+ # Choose!
35
+
36
+ #CharSource = CharSourceStrscan
37
+ CharSource = CharSourceManual # faster! 58ms vs. 65ms
38
+ #CharSource = CharSourceDebug
39
+
40
+
41
+ class CharSourceManual
42
+ include MaRuKu::Strings
43
+
44
+ def initialize(s)
45
+ @buffer = s
46
+ @buffer_index = 0
47
+ end
48
+
49
+ # Return current char as a FixNum (or nil).
50
+ def cur_char; @buffer[@buffer_index] end
51
+
52
+ # Return the next n chars as a String.
53
+ def cur_chars(n); @buffer[@buffer_index,n] end
54
+
55
+ # Return the char after current char as a FixNum (or nil).
56
+ def next_char; @buffer[@buffer_index+1] end
57
+
58
+ def shift_char
59
+ c = @buffer[@buffer_index]
60
+ @buffer_index+=1
61
+ c
62
+ end
63
+
64
+ def ignore_char
65
+ @buffer_index+=1
66
+ nil
67
+ end
68
+
69
+ def ignore_chars(n)
70
+ @buffer_index+=n
71
+ nil
72
+ end
73
+
74
+ def current_remaining_buffer
75
+ @buffer[@buffer_index, @buffer.size-@buffer_index]
76
+ end
77
+
78
+ def cur_chars_are(string)
79
+ # There is a bug here
80
+ if false
81
+ r2 = /^.{#{@buffer_index}}#{Regexp.escape string}/m
82
+ @buffer =~ r2
83
+ else
84
+ cur_chars(string.size) == string
85
+ end
86
+ end
87
+
88
+ def next_matches(r)
89
+ r2 = /^.{#{@buffer_index}}#{r}/m
90
+ md = r2.match @buffer
91
+ return !!md
92
+ end
93
+
94
+ def read_regexp3(r)
95
+ r2 = /^.{#{@buffer_index}}#{r}/m
96
+ m = r2.match @buffer
97
+ if m
98
+ consumed = m.to_s.size - @buffer_index
99
+ # puts "Consumed #{consumed} chars (entire is #{m.to_s.inspect})"
100
+ ignore_chars consumed
101
+ else
102
+ # puts "Could not read regexp #{r2.inspect} from buffer "+
103
+ # " index=#{@buffer_index}"
104
+ # puts "Cur chars = #{cur_chars(20).inspect}"
105
+ # puts "Matches? = #{cur_chars(20) =~ r}"
106
+ end
107
+ m
108
+ end
109
+
110
+ def read_regexp(r)
111
+ r2 = /^#{r}/
112
+ rest = current_remaining_buffer
113
+ m = r2.match(rest)
114
+ if m
115
+ @buffer_index += m.to_s.size
116
+ # puts "#{r} matched #{rest.inspect}: #{m.to_s.inspect}"
117
+ end
118
+ return m
119
+ end
120
+
121
+ def consume_whitespace
122
+ while c = cur_char
123
+ if (c == 32 || c == ?\t)
124
+ # puts "ignoring #{c}"
125
+ ignore_char
126
+ else
127
+ # puts "#{c} is not ws: "<<c
128
+ break
129
+ end
130
+ end
131
+ end
132
+
133
+ def read_text_chars(out)
134
+ s = @buffer.size; c=nil
135
+ while @buffer_index < s && (c=@buffer[@buffer_index]) &&
136
+ ((c>=?a && c<=?z) || (c>=?A && c<=?Z))
137
+ out << c
138
+ @buffer_index += 1
139
+ end
140
+ end
141
+
142
+ def describe
143
+ describe_pos(@buffer, @buffer_index)
144
+ end
145
+ include SpanLevelParser
146
+ end
147
+
148
+ def describe_pos(buffer, buffer_index)
149
+ len = 75
150
+ num_before = [len/2, buffer_index].min
151
+ num_after = [len/2, buffer.size-buffer_index].min
152
+ num_before_max = buffer_index
153
+ num_after_max = buffer.size-buffer_index
154
+
155
+ # puts "num #{num_before} #{num_after}"
156
+ num_before = [num_before_max, len-num_after].min
157
+ num_after = [num_after_max, len-num_before].min
158
+ # puts "num #{num_before} #{num_after}"
159
+
160
+ index_start = [buffer_index - num_before, 0].max
161
+ index_end = [buffer_index + num_after, buffer.size].min
162
+
163
+ size = index_end- index_start
164
+
165
+ # puts "- #{index_start} #{size}"
166
+
167
+ str = buffer[index_start, size]
168
+ str.gsub!("\n",'N')
169
+ str.gsub!("\t",'T')
170
+
171
+ if index_end == buffer.size
172
+ str += "EOF"
173
+ end
174
+
175
+ pre_s = buffer_index-index_start
176
+ pre_s = [pre_s, 0].max
177
+ pre_s2 = [len-pre_s,0].max
178
+ # puts "pre_S = #{pre_s}"
179
+ pre =" "*(pre_s)
180
+
181
+ "-"*len+"\n"+
182
+ str + "\n" +
183
+ "-"*pre_s + "|" + "-"*(pre_s2)+"\n"+
184
+ # pre + "|\n"+
185
+ pre + "+--- Byte #{buffer_index}\n"+
186
+
187
+ "Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+
188
+ add_tabs(buffer,1,">")
189
+
190
+ # "CharSource: At character #{@buffer_index} of block "+
191
+ # " beginning with:\n #{@buffer[0,50].inspect} ...\n"+
192
+ # " before: \n ... #{cur_chars(50).inspect} ... "
193
+ end
194
+
195
+
196
+ require 'strscan'
197
+
198
+ class CharSourceStrscan
199
+ include SpanLevelParser
200
+ include MaRuKu::Strings
201
+
202
+ def initialize(s)
203
+ @s = StringScanner.new(s)
204
+ end
205
+
206
+ # Return current char as a FixNum (or nil).
207
+ def cur_char
208
+ @s.peek(1)[0]
209
+ end
210
+
211
+ # Return the next n chars as a String.
212
+ def cur_chars(n);
213
+ @s.peek(n)
214
+ end
215
+
216
+ # Return the char after current char as a FixNum (or nil).
217
+ def next_char;
218
+ @s.peek(2)[1]
219
+ end
220
+
221
+ def shift_char
222
+ (@s.get_byte)[0]
223
+ end
224
+
225
+ def ignore_char
226
+ @s.get_byte
227
+ nil
228
+ end
229
+
230
+ def ignore_chars(n)
231
+ n.times do @s.get_byte end
232
+ nil
233
+ end
234
+
235
+ def current_remaining_buffer
236
+ @s.rest #nil #@buffer[@buffer_index, @buffer.size-@buffer_index]
237
+ end
238
+
239
+ def cur_chars_are(string)
240
+ cur_chars(string.size) == string
241
+ end
242
+
243
+ def next_matches(r)
244
+ len = @s.match?(r)
245
+ return !!len
246
+ end
247
+
248
+ def read_regexp(r)
249
+ string = @s.scan(r)
250
+ if string
251
+ return r.match(string)
252
+ else
253
+ return nil
254
+ end
255
+ end
256
+
257
+ def consume_whitespace
258
+ @s.scan /\s+/
259
+ nil
260
+ end
261
+
262
+ def describe
263
+ describe_pos(@s.string, @s.pos)
264
+ end
265
+
266
+ end
267
+
268
+
269
+ class CharSourceDebug
270
+ def initialize(s)
271
+ @a = CharSourceManual.new(s)
272
+ @b = CharSourceStrscan.new(s)
273
+ end
274
+
275
+ def method_missing(methodname, *args)
276
+ a_bef = @a.describe
277
+ b_bef = @b.describe
278
+
279
+ a = @a.send(methodname, *args)
280
+ b = @b.send(methodname, *args)
281
+
282
+ # if methodname == :describe
283
+ # return a
284
+ # end
285
+
286
+ if a.kind_of? MatchData
287
+ if a.to_a != b.to_a
288
+ puts "called: #{methodname}(#{args})"
289
+ puts "Matchdata:\na = #{a.to_a.inspect}\nb = #{b.to_a.inspect}"
290
+ puts "AFTER: "+@a.describe
291
+ puts "AFTER: "+@b.describe
292
+ puts "BEFORE: "+a_bef
293
+ puts "BEFORE: "+b_bef
294
+ puts caller.join("\n")
295
+ exit
296
+ end
297
+ else
298
+ if a!=b
299
+ puts "called: #{methodname}(#{args})"
300
+ puts "Attenzione!\na = #{a.inspect}\nb = #{b.inspect}"
301
+ puts ""+@a.describe
302
+ puts ""+@b.describe
303
+ puts caller.join("\n")
304
+ exit
305
+ end
306
+ end
307
+
308
+ if @a.cur_char != @b.cur_char
309
+ puts "Fuori sincronia dopo #{methodname}(#{args})"
310
+ puts ""+@a.describe
311
+ puts ""+@b.describe
312
+ exit
313
+ end
314
+
315
+ return a
316
+ end
317
+ end
318
+
319
+ end end end end