mathml 0.8.0

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