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