mathml 0.8.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.
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Extension of String class by MathML Library
4
+ #
5
+ # Copyright (C) 2007, KURODA Hiraku <hiraku@hinet.mydns.jp>
6
+ # You can redistribute it and/or modify it under GPL2.
7
+ #
8
+
9
+ require "math_ml"
10
+
11
+ module MathML
12
+ module String
13
+ @@mathml_latex_parser = nil
14
+ def self.mathml_latex_parser
15
+ @@mathml_latex_parser = MathML::LaTeX::Parser.new unless @@mathml_latex_parser
16
+ @@mathml_latex_parser
17
+ end
18
+
19
+ def self.mathml_latex_parser=(mlp)
20
+ raise TypeError unless mlp.is_a?(MathML::LaTeX::Parser) || mlp==nil
21
+ @@mathml_latex_parser = mlp
22
+ end
23
+
24
+ def to_mathml(displaystyle=false)
25
+ MathML::String.mathml_latex_parser.parse(self, displaystyle)
26
+ end
27
+ end
28
+ end
29
+
30
+ class String
31
+ include MathML::String
32
+ end
@@ -0,0 +1,350 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Utility for MathML Library
4
+ #
5
+ # Copyright (C) 2006, KURODA Hiraku <hiraku@hinet.mydns.jp>
6
+ # You can redistribute it and/or modify it under GPL2.
7
+ #
8
+
9
+ require "math_ml"
10
+
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
350
+ end
@@ -0,0 +1,446 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift("../")
4
+ require "cgi"
5
+ require "math_ml"
6
+
7
+ include MathML::LaTeX
8
+
9
+ BEC = /\\.|[^\\\n]/ # Back slash Escaped Character
10
+ TEXMF_DIR = "/usr/share/texmf-tetex"
11
+
12
+ def brace_nest(s)
13
+ nest=0
14
+ s.gsub(/(\{|\})/) do
15
+ case $1
16
+ when "{"
17
+ nest+=1
18
+ "{#{nest}."
19
+ when "}"
20
+ nest-=1
21
+ "}#{nest+1}."
22
+ end
23
+ end
24
+ end
25
+
26
+ def load_style(name)
27
+ r = IO.read("#{TEXMF_DIR}/tex/latex/#{name}").gsub(/^\%.*\n/, "").gsub(/^(#{BEC}*?)\%.*$/){$1}
28
+ end
29
+
30
+ def parse_DeclareMath(f, delims, robust_as_math = false)
31
+ r = Hash.new
32
+
33
+ f=f.gsub(/[a-zA-Z]\\Declare/, "")
34
+ f.scan(/\\DeclareMathSymbol|\\DeclareRobustCommand/) do
35
+ remain = Scanner.new($')
36
+ com = remain.scan_block ? remain[1] : remain.scan_command
37
+ next unless com=~/\A\\/
38
+ remain.scan_option
39
+ body = remain.scan_block ? remain[1] : remain.scan_any
40
+ case body
41
+ when /nomath/, /not@math/
42
+ next
43
+ when /\\mathord/, /\\mathalpha/, /\\mathbin/, /\\mathrel/, /\\mathpunct/
44
+ r[com] = :subsup
45
+ when /\\mathop/
46
+ r[com] = :underover
47
+ else
48
+ r[com] = robust_as_math ? :subsup : body
49
+ end
50
+ end
51
+
52
+ f.scan(/\\DeclareMathDelimiter\{(\\.+?)\}\s*\{(\\.+?)\}/m) do |m|
53
+ case m[1]
54
+ when "\\mathopen", "\\mathclose", "\\mathord", "\\mathrel"
55
+ r[m[0]] = :subsup
56
+ else
57
+ raise "#{m[0]} : #{m[1]}"
58
+ end
59
+ delims << m[0]
60
+ end
61
+
62
+ f.scan(/\\let(\\.+?)=?(\\.*)/) do |m|
63
+ r[m[0]] = m[1] unless r.include?(m[0]) # excepting "\let\com\undefined" or like it.
64
+ end
65
+
66
+ r
67
+ end
68
+
69
+ def trace_list(com, h, d)
70
+ s = h[com]
71
+ mmode = (s=~/\\ifmmode/ || s=~/mathinner/)
72
+ if s.is_a?(String)
73
+ sc = Scanner.new(s.dup.gsub(/[{}]/, ""))
74
+ until sc.eos?
75
+ b = sc.scan_any
76
+ s.slice!(0, b.size)
77
+ next unless h.include?(b)
78
+ trace_list(b, h, d)
79
+ h[com] = h[b] if h[com].is_a?(String)
80
+ unless d.include?(com)
81
+ d << com if d.include?(b)
82
+ end
83
+ end
84
+ end
85
+ if h[com].is_a?(String)
86
+ if mmode
87
+ h[com] = :subsup
88
+ else
89
+ h.delete(com)
90
+ end
91
+ end
92
+ end
93
+
94
+ def fetch_symbol(delims=[])
95
+ r = {}
96
+
97
+ f = load_style("base/latex.ltx")
98
+ r.merge!(parse_DeclareMath(f, delims))
99
+ f.scan(/^\\def(\\[a-zA-Z]+?)\{\\mathop(\W.*)$/) do |s|
100
+ if s[1]=~/\\nolimits/
101
+ r[s[0]] = :subsup
102
+ else
103
+ r[s[0]] = :underover
104
+ end
105
+ end
106
+ f.scan(/\\chardef(\\.)=\`\1/) do |m|
107
+ r[m[0]] = :subsup
108
+ end
109
+
110
+ f = load_style("base/latexsym.sty")
111
+ r.merge!(parse_DeclareMath(f, delims))
112
+
113
+ f = load_style("base/fontmath.ltx")
114
+ r.merge!(parse_DeclareMath(f, delims, true))
115
+ brace_nest(f).scan(/\\def(\\.+?)\{1\.(.*?)\}1\./m) do |m|
116
+ if m[0]=~/@|#/
117
+ elsif m[1]=~/\A\$/
118
+ else
119
+ r[m[0]] = :subsup
120
+ end
121
+ end
122
+ f.scan(/\\def(\\[^\{]+?)(\\.+)/) do |m|
123
+ raise StandardError.new("Uncaught commands")
124
+ end
125
+
126
+ f = load_style("amsfonts/amssymb.sty")
127
+ r.merge!(parse_DeclareMath(f, delims))
128
+
129
+ f = load_style("amsfonts/amsfonts.sty")
130
+ r.merge!(parse_DeclareMath(f, delims))
131
+
132
+ r.each_key do |k|
133
+ r.delete(k) if k=~/@/
134
+ end
135
+
136
+ r.each_key do |k|
137
+ trace_list(k, r, delims) if r[k].is_a?(String)
138
+ end
139
+ r
140
+ end
141
+
142
+ def sort_symbol_list_in(file, h)
143
+ r = Array.new
144
+ f = load_style(file)
145
+ f.scan(/\\[a-zA-Z@\#]+|\\./) do |m|
146
+ if h[m]
147
+ r << m
148
+ h.delete(m)
149
+ end
150
+ end
151
+ r
152
+ end
153
+
154
+ def sorted_symbol_list(h)
155
+ h = h.dup
156
+ r = Array.new
157
+ r.concat(sort_symbol_list_in("base/latex.ltx", h))
158
+ r.concat(sort_symbol_list_in("base/fontmath.ltx", h))
159
+ r.concat(sort_symbol_list_in("amsfonts/amssymb.sty", h))
160
+ r.concat(sort_symbol_list_in("amsfonts/amsfonts.sty", h))
161
+ r
162
+ end
163
+
164
+ def load_preput_list(list)
165
+ r = {}
166
+ list.each do |l|
167
+ next if l=~/\A\s*\#/
168
+ com, type, str = l.chomp.split(nil, 3)
169
+ r[com] = [type.to_sym, str]
170
+ end
171
+ r
172
+ end
173
+
174
+ def output_list(h, preput=nil)
175
+ p = preput ? load_preput_list(preput) : {}
176
+ sorted_symbol_list(h).each do |k|
177
+ data = p.include?(k) ? p[k][1] : ""
178
+ # puts "#{k} #{h[k]} #{data}"
179
+ end
180
+
181
+ $stderr.puts "### Update"
182
+ sorted_symbol_list(h).each do |k|
183
+ $stderr.puts k unless p.include?(k)
184
+ end
185
+
186
+ $stderr.puts "### Conflict"
187
+ sorted_symbol_list(h).each do |k|
188
+ next unless p.include?(k)
189
+ $stderr.puts k unless p[k][0]==h[k]
190
+ end
191
+
192
+ $stderr.puts "### Missing"
193
+ p.each_key do |k|
194
+ $stderr.puts k unless h.include?(k)
195
+ end
196
+ end
197
+
198
+ def output_latex(h)
199
+ puts <<'EOT'
200
+ \documentclass{article}
201
+ \usepackage{amssymb}
202
+ \newcommand{\bslash}{\texttt{\symbol{92}}}
203
+ \setlength{\oddsidemargin}{-1cm}
204
+ \setlength{\evensidemargin}{-1cm}
205
+ \begin{document}
206
+ EOT
207
+ col = 4
208
+ row=18
209
+ l = sorted_symbol_list(h)
210
+ (0 ... l.size).step(col*row) do |t|
211
+ puts '\begin{tabular}{|'+"c|"*col+'}\hline'
212
+ (0 ... col*row).step(col) do |r|
213
+ next unless l[t+r]
214
+ (0 ... col).each do |c|
215
+ i = t+r+c
216
+ com = l[i].to_s.gsub(/\\/, "\\bslash ").gsub(/([\$\{\}\#\%\&_])/){"\\#$1"}.
217
+ gsub(/\|/, "\\texttt|")
218
+ tex = l[i].to_s.dup
219
+ if l[i]
220
+ case h[l[i]]
221
+ when :subsup
222
+ tex << "_{sub}^{sup}"
223
+ when :underover
224
+ tex << "_{under}^{over}"
225
+ else
226
+ raise StandardError
227
+ end
228
+ end
229
+ tex = "$\\displaystyle#{tex}$"
230
+ str = (l[i] ? <<EOT : "")
231
+ \\begin{tabular}{c}
232
+ #{t+r+c} #{com} \\\\
233
+ #{tex}
234
+ \\end{tabular}
235
+ EOT
236
+ print str+(c==(col-1) ? " \\\\ \\hline\n" : " & ")
237
+ end
238
+ end
239
+ puts "\\end{tabular}\n\n"
240
+ end
241
+ puts '\end{document}'
242
+ end
243
+
244
+ def parse_list(list)
245
+ a = []
246
+ h = {}
247
+ list.each do |l|
248
+ next if l =~ /^\s*\#/
249
+ com, type, str = l.chomp.split(nil, 3)
250
+
251
+ case type
252
+ when "subsup"
253
+ type = :s
254
+ when "underover"
255
+ type = :u
256
+ else
257
+ raise l
258
+ end
259
+
260
+ str.slice!(/\s*\#.*$/)
261
+ el = nil
262
+ cl = nil
263
+ s = nil
264
+ case str
265
+ when /^([oinI])([\-\:=])(.*)$/
266
+ el = $1
267
+ cl = $2
268
+ s = $3
269
+ when "v"
270
+ when ""
271
+ cl = true
272
+ else
273
+ raise l
274
+ end
275
+ a << com
276
+ case cl
277
+ when "-"
278
+ h[com] = [type, el.to_sym, s ? s : ""]
279
+ when ":"
280
+ h[com] = [type, el.to_sym, s.to_s.length>0 ? s.to_sym : nil]
281
+ when "="
282
+ s = "0"+s if s=~/^x/
283
+ h[com] = [type, el.to_sym, s.to_i(0)]
284
+ when true
285
+ h[com] = [type, nil, nil]
286
+ when nil
287
+ h[com] = nil
288
+ else
289
+ raise l
290
+ end
291
+ h[com].pop while h[com] && h[com].last==nil
292
+ end
293
+ [a, h]
294
+ end
295
+
296
+ def to_mathml(com, data)
297
+ com = com[/^\\(.*)$/, 1]
298
+ unless data
299
+ ""
300
+ else
301
+ data[1] = :o unless data[1]
302
+ p=""
303
+ case data[1]
304
+ when :i
305
+ p = " mathvariant='normal'" unless data[2] && data[2].is_a?(String)
306
+ when :I
307
+ data[1] = :i
308
+ end
309
+
310
+ case data[2]
311
+ when String
312
+ if data[2].length>0
313
+ s = data[2]
314
+ else
315
+ s = com
316
+ end
317
+ when Symbol
318
+ s = "&#{data[2].to_s};"
319
+ when Integer
320
+ s = "&\#x#{data[2].to_s(16)};"
321
+ when nil
322
+ s = "&#{com};"
323
+ else
324
+ raise data[2]
325
+ end
326
+
327
+ e = "m#{data[1].to_s}"
328
+ "<#{e}#{p}>#{s}</#{e}>"
329
+ end
330
+ end
331
+
332
+ def output_xhtml(list)
333
+ a, h = parse_list(list)
334
+ puts <<EOT
335
+ <?xml version='1.0'?>
336
+ <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN' 'http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd'>
337
+ <html xmlns='http://www.w3.org/1999/xhtml'>
338
+ <body>
339
+ <ul>
340
+ EOT
341
+ a.each do |k|
342
+ raise k unless h.include?(k)
343
+ e = to_mathml(k, h[k])
344
+ e = nil unless e.length>0
345
+ mml = e ? "<math xmlns='http://www.w3.org/1998/Math/MathML' display='inline'>#{e}</math>" : ""
346
+ puts "<li>#{CGI.escapeHTML(k)} : #{mml}</li>"
347
+ end
348
+ puts <<EOT
349
+ </ul></body></html>
350
+ EOT
351
+ end
352
+
353
+ def output_hiki(h)
354
+ col = 5
355
+ row=20
356
+ l = sorted_symbol_list(h)
357
+ (0 ... l.size).step(col*row) do |t|
358
+ (0 ... col*row).step(col) do |r|
359
+ next unless l[t+r]
360
+ print "||"
361
+ (0 ... col).each do |c|
362
+ i = t+r+c
363
+ com = l[i].to_s.gsub(/\\/){"\\\\"}.gsub(/\$/){%[\\$]}.gsub(/([\{\}])/){"\\\\#$1"}
364
+ tex = l[i].to_s.dup
365
+ if l[i]
366
+ case h[l[i]]
367
+ when :subsup
368
+ tex << "_{sub}^{sup}"
369
+ when :underover
370
+ tex << "_{under}^{over}"
371
+ else
372
+ raise StandardError
373
+ end
374
+ end
375
+ print " #{com} $$#{tex}$$ ||"
376
+ end
377
+ puts ""
378
+ end
379
+ end
380
+ end
381
+
382
+ def gen_rb(list)
383
+ a, h = parse_list(list)
384
+ r = "SymbolCommands={\n"
385
+ a.each do |k|
386
+ d = h[k]
387
+ unless d
388
+ v = "nil"
389
+ else
390
+ v = "[:#{d[0].to_s}"
391
+ unless d[1]
392
+ v << "]"
393
+ else
394
+ v << ",:#{d[1].to_s}"
395
+ unless d[2]
396
+ v << "]"
397
+ else
398
+ case d[2]
399
+ when String
400
+ v << %[,"#{d[2].gsub(/\\/){"\\\\"}}"]
401
+ when Symbol
402
+ v << ",:#{d[2].to_s}"
403
+ when Fixnum
404
+ v << ",0x#{d[2].to_s(16)}"
405
+ else
406
+ raise [k, d]
407
+ end
408
+ v << "]"
409
+ end
410
+ end
411
+ end
412
+ r << %["#{k[/^\\(.*)/, 1].gsub(/\\/){"\\\\"}}"=>#{v},\n]
413
+ end
414
+ r << "}\n"
415
+ end
416
+
417
+ def output_delims
418
+ d = []
419
+ fetch_symbol(d)
420
+ puts "Delimiters=["
421
+ d.each do |i|
422
+ puts %["#{i.gsub(/\\/){""}}",]
423
+ end
424
+ puts "]"
425
+ end
426
+
427
+ def read_list
428
+ IO.read($*[1] || "list.txt")
429
+ end
430
+ if (File.expand_path(__FILE__)==File.expand_path($0)) && $*[0]
431
+ case $*[0]
432
+ when "list"
433
+ preput = $*[1] ? IO.read($*[1]) : nil
434
+ output_list(fetch_symbol, preput)
435
+ when "latex"
436
+ output_latex(fetch_symbol)
437
+ when "xhtml"
438
+ output_xhtml(read_list)
439
+ when "hiki"
440
+ output_hiki(fetch_symbol)
441
+ when "delims"
442
+ output_delims
443
+ when "rb"
444
+ puts gen_rb(read_list)
445
+ end
446
+ end