]> git.lyx.org Git - lyx.git/blob - src/tex2lyx/math.C
make tex2lyx lyxstring agnostic
[lyx.git] / src / tex2lyx / math.C
1 /** The .tex to .lyx converter
2     \author André Pönitz (2003)
3  */
4
5 // {[(
6
7 #include <config.h>
8
9 #include "tex2lyx.h"
10
11 #include <iostream>
12 #include <vector>
13
14 using std::cerr;
15 using std::endl;
16 using std::ostream;
17 using std::string;
18 using std::vector;
19
20
21 bool is_math_env(string const & name)
22 {
23         static char const * known_math_envs[] = { "equation", "equation*",
24         "eqnarray", "eqnarray*", "align", "align*", "gather", "gather*",
25         "multline", "multline*", 0};
26
27         for (char const ** what = known_math_envs; *what; ++what)
28                 if (*what == name)
29                         return true;
30         return false;
31 }
32
33
34 void parse_math(Parser & p, ostream & os, unsigned flags, const mode_type mode)
35 {
36         while (p.good()) {
37                 Token const & t = p.get_token();
38
39 #ifdef FILEDEBUG
40                 cerr << "t: " << t << " flags: " << flags << "\n";
41 #endif
42
43                 if (flags & FLAG_ITEM) {
44                         if (t.cat() == catSpace)
45                                 continue;
46
47                         flags &= ~FLAG_ITEM;
48                         if (t.cat() == catBegin) {
49                                 // skip the brace and collect everything to the next matching
50                                 // closing brace
51                                 flags |= FLAG_BRACE_LAST;
52                                 continue;
53                         }
54
55                         // handle only this single token, leave the loop if done
56                         flags |= FLAG_LEAVE;
57                 }
58
59
60                 //
61                 // cat codes
62                 //
63                 if (t.cat() == catMath) {
64                         if (mode == MATHTEXT_MODE) {
65                                 // we are inside some text mode thingy, so opening new math is allowed
66                                 Token const & n = p.get_token();
67                                 if (n.cat() == catMath) {
68                                         // TeX's $$...$$ syntax for displayed math
69                                         os << "\\[";
70                                         parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
71                                         os << "\\]";
72                                         p.get_token(); // skip the second '$' token
73                                 } else {
74                                         // simple $...$  stuff
75                                         p.putback();
76                                         os << '$';
77                                         parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
78                                         os << '$';
79                                 }
80                         }
81
82                         else if (flags & FLAG_SIMPLE) {
83                                 // this is the end of the formula
84                                 return;
85                         }
86
87                         else {
88                                 cerr << "\nmode: " << mode << endl;
89                                 p.error("something strange in the parser\n");
90                                 break;
91                         }
92                 }
93
94                 else if (t.cat() == catLetter ||
95                                t.cat() == catSpace ||
96                                t.cat() == catSuper ||
97                                t.cat() == catSub ||
98                                t.cat() == catOther ||
99                                t.cat() == catAlign ||
100                                t.cat() == catActive ||
101                                t.cat() == catParameter)
102                         os << t.character();
103
104                 else if (t.cat() == catNewline) {
105                         //if (p.next_token().cat() == catNewline) {
106                         //      p.get_token();
107                         //      handle_par(os);
108                         //} else {
109                                 os << "\n "; // note the space
110                         //}
111                 }
112
113                 else if (t.cat() == catBegin) {
114                         os << '{';
115                         parse_math(p, os, FLAG_BRACE_LAST, mode);
116                         os << '}';
117                 }
118
119                 else if (t.cat() == catEnd) {
120                         if (flags & FLAG_BRACE_LAST)
121                                 return;
122                         os << "unexpected '}' in math\n";
123                 }
124
125                 else if (t.cat() == catComment)
126                         handle_comment(p);
127
128                 //
129                 // control sequences
130                 //
131
132                 else if (t.cs() == "(") {
133                         os << "\\(";
134                         parse_math(p, os, FLAG_SIMPLE2, MATH_MODE);
135                         os << "\\)";
136                 }
137
138                 else if (t.cs() == "[") {
139                         // special handling of a few common SW user quirks
140                         p.skip_spaces();
141                         //if (p.next_token().cs() == 
142                         os << "\\[";
143                         parse_math(p, os, FLAG_EQUATION, MATH_MODE);
144                         os << "\\]";
145                 }
146
147                 else if (t.cs() == "protect")
148                         // ignore \\protect, will hopefully be re-added during output
149                         ;
150
151                 else if (t.cs() == "begin") {
152                         string const name = p.getArg('{', '}');
153                         active_environments.push_back(name);
154                         os << "\\begin{" << name << "}";
155                         if (name == "tabular")
156                                 parse_math(p, os, FLAG_END, MATHTEXT_MODE);
157                         else
158                                 parse_math(p, os, FLAG_END, mode);
159                         os << "\\end{" << name << "}";
160                 }
161
162                 else if (t.cs() == "end") {
163                         if (flags & FLAG_END) {
164                                 // eat environment name
165                                 string const name = p.getArg('{', '}');
166                                 if (name != active_environment())
167                                         p.error("\\end{" + name + "} does not match \\begin{"
168                                                 + active_environment() + "}");
169                                 active_environments.pop_back();
170                                 return;
171                         }
172                         p.error("found 'end' unexpectedly");
173                 }
174
175                 else if (t.cs() == ")") {
176                         if (flags & FLAG_SIMPLE2)
177                                 return;
178                         p.error("found '\\)' unexpectedly");
179                 }
180
181                 else if (t.cs() == "]") {
182                         if (flags & FLAG_EQUATION)
183                                 return;
184                         p.error("found '\\]' unexpectedly");
185                 }
186
187                 else if (t.cs() == "textrm" || t.cs() == "textsf" || t.cs() == "textbf"
188                                 || t.cs() == "texttt" || t.cs() == "textsc") {
189                         os << '\\' << t.cs() << '{';
190                         parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
191                         os << '}';
192                 }
193
194                 else if (t.cs() == "mbox") {
195                         os << "\\mbox{";
196                         parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
197                         os << '}';
198                 }
199
200                 else if (t.cs() == "\"") {
201                         string const name = p.verbatim_item();
202                              if (name == "a") os << 'ä';
203                         else if (name == "o") os << 'ö';
204                         else if (name == "u") os << 'ü';
205                         else if (name == "A") os << 'Ä';
206                         else if (name == "O") os << 'Ö';
207                         else if (name == "U") os << 'Ü';
208                         else os << "\"{" << name << "}";
209                 }
210
211                 else if (t.cs() == "ss")
212                         os << "ß";
213
214                 else 
215                         os << t.asInput();
216
217                 if (flags & FLAG_LEAVE) {
218                         flags &= ~FLAG_LEAVE;
219                         break;
220                 }
221         }
222 }
223
224
225
226
227 // }])