ritex 0.1

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,140 @@
1
+ /*
2
+ -*- text -*-
3
+ ## lib/ritex/lexer.rb -- contains Ritex::Lexer
4
+ ## Author:: William Morgan (mailto: wmorgan-ritex@masanjin.net)
5
+ ## Copyright:: Copyright 2005 William Morgan
6
+ ## License:: GNU GPL version 2
7
+ */
8
+
9
+ class Ritex::Parser
10
+
11
+ /* don't forget to re-run racc after editing this file!!!
12
+ or 'rake racc'
13
+ */
14
+
15
+ /* spacing: spacing is ignored by the lexer except immediately after a
16
+ '{' or before a '{' the value of those two tokens is the actual
17
+ space inbetween (nil if none)
18
+
19
+ unary minus: handled by the lexer. too complicated to really put in
20
+ to the parser, even with precedence mangling, because i'm trying
21
+ not to actually parse the stuff as much as possible.
22
+ */
23
+
24
+ token NUMBER VAR SYMBOL ARRAY FUNC0 FUNC1 FUNC2 FUNC3 MACRO0 MACRO1 MACRO2 MACRO3 ENV DOUBLEBACK DEFINE UNARYMINUS SPACE LEFT RIGHT
25
+
26
+ expect 18 /* all from the \left\{ \right\} thing, which is naturally
27
+ ambiguous and there's nothing i can do to fix that. */
28
+
29
+ rule
30
+ exp: /* nothing */ { result = "" }
31
+ | exp expel { result = join val[0], val[1] }
32
+
33
+ expel: atom
34
+ | atom '^' atom '_' atom { result = markup join(val[0], val[4], val[2]), :subsup }
35
+ | atom '_' atom '^' atom { result = markup join(val[0], val[2], val[4]), :subsup }
36
+ | atom '_' atom { result = markup join(val[0], val[2]), :sub }
37
+ | atom '^' atom { result = markup join(val[0], val[2]), :sup }
38
+
39
+ atom: NUMBER { result = markup val[0], :num }
40
+ | VAR { result = markup val[0], :var }
41
+ | SYMBOL { result = lookup val[0] }
42
+ | func
43
+ | macro
44
+ | ENV arg { result = special(*val) }
45
+ | '{' exp '}' { result = markup val[1], :group }
46
+ | UNARYMINUS { result = markup val[0], :unaryminus }
47
+ | array
48
+ | macrodef
49
+ | plainop { result = markup val[0], :op }
50
+ | LEFT exp RIGHT pos { result = markup join(val[1], val[3]), :group }
51
+ | LEFT exp RIGHT { result = markup val[1], :group }
52
+
53
+
54
+ func: FUNC0 { result = special(*val) }
55
+ | FUNC1 atom { result = special(*val) }
56
+ | FUNC2 atom atom { result = special(*val) }
57
+ | FUNC3 atom atom atom { result = special(*val) }
58
+
59
+
60
+ macro: MACRO0 { result = special(*val) }
61
+ | MACRO1 arg { result = special(*val) }
62
+ | MACRO2 arg arg { result = special(*val) }
63
+ | MACRO3 arg arg arg { result = special(*val) }
64
+
65
+ /* un-evalauted argument */
66
+ arg: '{' string '}' { result = safe(val[1]) }
67
+
68
+ pos: plainop { result = markup val[0], :op }
69
+ | SYMBOL { result = lookup val[0] }
70
+
71
+ stringel: NUMBER
72
+ | plainop
73
+ | '^'
74
+ | '_'
75
+ | VAR
76
+ | ARRAY
77
+ | escapeme { result = '\\' + val[0] } /* have to re-escape these */
78
+ | DOUBLEBACK
79
+ | SPACE
80
+ | '{' string '}' { result = "{#{val[1]}}" } /* nested shit must match up or we won't know when to end */
81
+
82
+ escapeme: SYMBOL
83
+ | FUNC0
84
+ | FUNC1
85
+ | FUNC2
86
+ | FUNC3
87
+ | MACRO0
88
+ | MACRO1
89
+ | MACRO2
90
+ | MACRO3
91
+ | ENV
92
+
93
+ string: /* empty */ { result = "" }
94
+ | string stringel { result = val[0] + val[1] }
95
+
96
+
97
+ macrodef: DEFINE '{' symspec '}' '{' string '}' { result = define val[2], 0, join(val[4], val[5], val[6]) }
98
+ | DEFINE '{' symspec '}' '[' NUMBER ']' '{' string '}' { result = define val[2], val[5], join(val[7], val[8], val[9]) }
99
+
100
+
101
+ symspec: SYMBOL
102
+ | FUNC0
103
+ | FUNC1
104
+ | FUNC2
105
+ | FUNC3
106
+ | MACRO0
107
+ | MACRO1
108
+ | MACRO2
109
+ | MACRO3
110
+
111
+ array: ARRAY '{' ainnards '}' { result = markup markup(val[2], :array), :group }
112
+
113
+ ainnards: arow
114
+ | ainnards DOUBLEBACK arow { result = val[0] + val[2] }
115
+
116
+ arow: arow1 { result = markup val[0], :row }
117
+
118
+ arow1: acol
119
+ | arow1 '&' acol { result = val[0] + val[2] }
120
+
121
+ /* wrapper */
122
+ acol: exp { result = markup val[0], :col }
123
+
124
+ plainop: '+'
125
+ | '-'
126
+ | '*'
127
+ | '/'
128
+ | '['
129
+ | ']'
130
+ | '|'
131
+ | '.'
132
+ | ','
133
+ | ';'
134
+ | ':'
135
+ | '<' { result = safe val[0] }
136
+ | '>' { result = safe val[0] }
137
+ | '='
138
+ | '('
139
+ | ')'
140
+ | '#'
@@ -0,0 +1,7 @@
1
+ ## test/all.rb -- loads all unit tests
2
+ ## Author:: William Morgan (mailto: wmorgan-ritex@masanjin.net)
3
+ ## Copyright:: Copyright 2005 William Morgan
4
+ ## License:: GNU GPL version 2
5
+
6
+ require "test/mathml"
7
+ require "test/parser"
@@ -0,0 +1,292 @@
1
+ ---
2
+ "\\left ( x \\right )": "<math
3
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></math>"
4
+ "\\mathcal{Hello}": "<math
5
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>&Hscr;&escr;&lscr;&lscr;&oscr;</mi></math>"
6
+ "-3": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo
7
+ lspace=\"thinthinmathspace\" rspace=\"0em\">-</mo><mn>3</mn></math>"
8
+ "\\lim_3": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msub><mo
9
+ lspace=\"thinmathspace\" rspace=\"thinmathspace\">lim</mo>
10
+ <mn>3</mn></msub></math>"
11
+ '': ''
12
+ "\\forall x\\,x<0": "<math
13
+ xmlns='http://www.w3.org/1998/Math/MathML'><mo>&forall;</mo><mi>x</mi><mspace
14
+ width=\"thinmathspace\"/><mi>x</mi><mo>&lt;</mo><mn>0</mn></math>"
15
+ "{{N-x}-x}": "<math
16
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mrow><mi>N</mi><mo>-</mo><mi>x</mi></mrow><mo>-</mo><mi>x</mi></mrow></math>"
17
+ if: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>i</mi><mi>f</mi></math>"
18
+ "\\alpha": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi></math>"
19
+ a ^ b: "<math
20
+ xmlns='http://www.w3.org/1998/Math/MathML'><msup><mi>a</mi><mi>b</mi></msup></math>"
21
+ "\\define { \\goat }{3+4}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace='0em'
22
+ rspace='thinmathspace'>define</mo><mrow><mo lspace='0em'
23
+ rspace='thinmathspace'>goat</mo></mrow><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow></math>"
24
+ a\text{ if }b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mtext> if
25
+ </mtext><mi>b</mi></math>"
26
+ a\in S: "<math
27
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mo>&Element;</mo><mi>S</mi></math>"
28
+ " G(y) = \\left\\{\\array{ 1 - e^{-\\lambda y} & \\text{ if } y \\geq 0 \\ 0 & \\text{ if } y < 0 }\\right. .": "<math
29
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>G</mi><mo>(</mo><mi>y</mi><mo>)</mo><mo>=</mo><mrow><mo>{</mo><mrow><mtable><mtr><mtd><mn>1</mn><mo>-</mo><msup><mi>e</mi>
30
+ <mrow><mo lspace=\"thinthinmathspace\"
31
+ rspace=\"0em\">-</mo><mi>&lambda;</mi><mi>y</mi></mrow></msup></mtd>
32
+ <mtd><mtext> if </mtext><mi>y</mi><mo>&geq;</mo><mn>0</mn><mspace
33
+ width=\"mediummathspace\"/><mn>0</mn></mtd> <mtd><mtext> if
34
+ </mtext><mi>y</mi><mo>&lt;</mo><mn>0</mn></mtd></mtr></mtable></mrow>
35
+ <mo>.</mo></mrow><mo>.</mo></math>"
36
+ " a": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>"
37
+ "{x}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mi>x</mi></mrow></math>"
38
+ "\\bigcup + x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace='thinmathspace'
39
+ rspace='thinmathspace'>&Union;</mo><mo>+</mo><mi>x</mi></math>"
40
+ "\\overset{\\text{n terms}}{\\overbrace{1+2+\\cdots+n}}": "<math
41
+ xmlns='http://www.w3.org/1998/Math/MathML'><mover><mrow><mover><mrow><mn>1</mn><mo>+</mo><mn>2</mn><mo>+</mo><mo>&sdot;
42
+ &sdot;
43
+ &sdot;</mo><mo>+</mo><mi>n</mi></mrow><mo>&OverBrace;</mo></mover></mrow><mrow><mtext>n
44
+ terms</mtext></mrow></mover></math>"
45
+ a < b: "<math
46
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mo>&lt;</mo><mi>b</mi></math>"
47
+ "\\array{1 & 0 \\\\ 0 & 1}": "<math
48
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable><mtr><mtd><mn>1</mn></mtd>
49
+ <mtd><mn>0</mn></mtd></mtr> <mtr><mtd><mn>0</mn></mtd>
50
+ <mtd><mn>1</mn></mtd></mtr></mtable></mrow></math>"
51
+ "\\alpha + b + c": "<math
52
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi><mo>+</mo><mi>b</mi><mo>+</mo><mi>c</mi></math>"
53
+ "\\left ( \\frac{2}{4+x} \\right )^3": "<math
54
+ xmlns='http://www.w3.org/1998/Math/MathML'><msup><mrow><mo>(</mo><mfrac><mrow><mn>2</mn></mrow><mrow><mn>4</mn><mo>+</mo><mi>x</mi></mrow></mfrac><mo>)</mo></mrow><mn>3</mn></msup></math>"
55
+ "\\left ( \\binom{2}{3} \\right )": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mo>(</mo><mfrac
56
+ linethickness=\"0\"><mrow><mn>2</mn></mrow><mrow><mn>3</mn></mrow></mfrac>
57
+ <mo>)</mo></mrow></math>"
58
+ a\text{ if a fd ew s }b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mtext> if a fd ew s
59
+ </mtext><mi>b</mi></math>"
60
+ "\\bigcup - x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace='thinmathspace'
61
+ rspace='thinmathspace'>&Union;</mo><mo lspace='thinthinmathspace'
62
+ rspace='0em'>-</mo><mi>x</mi></math>"
63
+ "x + - x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>x</mi><mo>+</mo><mo
64
+ lspace='thinthinmathspace' rspace='0em'>-</mo><mi>x</mi></math>"
65
+ "\\text{if}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mtext>if</mtext></math>"
66
+ "\\frac{1}{2}": "<math
67
+ xmlns='http://www.w3.org/1998/Math/MathML'><mfrac><mrow><mn>1</mn></mrow><mrow><mn>2</mn></mrow></mfrac></math>"
68
+ "-x-x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo
69
+ lspace=\"thinthinmathspace\"
70
+ rspace=\"0em\">-</mo><mi>x</mi><mo>-</mo><mi>x</mi></math>"
71
+ a+3: "<math
72
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mo>+</mo><mn>3</mn></math>"
73
+ a^b_c: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msubsup><mi>a</mi> <mi>c</mi>
74
+ <mi>b</mi></msubsup></math>"
75
+ "\\arccos - x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace='0em'
76
+ rspace='thinmathspace'>arccos</mo><mo lspace='thinthinmathspace'
77
+ rspace='0em'>-</mo><mi>x</mi></math>"
78
+ w_r \equiv \frac{P^*(\sampx)}{Q^*(\sampx)}.: "<math
79
+ xmlns='http://www.w3.org/1998/Math/MathML'><msub><mi>w</mi><mi>r</mi></msub><mo>&equiv;</mo><mfrac><mrow><msup><mi>P</mi><mo>*</mo></msup><mo>(</mo><mrow><msup><mi>x</mi><mrow><mo>(</mo><mi>r</mi><mo>)</mo></mrow></msup></mrow><mo>)</mo></mrow><mrow><msup><mi>Q</mi><mo>*</mo></msup><mo>(</mo><mrow><msup><mi>x</mi><mrow><mo>(</mo><mi>r</mi><mo>)</mo></mrow></msup></mrow><mo>)</mo></mrow></mfrac><mo>.</mo></math>"
80
+ ? |2-
81
+ G(y) = \left\{\array{ 1 - e^{-\lambda y} & \text{ if } y \geq 0 \
82
+ 0 & \text{ if } y < 0 }\right. .
83
+ : "<math
84
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>G</mi><mo>(</mo><mi>y</mi><mo>)</mo><mo>=</mo><mrow><mo>{</mo><mrow><mtable><mtr><mtd><mn>1</mn><mo>-</mo><msup><mi>e</mi>
85
+ <mrow><mo lspace=\"thinthinmathspace\"
86
+ rspace=\"0em\">-</mo><mi>&lambda;</mi><mi>y</mi></mrow></msup></mtd>
87
+ <mtd><mtext> if </mtext><mi>y</mi><mo>&geq;</mo><mn>0</mn><merror>Unknown
88
+ character</merror><mn>0</mn></mtd> <mtd><mtext> if
89
+ </mtext><mi>y</mi><mo>&lt;</mo><mn>0</mn></mtd></mtr></mtable></mrow>
90
+ <mo>.</mo></mrow><mo>.</mo></math>"
91
+ a+-3: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mo>+</mo><mo
92
+ lspace=\"thinthinmathspace\" rspace=\"0em\">-</mo><mn>3</mn></math>"
93
+ " a": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi></math>"
94
+ ? |-
95
+ \mathop{monkey}
96
+ <
97
+ b
98
+ : "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace=\"0em\"
99
+ rspace=\"thinmathspace\">monkey</mo><mo>&lt;</mo><mi>b</mi></math>"
100
+ "\\left ( x \\right + 3": "<math
101
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mo>(</mo><mi>x</mi><mo>+</mo></mrow><mn>3</mn></math>"
102
+ a_b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msub><mi>a</mi>
103
+ <mi>b</mi></msub></math>"
104
+ a^{b_c} < a^b_c: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msup><mi>a</mi>
105
+ <mrow><msub><mi>b</mi>
106
+ <mi>c</mi></msub></mrow></msup><mo>&lt;</mo><msubsup><mi>a</mi> <mi>c</mi>
107
+ <mi>b</mi></msubsup></math>"
108
+ x--x: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>x</mi><mo>-</mo><mo
109
+ lspace='thinthinmathspace' rspace='0em'>-</mo><mi>x</mi></math>"
110
+ "\\int_x f(x)\\ dx": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msub><mo>&Integral;</mo>
111
+ <mi>x</mi></msub><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mspace
112
+ width=\"mediummathspace\"/><mi>d</mi><mi>x</mi></math>"
113
+ "\\sampx": "<math
114
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><msup><mi>x</mi><mrow><mo>(</mo><mi>r</mi><mo>)</mo></mrow></msup></mrow></math>"
115
+ "\\ln x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace=\"0em\"
116
+ rspace=\"thinmathspace\">ln</mo><mi>x</mi></math>"
117
+ F(x) = \Pr(X \leq x) \text{ for } -\infinity < x < \infinity: "<math
118
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>F</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mo
119
+ lspace=\"0em\"
120
+ rspace=\"thinmathspace\">Pr</mo><mo>(</mo><mi>X</mi><mo>&leq;</mo><mi>x</mi><mo>)</mo><mtext>
121
+ for
122
+ </mtext><mo>-</mo><mn>&infin;</mn><mo>&lt;</mo><mi>x</mi><mo>&lt;</mo><mn>&infin;</mn></math>"
123
+ "{\\mathbb{GOAT}_3}": "<math
124
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><msub><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi><mn>3</mn></msub></mrow></math>"
125
+ a\mathbb{GOAT}: "<math
126
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi></math>"
127
+ x: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>x</mi></math>"
128
+ "\\alpha - x": "<math
129
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>&alpha;</mi><mo>-</mo><mi>x</mi></math>"
130
+ "\\int_{-\\infinity}^\\infinity f(x)\\ dx = 1": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msubsup><mo>&Integral;</mo>
131
+ <mrow><mo lspace=\"thinthinmathspace\"
132
+ rspace=\"0em\">-</mo><mn>&infin;</mn></mrow>
133
+ <mn>&infin;</mn></msubsup><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mspace
134
+ width=\"mediummathspace\"/> <mi>d</mi><mi>x</mi><mo>=</mo><mn>1</mn></math>"
135
+ "\\Pr(a < X \\leq b) = \\int_a^b f(x)\\ dx": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace=\"0em\"
136
+ rspace=\"thinmathspace\">Pr</mo><mo>(</mo><mi>a</mi><mo>&lt;</mo><mi>X</mi><mo>&leq;</mo><mi>b</mi><mo>)</mo><mo>=</mo><msubsup><mo>&Integral;</mo>
137
+ <mi>a</mi> <mi>b</mi></msubsup><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mspace
138
+ width=\"mediummathspace\"/><mi>d</mi><mi>x</mi></math>"
139
+ ? |-
140
+ \define{\sampx}{x^{(r)}}
141
+ \frac{1}{N} \sum_r \phi(\sampx),
142
+ : "<math
143
+ xmlns='http://www.w3.org/1998/Math/MathML'><mfrac><mrow><mn>1</mn></mrow><mrow><mi>N</mi></mrow></mfrac><msub><mo
144
+ lspace='thinmathspace'
145
+ rspace='thinmathspace'>&Sum;</mo><mi>r</mi></msub><mi>&phi;</mi><mo>(</mo><mrow><msup><mi>x</mi><mrow><mo>(</mo><mi>r</mi><mo>)</mo></mrow></msup></mrow><mo>)</mo><mo>,</mo></math>"
146
+ "\\overset{\\text{$n$ terms}}{\\overbrace{1+2+\\cdots+n}}": "<math
147
+ xmlns='http://www.w3.org/1998/Math/MathML'><mover><mrow><mover><mrow><mn>1</mn><mo>+</mo><mn>2</mn><mo>+</mo><mo>&sdot;
148
+ &sdot;
149
+ &sdot;</mo><mo>+</mo><mi>n</mi></mrow><mo>&OverBrace;</mo></mover></mrow><mrow><mtext>$n$
150
+ terms</mtext></mrow></mover></math>"
151
+ x\textstyle{\int_0^1}\displaystyle{\int_0^1}y: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>x</mi><mstyle
152
+ displaystyle='false'><mrow><msubsup><mo>&Integral;</mo><mn>0</mn><mn>1</mn></msubsup></mrow></mstyle><mstyle
153
+ displaystyle='true'><mrow><msubsup><mo>&Integral;</mo><mn>0</mn><mn>1</mn></msubsup></mrow></mstyle><mi>y</mi></math>"
154
+ " G^{-1}(x) = -\\log(1 - x)/\\lambda\\text{ if } 0 < x < 1.": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msup><mi>G</mi> <mrow><mo
155
+ lspace=\"thinthinmathspace\"
156
+ rspace=\"0em\">-</mo><mn>1</mn></mrow></msup><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mo
157
+ lspace=\"thinthinmathspace\" rspace=\"0em\">-</mo><mo lspace=\"0em\"
158
+ rspace=\"thinmathspace\">log</mo><mo>(</mo><mn>1</mn><mo>-</mo><mi>x</mi><mo>)</mo><mo>/</mo><mi>&lambda;</mi><mtext>
159
+ if
160
+ </mtext><mn>0</mn><mo>&lt;</mo><mi>x</mi><mo>&lt;</mo><mn>1</mn><mo>.</mo></math>"
161
+ a\text{if}b: "<math
162
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mtext>if</mtext><mi>b</mi></math>"
163
+ a\text{if }b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mtext>if
164
+ </mtext><mi>b</mi></math>"
165
+ "\\array{ }": ''
166
+ ? |-
167
+ \mathbb{monkey}
168
+ <
169
+ b
170
+ : "<math
171
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>monkey</mi><mo>&lt;</mo><mi>b</mi></math>"
172
+ w_r \defnas \frac{P^*(\sampx)}{Q^*(\sampx)}.: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msub><mi>w</mi>
173
+ <mi>r</mi></msub><mo lspace=\"0em\"
174
+ rspace=\"thinmathspace\">defnas</mo><mfrac><mrow><msup><mi>P</mi>
175
+ <mo>*</mo></msup><mo>(</mo><mo lspace=\"0em\"
176
+ rspace=\"thinmathspace\">sampx</mo><mo>)</mo></mrow><mrow><msup><mi>Q</mi>
177
+ <mo>*</mo></msup><mo>(</mo><mo lspace=\"0em\"
178
+ rspace=\"thinmathspace\">sampx</mo><mo>)</mo></mrow></mfrac><mo>.</mo></math>"
179
+ "\\mathbb{GOAT}_3": "<math
180
+ xmlns='http://www.w3.org/1998/Math/MathML'><msub><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi><mn>3</mn></msub></math>"
181
+ "\\array{}": ''
182
+ "\\array{1}": "<math
183
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable><mtr><mtd><mn>1</mn></mtd></mtr></mtable></mrow></math>"
184
+ "\\array{1 & 0}": "<math
185
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable><mtr><mtd><mn>1</mn></mtd>
186
+ <mtd><mn>0</mn></mtd></mtr></mtable></mrow></math>"
187
+ "\\sum_{n=1}^\\infty \\frac{1}{n} \\text{ is divergent, but } \\lim_{n \\to
188
+ \\infty} \\sum_{i=1}^n \\frac{1}{i} - \\ln n \\text{ exists.}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msubsup><mo
189
+ lspace=\"thinmathspace\" rspace=\"thinmathspace\">&Sum;</mo>
190
+ <mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow>
191
+ <mn>&infin;</mn></msubsup><mfrac><mrow><mn>1</mn></mrow><mrow><mi>n</mi></mrow></mfrac><mtext>
192
+ is divergent, but </mtext><msub><mo lspace=\"thinmathspace\"
193
+ rspace=\"thinmathspace\">lim</mo>
194
+ <mrow><mi>n</mi><mo>&rightarrow;</mo><mn>&infin;</mn></mrow></msub><msubsup><mo
195
+ lspace=\"thinmathspace\" rspace=\"thinmathspace\">&Sum;</mo>
196
+ <mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow>
197
+ <mi>n</mi></msubsup><mfrac><mrow><mn>1</mn></mrow><mrow><mi>i</mi></mrow></mfrac><mo>-</mo><mo
198
+ lspace=\"0em\" rspace=\"thinmathspace\">ln</mo><mi>n</mi><mtext>
199
+ exists.</mtext></math>"
200
+ "{\\frac{\\alpha-\\delta}{\\beta-\\gamma}}": "<math
201
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mfrac><mrow><mi>&alpha;</mi><mo>-</mo><mi>&delta;</mi></mrow><mrow><mi>&beta;</mi><mo>-</mo><mi>&gamma;</mi></mrow></mfrac></mrow></math>"
202
+ "\\mathbb{Hello}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>&Hopf;ello</mi></math>"
203
+ "{N-{N-x}}": "<math
204
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mi>N</mi><mo>-</mo><mrow><mi>N</mi><mo>-</mo><mi>x</mi></mrow></mrow></math>"
205
+ "\\sqrt{i}": "<math
206
+ xmlns='http://www.w3.org/1998/Math/MathML'><msqrt><mrow><mi>i</mi></mrow></msqrt></math>"
207
+ ? |-
208
+ \array{1 & 0 \\
209
+ 0 & 1}
210
+ : "<math
211
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable><mtr><mtd><mn>1</mn></mtd>
212
+ <mtd><mn>0</mn></mtd></mtr> <mtr><mtd><mn>0</mn></mtd>
213
+ <mtd><mn>1</mn></mtd></mtr></mtable></mrow></math>"
214
+ "\\binom{x}{2}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mfrac
215
+ linethickness=\"0\"><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></mfrac></math>"
216
+ "\\lim_{x\\to\\infty}f(x)=0": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msub><mo
217
+ lspace=\"thinmathspace\" rspace=\"thinmathspace\">lim</mo>
218
+ <mrow><mi>x</mi><mo>&rightarrow;</mo><mn>&infin;</mn></mrow></msub><mi>f</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><mn>0</mn></math>"
219
+ "{{{N-x}-x}-x}": "<math
220
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mrow><mrow><mi>N</mi><mo>-</mo><mi>x</mi></mrow><mo>-</mo><mi>x</mi></mrow><mo>-</mo><mi>x</mi></mrow></math>"
221
+ "\\underoverset{S}{\\alpha}{x=\\infty}": "<math
222
+ xmlns='http://www.w3.org/1998/Math/MathML'><munderover><mrow><mi>x</mi><mo>=</mo><mn>&infin;</mn></mrow><mrow><mi>S</mi></mrow><mrow><mi>&alpha;</mi></mrow></munderover></math>"
223
+ "\\text{ if }": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mtext> if </mtext></math>"
224
+ "-\\log(1 - X)/\\lambda": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo
225
+ lspace=\"thinthinmathspace\" rspace=\"0em\">-</mo><mo lspace=\"0em\"
226
+ rspace=\"thinmathspace\">log</mo><mo>(</mo><mn>1</mn><mo>-</mo><mi>X</mi><mo>)</mo><mo>/</mo><mi>&lambda;</mi></math>"
227
+ "\\left \\frac{x}{y} \\right|_{x=0}": "<math
228
+ xmlns='http://www.w3.org/1998/Math/MathML'><msub><mrow><mfrac><mrow><mi>x</mi></mrow><mrow><mi>y</mi></mrow></mfrac><mo>|</mo></mrow><mrow><mi>x</mi><mo>=</mo><mn>0</mn></mrow></msub></math>"
229
+ "-x": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo lspace='thinthinmathspace'
230
+ rspace='0em'>-</mo><mi>x</mi></math>"
231
+ "\\frac{N-x}{2}": "<math
232
+ xmlns='http://www.w3.org/1998/Math/MathML'><mfrac><mrow><mi>N</mi><mo>-</mo><mi>x</mi></mrow><mrow><mn>2</mn></mrow></mfrac></math>"
233
+ 2^{-3}: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msup><mn>2</mn> <mrow><mo
234
+ lspace=\"thinthinmathspace\"
235
+ rspace=\"0em\">-</mo><mn>3</mn></mrow></msup></math>"
236
+ P(x) = P^*(x)/Z: "<math
237
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>P</mi><mo>(</mo><mi>x</mi><mo>)</mo><mo>=</mo><msup><mi>P</mi>
238
+ <mo>*</mo></msup><mo>(</mo><mi>x</mi><mo>)</mo><mo>/</mo><mi>Z</mi></math>"
239
+ "\\text{if \\alpha}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mtext>if
240
+ \\alpha</mtext></math>"
241
+ "\\sum_{n=1}^\\infty \\frac{(-1)^n}{n} = \\ln 2": "<math xmlns='http://www.w3.org/1998/Math/MathML'><msubsup><mo
242
+ lspace=\"thinmathspace\" rspace=\"thinmathspace\">&Sum;</mo>
243
+ <mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow>
244
+ <mn>&infin;</mn></msubsup><mfrac><mrow><mo>(</mo><mo
245
+ lspace=\"thinthinmathspace\" rspace=\"0em\">-</mo><mn>1</mn><msup><mo>)</mo>
246
+ <mi>n</mi></msup></mrow><mrow><mi>n</mi></mrow></mfrac><mo>=</mo><mo
247
+ lspace=\"0em\" rspace=\"thinmathspace\">ln</mo><mn>2</mn></math>"
248
+ "{y-x}": "<math
249
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mi>y</mi><mo>-</mo><mi>x</mi></mrow></math>"
250
+ "\\left \\{ x \\right \\}": "<math
251
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mo>{</mo><mi>x</mi><mo>}</mo></mrow></math>"
252
+ a\text{ if}b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mtext>
253
+ if</mtext><mi>b</mi></math>"
254
+ "\\root{3}{x+y}": "<math
255
+ xmlns='http://www.w3.org/1998/Math/MathML'><mroot><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mrow><mn>3</mn></mrow></mroot></math>"
256
+ ? |-
257
+ a
258
+ <
259
+ b
260
+ : "<math
261
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>a</mi><mo>&lt;</mo><mi>b</mi></math>"
262
+ "x - x": "<math
263
+ xmlns='http://www.w3.org/1998/Math/MathML'><mi>x</mi><mo>-</mo><mi>x</mi></math>"
264
+ "{\\frac{\\alpha-{\\mathbb{GOAT}}}{\\beta-{{\\mathbb{GOAT}}-x}}}": "<math
265
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mfrac><mrow><mi>&alpha;</mi><mo>-</mo><mrow><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi></mrow></mrow><mrow><mi>&beta;</mi><mo>-</mo><mrow><mrow><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi></mrow><mo>-</mo><mi>x</mi></mrow></mrow></mfrac></mrow></math>"
266
+ "\\goat_3": "<math
267
+ xmlns='http://www.w3.org/1998/Math/MathML'><msub><mrow><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi></mrow><mn>3</mn></msub></math>"
268
+ "\\frac{\\sum_r w_r \\phi(\\sampx)}{\\sum_r w_r}": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mfrac><mrow><msub><mo
269
+ lspace='thinmathspace'
270
+ rspace='thinmathspace'>&Sum;</mo><mi>r</mi></msub><msub><mi>w</mi><mi>r</mi></msub><mi>&phi;</mi><mo>(</mo><mrow><msup><mi>x</mi><mrow><mo>(</mo><mi>r</mi><mo>)</mo></mrow></msup></mrow><mo>)</mo></mrow><mrow><msub><mo
271
+ lspace='thinmathspace'
272
+ rspace='thinmathspace'>&Sum;</mo><mi>r</mi></msub><msub><mi>w</mi><mi>r</mi></msub></mrow></mfrac></math>"
273
+ "\\frac{{N-x}}{2}": "<math
274
+ xmlns='http://www.w3.org/1998/Math/MathML'><mfrac><mrow><mrow><mi>N</mi><mo>-</mo><mi>x</mi></mrow></mrow><mrow><mn>2</mn></mrow></mfrac></math>"
275
+ "#{x}{x}": "<math
276
+ xmlns='http://www.w3.org/1998/Math/MathML'><mo>#</mo><mrow><mi>x</mi></mrow><mrow><mi>x</mi></mrow></math>"
277
+ a^b: "<math xmlns='http://www.w3.org/1998/Math/MathML'><msup><mi>a</mi>
278
+ <mi>b</mi></msup></math>"
279
+ "\\left ( x \\right": "<math
280
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mo>(</mo><mi>x</mi></mrow></math>"
281
+ "-log(1 - X)/\\lambda": "<math xmlns='http://www.w3.org/1998/Math/MathML'><mo
282
+ lspace=\"thinthinmathspace\"
283
+ rspace=\"0em\">-</mo><mi>log</mi><mo>(</mo><mn>1</mn><mo>-</mo><mi>X</mi><mo>)</mo><mo>/</mo><mi>&lambda;</mi></math>"
284
+ ? |-
285
+ \array{1 & 0 \\
286
+ 0 & 1}
287
+ : "<math
288
+ xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable><mtr><mtd><mn>1</mn></mtd>
289
+ <mtd><mn>0</mn></mtd></mtr> <mtr><mtd><mn>0</mn></mtd>
290
+ <mtd><mn>1</mn></mtd></mtr></mtable></mrow></math>"
291
+ "{\\mathbb{GOAT}}_3": "<math
292
+ xmlns='http://www.w3.org/1998/Math/MathML'><msub><mrow><mi>&Gopf;&Oopf;&Aopf;&Topf;</mi></mrow><mn>3</mn></msub></math>"
@@ -0,0 +1,265 @@
1
+ ## test/mathml.rb -- contains Ritex::Test::MathML
2
+ ## Author:: William Morgan (mailto: wmorgan-ritex@masanjin.net)
3
+ ## Copyright:: Copyright 2005 William Morgan
4
+ ## License:: GNU GPL version 2
5
+
6
+ require 'test/unit'
7
+ require 'yaml'
8
+ require 'ritex'
9
+
10
+ module Ritex
11
+
12
+ ## Module for all Ritex unit tests.
13
+ ##
14
+ ## Currently contains only one set of tests: Ritex::Test::MathML.
15
+ module Test
16
+
17
+ ## Ritex unit tests for itex->MathML conversion.
18
+ ##
19
+ ## = Preface
20
+ ##
21
+ ## Let me take a moment to express how much I love unit tests. Before
22
+ ## Ruby, I never thought they'd be a practical part of any real
23
+ ## development. But Test::Unit has made me a convert. Developing the
24
+ ## tests at the same time as writing the code has forced me to think
25
+ ## deeply about how the program functions. Having this test suite
26
+ ## around to vett every change I make has been invaluable. And best of
27
+ ## all: it's just so easy to do.
28
+ ##
29
+ ## = The test suite
30
+ ##
31
+ ## Ritex mathml output is based on itex2mml, so the mathml tests are
32
+ ## designed to ultimately look there for the correct answer. But
33
+ ## there's a level of caching in between, which a) helps people who
34
+ ## don't have itex2mml and b) allows us to "correct" itex2mml.
35
+ ##
36
+ ## Tests are run with a simple call to #cmp, e.g.:
37
+ ##
38
+ ## cmp '\int_{x=0}^1 \alpha(x)'
39
+ ##
40
+ ## The test framework first looks for the corresponding answer in the
41
+ ## key file (KEY below). If it doesn't exist, the itex2mml binary is
42
+ ## called (BIN below) to parse the string.
43
+ ##
44
+ ## = Adding new tests
45
+ ##
46
+ ## To add a new test, you need to either insert the correct mathml in
47
+ ## the key file, or compile itex2mml and have it generate the mathml
48
+ ## for you. Of course, if itex2mml doesn't do the correct thing,
49
+ ## you'll then have to go to the key file and edit the answer
50
+ ## accordingly. See the README for a list of differences between Ritex
51
+ ## mathml output and itex2mml.
52
+ ##
53
+ ## Itex2mml can be found at:
54
+ ## http://pear.math.pitt.edu/mathzilla/itex2mml.html
55
+ class MathML < ::Test::Unit::TestCase
56
+ KEY = "test/itex2mml-key.yaml"
57
+ BIN = "./itex2MML"
58
+
59
+ def setup #:nodoc:
60
+ @p = Ritex::Parser.new :mathml
61
+ @key = (File.exists?(KEY) ? YAML::load_file(KEY) : {})
62
+ @key_dirty = false
63
+ end
64
+
65
+ def teardown #:nodoc:
66
+ if @key_dirty
67
+ puts "s"
68
+ File.open(KEY, "wb") { |f| f.puts @key.to_yaml }
69
+ @key_dirty = false
70
+ end
71
+ end
72
+
73
+ ## Tests whether an itex string is converted correctly by comparing
74
+ ## it to the cached answer, or, if none is found, by running it
75
+ ## through itex2mml directly.
76
+ ##
77
+ ## If _same_as_ is given, it means the conversion of _s_ should be
78
+ ## the same as the itex2mml's rendering of _same_as_. This is mostly
79
+ ## useful for macros.
80
+ def cmp s, same_as=nil
81
+ gold = gold_standard(same_as || s)
82
+ test = @p.parse s
83
+
84
+ [gold, test].each do |l|
85
+ l.gsub!(/>[\s\n]+</, "><")
86
+ l.gsub!(/"/, "'")
87
+ end
88
+
89
+ assert_equal gold, test, "Difference in XML transform of #{s}"
90
+ end
91
+
92
+ def test_grouping
93
+ cmp 'x'
94
+ cmp '{x}'
95
+ end
96
+
97
+ def test_environments
98
+ cmp 'if'
99
+ cmp '\text{if}'
100
+ cmp '\text{ if }'
101
+ cmp '\text{if \alpha}'
102
+ cmp '\mathbb{Hello}'
103
+ cmp '\mathcal{Hello}'
104
+ end
105
+
106
+ def test_vars
107
+ cmp '\alpha'
108
+ cmp 'a+3'
109
+ cmp '\alpha + b + c'
110
+ end
111
+
112
+ def test_funcs
113
+ cmp '\sqrt{i}'
114
+ cmp '\frac{1}{2}'
115
+ cmp '\binom{x}{2}'
116
+ cmp '\root{3}{x+y}'
117
+ end
118
+
119
+ def test_scripts
120
+ cmp 'a^b'
121
+ cmp 'a_b'
122
+ cmp 'a^b_c'
123
+ end
124
+
125
+ def test_ops
126
+ cmp 'a\in S'
127
+ end
128
+
129
+ def test_lim
130
+ cmp '\lim_3'
131
+ cmp '\lim_{x\to\infty}f(x)=0'
132
+ end
133
+
134
+ def test_displaystyle
135
+ cmp 'x\textstyle{\int_0^1}\displaystyle{\int_0^1}y'
136
+ end
137
+
138
+ def test_spacing
139
+ cmp 'a ^ b'
140
+ cmp '\define { \goat }{3+4}', ''
141
+ cmp 'a\text{if}b'
142
+ cmp 'a\text{if }b'
143
+ cmp 'a\text{ if}b'
144
+ cmp 'a\text{ if }b'
145
+ cmp 'a\text{ if a fd ew s }b'
146
+ cmp ' a'
147
+ cmp ' a'
148
+ cmp '\forall x\,x<0'
149
+ cmp '\int_x f(x)\ dx'
150
+ end
151
+
152
+ def test_escaping
153
+ cmp 'a < b'
154
+ end
155
+
156
+ def test_larger
157
+ cmp 'a^{b_c} < a^b_c'
158
+ end
159
+
160
+ def test_fonts
161
+ cmp 'a\mathbb{GOAT}'
162
+ end
163
+
164
+ def test_leftright
165
+ cmp '\left ( \binom{2}{3} \right )'
166
+ end
167
+
168
+ def test_misc
169
+ cmp '\ln x'
170
+ end
171
+
172
+ def test_multiline
173
+ cmp '\mathop{monkey}
174
+ <
175
+ b'
176
+ end
177
+
178
+ def test_delimiters
179
+ cmp '\left ( x \right )'
180
+ cmp '\left \{ x \right \}'
181
+ cmp '\left ( x \right'
182
+ cmp '\left ( x \right + 3'
183
+ cmp '\left ( \frac{2}{4+x} \right )^3'
184
+ cmp '\left \frac{x}{y} \right|_{x=0}'
185
+ end
186
+
187
+ def test_arrays
188
+ cmp '\array{1}'
189
+ cmp '\array{1 & 0}'
190
+ cmp '\array{1 & 0 \\\\ 0 & 1}'
191
+ cmp '\array{1 & 0 \\\\
192
+ 0 & 1}'
193
+ end
194
+
195
+ def test_real_life
196
+ cmp '\Pr(a < X \leq b) = \int_a^b f(x)\ dx'
197
+ cmp '\int_{-\infinity}^\infinity f(x)\ dx = 1'
198
+ cmp 'F(x) = \Pr(X \leq x) \text{ for } -\infinity < x < \infinity'
199
+ cmp ' G^{-1}(x) = -\log(1 - x)/\lambda\text{ if } 0 < x < 1.'
200
+ cmp '-\log(1 - X)/\lambda'
201
+ cmp 'P(x) = P^*(x)/Z'
202
+ cmp '\sum_{n=1}^\infty \frac{(-1)^n}{n} = \ln 2'
203
+ cmp '\sum_{n=1}^\infty \frac{1}{n} \text{ is divergent, but } \lim_{n \to \infty} \sum_{i=1}^n \frac{1}{i} - \ln n \text{ exists.}'
204
+ cmp ' G(y) = \left\{\array{ 1 - e^{-\lambda y} & \text{ if } y \geq 0 \\ 0 & \text{ if } y < 0 }\right. .'
205
+ cmp '\define{\sampx}{x^{(r)}}
206
+ \frac{1}{N} \sum_r \phi(\sampx),'
207
+ cmp '\frac{\sum_r w_r \phi(\sampx)}{\sum_r w_r}'
208
+ cmp 'w_r \equiv \frac{P^*(\sampx)}{Q^*(\sampx)}.'
209
+ end
210
+
211
+ def test_overs
212
+ %w(hat bar dot ddot vec check tilde widehat widecheck widebar widevec widetilde).each do |x|
213
+ cmp "\#{x}{x}"
214
+ end
215
+ cmp '\overset{\text{n terms}}{\overbrace{1+2+\cdots+n}}'
216
+ cmp '\underoverset{S}{\alpha}{x=\infty}'
217
+ end
218
+
219
+ def test_macros
220
+ cmp '\define{\goat}{\mathbb{GOAT}}', ''
221
+ cmp '\goat_3', '{\mathbb{GOAT}}_3'
222
+ cmp '\define{\boat}[1]{#1-x}', ''
223
+ cmp '\boat{y}', '{y-x}'
224
+ cmp '\boat{\boat{N}}', '{{N-x}-x}'
225
+ cmp '\boat{\boat{\boat{N}}}', '{{{N-x}-x}-x}'
226
+ cmp '\frac{\boat{N}}{2}', '\frac{{N-x}}{2}'
227
+ cmp '\define{\float}[2]{\frac{\alpha-#1}{\beta-#2}}', ''
228
+ cmp '\float{\delta}{\gamma}', '{\frac{\alpha-\delta}{\beta-\gamma}}'
229
+ cmp '\float{\goat}{\boat{\goat}}', '{\frac{\alpha-{\mathbb{GOAT}}}{\beta-{{\mathbb{GOAT}}-x}}}'
230
+ end
231
+
232
+ def test_unary_minus
233
+ cmp '-x'
234
+ cmp 'x - x'
235
+ cmp 'x--x'
236
+ cmp 'x + - x'
237
+ cmp '\alpha - x'
238
+ cmp '\arccos - x'
239
+ cmp '\bigcup + x'
240
+ cmp '\bigcup - x'
241
+ end
242
+
243
+ private
244
+
245
+ def normalize s
246
+ s.gsub(/&/, "&amp;").gsub(/</, "&lt;").gsub(/>/, "&gt;")
247
+ end
248
+
249
+ ## Returns the correct translation of _s_, by looking in the key
250
+ ## file or, if that fails, by calling itex2mml directly.
251
+ def gold_standard s
252
+ return @key[s] if @key.member? s
253
+ ret = IO.popen(BIN, "wb+") do |io|
254
+ io.puts "$#{normalize s}$"
255
+ io.close_write
256
+ io.readlines.join.gsub(/\n/, "")
257
+ end
258
+ @key_dirty = true
259
+ @key[s] = ret
260
+ end
261
+
262
+ end
263
+
264
+ end
265
+ end