math_ml 0.13 → 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.
data/lib/math_ml/util.rb CHANGED
@@ -6,345 +6,356 @@
6
6
  # You can redistribute it and/or modify it under GPL2.
7
7
  #
8
8
 
9
- require "math_ml"
9
+ require 'math_ml'
10
10
 
11
11
  module MathML::Util
12
- ESCAPES = {"<"=>"lt",
13
- ">"=>"gt",
14
- "&"=>"amp",
15
- "\""=>"quot",
16
- "'"=>"apos"
17
- }
18
- INVALID_RE = /(?!)/
19
- EQNARRAY_RE = /\\begin\s*\{eqnarray\}(#{MathML::LaTeX::MBEC}*?)\\end\s*\{eqnarray\}/
20
- SINGLE_COMMAND_RE = /(\\([a-zA-Z]+))[ \t]?/
21
-
22
- def self.escapeXML(s, br=false)
23
- r = s.gsub(/[<>&"']/){|m| "&#{ESCAPES[m]};"}
24
- br ? r.gsub(/\n/, "<br />\n") : r
25
- end
26
-
27
- def escapeXML(s, br=false)
28
- MathML::Util.escapeXML(s, br)
29
- end
30
-
31
- def self.collect_regexp(a)
32
- if a
33
- a = [a].flatten
34
- a.size>0 ? Regexp.new(a.inject(""){|r, i| i.is_a?(Regexp) ? "#{r}#{i.to_s}|" : r}.chop) : INVALID_RE
35
- else
36
- INVALID_RE
37
- end
38
- end
39
-
40
- def collect_regexp(a)
41
- MathML::Util.collect_regexp(a)
42
- end
43
-
44
- class MathData
45
- attr_reader :math_list, :msrc_list, :dmath_list, :dsrc_list, :escape_list, :esrc_list, :user_list, :usrc_list
46
- def initialize
47
- @math_list = []
48
- @msrc_list = []
49
- @dmath_list = []
50
- @dsrc_list = []
51
- @escape_list = []
52
- @esrc_list = []
53
- @user_list = []
54
- @usrc_list = []
55
- end
56
-
57
- def update(s)
58
- @math_list.concat(s.math_list)
59
- @msrc_list.concat(s.msrc_list)
60
- @dmath_list.concat(s.dmath_list)
61
- @dsrc_list.concat(s.dsrc_list)
62
- @escape_list.concat(s.escape_list)
63
- @esrc_list.concat(s.esrc_list)
64
- @user_list.concat(s.user_list)
65
- @usrc_list.concat(s.usrc_list)
66
- end
67
- end
68
-
69
- class SimpleLaTeX
70
- include MathML::Util
71
- @@default_latex = nil
72
- DEFAULT = {
73
- :delimiter=>"\001",
74
- :math_env_list=>[
75
- /\$((?:\\.|[^\\\$])#{MathML::LaTeX::MBEC}*?)\$/m,
76
- /\\\((#{MathML::LaTeX::MBEC}*?)\\\)/m
77
- ],
78
- :dmath_env_list=>[
79
- /\$\$(#{MathML::LaTeX::MBEC}*?)\$\$/m,
80
- /\\\[(#{MathML::LaTeX::MBEC}*?)\\\]/m
81
- ],
82
- :escape_list=>[
83
- /\\(.)/m
84
- ],
85
- :through_list=>[
86
- ],
87
- :escape_any=> false,
88
- :without_parse=>false
89
- }
90
-
91
- def initialize(options = {})
92
- @params = DEFAULT.merge(options)
93
- @params[:parser] = MathML::LaTeX::Parser.new unless @params[:parser] || @params[:without_parse]
94
-
95
- @params[:math_envs] = collect_regexp(@params[:math_env_list])
96
- @params[:dmath_envs] = collect_regexp(@params[:dmath_env_list])
97
- @params[:escapes] = collect_regexp(@params[:escape_list])
98
- @params[:throughs] = collect_regexp(@params[:through_list])
99
- reset_encode_proc
100
- reset_rescue_proc
101
- reset_decode_proc
102
- reset_unencode_proc
103
- end
104
-
105
- def reset_encode_proc
106
- @encode_proc_re = INVALID_RE
107
- @encode_proc = nil
108
- end
109
-
110
- def set_encode_proc(*re, &proc)
111
- @encode_proc_re = collect_regexp(re)
112
- @encode_proc = proc
113
- end
114
-
115
- def reset_rescue_proc
116
- @rescue_proc = nil
117
- end
118
-
119
- def set_rescue_proc(&proc)
120
- @rescue_proc = proc
121
- end
122
-
123
- def reset_decode_proc
124
- @decode_proc = nil
125
- end
126
-
127
- def set_decode_proc(&proc)
128
- @decode_proc = proc
129
- end
130
-
131
- def set_unencode_proc(&proc)
132
- @unencode_proc = proc
133
- end
134
-
135
- def reset_unencode_proc
136
- @unencode_proc = nil
137
- end
138
-
139
- def encode(src, *proc_re, &proc)
140
- if proc_re.size>0 && proc_re[0].is_a?(MathData)
141
- data = proc_re.shift
142
- else
143
- data = MathData.new
144
- end
145
-
146
- proc_re = proc_re.size==0 ? @encode_proc_re : collect_regexp(proc_re)
147
- proc = @encode_proc unless proc
148
-
149
- s = StringScanner.new(src)
150
- encoded = ""
151
-
152
- until s.eos?
153
- if s.scan(/(.*?)(((((#{@params[:throughs]})|#{@params[:dmath_envs]})|#{@params[:math_envs]})|#{proc_re})|#{@params[:escapes]})/m)
154
- encoded << s[1]
155
- case
156
- when s[6]
157
- encoded << s[6]
158
- when s[5], s[4]
159
- env_src = s[5] || s[4]
160
- if @params[:dmath_envs]=~env_src
161
- encoded << "#{@params[:delimiter]}d#{data.dsrc_list.size}#{@params[:delimiter]}"
162
- data.dsrc_list << env_src
163
- else
164
- encoded << "#{@params[:delimiter]}m#{data.msrc_list.size}#{@params[:delimiter]}"
165
- data.msrc_list << env_src
166
- end
167
- when s[3]
168
- size = s[3].size
169
- s.pos = left = s.pos-size
170
- if r=proc.call(s)
171
- right = s.pos
172
- encoded << "#{@params[:delimiter]}u#{data.user_list.size}#{@params[:delimiter]}"
173
- data.user_list << r
174
- data.usrc_list << s.string[left...right]
175
- else
176
- encoded << s.peek(size)
177
- s.pos = s.pos+size
178
- end
179
- when s[2]
180
- encoded << "#{@params[:delimiter]}e#{data.escape_list.size}#{@params[:delimiter]}"
181
- @params[:escapes]=~s[2]
182
- data.esrc_list << s[2]
183
- data.escape_list << escapeXML($+, true)
184
- end
185
- else
186
- encoded << s.rest
187
- s.terminate
188
- end
189
- end
190
-
191
- parse(data, @params[:parser]) unless @params[:without_parse]
192
-
193
- return encoded, data
194
- end
195
-
196
- def error_to_html(e)
197
- "<br />\n#{escapeXML(e.message)}<br />\n<code>#{escapeXML(e.done).gsub(/\n/, "<br />\n")}<strong>#{escapeXML(e.rest).gsub(/\n/, "<br />\n")}</strong></code><br />"
198
- end
199
-
200
- def latex_parser
201
- @params[:parser] = MathML::LaTeX::Parser.new unless @params[:parser]
202
- @params[:parser]
203
- end
204
-
205
- def parse(data, parser=nil)
206
- parser = latex_parser unless parser
207
- (data.math_list.size...data.msrc_list.size).each do |i|
208
- begin
209
- @params[:math_envs]=~data.msrc_list[i]
210
- data.math_list[i] = parser.parse($+)
211
- rescue MathML::LaTeX::ParseError => e
212
- if @rescue_proc
213
- data.math_list[i] = @rescue_proc.call(e)
214
- else
215
- data.math_list[i] = error_to_html(e)
216
- end
217
- end
218
- end
219
- (data.dmath_list.size...data.dsrc_list.size).each do |i|
220
- begin
221
- @params[:dmath_envs]=~data.dsrc_list[i]
222
- data.dmath_list[i] = parser.parse($+, true)
223
- rescue MathML::LaTeX::ParseError => e
224
- if @rescue_proc
225
- data.dmath_list[i] = @rescue_proc.call(e)
226
- else
227
- data.dmath_list[i] = error_to_html(e)
228
- end
229
- end
230
- end
231
- end
232
-
233
- def decode(encoded, data, without_parsed = false, &proc)
234
- return nil if encoded==nil
235
- proc = @decode_proc unless proc
236
- encoded.gsub(/#{Regexp.escape(@params[:delimiter])}([demu])(\d+)#{Regexp.escape(@params[:delimiter])}/) do
237
- i = $2.to_i
238
- t, d, s =
239
- case $1
240
- when "d"
241
- [:dmath, without_parsed ? escapeXML(data.dsrc_list[i], true) : data.dmath_list[i], data.dsrc_list[i]]
242
- when "e"
243
- [:escape, data.escape_list[i], data.esrc_list[i]]
244
- when "m"
245
- [:math, without_parsed ? escapeXML(data.msrc_list[i], true) : data.math_list[i], data.msrc_list[i]]
246
- when "u"
247
- [:user, data.user_list[i], data.usrc_list[i]]
248
- end
249
- if proc
250
- proc.call(d, :type=>t, :index=>i, :src=>s) || d
251
- else
252
- d
253
- end
254
- end
255
- end
256
-
257
- def decode_partial(type, encoded, data, &proc)
258
- return nil if encoded==nil
259
- head =
260
- case type
261
- when :math
262
- "m"
263
- when :dmath
264
- "d"
265
- when :escape
266
- "e"
267
- when :user
268
- "u"
269
- else
270
- return
271
- end
272
- encoded.gsub(/#{Regexp.escape(@params[:delimiter])}#{head}(\d+)#{Regexp.escape(@params[:delimiter])}/) do
273
- i = $1.to_i
274
- t, d, s =
275
- case head
276
- when "d"
277
- [:dmath, data.dmath_list[i], data.dsrc_list[i]]
278
- when "e"
279
- [:escape, data.escape_list[i], data.esrc_list[i]]
280
- when "m"
281
- [:math, data.math_list[i], data.msrc_list[i]]
282
- when "u"
283
- [:user, data.user_list[i], data.usrc_list[i]]
284
- end
285
- if proc
286
- proc.call(d, :type=>t, :index=>i, :src=>s) || "#{@params[:delimiter]}#{head}#{i}#{@params[:delimiter]}"
287
- else
288
- d
289
- end
290
- end
291
- end
292
-
293
- def unencode(encoded, data, without_escape=false, &proc)
294
- return nil if encoded==nil
295
- proc = @unencode_proc unless proc
296
- encoded.gsub(/#{Regexp.escape(@params[:delimiter])}([demu])(\d+)#{Regexp.escape(@params[:delimiter])}/) do
297
- i = $2.to_i
298
- t, s =
299
- case $1
300
- when "d"
301
- [:dmath, data.dsrc_list[i]]
302
- when "e"
303
- [:escape, data.esrc_list[i]]
304
- when "m"
305
- [:math, data.msrc_list[i]]
306
- when "u"
307
- [:user, data.usrc_list[i]]
308
- end
309
- s = escapeXML(s, true) unless without_escape
310
- if proc
311
- proc.call(s, :type=>t, :index=>i) || s
312
- else
313
- s
314
- end
315
- end
316
- end
317
-
318
- def self.encode(src)
319
- @@default_latex = self.new unless @@default_latex
320
- @@default_latex.encode(src)
321
- end
322
-
323
- def self.decode(src, data)
324
- @@default_latex.decode(src, data)
325
- end
326
-
327
- def parse_eqnarray(src, parser=nil)
328
- src = "\\begin{array}{ccc}#{src}\\end{array}"
329
- parser = latex_parser unless parser
330
- begin
331
- parser.parse(src, true)
332
- rescue MathML::LaTeX::ParseError => e
333
- e = MathML::LaTeX::ParseError.new(e.message,
334
- e.rest.sub(/\\end\{array\}\z/, '\end{eqnarray}'),
335
- e.done.sub(/\A\\begin\{array\}\{ccc\}/, '\begin{eqnarray}'))
336
- @rescue_proc ? @rescue_proc.call(e) : error_to_html(e)
337
- end
338
- end
339
-
340
- def parse_single_command(src, parser=nil)
341
- s = src[SINGLE_COMMAND_RE, 1]
342
- parser = latex_parser unless parser
343
- begin
344
- parser.parse(s)
345
- rescue MathML::LaTeX::ParseError => e
346
- src[SINGLE_COMMAND_RE, 2]
347
- end
348
- end
349
- end
12
+ ESCAPES = { '<' => 'lt',
13
+ '>' => 'gt',
14
+ '&' => 'amp',
15
+ '"' => 'quot',
16
+ "'" => 'apos' }
17
+ INVALID_RE = /(?!)/
18
+ EQNARRAY_RE = /\\begin\s*\{eqnarray\}(#{MathML::LaTeX::MBEC}*?)\\end\s*\{eqnarray\}/
19
+ SINGLE_COMMAND_RE = /(\\([a-zA-Z]+))[ \t]?/
20
+
21
+ def self.escapeXML(s, br = false)
22
+ r = s.gsub(/[<>&"']/) { |m| "&#{ESCAPES[m]};" }
23
+ br ? r.gsub(/\n/, "<br />\n") : r
24
+ end
25
+
26
+ def escapeXML(s, br = false)
27
+ MathML::Util.escapeXML(s, br)
28
+ end
29
+
30
+ def self.collect_regexp(a)
31
+ if a
32
+ a = [a].flatten
33
+ if a.size > 0
34
+ Regexp.new(a.inject('') { |r, i| i.is_a?(Regexp) ? "#{r}#{i}|" : r }.chop)
35
+ else
36
+ INVALID_RE
37
+ end
38
+ else
39
+ INVALID_RE
40
+ end
41
+ end
42
+
43
+ def collect_regexp(a)
44
+ MathML::Util.collect_regexp(a)
45
+ end
46
+
47
+ class MathData
48
+ attr_reader :math_list, :msrc_list, :dmath_list, :dsrc_list, :escape_list, :esrc_list, :user_list, :usrc_list
49
+
50
+ def initialize
51
+ @math_list = []
52
+ @msrc_list = []
53
+ @dmath_list = []
54
+ @dsrc_list = []
55
+ @escape_list = []
56
+ @esrc_list = []
57
+ @user_list = []
58
+ @usrc_list = []
59
+ end
60
+
61
+ def update(s)
62
+ @math_list.concat(s.math_list)
63
+ @msrc_list.concat(s.msrc_list)
64
+ @dmath_list.concat(s.dmath_list)
65
+ @dsrc_list.concat(s.dsrc_list)
66
+ @escape_list.concat(s.escape_list)
67
+ @esrc_list.concat(s.esrc_list)
68
+ @user_list.concat(s.user_list)
69
+ @usrc_list.concat(s.usrc_list)
70
+ end
71
+ end
72
+
73
+ class SimpleLaTeX
74
+ include MathML::Util
75
+ @@default_latex = nil
76
+ DEFAULT = {
77
+ delimiter: "\001",
78
+ math_env_list: [
79
+ /\$((?:\\.|[^\\$])#{MathML::LaTeX::MBEC}*?)\$/m,
80
+ /\\\((#{MathML::LaTeX::MBEC}*?)\\\)/m
81
+ ],
82
+ dmath_env_list: [
83
+ /\$\$(#{MathML::LaTeX::MBEC}*?)\$\$/m,
84
+ /\\\[(#{MathML::LaTeX::MBEC}*?)\\\]/m
85
+ ],
86
+ escape_list: [
87
+ /\\(.)/m
88
+ ],
89
+ through_list: [],
90
+ escape_any: false,
91
+ without_parse: false
92
+ }
93
+
94
+ def initialize(options = {})
95
+ @params = DEFAULT.merge(options)
96
+ @params[:parser] = MathML::LaTeX::Parser.new unless @params[:parser] || @params[:without_parse]
97
+
98
+ @params[:math_envs] = collect_regexp(@params[:math_env_list])
99
+ @params[:dmath_envs] = collect_regexp(@params[:dmath_env_list])
100
+ @params[:escapes] = collect_regexp(@params[:escape_list])
101
+ @params[:throughs] = collect_regexp(@params[:through_list])
102
+ reset_encode_proc
103
+ reset_rescue_proc
104
+ reset_decode_proc
105
+ reset_unencode_proc
106
+ end
107
+
108
+ def reset_encode_proc
109
+ @encode_proc_re = INVALID_RE
110
+ @encode_proc = nil
111
+ end
112
+
113
+ def set_encode_proc(*re, &proc)
114
+ @encode_proc_re = collect_regexp(re)
115
+ @encode_proc = proc
116
+ end
117
+
118
+ def reset_rescue_proc
119
+ @rescue_proc = nil
120
+ end
121
+
122
+ def set_rescue_proc(&proc)
123
+ @rescue_proc = proc
124
+ end
125
+
126
+ def reset_decode_proc
127
+ @decode_proc = nil
128
+ end
129
+
130
+ def set_decode_proc(&proc)
131
+ @decode_proc = proc
132
+ end
133
+
134
+ def set_unencode_proc(&proc)
135
+ @unencode_proc = proc
136
+ end
137
+
138
+ def reset_unencode_proc
139
+ @unencode_proc = nil
140
+ end
141
+
142
+ def encode(src, *proc_re, &proc)
143
+ data = if proc_re.size > 0 && proc_re[0].is_a?(MathData)
144
+ proc_re.shift
145
+ else
146
+ MathData.new
147
+ end
148
+
149
+ proc_re = proc_re.size == 0 ? @encode_proc_re : collect_regexp(proc_re)
150
+ proc ||= @encode_proc
151
+
152
+ s = StringScanner.new(src)
153
+ encoded = ''
154
+
155
+ until s.eos?
156
+ if s.scan(/
157
+ (.*?)
158
+ (((((#{@params[:throughs]})|
159
+ #{@params[:dmath_envs]})|
160
+ #{@params[:math_envs]})|
161
+ #{proc_re})|
162
+ #{@params[:escapes]})
163
+ /mx)
164
+ encoded << s[1]
165
+ if s[6]
166
+ encoded << s[6]
167
+ elsif s[5] || s[4]
168
+ env_src = s[5] || s[4]
169
+ if @params[:dmath_envs] =~ env_src
170
+ encoded << "#{@params[:delimiter]}d#{data.dsrc_list.size}#{@params[:delimiter]}"
171
+ data.dsrc_list << env_src
172
+ else
173
+ encoded << "#{@params[:delimiter]}m#{data.msrc_list.size}#{@params[:delimiter]}"
174
+ data.msrc_list << env_src
175
+ end
176
+ elsif s[3]
177
+ size = s[3].size
178
+ s.pos = left = s.pos - size
179
+ if r = proc.call(s)
180
+ right = s.pos
181
+ encoded << "#{@params[:delimiter]}u#{data.user_list.size}#{@params[:delimiter]}"
182
+ data.user_list << r
183
+ data.usrc_list << s.string[left...right]
184
+ else
185
+ encoded << s.peek(size)
186
+ s.pos = s.pos + size
187
+ end
188
+ elsif s[2]
189
+ encoded << "#{@params[:delimiter]}e#{data.escape_list.size}#{@params[:delimiter]}"
190
+ @params[:escapes] =~ s[2]
191
+ data.esrc_list << s[2]
192
+ data.escape_list << escapeXML($+, true)
193
+ end
194
+ else
195
+ encoded << s.rest
196
+ s.terminate
197
+ end
198
+ end
199
+
200
+ parse(data, @params[:parser]) unless @params[:without_parse]
201
+
202
+ [encoded, data]
203
+ end
204
+
205
+ def error_to_html(e)
206
+ "<br />\n#{escapeXML(e.message)}<br />\n<code>#{escapeXML(e.done).gsub(/\n/, "<br />\n")}" \
207
+ "<strong>#{escapeXML(e.rest).gsub(/\n/, "<br />\n")}</strong></code><br />"
208
+ end
209
+
210
+ def latex_parser
211
+ @params[:parser] = MathML::LaTeX::Parser.new unless @params[:parser]
212
+ @params[:parser]
213
+ end
214
+
215
+ def parse(data, parser = nil)
216
+ parser ||= latex_parser
217
+ (data.math_list.size...data.msrc_list.size).each do |i|
218
+ @params[:math_envs] =~ data.msrc_list[i]
219
+ data.math_list[i] = parser.parse($+)
220
+ rescue MathML::LaTeX::ParseError => e
221
+ data.math_list[i] = if @rescue_proc
222
+ @rescue_proc.call(e)
223
+ else
224
+ error_to_html(e)
225
+ end
226
+ end
227
+ (data.dmath_list.size...data.dsrc_list.size).each do |i|
228
+ @params[:dmath_envs] =~ data.dsrc_list[i]
229
+ data.dmath_list[i] = parser.parse($+, true)
230
+ rescue MathML::LaTeX::ParseError => e
231
+ data.dmath_list[i] = if @rescue_proc
232
+ @rescue_proc.call(e)
233
+ else
234
+ error_to_html(e)
235
+ end
236
+ end
237
+ end
238
+
239
+ def decode(encoded, data, without_parsed = false, &proc)
240
+ return nil if encoded.nil?
241
+
242
+ proc ||= @decode_proc
243
+ encoded.gsub(/#{Regexp.escape(@params[:delimiter])}([demu])(\d+)#{Regexp.escape(@params[:delimiter])}/) do
244
+ i = $2.to_i
245
+ t, d, s =
246
+ case $1
247
+ when 'd'
248
+ [:dmath, without_parsed ? escapeXML(data.dsrc_list[i], true) : data.dmath_list[i], data.dsrc_list[i]]
249
+ when 'e'
250
+ [:escape, data.escape_list[i], data.esrc_list[i]]
251
+ when 'm'
252
+ [:math, without_parsed ? escapeXML(data.msrc_list[i], true) : data.math_list[i], data.msrc_list[i]]
253
+ when 'u'
254
+ [:user, data.user_list[i], data.usrc_list[i]]
255
+ end
256
+ if proc
257
+ proc.call(d, type: t, index: i, src: s) || d
258
+ else
259
+ d
260
+ end
261
+ end
262
+ end
263
+
264
+ def decode_partial(type, encoded, data, &proc)
265
+ return nil if encoded.nil?
266
+
267
+ head =
268
+ case type
269
+ when :math
270
+ 'm'
271
+ when :dmath
272
+ 'd'
273
+ when :escape
274
+ 'e'
275
+ when :user
276
+ 'u'
277
+ else
278
+ return
279
+ end
280
+ encoded.gsub(/#{Regexp.escape(@params[:delimiter])}#{head}(\d+)#{Regexp.escape(@params[:delimiter])}/) do
281
+ i = $1.to_i
282
+ t, d, s =
283
+ case head
284
+ when 'd'
285
+ [:dmath, data.dmath_list[i], data.dsrc_list[i]]
286
+ when 'e'
287
+ [:escape, data.escape_list[i], data.esrc_list[i]]
288
+ when 'm'
289
+ [:math, data.math_list[i], data.msrc_list[i]]
290
+ when 'u'
291
+ [:user, data.user_list[i], data.usrc_list[i]]
292
+ end
293
+ if proc
294
+ proc.call(d, type: t, index: i, src: s) || "#{@params[:delimiter]}#{head}#{i}#{@params[:delimiter]}"
295
+ else
296
+ d
297
+ end
298
+ end
299
+ end
300
+
301
+ def unencode(encoded, data, without_escape = false, &proc)
302
+ return nil if encoded.nil?
303
+
304
+ proc ||= @unencode_proc
305
+ encoded.gsub(/#{Regexp.escape(@params[:delimiter])}([demu])(\d+)#{Regexp.escape(@params[:delimiter])}/) do
306
+ i = $2.to_i
307
+ t, s =
308
+ case $1
309
+ when 'd'
310
+ [:dmath, data.dsrc_list[i]]
311
+ when 'e'
312
+ [:escape, data.esrc_list[i]]
313
+ when 'm'
314
+ [:math, data.msrc_list[i]]
315
+ when 'u'
316
+ [:user, data.usrc_list[i]]
317
+ end
318
+ s = escapeXML(s, true) unless without_escape
319
+ if proc
320
+ proc.call(s, type: t, index: i) || s
321
+ else
322
+ s
323
+ end
324
+ end
325
+ end
326
+
327
+ def self.encode(src)
328
+ @@default_latex ||= new
329
+ @@default_latex.encode(src)
330
+ end
331
+
332
+ def self.decode(src, data)
333
+ @@default_latex.decode(src, data)
334
+ end
335
+
336
+ def parse_eqnarray(src, parser = nil)
337
+ src = "\\begin{array}{ccc}#{src}\\end{array}"
338
+ parser ||= latex_parser
339
+ begin
340
+ parser.parse(src, true)
341
+ rescue MathML::LaTeX::ParseError => e
342
+ e = MathML::LaTeX::ParseError.new(
343
+ e.message,
344
+ e.rest.sub(/\\end\{array\}\z/, '\end{eqnarray}'),
345
+ e.done.sub(/\A\\begin\{array\}\{ccc\}/, '\begin{eqnarray}')
346
+ )
347
+ @rescue_proc ? @rescue_proc.call(e) : error_to_html(e)
348
+ end
349
+ end
350
+
351
+ def parse_single_command(src, parser = nil)
352
+ s = src[SINGLE_COMMAND_RE, 1]
353
+ parser ||= latex_parser
354
+ begin
355
+ parser.parse(s)
356
+ rescue MathML::LaTeX::ParseError => e
357
+ src[SINGLE_COMMAND_RE, 2]
358
+ end
359
+ end
360
+ end
350
361
  end