Another minor change, but this should almost get us to the point that we
[lyx.git] / src / tex2lyx / math.cpp
blobf615926efa6e2d6daf0eae8902b58891e6025c18
1 /**
2 * \file math.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author André Pönitz
8 * Full author contact details are available in file CREDITS.
9 */
11 // {[(
13 #include <config.h>
15 #include "tex2lyx.h"
17 #include <iostream>
19 using namespace std;
21 namespace lyx {
24 bool is_math_env(string const & name)
26 return known_math_environments.find(name) != known_math_environments.end();
30 void parse_math(Parser & p, ostream & os, unsigned flags, const mode_type mode)
32 while (p.good()) {
33 Token const & t = p.get_token();
35 #ifdef FILEDEBUG
36 cerr << "t: " << t << " flags: " << flags << "\n";
37 #endif
39 if (flags & FLAG_ITEM) {
40 if (t.cat() == catSpace)
41 continue;
43 flags &= ~FLAG_ITEM;
44 if (t.cat() == catBegin) {
45 // skip the brace and collect everything to the next matching
46 // closing brace
47 flags |= FLAG_BRACE_LAST;
48 continue;
51 // handle only this single token, leave the loop if done
52 flags |= FLAG_LEAVE;
57 // cat codes
59 if (t.cat() == catMath) {
60 if (mode == MATHTEXT_MODE) {
61 // we are inside some text mode thing, so opening new math is allowed
62 Token const & n = p.get_token();
63 if (n.cat() == catMath) {
64 // TeX's $$...$$ syntax for displayed math
65 os << "\\[";
66 parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
67 os << "\\]";
68 p.get_token(); // skip the second '$' token
69 } else {
70 // simple $...$ stuff
71 p.putback();
72 os << '$';
73 parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
74 os << '$';
78 else if (flags & FLAG_SIMPLE) {
79 // this is the end of the formula
80 return;
83 else {
84 cerr << "\nmode: " << mode << endl;
85 p.error("something strange in the parser\n");
86 break;
90 else if (t.cat() == catLetter ||
91 t.cat() == catSuper ||
92 t.cat() == catSub ||
93 t.cat() == catOther ||
94 t.cat() == catAlign ||
95 t.cat() == catActive ||
96 t.cat() == catParameter)
97 os << t.cs();
99 else if (t.cat() == catBegin) {
100 os << '{';
101 parse_math(p, os, FLAG_BRACE_LAST, mode);
102 os << '}';
105 else if (t.cat() == catEnd) {
106 if (flags & FLAG_BRACE_LAST)
107 return;
108 os << "unexpected '}' in math\n";
111 else if (t.cat() == catComment) {
112 if (!t.cs().empty())
113 cerr << "Ignoring comment: " << t.asInput();
114 else
115 // "%\n" combination
116 p.skip_spaces();
120 // control sequences
123 else if (t.cs() == "(") {
124 os << "\\(";
125 parse_math(p, os, FLAG_SIMPLE2, MATH_MODE);
126 os << "\\)";
129 else if (t.cs() == "[") {
130 // special handling of a few common SW user quirks
131 p.skip_spaces();
132 //if (p.next_token().cs() ==
133 os << "\\[";
134 parse_math(p, os, FLAG_EQUATION, MATH_MODE);
135 os << "\\]";
138 else if (t.cs() == "protect")
139 // ignore \\protect, will hopefully be re-added during output
142 else if (t.cs() == "begin") {
143 string const name = p.getArg('{', '}');
144 active_environments.push_back(name);
145 os << "\\begin{" << name << "}";
146 if (name == "tabular")
147 parse_math(p, os, FLAG_END, MATHTEXT_MODE);
148 else
149 parse_math(p, os, FLAG_END, mode);
150 os << "\\end{" << name << "}";
151 active_environments.pop_back();
154 else if (t.cs() == "end") {
155 if (flags & FLAG_END) {
156 // eat environment name
157 string const name = p.getArg('{', '}');
158 if (name != active_environment())
159 p.error("\\end{" + name + "} does not match \\begin{"
160 + active_environment() + "}");
161 return;
163 p.error("found 'end' unexpectedly");
166 else if (t.cs() == ")") {
167 if (flags & FLAG_SIMPLE2)
168 return;
169 p.error("found '\\)' unexpectedly");
172 else if (t.cs() == "]") {
173 if (flags & FLAG_EQUATION)
174 return;
175 p.error("found '\\]' unexpectedly");
178 else if (t.cs() == "textrm" || t.cs() == "textsf" || t.cs() == "textbf"
179 || t.cs() == "texttt" || t.cs() == "textsc"
180 || t.cs() == "text" || t.cs() == "intertext") {
181 os << '\\' << t.cs() << '{';
182 parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
183 os << '}';
186 else if (t.cs() == "tag") {
187 os << '\\' << t.cs();
188 if (p.next_token().asInput() == "*") {
189 p.get_token();
190 os << '*';
192 os << '{';
193 parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
194 os << '}';
197 else if (t.cs() == "mbox" || t.cs() == "fbox") {
198 os << "\\" << t.cs() << '{';
199 parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
200 os << '}';
203 else if (t.cs() == "\"") {
204 string const name = p.verbatim_item();
205 if (name == "a") os << '\xe4';
206 else if (name == "o") os << '\xf6';
207 else if (name == "u") os << '\xfc';
208 else if (name == "A") os << '\xc4';
209 else if (name == "O") os << '\xd6';
210 else if (name == "U") os << '\xdc';
211 else os << "\"{" << name << "}";
214 else if (t.cs() == "ss")
215 os << "\xdf";
217 else if (t.cs() == "cr") {
218 // lyx can't handle \\cr
219 cerr << "Warning: Converting TeX '\\cr' to LaTeX '\\\\'."
220 << endl;
221 os << "\\\\";
224 else
225 os << t.asInput();
227 if (flags & FLAG_LEAVE) {
228 flags &= ~FLAG_LEAVE;
229 break;
237 // }])
240 } // namespace lyx