1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_starmath.hxx"
26
27
28 #include <stdio.h>
29
30 #define SMDLL 1
31
32 #include <com/sun/star/i18n/UnicodeType.hpp>
33 #include <i18npool/lang.h>
34 #include <unotools/charclass.hxx>
35 #include <editeng/unolingu.hxx>
36 #include <unotools/syslocale.hxx>
37 #include "parse.hxx"
38 #ifndef _STARMATH_HRC
39 #include "starmath.hrc"
40 #endif
41 #ifndef _SMDLL_HXX
42 #include "smdll.hxx"
43 #endif
44 #include "smmod.hxx"
45 #include "config.hxx"
46
47 #include "node.hxx"
48
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::i18n;
51
52 ///////////////////////////////////////////////////////////////////////////
53
strnccmp(const String & u1,xub_StrLen nIdx,const sal_Char * s2,xub_StrLen nLen)54 static inline sal_Bool strnccmp(const String &u1, xub_StrLen nIdx,
55 const sal_Char *s2, xub_StrLen nLen)
56 {
57 return u1.EqualsIgnoreCaseAscii( s2, nIdx, nLen );
58 }
59
60 static const sal_Unicode aDelimiterTable[] =
61 {
62 ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#',
63 '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(',
64 ')', '{', '}', '[', ']', '^', '_',
65 '\0' // end of list symbol
66 };
67
68
IsDigit(sal_Unicode cChar)69 static inline sal_Bool IsDigit( sal_Unicode cChar )
70 {
71 return '0' <= cChar && cChar <= '9';
72 }
73
74 ///////////////////////////////////////////////////////////////////////////
75
SmToken()76 SmToken::SmToken() :
77 eType (TUNKNOWN),
78 cMathChar ('\0')
79 {
80 nGroup = nCol = nRow = nLevel = 0;
81 }
82
83 ///////////////////////////////////////////////////////////////////////////
84
85 struct SmTokenTableEntry
86 {
87 const sal_Char* pIdent;
88 SmTokenType eType;
89 sal_Unicode cMathChar;
90 sal_uLong nGroup;
91 sal_uInt16 nLevel;
92 };
93
94 static const SmTokenTableEntry aTokenTable[] =
95 {
96 // { "#", TPOUND, '\0', 0, 0 },
97 // { "##", TDPOUND, '\0', 0, 0 },
98 // { "&", TAND, MS_AND, TGPRODUCT, 0 },
99 // { "(", TLPARENT, MS_LPARENT, TGLBRACES, 5 }, //! 5 to continue expression
100 // { ")", TRPARENT, MS_RPARENT, TGRBRACES, 0 }, //! 0 to terminate expression
101 // { "*", TMULTIPLY, MS_MULTIPLY, TGPRODUCT, 0 },
102 // { "+", TPLUS, MS_PLUS, TGUNOPER | TGSUM, 5 },
103 // { "+-", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5 },
104 // { "-", TMINUS, MS_MINUS, TGUNOPER | TGSUM, 5 },
105 // { "-+", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5 },
106 // { ".", TPOINT, '\0', 0, 0 },
107 // { "/", TDIVIDEBY, MS_SLASH, TGPRODUCT, 0 },
108 // { "<", TLT, MS_LT, TGRELATION, 0 },
109 // { "<<", TLL, MS_LL, TGRELATION, 0 },
110 // { "<=", TLE, MS_LE, TGRELATION, 0 },
111 // { "<>", TNEQ, MS_NEQ, TGRELATION, 0},
112 // { "<?>", TPLACE, MS_PLACE, 0, 5 },
113 // { "=", TASSIGN, MS_ASSIGN, TGRELATION, 0},
114 // { ">", TGT, MS_GT, TGRELATION, 0 },
115 // { ">=", TGE, MS_GE, TGRELATION, 0 },
116 // { ">>", TGG, MS_GG, TGRELATION, 0 },
117 { "Im" , TIM, MS_IM, TGSTANDALONE, 5 },
118 { "MZ23", TDEBUG, '\0', TGATTRIBUT, 0 },
119 { "Re" , TRE, MS_RE, TGSTANDALONE, 5 },
120 { "abs", TABS, '\0', TGUNOPER, 13 },
121 { "arcosh", TACOSH, '\0', TGFUNCTION, 5 },
122 { "arcoth", TACOTH, '\0', TGFUNCTION, 5 },
123 { "acute", TACUTE, MS_ACUTE, TGATTRIBUT, 5 },
124 { "aleph" , TALEPH, MS_ALEPH, TGSTANDALONE, 5 },
125 { "alignb", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
126 { "alignc", TALIGNC, '\0', TGALIGN, 0},
127 { "alignl", TALIGNL, '\0', TGALIGN, 0},
128 { "alignm", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
129 { "alignr", TALIGNR, '\0', TGALIGN, 0},
130 { "alignt", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
131 { "and", TAND, MS_AND, TGPRODUCT, 0},
132 { "approx", TAPPROX, MS_APPROX, TGRELATION, 0},
133 { "aqua", TAQUA, '\0', TGCOLOR, 0},
134 { "arccos", TACOS, '\0', TGFUNCTION, 5},
135 { "arccot", TACOT, '\0', TGFUNCTION, 5},
136 { "arcsin", TASIN, '\0', TGFUNCTION, 5},
137 { "arctan", TATAN, '\0', TGFUNCTION, 5},
138 { "arsinh", TASINH, '\0', TGFUNCTION, 5},
139 { "artanh", TATANH, '\0', TGFUNCTION, 5},
140 { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TGSTANDALONE, 5},
141 { "bar", TBAR, MS_BAR, TGATTRIBUT, 5},
142 { "binom", TBINOM, '\0', 0, 5 },
143 { "black", TBLACK, '\0', TGCOLOR, 0},
144 { "blue", TBLUE, '\0', TGCOLOR, 0},
145 { "bold", TBOLD, '\0', TGFONTATTR, 5},
146 { "boper", TBOPER, '\0', TGPRODUCT, 0},
147 { "breve", TBREVE, MS_BREVE, TGATTRIBUT, 5},
148 { "bslash", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
149 { "cdot", TCDOT, MS_CDOT, TGPRODUCT, 0},
150 { "check", TCHECK, MS_CHECK, TGATTRIBUT, 5},
151 { "circ" , TCIRC, MS_CIRC, TGSTANDALONE, 5},
152 { "circle", TCIRCLE, MS_CIRCLE, TGATTRIBUT, 5},
153 { "color", TCOLOR, '\0', TGFONTATTR, 5},
154 { "coprod", TCOPROD, MS_COPROD, TGOPER, 5},
155 { "cos", TCOS, '\0', TGFUNCTION, 5},
156 { "cosh", TCOSH, '\0', TGFUNCTION, 5},
157 { "cot", TCOT, '\0', TGFUNCTION, 5},
158 { "coth", TCOTH, '\0', TGFUNCTION, 5},
159 { "csub", TCSUB, '\0', TGPOWER, 0},
160 { "csup", TCSUP, '\0', TGPOWER, 0},
161 { "cyan", TCYAN, '\0', TGCOLOR, 0},
162 { "dddot", TDDDOT, MS_DDDOT, TGATTRIBUT, 5},
163 { "ddot", TDDOT, MS_DDOT, TGATTRIBUT, 5},
164 { "def", TDEF, MS_DEF, TGRELATION, 0},
165 { "div", TDIV, MS_DIV, TGPRODUCT, 0},
166 { "divides", TDIVIDES, MS_LINE, TGRELATION, 0},
167 { "dlarrow" , TDLARROW, MS_DLARROW, TGSTANDALONE, 5},
168 { "dlrarrow" , TDLRARROW, MS_DLRARROW, TGSTANDALONE, 5},
169 { "dot", TDOT, MS_DOT, TGATTRIBUT, 5},
170 { "dotsaxis", TDOTSAXIS, MS_DOTSAXIS, TGSTANDALONE, 5}, // 5 to continue expression
171 { "dotsdiag", TDOTSDIAG, MS_DOTSUP, TGSTANDALONE, 5}, //
172 { "dotsdown", TDOTSDOWN, MS_DOTSDOWN, TGSTANDALONE, 5}, //
173 { "dotslow", TDOTSLOW, MS_DOTSLOW, TGSTANDALONE, 5}, //
174 { "dotsup", TDOTSUP, MS_DOTSUP, TGSTANDALONE, 5}, //
175 { "dotsvert", TDOTSVERT, MS_DOTSVERT, TGSTANDALONE, 5}, //
176 { "downarrow" , TDOWNARROW, MS_DOWNARROW, TGSTANDALONE, 5},
177 { "drarrow" , TDRARROW, MS_DRARROW, TGSTANDALONE, 5},
178 { "emptyset" , TEMPTYSET, MS_EMPTYSET, TGSTANDALONE, 5},
179 { "equiv", TEQUIV, MS_EQUIV, TGRELATION, 0},
180 { "exists", TEXISTS, MS_EXISTS, TGSTANDALONE, 5},
181 { "exp", TEXP, '\0', TGFUNCTION, 5},
182 { "fact", TFACT, MS_FACT, TGUNOPER, 5},
183 { "fixed", TFIXED, '\0', TGFONT, 0},
184 { "font", TFONT, '\0', TGFONTATTR, 5},
185 { "forall", TFORALL, MS_FORALL, TGSTANDALONE, 5},
186 { "from", TFROM, '\0', TGLIMIT, 0},
187 { "fuchsia", TFUCHSIA, '\0', TGCOLOR, 0},
188 { "func", TFUNC, '\0', TGFUNCTION, 5},
189 { "ge", TGE, MS_GE, TGRELATION, 0},
190 { "geslant", TGESLANT, MS_GESLANT, TGRELATION, 0 },
191 { "gg", TGG, MS_GG, TGRELATION, 0},
192 { "grave", TGRAVE, MS_GRAVE, TGATTRIBUT, 5},
193 { "gray", TGRAY, '\0', TGCOLOR, 0},
194 { "green", TGREEN, '\0', TGCOLOR, 0},
195 { "gt", TGT, MS_GT, TGRELATION, 0},
196 { "hat", THAT, MS_HAT, TGATTRIBUT, 5},
197 { "hbar" , THBAR, MS_HBAR, TGSTANDALONE, 5},
198 { "iiint", TIIINT, MS_IIINT, TGOPER, 5},
199 { "iint", TIINT, MS_IINT, TGOPER, 5},
200 { "in", TIN, MS_IN, TGRELATION, 0},
201 { "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
202 { "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
203 { "int", TINT, MS_INT, TGOPER, 5},
204 { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0},
205 { "ital", TITALIC, '\0', TGFONTATTR, 5},
206 { "italic", TITALIC, '\0', TGFONTATTR, 5},
207 { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TGSTANDALONE, 5},
208 { "langle", TLANGLE, MS_LANGLE, TGLBRACES, 5},
209 { "lbrace", TLBRACE, MS_LBRACE, TGLBRACES, 5},
210 { "lceil", TLCEIL, MS_LCEIL, TGLBRACES, 5},
211 { "ldbracket", TLDBRACKET, MS_LDBRACKET, TGLBRACES, 5},
212 { "ldline", TLDLINE, MS_DLINE, TGLBRACES, 5},
213 { "le", TLE, MS_LE, TGRELATION, 0},
214 { "left", TLEFT, '\0', 0, 5},
215 { "leftarrow" , TLEFTARROW, MS_LEFTARROW, TGSTANDALONE, 5},
216 { "leslant", TLESLANT, MS_LESLANT, TGRELATION, 0 },
217 { "lfloor", TLFLOOR, MS_LFLOOR, TGLBRACES, 5},
218 { "lim", TLIM, '\0', TGOPER, 5},
219 { "lime", TLIME, '\0', TGCOLOR, 0},
220 { "liminf", TLIMINF, '\0', TGOPER, 5},
221 { "limsup", TLIMSUP, '\0', TGOPER, 5},
222 { "lint", TLINT, MS_LINT, TGOPER, 5},
223 { "ll", TLL, MS_LL, TGRELATION, 0},
224 { "lline", TLLINE, MS_LINE, TGLBRACES, 5},
225 { "llint", TLLINT, MS_LLINT, TGOPER, 5},
226 { "lllint", TLLLINT, MS_LLLINT, TGOPER, 5},
227 { "ln", TLN, '\0', TGFUNCTION, 5},
228 { "log", TLOG, '\0', TGFUNCTION, 5},
229 { "lsub", TLSUB, '\0', TGPOWER, 0},
230 { "lsup", TLSUP, '\0', TGPOWER, 0},
231 { "lt", TLT, MS_LT, TGRELATION, 0},
232 { "magenta", TMAGENTA, '\0', TGCOLOR, 0},
233 { "maroon", TMAROON, '\0', TGCOLOR, 0},
234 { "matrix", TMATRIX, '\0', 0, 5},
235 { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5},
236 { "mline", TMLINE, MS_LINE, 0, 0}, //! nicht in TGRBRACES, Level 0
237 { "nabla", TNABLA, MS_NABLA, TGSTANDALONE, 5},
238 { "navy", TNAVY, '\0', TGCOLOR, 0},
239 { "nbold", TNBOLD, '\0', TGFONTATTR, 5},
240 { "ndivides", TNDIVIDES, MS_NDIVIDES, TGRELATION, 0},
241 { "neg", TNEG, MS_NEG, TGUNOPER, 5 },
242 { "neq", TNEQ, MS_NEQ, TGRELATION, 0},
243 { "newline", TNEWLINE, '\0', 0, 0},
244 { "ni", TNI, MS_NI, TGRELATION, 0},
245 { "nitalic", TNITALIC, '\0', TGFONTATTR, 5},
246 { "none", TNONE, '\0', TGLBRACES | TGRBRACES, 0},
247 { "nospace", TNOSPACE, '\0', TGSTANDALONE, 5},
248 { "notin", TNOTIN, MS_NOTIN, TGRELATION, 0},
249 { "nroot", TNROOT, MS_SQRT, TGUNOPER, 5},
250 { "nsubset", TNSUBSET, MS_NSUBSET, TGRELATION, 0 },
251 { "nsupset", TNSUPSET, MS_NSUPSET, TGRELATION, 0 },
252 { "nsubseteq", TNSUBSETEQ, MS_NSUBSETEQ, TGRELATION, 0 },
253 { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TGRELATION, 0 },
254 { "odivide", TODIVIDE, MS_ODIVIDE, TGPRODUCT, 0},
255 { "odot", TODOT, MS_ODOT, TGPRODUCT, 0},
256 { "olive", TOLIVE, '\0', TGCOLOR, 0},
257 { "ominus", TOMINUS, MS_OMINUS, TGSUM, 0},
258 { "oper", TOPER, '\0', TGOPER, 5},
259 { "oplus", TOPLUS, MS_OPLUS, TGSUM, 0},
260 { "or", TOR, MS_OR, TGSUM, 0},
261 { "ortho", TORTHO, MS_ORTHO, TGRELATION, 0},
262 { "otimes", TOTIMES, MS_OTIMES, TGPRODUCT, 0},
263 { "over", TOVER, '\0', TGPRODUCT, 0},
264 { "overbrace", TOVERBRACE, MS_OVERBRACE, TGPRODUCT, 5},
265 { "overline", TOVERLINE, '\0', TGATTRIBUT, 5},
266 { "overstrike", TOVERSTRIKE, '\0', TGATTRIBUT, 5},
267 { "owns", TNI, MS_NI, TGRELATION, 0},
268 { "parallel", TPARALLEL, MS_DLINE, TGRELATION, 0},
269 { "partial", TPARTIAL, MS_PARTIAL, TGSTANDALONE, 5 },
270 { "phantom", TPHANTOM, '\0', TGFONTATTR, 5},
271 { "plusminus", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5},
272 { "prod", TPROD, MS_PROD, TGOPER, 5},
273 { "prop", TPROP, MS_PROP, TGRELATION, 0},
274 { "purple", TPURPLE, '\0', TGCOLOR, 0},
275 { "rangle", TRANGLE, MS_RANGLE, TGRBRACES, 0}, //! 0 to terminate expression
276 { "rbrace", TRBRACE, MS_RBRACE, TGRBRACES, 0}, //
277 { "rceil", TRCEIL, MS_RCEIL, TGRBRACES, 0}, //
278 { "rdbracket", TRDBRACKET, MS_RDBRACKET, TGRBRACES, 0}, //
279 { "rdline", TRDLINE, MS_DLINE, TGRBRACES, 0}, //
280 { "red", TRED, '\0', TGCOLOR, 0},
281 { "rfloor", TRFLOOR, MS_RFLOOR, TGRBRACES, 0}, //! 0 to terminate expression
282 { "right", TRIGHT, '\0', 0, 0},
283 { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TGSTANDALONE, 5},
284 { "rline", TRLINE, MS_LINE, TGRBRACES, 0}, //! 0 to terminate expression
285 { "rsub", TRSUB, '\0', TGPOWER, 0},
286 { "rsup", TRSUP, '\0', TGPOWER, 0},
287 { "sans", TSANS, '\0', TGFONT, 0},
288 { "serif", TSERIF, '\0', TGFONT, 0},
289 { "setC" , TSETC, MS_SETC, TGSTANDALONE, 5},
290 { "setN" , TSETN, MS_SETN, TGSTANDALONE, 5},
291 { "setQ" , TSETQ, MS_SETQ, TGSTANDALONE, 5},
292 { "setR" , TSETR, MS_SETR, TGSTANDALONE, 5},
293 { "setZ" , TSETZ, MS_SETZ, TGSTANDALONE, 5},
294 { "setminus", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
295 { "silver", TSILVER, '\0', TGCOLOR, 0},
296 { "sim", TSIM, MS_SIM, TGRELATION, 0},
297 { "simeq", TSIMEQ, MS_SIMEQ, TGRELATION, 0},
298 { "sin", TSIN, '\0', TGFUNCTION, 5},
299 { "sinh", TSINH, '\0', TGFUNCTION, 5},
300 { "size", TSIZE, '\0', TGFONTATTR, 5},
301 { "slash", TSLASH, MS_SLASH, TGPRODUCT, 0 },
302 { "sqrt", TSQRT, MS_SQRT, TGUNOPER, 5},
303 { "stack", TSTACK, '\0', 0, 5},
304 { "sub", TRSUB, '\0', TGPOWER, 0},
305 { "subset", TSUBSET, MS_SUBSET, TGRELATION, 0},
306 { "subseteq", TSUBSETEQ, MS_SUBSETEQ, TGRELATION, 0},
307 { "sum", TSUM, MS_SUM, TGOPER, 5},
308 { "sup", TRSUP, '\0', TGPOWER, 0},
309 { "supset", TSUPSET, MS_SUPSET, TGRELATION, 0},
310 { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TGRELATION, 0},
311 { "tan", TTAN, '\0', TGFUNCTION, 5},
312 { "tanh", TTANH, '\0', TGFUNCTION, 5},
313 { "teal", TTEAL, '\0', TGCOLOR, 0},
314 { "tilde", TTILDE, MS_TILDE, TGATTRIBUT, 5},
315 { "times", TTIMES, MS_TIMES, TGPRODUCT, 0},
316 { "to", TTO, '\0', TGLIMIT, 0},
317 { "toward", TTOWARD, MS_RIGHTARROW, TGRELATION, 0},
318 { "transl", TTRANSL, MS_TRANSL, TGRELATION, 0},
319 { "transr", TTRANSR, MS_TRANSR, TGRELATION, 0},
320 { "underbrace", TUNDERBRACE, MS_UNDERBRACE, TGPRODUCT, 5},
321 { "underline", TUNDERLINE, '\0', TGATTRIBUT, 5},
322 { "union", TUNION, MS_UNION, TGSUM, 0},
323 { "uoper", TUOPER, '\0', TGUNOPER, 5},
324 { "uparrow" , TUPARROW, MS_UPARROW, TGSTANDALONE, 5},
325 { "vec", TVEC, MS_VEC, TGATTRIBUT, 5},
326 { "white", TWHITE, '\0', TGCOLOR, 0},
327 { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
328 { "widehat", TWIDEHAT, MS_HAT, TGATTRIBUT, 5},
329 { "widetilde", TWIDETILDE, MS_TILDE, TGATTRIBUT, 5},
330 { "wideslash", TWIDESLASH, MS_SLASH, TGPRODUCT, 0 },
331 { "widevec", TWIDEVEC, MS_VEC, TGATTRIBUT, 5},
332 { "wp" , TWP, MS_WP, TGSTANDALONE, 5},
333 { "yellow", TYELLOW, '\0', TGCOLOR, 0},
334 // { "[", TLBRACKET, MS_LBRACKET, TGLBRACES, 5}, //! 5 to continue expression
335 // { "\\", TESCAPE, '\0', 0, 5},
336 // { "]", TRBRACKET, MS_RBRACKET, TGRBRACES, 0}, //! 0 to terminate expression
337 // { "^", TRSUP, '\0', TGPOWER, 0},
338 // { "_", TRSUB, '\0', TGPOWER, 0},
339 // { "`", TSBLANK, '\0', TGBLANK, 5},
340 // { "{", TLGROUP, MS_LBRACE, 0, 5}, //! 5 to continue expression
341 // { "|", TOR, MS_OR, TGSUM, 0},
342 // { "}", TRGROUP, MS_RBRACE, 0, 0}, //! 0 to terminate expression
343 // { "~", TBLANK, '\0', TGBLANK, 5},
344 { "", TEND, '\0', 0, 0}
345 };
346
347
GetTokenTableEntry(const String & rName)348 static const SmTokenTableEntry * GetTokenTableEntry( const String &rName )
349 {
350 const SmTokenTableEntry * pRes = 0;
351 if (rName.Len())
352 {
353 sal_Int32 nEntries = sizeof( aTokenTable ) / sizeof( aTokenTable[0] );
354 for (sal_Int32 i = 0; i < nEntries; ++i)
355 {
356 if (rName.EqualsIgnoreCaseAscii( aTokenTable[i].pIdent ))
357 {
358 pRes = &aTokenTable[i];
359 break;
360 }
361 }
362
363 }
364
365 return pRes;
366 }
367
368
369 ///////////////////////////////////////////////////////////////////////////
370
371 #if OSL_DEBUG_LEVEL
372
IsDelimiter(const String & rTxt,xub_StrLen nPos)373 sal_Bool SmParser::IsDelimiter( const String &rTxt, xub_StrLen nPos )
374 // returns 'sal_True' iff cChar is '\0' or a delimeter
375 {
376 DBG_ASSERT( nPos <= rTxt.Len(), "index out of range" );
377
378 sal_Unicode cChar = rTxt.GetChar( nPos );
379 if(!cChar)
380 return sal_True;
381
382 // check if 'cChar' is in the delimeter table
383 const sal_Unicode *pDelim = &aDelimiterTable[0];
384 for ( ; *pDelim != 0; pDelim++)
385 if (*pDelim == cChar)
386 break;
387
388 sal_Bool bIsDelim = *pDelim != 0;
389
390 sal_Int16 nTypJp = SM_MOD()->GetSysLocale().GetCharClass().getType( rTxt, nPos );
391 bIsDelim |= nTypJp == com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR ||
392 nTypJp == com::sun::star::i18n::UnicodeType::CONTROL;
393
394 return bIsDelim;
395 }
396
397 #endif
398
Insert(const String & rText,sal_uInt16 nPos)399 void SmParser::Insert(const String &rText, sal_uInt16 nPos)
400 {
401 m_aBufferString.Insert(rText, nPos);
402
403 xub_StrLen nLen = rText.Len();
404 m_nBufferIndex = m_nBufferIndex + nLen;
405 m_nTokenIndex = m_nTokenIndex + nLen;
406 }
407
408
Replace(sal_uInt16 nPos,sal_uInt16 nLen,const String & rText)409 void SmParser::Replace( sal_uInt16 nPos, sal_uInt16 nLen, const String &rText )
410 {
411 DBG_ASSERT( nPos + nLen <= m_aBufferString.Len(), "argument mismatch" );
412
413 m_aBufferString.Replace( nPos, nLen, rText );
414 sal_Int16 nChg = rText.Len() - nLen;
415 m_nBufferIndex = m_nBufferIndex + nChg;
416 m_nTokenIndex = m_nTokenIndex + nChg;
417 }
418
419
420 // First character may be any alphabetic
421 const sal_Int32 coStartFlags =
422 KParseTokens::ANY_LETTER_OR_NUMBER |
423 KParseTokens::IGNORE_LEADING_WS;
424
425 // Continuing characters may be any alphanumeric or dot.
426 const sal_Int32 coContFlags =
427 ((coStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS)
428 | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
429
430 // First character for numbers, may be any numeric or dot
431 const sal_Int32 coNumStartFlags =
432 KParseTokens::ASC_DIGIT |
433 KParseTokens::ASC_DOT |
434 KParseTokens::IGNORE_LEADING_WS;
435 // Continuing characters for numbers, may be any numeric or dot.
436 const sal_Int32 coNumContFlags =
437 (coNumStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS;
438
NextToken()439 void SmParser::NextToken()
440 {
441 static const String aEmptyStr;
442
443 xub_StrLen nBufLen = m_aBufferString.Len();
444 ParseResult aRes;
445 xub_StrLen nRealStart;
446 sal_Bool bCont;
447 sal_Bool bNumStart = sal_False;
448 CharClass aCC(SM_MOD()->GetSysLocale().GetCharClass().getLocale());
449 do
450 {
451 // skip white spaces
452 while (UnicodeType::SPACE_SEPARATOR ==
453 aCC.getType( m_aBufferString, m_nBufferIndex ))
454 ++m_nBufferIndex;
455
456 sal_Int32 nStartFlags = coStartFlags;
457 sal_Int32 nContFlags = coContFlags;
458 sal_Unicode cFirstChar = m_aBufferString.GetChar( m_nBufferIndex );
459 /*
460 removed because of #i11752#
461 bNumStart = cFirstChar == '.' || ('0' <= cFirstChar && cFirstChar <= '9');
462 if (bNumStart)
463 {
464 nStartFlags = coNumStartFlags;
465 nContFlags = coNumContFlags;
466 }
467 */
468 aRes = aCC.parseAnyToken( m_aBufferString, m_nBufferIndex,
469 nStartFlags, aEmptyStr,
470 nContFlags, aEmptyStr );
471
472 // #i45779# parse numbers correctly
473 // i.e. independent from the locale setting.
474 // (note that #i11752# remains fixed)
475 if ((aRes.TokenType & KParseType::IDENTNAME) && IsDigit( cFirstChar ))
476 {
477 //! locale where '.' is decimal seperator!
478 static lang::Locale aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US ) );
479
480 ParseResult aTmpRes;
481 lang::Locale aOldLoc( aCC.getLocale() );
482 aCC.setLocale( aDotLoc );
483 aTmpRes = aCC.parsePredefinedToken(
484 KParseType::ASC_NUMBER,
485 m_aBufferString, m_nBufferIndex,
486 KParseTokens::ASC_DIGIT, aEmptyStr,
487 KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT, aEmptyStr );
488 aCC.setLocale( aOldLoc );
489 if (aTmpRes.TokenType & KParseType::ASC_NUMBER)
490 aRes.TokenType = aTmpRes.TokenType;
491 }
492
493 nRealStart = m_nBufferIndex + sal::static_int_cast< xub_StrLen >(aRes.LeadingWhiteSpace);
494 m_nBufferIndex = nRealStart;
495
496 bCont = sal_False;
497 if ( aRes.TokenType == 0 &&
498 nRealStart < nBufLen &&
499 '\n' == m_aBufferString.GetChar( nRealStart ) )
500 {
501 // keep data needed for tokens row and col entry up to date
502 ++m_Row;
503 m_nBufferIndex = m_nColOff = nRealStart + 1;
504 bCont = sal_True;
505 }
506 else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
507 {
508 String aName( m_aBufferString.Copy( nRealStart, 2 ));
509 if ( aName.EqualsAscii( "%%" ))
510 {
511 //SkipComment
512 m_nBufferIndex = nRealStart + 2;
513 while (m_nBufferIndex < nBufLen &&
514 '\n' != m_aBufferString.GetChar( m_nBufferIndex ))
515 ++m_nBufferIndex;
516 bCont = sal_True;
517 }
518 }
519
520 } while (bCont);
521
522 // set index of current token
523 m_nTokenIndex = m_nBufferIndex;
524
525 m_aCurToken.nRow = m_Row;
526 m_aCurToken.nCol = nRealStart - m_nColOff + 1;
527
528 sal_Bool bHandled = sal_True;
529 if (nRealStart >= nBufLen)
530 {
531 m_aCurToken.eType = TEND;
532 m_aCurToken.cMathChar = '\0';
533 m_aCurToken.nGroup = 0;
534 m_aCurToken.nLevel = 0;
535 m_aCurToken.aText.Erase();
536 }
537 else if ((aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
538 || (bNumStart && (aRes.TokenType & KParseType::IDENTNAME)))
539 {
540 sal_Int32 n = aRes.EndPos - nRealStart;
541 DBG_ASSERT( n >= 0, "length < 0" );
542 m_aCurToken.eType = TNUMBER;
543 m_aCurToken.cMathChar = '\0';
544 m_aCurToken.nGroup = 0;
545 m_aCurToken.nLevel = 5;
546 m_aCurToken.aText = m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) );
547
548 #if OSL_DEBUG_LEVEL > 1
549 if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) ))
550 {
551 DBG_WARNING( "identifier really finished? (compatibility!)" );
552 }
553 #endif
554 }
555 else if (aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING)
556 {
557 m_aCurToken.eType = TTEXT;
558 m_aCurToken.cMathChar = '\0';
559 m_aCurToken.nGroup = 0;
560 m_aCurToken.nLevel = 5;
561 m_aCurToken.aText = aRes.DequotedNameOrString;
562 m_aCurToken.nRow = m_Row;
563 m_aCurToken.nCol = nRealStart - m_nColOff + 2;
564 }
565 else if (aRes.TokenType & KParseType::IDENTNAME)
566 {
567 sal_Int32 n = aRes.EndPos - nRealStart;
568 DBG_ASSERT( n >= 0, "length < 0" );
569 String aName( m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ) );
570 const SmTokenTableEntry *pEntry = GetTokenTableEntry( aName );
571
572 if (pEntry)
573 {
574 m_aCurToken.eType = pEntry->eType;
575 m_aCurToken.cMathChar = pEntry->cMathChar;
576 m_aCurToken.nGroup = pEntry->nGroup;
577 m_aCurToken.nLevel = pEntry->nLevel;
578 m_aCurToken.aText.AssignAscii( pEntry->pIdent );
579 }
580 else
581 {
582 m_aCurToken.eType = TIDENT;
583 m_aCurToken.cMathChar = '\0';
584 m_aCurToken.nGroup = 0;
585 m_aCurToken.nLevel = 5;
586 m_aCurToken.aText = aName;
587
588 #if OSL_DEBUG_LEVEL > 1
589 if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) ))
590 {
591 DBG_WARNING( "identifier really finished? (compatibility!)" );
592 }
593 #endif
594 }
595 }
596 else if (aRes.TokenType == 0 && '_' == m_aBufferString.GetChar( nRealStart ))
597 {
598 m_aCurToken.eType = TRSUB;
599 m_aCurToken.cMathChar = '\0';
600 m_aCurToken.nGroup = TGPOWER;
601 m_aCurToken.nLevel = 0;
602 m_aCurToken.aText.AssignAscii( "_" );
603
604 aRes.EndPos = nRealStart + 1;
605 }
606 else if (aRes.TokenType & KParseType::BOOLEAN)
607 {
608 sal_Int32 &rnEndPos = aRes.EndPos;
609 String aName( m_aBufferString.Copy( nRealStart,
610 sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ));
611 if (2 >= aName.Len())
612 {
613 sal_Unicode ch = aName.GetChar( 0 );
614 switch (ch)
615 {
616 case '<':
617 {
618 if (m_aBufferString.Copy( nRealStart, 2 ).
619 EqualsAscii( "<<" ))
620 {
621 m_aCurToken.eType = TLL;
622 m_aCurToken.cMathChar = MS_LL;
623 m_aCurToken.nGroup = TGRELATION;
624 m_aCurToken.nLevel = 0;
625 m_aCurToken.aText.AssignAscii( "<<" );
626
627 rnEndPos = nRealStart + 2;
628 }
629 else if (m_aBufferString.Copy( nRealStart, 2 ).
630 EqualsAscii( "<=" ))
631 {
632 m_aCurToken.eType = TLE;
633 m_aCurToken.cMathChar = MS_LE;
634 m_aCurToken.nGroup = TGRELATION;
635 m_aCurToken.nLevel = 0;
636 m_aCurToken.aText.AssignAscii( "<=" );
637
638 rnEndPos = nRealStart + 2;
639 }
640 else if (m_aBufferString.Copy( nRealStart, 2 ).
641 EqualsAscii( "<>" ))
642 {
643 m_aCurToken.eType = TNEQ;
644 m_aCurToken.cMathChar = MS_NEQ;
645 m_aCurToken.nGroup = TGRELATION;
646 m_aCurToken.nLevel = 0;
647 m_aCurToken.aText.AssignAscii( "<>" );
648
649 rnEndPos = nRealStart + 2;
650 }
651 else if (m_aBufferString.Copy( nRealStart, 3 ).
652 EqualsAscii( "<?>" ))
653 {
654 m_aCurToken.eType = TPLACE;
655 m_aCurToken.cMathChar = MS_PLACE;
656 m_aCurToken.nGroup = 0;
657 m_aCurToken.nLevel = 5;
658 m_aCurToken.aText.AssignAscii( "<?>" );
659
660 rnEndPos = nRealStart + 3;
661 }
662 else
663 {
664 m_aCurToken.eType = TLT;
665 m_aCurToken.cMathChar = MS_LT;
666 m_aCurToken.nGroup = TGRELATION;
667 m_aCurToken.nLevel = 0;
668 m_aCurToken.aText.AssignAscii( "<" );
669 }
670 }
671 break;
672 case '>':
673 {
674 if (m_aBufferString.Copy( nRealStart, 2 ).
675 EqualsAscii( ">=" ))
676 {
677 m_aCurToken.eType = TGE;
678 m_aCurToken.cMathChar = MS_GE;
679 m_aCurToken.nGroup = TGRELATION;
680 m_aCurToken.nLevel = 0;
681 m_aCurToken.aText.AssignAscii( ">=" );
682
683 rnEndPos = nRealStart + 2;
684 }
685 else if (m_aBufferString.Copy( nRealStart, 2 ).
686 EqualsAscii( ">>" ))
687 {
688 m_aCurToken.eType = TGG;
689 m_aCurToken.cMathChar = MS_GG;
690 m_aCurToken.nGroup = TGRELATION;
691 m_aCurToken.nLevel = 0;
692 m_aCurToken.aText.AssignAscii( ">>" );
693
694 rnEndPos = nRealStart + 2;
695 }
696 else
697 {
698 m_aCurToken.eType = TGT;
699 m_aCurToken.cMathChar = MS_GT;
700 m_aCurToken.nGroup = TGRELATION;
701 m_aCurToken.nLevel = 0;
702 m_aCurToken.aText.AssignAscii( ">" );
703 }
704 }
705 break;
706 default:
707 bHandled = sal_False;
708 }
709 }
710 }
711 else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
712 {
713 sal_Int32 &rnEndPos = aRes.EndPos;
714 String aName( m_aBufferString.Copy( nRealStart,
715 sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ) );
716
717 if (1 == aName.Len())
718 {
719 sal_Unicode ch = aName.GetChar( 0 );
720 switch (ch)
721 {
722 case '%':
723 {
724 //! modifies aRes.EndPos
725
726 DBG_ASSERT( rnEndPos >= nBufLen ||
727 '%' != m_aBufferString.GetChar( sal::static_int_cast< xub_StrLen >(rnEndPos) ),
728 "unexpected comment start" );
729
730 // get identifier of user-defined character
731 ParseResult aTmpRes = aCC.parseAnyToken(
732 m_aBufferString, rnEndPos,
733 KParseTokens::ANY_LETTER,
734 aEmptyStr,
735 coContFlags,
736 aEmptyStr );
737
738 xub_StrLen nTmpStart = sal::static_int_cast< xub_StrLen >(rnEndPos +
739 aTmpRes.LeadingWhiteSpace);
740
741 // default setting for the case that no identifier
742 // i.e. a valid symbol-name is following the '%'
743 // character
744 m_aCurToken.eType = TTEXT;
745 m_aCurToken.cMathChar = '\0';
746 m_aCurToken.nGroup = 0;
747 m_aCurToken.nLevel = 5;
748 m_aCurToken.aText = String();
749 m_aCurToken.nRow = sal::static_int_cast< xub_StrLen >(m_Row);
750 m_aCurToken.nCol = nTmpStart - m_nColOff;
751
752 if (aTmpRes.TokenType & KParseType::IDENTNAME)
753 {
754
755 xub_StrLen n = sal::static_int_cast< xub_StrLen >(aTmpRes.EndPos - nTmpStart);
756 m_aCurToken.eType = TSPECIAL;
757 m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTmpStart-1), n+1 );
758
759 DBG_ASSERT( aTmpRes.EndPos > rnEndPos,
760 "empty identifier" );
761 if (aTmpRes.EndPos > rnEndPos)
762 rnEndPos = aTmpRes.EndPos;
763 else
764 ++rnEndPos;
765 }
766
767 // if no symbol-name was found we start-over with
768 // finding the next token right afer the '%' sign.
769 // I.e. we leave rnEndPos unmodified.
770 }
771 break;
772 case '[':
773 {
774 m_aCurToken.eType = TLBRACKET;
775 m_aCurToken.cMathChar = MS_LBRACKET;
776 m_aCurToken.nGroup = TGLBRACES;
777 m_aCurToken.nLevel = 5;
778 m_aCurToken.aText.AssignAscii( "[" );
779 }
780 break;
781 case '\\':
782 {
783 m_aCurToken.eType = TESCAPE;
784 m_aCurToken.cMathChar = '\0';
785 m_aCurToken.nGroup = 0;
786 m_aCurToken.nLevel = 5;
787 m_aCurToken.aText.AssignAscii( "\\" );
788 }
789 break;
790 case ']':
791 {
792 m_aCurToken.eType = TRBRACKET;
793 m_aCurToken.cMathChar = MS_RBRACKET;
794 m_aCurToken.nGroup = TGRBRACES;
795 m_aCurToken.nLevel = 0;
796 m_aCurToken.aText.AssignAscii( "]" );
797 }
798 break;
799 case '^':
800 {
801 m_aCurToken.eType = TRSUP;
802 m_aCurToken.cMathChar = '\0';
803 m_aCurToken.nGroup = TGPOWER;
804 m_aCurToken.nLevel = 0;
805 m_aCurToken.aText.AssignAscii( "^" );
806 }
807 break;
808 case '`':
809 {
810 m_aCurToken.eType = TSBLANK;
811 m_aCurToken.cMathChar = '\0';
812 m_aCurToken.nGroup = TGBLANK;
813 m_aCurToken.nLevel = 5;
814 m_aCurToken.aText.AssignAscii( "`" );
815 }
816 break;
817 case '{':
818 {
819 m_aCurToken.eType = TLGROUP;
820 m_aCurToken.cMathChar = MS_LBRACE;
821 m_aCurToken.nGroup = 0;
822 m_aCurToken.nLevel = 5;
823 m_aCurToken.aText.AssignAscii( "{" );
824 }
825 break;
826 case '|':
827 {
828 m_aCurToken.eType = TOR;
829 m_aCurToken.cMathChar = MS_OR;
830 m_aCurToken.nGroup = TGSUM;
831 m_aCurToken.nLevel = 0;
832 m_aCurToken.aText.AssignAscii( "|" );
833 }
834 break;
835 case '}':
836 {
837 m_aCurToken.eType = TRGROUP;
838 m_aCurToken.cMathChar = MS_RBRACE;
839 m_aCurToken.nGroup = 0;
840 m_aCurToken.nLevel = 0;
841 m_aCurToken.aText.AssignAscii( "}" );
842 }
843 break;
844 case '~':
845 {
846 m_aCurToken.eType = TBLANK;
847 m_aCurToken.cMathChar = '\0';
848 m_aCurToken.nGroup = TGBLANK;
849 m_aCurToken.nLevel = 5;
850 m_aCurToken.aText.AssignAscii( "~" );
851 }
852 break;
853 case '#':
854 {
855 if (m_aBufferString.Copy( nRealStart, 2 ).
856 EqualsAscii( "##" ))
857 {
858 m_aCurToken.eType = TDPOUND;
859 m_aCurToken.cMathChar = '\0';
860 m_aCurToken.nGroup = 0;
861 m_aCurToken.nLevel = 0;
862 m_aCurToken.aText.AssignAscii( "##" );
863
864 rnEndPos = nRealStart + 2;
865 }
866 else
867 {
868 m_aCurToken.eType = TPOUND;
869 m_aCurToken.cMathChar = '\0';
870 m_aCurToken.nGroup = 0;
871 m_aCurToken.nLevel = 0;
872 m_aCurToken.aText.AssignAscii( "#" );
873 }
874 }
875 break;
876 case '&':
877 {
878 m_aCurToken.eType = TAND;
879 m_aCurToken.cMathChar = MS_AND;
880 m_aCurToken.nGroup = TGPRODUCT;
881 m_aCurToken.nLevel = 0;
882 m_aCurToken.aText.AssignAscii( "&" );
883 }
884 break;
885 case '(':
886 {
887 m_aCurToken.eType = TLPARENT;
888 m_aCurToken.cMathChar = MS_LPARENT;
889 m_aCurToken.nGroup = TGLBRACES;
890 m_aCurToken.nLevel = 5; //! 0 to continue expression
891 m_aCurToken.aText.AssignAscii( "(" );
892 }
893 break;
894 case ')':
895 {
896 m_aCurToken.eType = TRPARENT;
897 m_aCurToken.cMathChar = MS_RPARENT;
898 m_aCurToken.nGroup = TGRBRACES;
899 m_aCurToken.nLevel = 0; //! 0 to terminate expression
900 m_aCurToken.aText.AssignAscii( ")" );
901 }
902 break;
903 case '*':
904 {
905 m_aCurToken.eType = TMULTIPLY;
906 m_aCurToken.cMathChar = MS_MULTIPLY;
907 m_aCurToken.nGroup = TGPRODUCT;
908 m_aCurToken.nLevel = 0;
909 m_aCurToken.aText.AssignAscii( "*" );
910 }
911 break;
912 case '+':
913 {
914 if (m_aBufferString.Copy( nRealStart, 2 ).
915 EqualsAscii( "+-" ))
916 {
917 m_aCurToken.eType = TPLUSMINUS;
918 m_aCurToken.cMathChar = MS_PLUSMINUS;
919 m_aCurToken.nGroup = TGUNOPER | TGSUM;
920 m_aCurToken.nLevel = 5;
921 m_aCurToken.aText.AssignAscii( "+-" );
922
923 rnEndPos = nRealStart + 2;
924 }
925 else
926 {
927 m_aCurToken.eType = TPLUS;
928 m_aCurToken.cMathChar = MS_PLUS;
929 m_aCurToken.nGroup = TGUNOPER | TGSUM;
930 m_aCurToken.nLevel = 5;
931 m_aCurToken.aText.AssignAscii( "+" );
932 }
933 }
934 break;
935 case '-':
936 {
937 if (m_aBufferString.Copy( nRealStart, 2 ).
938 EqualsAscii( "-+" ))
939 {
940 m_aCurToken.eType = TMINUSPLUS;
941 m_aCurToken.cMathChar = MS_MINUSPLUS;
942 m_aCurToken.nGroup = TGUNOPER | TGSUM;
943 m_aCurToken.nLevel = 5;
944 m_aCurToken.aText.AssignAscii( "-+" );
945
946 rnEndPos = nRealStart + 2;
947 }
948 else
949 {
950 m_aCurToken.eType = TMINUS;
951 m_aCurToken.cMathChar = MS_MINUS;
952 m_aCurToken.nGroup = TGUNOPER | TGSUM;
953 m_aCurToken.nLevel = 5;
954 m_aCurToken.aText.AssignAscii( "-" );
955 }
956 }
957 break;
958 case '.':
959 {
960 // for compatibility with SO5.2
961 // texts like .34 ...56 ... h ...78..90
962 // will be treated as numbers
963 m_aCurToken.eType = TNUMBER;
964 m_aCurToken.cMathChar = '\0';
965 m_aCurToken.nGroup = 0;
966 m_aCurToken.nLevel = 5;
967
968 xub_StrLen nTxtStart = m_nBufferIndex;
969 sal_Unicode cChar;
970 do
971 {
972 cChar = m_aBufferString.GetChar( ++m_nBufferIndex );
973 }
974 while ( cChar == '.' || IsDigit( cChar ) );
975
976 m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTxtStart),
977 sal::static_int_cast< xub_StrLen >(m_nBufferIndex - nTxtStart) );
978 aRes.EndPos = m_nBufferIndex;
979 }
980 break;
981 case '/':
982 {
983 m_aCurToken.eType = TDIVIDEBY;
984 m_aCurToken.cMathChar = MS_SLASH;
985 m_aCurToken.nGroup = TGPRODUCT;
986 m_aCurToken.nLevel = 0;
987 m_aCurToken.aText.AssignAscii( "/" );
988 }
989 break;
990 case '=':
991 {
992 m_aCurToken.eType = TASSIGN;
993 m_aCurToken.cMathChar = MS_ASSIGN;
994 m_aCurToken.nGroup = TGRELATION;
995 m_aCurToken.nLevel = 0;
996 m_aCurToken.aText.AssignAscii( "=" );
997 }
998 break;
999 default:
1000 bHandled = sal_False;
1001 }
1002 }
1003 }
1004 else
1005 bHandled = sal_False;
1006
1007 if (!bHandled)
1008 {
1009 m_aCurToken.eType = TCHARACTER;
1010 m_aCurToken.cMathChar = '\0';
1011 m_aCurToken.nGroup = 0;
1012 m_aCurToken.nLevel = 5;
1013 m_aCurToken.aText = m_aBufferString.Copy( nRealStart, 1 );
1014
1015 aRes.EndPos = nRealStart + 1;
1016 }
1017
1018 if (TEND != m_aCurToken.eType)
1019 m_nBufferIndex = sal::static_int_cast< xub_StrLen >(aRes.EndPos);
1020 }
1021
1022
1023 ////////////////////////////////////////
1024 // grammar
1025 //
1026
1027
Table()1028 void SmParser::Table()
1029 {
1030 SmNodeArray LineArray;
1031
1032 Line();
1033 while (m_aCurToken.eType == TNEWLINE)
1034 {
1035 NextToken();
1036 Line();
1037 }
1038
1039 if (m_aCurToken.eType != TEND)
1040 Error(PE_UNEXPECTED_CHAR);
1041
1042 sal_uLong n = m_aNodeStack.Count();
1043
1044 LineArray.resize(n);
1045
1046 for (sal_uLong i = 0; i < n; i++)
1047 LineArray[n - (i + 1)] = m_aNodeStack.Pop();
1048
1049 SmStructureNode *pSNode = new SmTableNode(m_aCurToken);
1050 pSNode->SetSubNodes(LineArray);
1051 m_aNodeStack.Push(pSNode);
1052 }
1053
1054
Align()1055 void SmParser::Align()
1056 // parse alignment info (if any), then go on with rest of expression
1057 {
1058 SmStructureNode *pSNode = 0;
1059 sal_Bool bNeedGroupClose = sal_False;
1060
1061 if (TokenInGroup(TGALIGN))
1062 {
1063 if (CONVERT_40_TO_50 == GetConversion())
1064 // encapsulate expression to be aligned in group braces
1065 // (here group-open brace)
1066 { Insert('{', GetTokenIndex());
1067 bNeedGroupClose = sal_True;
1068
1069 // get first valid align statement in sequence
1070 // (the dominant one in 4.0) and erase all others (especially old
1071 // discarded tokens) from command string.
1072 while (TokenInGroup(TGALIGN))
1073 {
1074 if (TokenInGroup(TGDISCARDED) || pSNode)
1075 {
1076 m_nBufferIndex = GetTokenIndex();
1077 m_aBufferString.Erase(m_nBufferIndex, m_aCurToken.aText.Len());
1078 }
1079 else
1080 pSNode = new SmAlignNode(m_aCurToken);
1081
1082 NextToken();
1083 }
1084 }
1085 else
1086 {
1087 pSNode = new SmAlignNode(m_aCurToken);
1088
1089 NextToken();
1090
1091 // allow for just one align statement in 5.0
1092 if (CONVERT_40_TO_50 != GetConversion() && TokenInGroup(TGALIGN))
1093 { Error(PE_DOUBLE_ALIGN);
1094 return;
1095 }
1096 }
1097 }
1098
1099 Expression();
1100
1101 if (bNeedGroupClose)
1102 Insert('}', GetTokenIndex());
1103
1104 if (pSNode)
1105 { pSNode->SetSubNodes(m_aNodeStack.Pop(), 0);
1106 m_aNodeStack.Push(pSNode);
1107 }
1108 }
1109
1110
Line()1111 void SmParser::Line()
1112 {
1113 sal_uInt16 n = 0;
1114 SmNodeArray ExpressionArray;
1115
1116 ExpressionArray.resize(n);
1117
1118 // start with single expression that may have an alignment statement
1119 // (and go on with expressions that must not have alignment
1120 // statements in 'while' loop below. See also 'Expression()'.)
1121 if (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE)
1122 { Align();
1123 ExpressionArray.resize(++n);
1124 ExpressionArray[n - 1] = m_aNodeStack.Pop();
1125 }
1126
1127 while (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE)
1128 { if (CONVERT_40_TO_50 != GetConversion())
1129 Expression();
1130 else
1131 Align();
1132 ExpressionArray.resize(++n);
1133 ExpressionArray[n - 1] = m_aNodeStack.Pop();
1134 }
1135
1136 SmStructureNode *pSNode = new SmLineNode(m_aCurToken);
1137 pSNode->SetSubNodes(ExpressionArray);
1138 m_aNodeStack.Push(pSNode);
1139 }
1140
1141
Expression()1142 void SmParser::Expression()
1143 {
1144 sal_Bool bUseExtraSpaces = sal_True;
1145 SmNode *pNode = m_aNodeStack.Pop();
1146 if (pNode)
1147 {
1148 if (pNode->GetToken().eType == TNOSPACE)
1149 bUseExtraSpaces = sal_False;
1150 else
1151 m_aNodeStack.Push(pNode); // push the node from above again (now to be used as argument to this current 'nospace' node)
1152 }
1153
1154 sal_uInt16 n = 0;
1155 SmNodeArray RelationArray;
1156
1157 RelationArray.resize(n);
1158
1159 Relation();
1160 RelationArray.resize(++n);
1161 RelationArray[n - 1] = m_aNodeStack.Pop();
1162
1163 while (m_aCurToken.nLevel >= 4)
1164 { Relation();
1165 RelationArray.resize(++n);
1166 RelationArray[n - 1] = m_aNodeStack.Pop();
1167 }
1168
1169 SmExpressionNode *pSNode = new SmExpressionNode(m_aCurToken);
1170 pSNode->SetSubNodes(RelationArray);
1171 pSNode->SetUseExtraSpaces(bUseExtraSpaces);
1172 m_aNodeStack.Push(pSNode);
1173 }
1174
1175
Relation()1176 void SmParser::Relation()
1177 {
1178 Sum();
1179 while (TokenInGroup(TGRELATION))
1180 {
1181 SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken);
1182 SmNode *pFirst = m_aNodeStack.Pop();
1183
1184 OpSubSup();
1185 SmNode *pSecond = m_aNodeStack.Pop();
1186
1187 Sum();
1188
1189 pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop());
1190 m_aNodeStack.Push(pSNode);
1191 }
1192 }
1193
1194
Sum()1195 void SmParser::Sum()
1196 {
1197 Product();
1198 while (TokenInGroup(TGSUM))
1199 {
1200 SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken);
1201 SmNode *pFirst = m_aNodeStack.Pop();
1202
1203 OpSubSup();
1204 SmNode *pSecond = m_aNodeStack.Pop();
1205
1206 Product();
1207
1208 pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop());
1209 m_aNodeStack.Push(pSNode);
1210 }
1211 }
1212
1213
Product()1214 void SmParser::Product()
1215 {
1216 Power();
1217
1218 while (TokenInGroup(TGPRODUCT))
1219 { SmStructureNode *pSNode;
1220 SmNode *pFirst = m_aNodeStack.Pop(),
1221 *pOper;
1222 sal_Bool bSwitchArgs = sal_False;
1223
1224 SmTokenType eType = m_aCurToken.eType;
1225 switch (eType)
1226 {
1227 case TOVER:
1228 pSNode = new SmBinVerNode(m_aCurToken);
1229 pOper = new SmRectangleNode(m_aCurToken);
1230 NextToken();
1231 break;
1232
1233 case TBOPER:
1234 pSNode = new SmBinHorNode(m_aCurToken);
1235
1236 NextToken();
1237
1238 GlyphSpecial();
1239 pOper = m_aNodeStack.Pop();
1240 break;
1241
1242 case TOVERBRACE :
1243 case TUNDERBRACE :
1244 pSNode = new SmVerticalBraceNode(m_aCurToken);
1245 pOper = new SmMathSymbolNode(m_aCurToken);
1246
1247 NextToken();
1248 break;
1249
1250 case TWIDEBACKSLASH:
1251 case TWIDESLASH:
1252 {
1253 SmBinDiagonalNode *pSTmp = new SmBinDiagonalNode(m_aCurToken);
1254 pSTmp->SetAscending(eType == TWIDESLASH);
1255 pSNode = pSTmp;
1256
1257 pOper = new SmPolyLineNode(m_aCurToken);
1258 NextToken();
1259
1260 bSwitchArgs =sal_True;
1261 break;
1262 }
1263
1264 default:
1265 pSNode = new SmBinHorNode(m_aCurToken);
1266
1267 OpSubSup();
1268 pOper = m_aNodeStack.Pop();
1269 }
1270
1271 Power();
1272
1273 if (bSwitchArgs)
1274 //! vgl siehe SmBinDiagonalNode::Arrange
1275 pSNode->SetSubNodes(pFirst, m_aNodeStack.Pop(), pOper);
1276 else
1277 pSNode->SetSubNodes(pFirst, pOper, m_aNodeStack.Pop());
1278 m_aNodeStack.Push(pSNode);
1279 }
1280 }
1281
1282
SubSup(sal_uLong nActiveGroup)1283 void SmParser::SubSup(sal_uLong nActiveGroup)
1284 {
1285 DBG_ASSERT(nActiveGroup == TGPOWER || nActiveGroup == TGLIMIT,
1286 "Sm: falsche Tokengruppe");
1287
1288 if (!TokenInGroup(nActiveGroup))
1289 // already finish
1290 return;
1291
1292 SmSubSupNode *pNode = new SmSubSupNode(m_aCurToken);
1293 //! Of course 'm_aCurToken' is just the first sub-/supscript token.
1294 //! It should be of no further interest. The positions of the
1295 //! sub-/supscripts will be identified by the corresponding subnodes
1296 //! index in the 'aSubNodes' array (enum value from 'SmSubSup').
1297
1298 pNode->SetUseLimits(nActiveGroup == TGLIMIT);
1299
1300 // initialize subnodes array
1301 SmNodeArray aSubNodes;
1302 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1303 aSubNodes[0] = m_aNodeStack.Pop();
1304 for (sal_uInt16 i = 1; i < aSubNodes.size(); i++)
1305 aSubNodes[i] = NULL;
1306
1307 // process all sub-/supscripts
1308 int nIndex = 0;
1309 while (TokenInGroup(nActiveGroup))
1310 { SmTokenType eType (m_aCurToken.eType);
1311
1312 // skip sub-/supscript token
1313 NextToken();
1314
1315 // get sub-/supscript node on top of stack
1316 if (eType == TFROM || eType == TTO)
1317 {
1318 // parse limits in old 4.0 and 5.0 style
1319 Relation();
1320 }
1321 else
1322 Term();
1323
1324 switch (eType)
1325 { case TRSUB : nIndex = (int) RSUB; break;
1326 case TRSUP : nIndex = (int) RSUP; break;
1327 case TFROM :
1328 case TCSUB : nIndex = (int) CSUB; break;
1329 case TTO :
1330 case TCSUP : nIndex = (int) CSUP; break;
1331 case TLSUB : nIndex = (int) LSUB; break;
1332 case TLSUP : nIndex = (int) LSUP; break;
1333 default :
1334 DBG_ASSERT(sal_False, "Sm: unbekannter Fall");
1335 }
1336 nIndex++;
1337 DBG_ASSERT(1 <= nIndex && nIndex <= 1 + SUBSUP_NUM_ENTRIES,
1338 "SmParser::Power() : sub-/supscript index falsch");
1339
1340 // set sub-/supscript if not already done
1341 if (aSubNodes[nIndex] != NULL)
1342 Error(PE_DOUBLE_SUBSUPSCRIPT);
1343 aSubNodes[nIndex] = m_aNodeStack.Pop();
1344 }
1345
1346 pNode->SetSubNodes(aSubNodes);
1347 m_aNodeStack.Push(pNode);
1348 }
1349
1350
OpSubSup()1351 void SmParser::OpSubSup()
1352 {
1353 // push operator symbol
1354 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken));
1355 // skip operator token
1356 NextToken();
1357 // get sub- supscripts if any
1358 if (TokenInGroup(TGPOWER))
1359 SubSup(TGPOWER);
1360 }
1361
1362
Power()1363 void SmParser::Power()
1364 {
1365 // get body for sub- supscripts on top of stack
1366 Term();
1367
1368 SubSup(TGPOWER);
1369 }
1370
1371
Blank()1372 void SmParser::Blank()
1373 {
1374 DBG_ASSERT(TokenInGroup(TGBLANK), "Sm : falsches Token");
1375 SmBlankNode *pBlankNode = new SmBlankNode(m_aCurToken);
1376
1377 while (TokenInGroup(TGBLANK))
1378 {
1379 pBlankNode->IncreaseBy(m_aCurToken);
1380 NextToken();
1381 }
1382
1383 // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist
1384 if ( m_aCurToken.eType == TNEWLINE ||
1385 (m_aCurToken.eType == TEND && SM_MOD()->GetConfig()->IsIgnoreSpacesRight()) )
1386 {
1387 pBlankNode->Clear();
1388 }
1389
1390 m_aNodeStack.Push(pBlankNode);
1391 }
1392
1393
Term()1394 void SmParser::Term()
1395 {
1396 switch (m_aCurToken.eType)
1397 {
1398 case TESCAPE :
1399 Escape();
1400 break;
1401
1402 case TNOSPACE :
1403 case TLGROUP :
1404 {
1405 bool bNoSpace = m_aCurToken.eType == TNOSPACE;
1406 if (bNoSpace) // push 'no space' node and continue to parse expression
1407 {
1408 m_aNodeStack.Push(new SmExpressionNode(m_aCurToken));
1409 NextToken();
1410 }
1411 if (m_aCurToken.eType != TLGROUP)
1412 {
1413 m_aNodeStack.Pop(); // get rid of the 'no space' node pushed above
1414 Term();
1415 }
1416 else
1417 {
1418 NextToken();
1419
1420 // allow for empty group
1421 if (m_aCurToken.eType == TRGROUP)
1422 {
1423 if (bNoSpace) // get rid of the 'no space' node pushed above
1424 m_aNodeStack.Pop();
1425 SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken);
1426 pSNode->SetSubNodes(NULL, NULL);
1427 m_aNodeStack.Push(pSNode);
1428
1429 NextToken();
1430 }
1431 else // go as usual
1432 {
1433 Align();
1434 if (m_aCurToken.eType != TRGROUP)
1435 Error(PE_RGROUP_EXPECTED);
1436 else
1437 NextToken();
1438 }
1439 }
1440 }
1441 break;
1442
1443 case TLEFT :
1444 Brace();
1445 break;
1446
1447 case TBLANK :
1448 case TSBLANK :
1449 Blank();
1450 break;
1451
1452 case TTEXT :
1453 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_TEXT));
1454 NextToken();
1455 break;
1456 case TIDENT :
1457 case TCHARACTER :
1458 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_VARIABLE));
1459 NextToken();
1460 break;
1461 case TNUMBER :
1462 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_NUMBER));
1463 NextToken();
1464 break;
1465
1466 case TLEFTARROW :
1467 case TRIGHTARROW :
1468 case TUPARROW :
1469 case TDOWNARROW :
1470 case TSETN :
1471 case TSETZ :
1472 case TSETQ :
1473 case TSETR :
1474 case TSETC :
1475 case THBAR :
1476 case TLAMBDABAR :
1477 case TCIRC :
1478 case TDRARROW :
1479 case TDLARROW :
1480 case TDLRARROW :
1481 case TBACKEPSILON :
1482 case TALEPH :
1483 case TIM :
1484 case TRE :
1485 case TWP :
1486 case TEMPTYSET :
1487 case TINFINITY :
1488 case TEXISTS :
1489 case TFORALL :
1490 case TPARTIAL :
1491 case TNABLA :
1492 case TTOWARD :
1493 case TDOTSAXIS :
1494 case TDOTSDIAG :
1495 case TDOTSDOWN :
1496 case TDOTSLOW :
1497 case TDOTSUP :
1498 case TDOTSVERT :
1499 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken));
1500 NextToken();
1501 break;
1502
1503 case TPLACE:
1504 m_aNodeStack.Push(new SmPlaceNode(m_aCurToken));
1505 NextToken();
1506 break;
1507
1508 case TSPECIAL:
1509 Special();
1510 break;
1511
1512 case TBINOM:
1513 Binom();
1514 break;
1515
1516 case TSTACK:
1517 Stack();
1518 break;
1519
1520 case TMATRIX:
1521 Matrix();
1522 break;
1523
1524 default:
1525 if (TokenInGroup(TGLBRACES))
1526 { Brace();
1527 }
1528 else if (TokenInGroup(TGOPER))
1529 { Operator();
1530 }
1531 else if (TokenInGroup(TGUNOPER))
1532 { UnOper();
1533 }
1534 else if ( TokenInGroup(TGATTRIBUT)
1535 || TokenInGroup(TGFONTATTR))
1536 { SmStructureNodeArray aArray;
1537
1538 sal_Bool bIsAttr;
1539 sal_uInt16 n = 0;
1540 while (sal_True == (bIsAttr = TokenInGroup(TGATTRIBUT))
1541 || TokenInGroup(TGFONTATTR))
1542 { aArray.resize(n + 1);
1543
1544 if (bIsAttr)
1545 Attribut();
1546 else
1547 FontAttribut();
1548
1549 // check if casting in following line is ok
1550 DBG_ASSERT(!m_aNodeStack.Top()->IsVisible(), "Sm : Ooops...");
1551
1552 aArray[n] = (SmStructureNode *) m_aNodeStack.Pop();
1553 n++;
1554 }
1555
1556 Power();
1557
1558 SmNode *pFirstNode = m_aNodeStack.Pop();
1559 while (n > 0)
1560 { aArray[n - 1]->SetSubNodes(0, pFirstNode);
1561 pFirstNode = aArray[n - 1];
1562 n--;
1563 }
1564 m_aNodeStack.Push(pFirstNode);
1565 }
1566 else if (TokenInGroup(TGFUNCTION))
1567 { if (CONVERT_40_TO_50 != GetConversion())
1568 { Function();
1569 }
1570 else // encapsulate old 4.0 style parsing in braces
1571 {
1572 // insert opening brace
1573 Insert('{', GetTokenIndex());
1574
1575 //
1576 // parse in 4.0 style
1577 //
1578 Function();
1579
1580 SmNode *pFunc = m_aNodeStack.Pop();
1581
1582 if (m_aCurToken.eType == TLPARENT)
1583 { Term();
1584 }
1585 else
1586 { Align();
1587 }
1588
1589 // insert closing brace
1590 Insert('}', GetTokenIndex());
1591
1592 SmStructureNode *pSNode = new SmExpressionNode(pFunc->GetToken());
1593 pSNode->SetSubNodes(pFunc, m_aNodeStack.Pop());
1594 m_aNodeStack.Push(pSNode);
1595 }
1596 }
1597 else
1598 Error(PE_UNEXPECTED_CHAR);
1599 }
1600 }
1601
1602
Escape()1603 void SmParser::Escape()
1604 {
1605 NextToken();
1606
1607 sal_Unicode cChar;
1608 switch (m_aCurToken.eType)
1609 { case TLPARENT : cChar = MS_LPARENT; break;
1610 case TRPARENT : cChar = MS_RPARENT; break;
1611 case TLBRACKET : cChar = MS_LBRACKET; break;
1612 case TRBRACKET : cChar = MS_RBRACKET; break;
1613 case TLDBRACKET : cChar = MS_LDBRACKET; break;
1614 case TRDBRACKET : cChar = MS_RDBRACKET; break;
1615 case TLBRACE :
1616 case TLGROUP : cChar = MS_LBRACE; break;
1617 case TRBRACE :
1618 case TRGROUP : cChar = MS_RBRACE; break;
1619 case TLANGLE : cChar = MS_LANGLE; break;
1620 case TRANGLE : cChar = MS_RANGLE; break;
1621 case TLCEIL : cChar = MS_LCEIL; break;
1622 case TRCEIL : cChar = MS_RCEIL; break;
1623 case TLFLOOR : cChar = MS_LFLOOR; break;
1624 case TRFLOOR : cChar = MS_RFLOOR; break;
1625 case TLLINE :
1626 case TRLINE : cChar = MS_LINE; break;
1627 case TLDLINE :
1628 case TRDLINE : cChar = MS_DLINE; break;
1629 default:
1630 Error(PE_UNEXPECTED_TOKEN);
1631 }
1632
1633 SmNode *pNode = new SmMathSymbolNode(m_aCurToken);
1634 m_aNodeStack.Push(pNode);
1635
1636 NextToken();
1637 }
1638
1639
Operator()1640 void SmParser::Operator()
1641 {
1642 if (TokenInGroup(TGOPER))
1643 { SmStructureNode *pSNode = new SmOperNode(m_aCurToken);
1644
1645 // put operator on top of stack
1646 Oper();
1647
1648 if (TokenInGroup(TGLIMIT) || TokenInGroup(TGPOWER))
1649 SubSup(m_aCurToken.nGroup);
1650 SmNode *pOperator = m_aNodeStack.Pop();
1651
1652 // get argument
1653 Power();
1654
1655 pSNode->SetSubNodes(pOperator, m_aNodeStack.Pop());
1656 m_aNodeStack.Push(pSNode);
1657 }
1658 }
1659
1660
Oper()1661 void SmParser::Oper()
1662 {
1663 SmTokenType eType (m_aCurToken.eType);
1664 SmNode *pNode = NULL;
1665
1666 switch (eType)
1667 {
1668 case TSUM :
1669 case TPROD :
1670 case TCOPROD :
1671 case TINT :
1672 case TIINT :
1673 case TIIINT :
1674 case TLINT :
1675 case TLLINT :
1676 case TLLLINT :
1677 pNode = new SmMathSymbolNode(m_aCurToken);
1678 break;
1679
1680 case TLIM :
1681 case TLIMSUP :
1682 case TLIMINF :
1683 {
1684 const sal_Char* pLim = 0;
1685 switch (eType)
1686 {
1687 case TLIM : pLim = "lim"; break;
1688 case TLIMSUP : pLim = "lim sup"; break;
1689 case TLIMINF : pLim = "lim inf"; break;
1690 default:
1691 break;
1692 }
1693 if( pLim )
1694 m_aCurToken.aText.AssignAscii( pLim );
1695 pNode = new SmTextNode(m_aCurToken, FNT_TEXT);
1696 }
1697 break;
1698
1699 case TOVERBRACE :
1700 case TUNDERBRACE :
1701 pNode = new SmMathSymbolNode(m_aCurToken);
1702 break;
1703
1704 case TOPER :
1705 NextToken();
1706
1707 DBG_ASSERT(m_aCurToken.eType == TSPECIAL, "Sm: falsches Token");
1708 pNode = new SmGlyphSpecialNode(m_aCurToken);
1709 break;
1710
1711 default :
1712 DBG_ASSERT(0, "Sm: unbekannter Fall");
1713 }
1714 m_aNodeStack.Push(pNode);
1715
1716 NextToken();
1717 }
1718
1719
UnOper()1720 void SmParser::UnOper()
1721 {
1722 DBG_ASSERT(TokenInGroup(TGUNOPER), "Sm: falsches Token");
1723
1724 SmToken aNodeToken = m_aCurToken;
1725 SmTokenType eType = m_aCurToken.eType;
1726 sal_Bool bIsPostfix = eType == TFACT;
1727
1728 SmStructureNode *pSNode;
1729 SmNode *pOper = 0,
1730 *pExtra = 0,
1731 *pArg;
1732
1733 switch (eType)
1734 {
1735 case TABS :
1736 case TSQRT :
1737 NextToken();
1738 break;
1739
1740 case TNROOT :
1741 NextToken();
1742 Power();
1743 pExtra = m_aNodeStack.Pop();
1744 break;
1745
1746 case TUOPER :
1747 NextToken();
1748 GlyphSpecial();
1749 pOper = m_aNodeStack.Pop();
1750 break;
1751
1752 case TPLUS :
1753 case TMINUS :
1754 case TPLUSMINUS :
1755 case TMINUSPLUS :
1756 case TNEG :
1757 case TFACT :
1758 OpSubSup();
1759 pOper = m_aNodeStack.Pop();
1760 break;
1761
1762 default :
1763 Error(PE_UNOPER_EXPECTED);
1764 }
1765
1766 // get argument
1767 Power();
1768 pArg = m_aNodeStack.Pop();
1769
1770 if (eType == TABS)
1771 { pSNode = new SmBraceNode(aNodeToken);
1772 pSNode->SetScaleMode(SCALE_HEIGHT);
1773
1774 // build nodes for left & right lines
1775 // (text, group, level of the used token are of no interrest here)
1776 // we'll use row & column of the keyword for abs
1777 aNodeToken.eType = TABS;
1778 //
1779 aNodeToken.cMathChar = MS_LINE;
1780 SmNode* pLeft = new SmMathSymbolNode(aNodeToken);
1781 //
1782 aNodeToken.cMathChar = MS_LINE;
1783 SmNode* pRight = new SmMathSymbolNode(aNodeToken);
1784
1785 pSNode->SetSubNodes(pLeft, pArg, pRight);
1786 }
1787 else if (eType == TSQRT || eType == TNROOT)
1788 { pSNode = new SmRootNode(aNodeToken);
1789 pOper = new SmRootSymbolNode(aNodeToken);
1790 pSNode->SetSubNodes(pExtra, pOper, pArg);
1791 }
1792 else
1793 { pSNode = new SmUnHorNode(aNodeToken);
1794
1795 if (bIsPostfix)
1796 pSNode->SetSubNodes(pArg, pOper);
1797 else
1798 // prefix operator
1799 pSNode->SetSubNodes(pOper, pArg);
1800 }
1801
1802 m_aNodeStack.Push(pSNode);
1803 }
1804
1805
Attribut()1806 void SmParser::Attribut()
1807 {
1808 DBG_ASSERT(TokenInGroup(TGATTRIBUT), "Sm: falsche Tokengruppe");
1809
1810 SmStructureNode *pSNode = new SmAttributNode(m_aCurToken);
1811 SmNode *pAttr;
1812 SmScaleMode eScaleMode = SCALE_NONE;
1813
1814 // get appropriate node for the attribut itself
1815 switch (m_aCurToken.eType)
1816 { case TUNDERLINE :
1817 case TOVERLINE :
1818 case TOVERSTRIKE :
1819 pAttr = new SmRectangleNode(m_aCurToken);
1820 eScaleMode = SCALE_WIDTH;
1821 break;
1822
1823 case TWIDEVEC :
1824 case TWIDEHAT :
1825 case TWIDETILDE :
1826 pAttr = new SmMathSymbolNode(m_aCurToken);
1827 eScaleMode = SCALE_WIDTH;
1828 break;
1829
1830 default :
1831 pAttr = new SmMathSymbolNode(m_aCurToken);
1832 }
1833
1834 NextToken();
1835
1836 pSNode->SetSubNodes(pAttr, 0);
1837 pSNode->SetScaleMode(eScaleMode);
1838 m_aNodeStack.Push(pSNode);
1839 }
1840
1841
FontAttribut()1842 void SmParser::FontAttribut()
1843 {
1844 DBG_ASSERT(TokenInGroup(TGFONTATTR), "Sm: falsche Tokengruppe");
1845
1846 switch (m_aCurToken.eType)
1847 {
1848 case TITALIC :
1849 case TNITALIC :
1850 case TBOLD :
1851 case TNBOLD :
1852 case TPHANTOM :
1853 m_aNodeStack.Push(new SmFontNode(m_aCurToken));
1854 NextToken();
1855 break;
1856
1857 case TSIZE :
1858 FontSize();
1859 break;
1860
1861 case TFONT :
1862 Font();
1863 break;
1864
1865 case TCOLOR :
1866 Color();
1867 break;
1868
1869 default :
1870 DBG_ASSERT(0, "Sm: unbekannter Fall");
1871 }
1872 }
1873
1874
Color()1875 void SmParser::Color()
1876 {
1877 DBG_ASSERT(m_aCurToken.eType == TCOLOR, "Sm : Ooops...");
1878
1879 // last color rules, get that one
1880 SmToken aToken;
1881 do
1882 { NextToken();
1883
1884 if (TokenInGroup(TGCOLOR))
1885 { aToken = m_aCurToken;
1886 NextToken();
1887 }
1888 else
1889 Error(PE_COLOR_EXPECTED);
1890 } while (m_aCurToken.eType == TCOLOR);
1891
1892 m_aNodeStack.Push(new SmFontNode(aToken));
1893 }
1894
1895
Font()1896 void SmParser::Font()
1897 {
1898 DBG_ASSERT(m_aCurToken.eType == TFONT, "Sm : Ooops...");
1899
1900 // last font rules, get that one
1901 SmToken aToken;
1902 do
1903 { NextToken();
1904
1905 if (TokenInGroup(TGFONT))
1906 { aToken = m_aCurToken;
1907 NextToken();
1908 }
1909 else
1910 Error(PE_FONT_EXPECTED);
1911 } while (m_aCurToken.eType == TFONT);
1912
1913 m_aNodeStack.Push(new SmFontNode(aToken));
1914 }
1915
1916
1917 // gets number used as arguments in Math formulas (e.g. 'size' command)
1918 // Format: no negative numbers, must start with a digit, no exponent notation, ...
lcl_IsNumber(const UniString & rText)1919 sal_Bool lcl_IsNumber(const UniString& rText)
1920 {
1921 sal_Bool bPoint = sal_False;
1922 const sal_Unicode* pBuffer = rText.GetBuffer();
1923 for(xub_StrLen nPos = 0; nPos < rText.Len(); nPos++, pBuffer++)
1924 {
1925 const sal_Unicode cChar = *pBuffer;
1926 if(cChar == '.')
1927 {
1928 if(bPoint)
1929 return sal_False;
1930 else
1931 bPoint = sal_True;
1932 }
1933 else if ( !IsDigit( cChar ) )
1934 return sal_False;
1935 }
1936 return sal_True;
1937 }
1938
FontSize()1939 void SmParser::FontSize()
1940 {
1941 DBG_ASSERT(m_aCurToken.eType == TSIZE, "Sm : Ooops...");
1942
1943 sal_uInt16 Type;
1944 SmFontNode *pFontNode = new SmFontNode(m_aCurToken);
1945
1946 NextToken();
1947
1948 switch (m_aCurToken.eType)
1949 {
1950 case TNUMBER: Type = FNTSIZ_ABSOLUT; break;
1951 case TPLUS: Type = FNTSIZ_PLUS; break;
1952 case TMINUS: Type = FNTSIZ_MINUS; break;
1953 case TMULTIPLY: Type = FNTSIZ_MULTIPLY; break;
1954 case TDIVIDEBY: Type = FNTSIZ_DIVIDE; break;
1955
1956 default:
1957 delete pFontNode;
1958 Error(PE_SIZE_EXPECTED);
1959 return;
1960 }
1961
1962 if (Type != FNTSIZ_ABSOLUT)
1963 {
1964 NextToken();
1965 if (m_aCurToken.eType != TNUMBER)
1966 {
1967 delete pFontNode;
1968 Error(PE_SIZE_EXPECTED);
1969 return;
1970 }
1971 }
1972
1973 // get number argument
1974 Fraction aValue( 1L );
1975 if (lcl_IsNumber( m_aCurToken.aText ))
1976 {
1977 double fTmp;
1978 if ((fTmp = m_aCurToken.aText.ToDouble()) != 0.0)
1979 {
1980 aValue = fTmp;
1981
1982 //!! keep the numerator and denominator from being to large
1983 //!! otherwise ongoing multiplications may result in overflows
1984 //!! (for example in SmNode::SetFontSize the font size calculated
1985 //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux
1986 //!! or ftmp = 1.11111111111111111... (11/9) on every platform.)
1987 if (aValue.GetDenominator() > 1000)
1988 {
1989 long nNum = aValue.GetNumerator();
1990 long nDenom = aValue.GetDenominator();
1991 while (nDenom > 1000)
1992 {
1993 nNum /= 10;
1994 nDenom /= 10;
1995 }
1996 aValue = Fraction( nNum, nDenom );
1997 }
1998 }
1999 }
2000
2001 NextToken();
2002
2003 pFontNode->SetSizeParameter(aValue, Type);
2004 m_aNodeStack.Push(pFontNode);
2005 }
2006
2007
Brace()2008 void SmParser::Brace()
2009 {
2010 DBG_ASSERT(m_aCurToken.eType == TLEFT || TokenInGroup(TGLBRACES),
2011 "Sm: kein Klammer Ausdruck");
2012
2013 SmStructureNode *pSNode = new SmBraceNode(m_aCurToken);
2014 SmNode *pBody = 0,
2015 *pLeft = 0,
2016 *pRight = 0;
2017 SmScaleMode eScaleMode = SCALE_NONE;
2018 SmParseError eError = PE_NONE;
2019
2020 if (m_aCurToken.eType == TLEFT)
2021 { NextToken();
2022
2023 eScaleMode = SCALE_HEIGHT;
2024
2025 // check for left bracket
2026 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES))
2027 {
2028 pLeft = new SmMathSymbolNode(m_aCurToken);
2029
2030 NextToken();
2031 Bracebody(sal_True);
2032 pBody = m_aNodeStack.Pop();
2033
2034 if (m_aCurToken.eType == TRIGHT)
2035 { NextToken();
2036
2037 // check for right bracket
2038 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES))
2039 {
2040 pRight = new SmMathSymbolNode(m_aCurToken);
2041 NextToken();
2042 }
2043 else
2044 eError = PE_RBRACE_EXPECTED;
2045 }
2046 else
2047 eError = PE_RIGHT_EXPECTED;
2048 }
2049 else
2050 eError = PE_LBRACE_EXPECTED;
2051 }
2052 else
2053 {
2054 if (TokenInGroup(TGLBRACES))
2055 {
2056 pLeft = new SmMathSymbolNode(m_aCurToken);
2057
2058 NextToken();
2059 Bracebody(sal_False);
2060 pBody = m_aNodeStack.Pop();
2061
2062 SmTokenType eExpectedType = TUNKNOWN;
2063 switch (pLeft->GetToken().eType)
2064 { case TLPARENT : eExpectedType = TRPARENT; break;
2065 case TLBRACKET : eExpectedType = TRBRACKET; break;
2066 case TLBRACE : eExpectedType = TRBRACE; break;
2067 case TLDBRACKET : eExpectedType = TRDBRACKET; break;
2068 case TLLINE : eExpectedType = TRLINE; break;
2069 case TLDLINE : eExpectedType = TRDLINE; break;
2070 case TLANGLE : eExpectedType = TRANGLE; break;
2071 case TLFLOOR : eExpectedType = TRFLOOR; break;
2072 case TLCEIL : eExpectedType = TRCEIL; break;
2073 default :
2074 DBG_ASSERT(0, "Sm: unbekannter Fall");
2075 }
2076
2077 if (m_aCurToken.eType == eExpectedType)
2078 {
2079 pRight = new SmMathSymbolNode(m_aCurToken);
2080 NextToken();
2081 }
2082 else
2083 eError = PE_PARENT_MISMATCH;
2084 }
2085 else
2086 eError = PE_LBRACE_EXPECTED;
2087 }
2088
2089 if (eError == PE_NONE)
2090 { DBG_ASSERT(pLeft, "Sm: NULL pointer");
2091 DBG_ASSERT(pRight, "Sm: NULL pointer");
2092 pSNode->SetSubNodes(pLeft, pBody, pRight);
2093 pSNode->SetScaleMode(eScaleMode);
2094 m_aNodeStack.Push(pSNode);
2095 }
2096 else
2097 { delete pSNode;
2098 delete pBody;
2099 delete pLeft;
2100 delete pRight;
2101
2102 Error(eError);
2103 }
2104 }
2105
2106
Bracebody(sal_Bool bIsLeftRight)2107 void SmParser::Bracebody(sal_Bool bIsLeftRight)
2108 {
2109 SmStructureNode *pBody = new SmBracebodyNode(m_aCurToken);
2110 SmNodeArray aNodes;
2111 sal_uInt16 nNum = 0;
2112
2113 // get body if any
2114 if (bIsLeftRight)
2115 {
2116 do
2117 {
2118 if (m_aCurToken.eType == TMLINE)
2119 {
2120 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken));
2121 NextToken();
2122 nNum++;
2123 }
2124 else if (m_aCurToken.eType != TRIGHT)
2125 { Align();
2126 nNum++;
2127
2128 if (m_aCurToken.eType != TMLINE && m_aCurToken.eType != TRIGHT)
2129 Error(PE_RIGHT_EXPECTED);
2130 }
2131 } while (m_aCurToken.eType != TEND && m_aCurToken.eType != TRIGHT);
2132 }
2133 else
2134 {
2135 do
2136 {
2137 if (m_aCurToken.eType == TMLINE)
2138 {
2139 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken));
2140 NextToken();
2141 nNum++;
2142 }
2143 else if (!TokenInGroup(TGRBRACES))
2144 { Align();
2145 nNum++;
2146
2147 if (m_aCurToken.eType != TMLINE && !TokenInGroup(TGRBRACES))
2148 Error(PE_RBRACE_EXPECTED);
2149 }
2150 } while (m_aCurToken.eType != TEND && !TokenInGroup(TGRBRACES));
2151 }
2152
2153 // build argument vector in parsing order
2154 aNodes.resize(nNum);
2155 for (sal_uInt16 i = 0; i < nNum; i++)
2156 aNodes[nNum - 1 - i] = m_aNodeStack.Pop();
2157
2158 pBody->SetSubNodes(aNodes);
2159 pBody->SetScaleMode(bIsLeftRight ? SCALE_HEIGHT : SCALE_NONE);
2160 m_aNodeStack.Push(pBody);
2161 }
2162
2163
Function()2164 void SmParser::Function()
2165 {
2166 switch (m_aCurToken.eType)
2167 {
2168 case TFUNC:
2169 NextToken(); // skip "FUNC"-statement
2170 // fall through
2171
2172 case TSIN :
2173 case TCOS :
2174 case TTAN :
2175 case TCOT :
2176 case TASIN :
2177 case TACOS :
2178 case TATAN :
2179 case TACOT :
2180 case TSINH :
2181 case TCOSH :
2182 case TTANH :
2183 case TCOTH :
2184 case TASINH :
2185 case TACOSH :
2186 case TATANH :
2187 case TACOTH :
2188 case TLN :
2189 case TLOG :
2190 case TEXP :
2191 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_FUNCTION));
2192 NextToken();
2193 break;
2194
2195 default:
2196 Error(PE_FUNC_EXPECTED);
2197 }
2198 }
2199
2200
Binom()2201 void SmParser::Binom()
2202 {
2203 SmNodeArray ExpressionArray;
2204 SmStructureNode *pSNode = new SmTableNode(m_aCurToken);
2205
2206 NextToken();
2207
2208 Sum();
2209 Sum();
2210
2211 ExpressionArray.resize(2);
2212
2213 for (int i = 0; i < 2; i++)
2214 ExpressionArray[2 - (i + 1)] = m_aNodeStack.Pop();
2215
2216 pSNode->SetSubNodes(ExpressionArray);
2217 m_aNodeStack.Push(pSNode);
2218 }
2219
2220
Stack()2221 void SmParser::Stack()
2222 {
2223 SmNodeArray ExpressionArray;
2224 NextToken();
2225 if (m_aCurToken.eType == TLGROUP)
2226 {
2227 sal_uInt16 n = 0;
2228
2229 do
2230 {
2231 NextToken();
2232 Align();
2233 n++;
2234 }
2235 while (m_aCurToken.eType == TPOUND);
2236
2237 ExpressionArray.resize(n);
2238
2239 for (sal_uInt16 i = 0; i < n; i++)
2240 ExpressionArray[n - (i + 1)] = m_aNodeStack.Pop();
2241
2242 if (m_aCurToken.eType != TRGROUP)
2243 Error(PE_RGROUP_EXPECTED);
2244
2245 NextToken();
2246
2247 SmStructureNode *pSNode = new SmTableNode(m_aCurToken);
2248 pSNode->SetSubNodes(ExpressionArray);
2249 m_aNodeStack.Push(pSNode);
2250 }
2251 else
2252 Error(PE_LGROUP_EXPECTED);
2253 }
2254
2255
Matrix()2256 void SmParser::Matrix()
2257 {
2258 SmNodeArray ExpressionArray;
2259
2260 NextToken();
2261 if (m_aCurToken.eType == TLGROUP)
2262 {
2263 sal_uInt16 c = 0;
2264
2265 do
2266 {
2267 NextToken();
2268 Align();
2269 c++;
2270 }
2271 while (m_aCurToken.eType == TPOUND);
2272
2273 sal_uInt16 r = 1;
2274
2275 while (m_aCurToken.eType == TDPOUND)
2276 {
2277 NextToken();
2278 for (sal_uInt16 i = 0; i < c; i++)
2279 {
2280 Align();
2281 if (i < (c - 1))
2282 {
2283 if (m_aCurToken.eType == TPOUND)
2284 {
2285 NextToken();
2286 }
2287 else
2288 Error(PE_POUND_EXPECTED);
2289 }
2290 }
2291
2292 r++;
2293 }
2294
2295 long nRC = r * c;
2296
2297 ExpressionArray.resize(nRC);
2298
2299 for (sal_uInt16 i = 0; i < (nRC); i++)
2300 ExpressionArray[(nRC) - (i + 1)] = m_aNodeStack.Pop();
2301
2302 if (m_aCurToken.eType != TRGROUP)
2303 Error(PE_RGROUP_EXPECTED);
2304
2305 NextToken();
2306
2307 SmMatrixNode *pMNode = new SmMatrixNode(m_aCurToken);
2308 pMNode->SetSubNodes(ExpressionArray);
2309 pMNode->SetRowCol(r, c);
2310 m_aNodeStack.Push(pMNode);
2311 }
2312 else
2313 Error(PE_LGROUP_EXPECTED);
2314 }
2315
2316
Special()2317 void SmParser::Special()
2318 {
2319 sal_Bool bReplace = sal_False;
2320 String &rName = m_aCurToken.aText;
2321 String aNewName;
2322
2323 if (CONVERT_NONE == GetConversion())
2324 {
2325 // conversion of symbol names for 6.0 (XML) file format
2326 // (name change on import / export.
2327 // UI uses localized names XML file format does not.)
2328 if( rName.Len() && rName.GetChar( 0 ) == sal_Unicode( '%' ) )
2329 {
2330 if (IsImportSymbolNames())
2331 {
2332 const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData();
2333 aNewName = rLSD.GetUiSymbolName( rName.Copy( 1 ) );
2334 bReplace = sal_True;
2335 }
2336 else if (IsExportSymbolNames())
2337 {
2338 const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData();
2339 aNewName = rLSD.GetExportSymbolName( rName.Copy( 1 ) );
2340 bReplace = sal_True;
2341 }
2342 }
2343 if( aNewName.Len() )
2344 aNewName.Insert( '%', 0 );
2345 }
2346 else // 5.0 <-> 6.0 formula text (symbol name) conversion
2347 {
2348 LanguageType nLanguage = GetLanguage();
2349 SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData();
2350 const ResStringArray *pFrom = 0;
2351 const ResStringArray *pTo = 0;
2352 if (CONVERT_50_TO_60 == GetConversion())
2353 {
2354 pFrom = rData.Get50NamesArray( nLanguage );
2355 pTo = rData.Get60NamesArray( nLanguage );
2356 }
2357 else if (CONVERT_60_TO_50 == GetConversion())
2358 {
2359 pFrom = rData.Get60NamesArray( nLanguage );
2360 pTo = rData.Get50NamesArray( nLanguage );
2361 }
2362 if (pFrom && pTo)
2363 {
2364 DBG_ASSERT( pFrom->Count() == pTo->Count(),
2365 "array length mismatch" );
2366 sal_uInt16 nCount = sal::static_int_cast< sal_uInt16 >(pFrom->Count());
2367 for (sal_uInt16 i = 0; i < nCount; ++i)
2368 {
2369 if (pFrom->GetString(i) == rName)
2370 {
2371 aNewName = pTo->GetString(i);
2372 bReplace = sal_True;
2373 }
2374 }
2375 }
2376 // else:
2377 // conversion arrays not found or (usually)
2378 // conversion not necessary
2379 }
2380
2381 if (bReplace && aNewName.Len() && rName != aNewName)
2382 {
2383 Replace( GetTokenIndex(), rName.Len(), aNewName );
2384 rName = aNewName;
2385 }
2386
2387 // add symbol name to list of used symbols
2388 const String aSymbolName( m_aCurToken.aText.Copy( 1 ) );
2389 if (aSymbolName.Len() > 0 )
2390 AddToUsedSymbols( aSymbolName );
2391
2392 m_aNodeStack.Push(new SmSpecialNode(m_aCurToken));
2393 NextToken();
2394 }
2395
2396
GlyphSpecial()2397 void SmParser::GlyphSpecial()
2398 {
2399 m_aNodeStack.Push(new SmGlyphSpecialNode(m_aCurToken));
2400 NextToken();
2401 }
2402
2403
Error(SmParseError eError)2404 void SmParser::Error(SmParseError eError)
2405 {
2406 SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken);
2407 SmErrorNode *pErr = new SmErrorNode(eError, m_aCurToken);
2408 pSNode->SetSubNodes(pErr, 0);
2409
2410 //! put a structure node on the stack (instead of the error node itself)
2411 //! because sometimes such a node is expected in order to attach some
2412 //! subnodes
2413 m_aNodeStack.Push(pSNode);
2414
2415 AddError(eError, pSNode);
2416
2417 NextToken();
2418 }
2419
2420
2421 // end gramar
2422
2423
SmParser()2424 SmParser::SmParser()
2425 {
2426 m_eConversion = CONVERT_NONE;
2427 m_bImportSymNames = m_bExportSymNames = sal_False;
2428 m_nLang = Application::GetSettings().GetUILanguage();
2429 }
2430
2431
Parse(const String & rBuffer)2432 SmNode *SmParser::Parse(const String &rBuffer)
2433 {
2434 ClearUsedSymbols();
2435
2436 m_aBufferString = rBuffer;
2437 m_aBufferString.ConvertLineEnd( LINEEND_LF );
2438 m_nBufferIndex =
2439 m_nTokenIndex = 0;
2440 m_Row = 1;
2441 m_nColOff = 0;
2442 m_nCurError = -1;
2443
2444 for (sal_uInt16 i = 0; i < m_aErrDescList.Count(); i++)
2445 delete m_aErrDescList.Remove(i);
2446
2447 m_aErrDescList.Clear();
2448
2449 m_aNodeStack.Clear();
2450
2451 SetLanguage( Application::GetSettings().GetUILanguage() );
2452 NextToken();
2453 Table();
2454
2455 return m_aNodeStack.Pop();
2456 }
2457
2458
AddError(SmParseError Type,SmNode * pNode)2459 sal_uInt16 SmParser::AddError(SmParseError Type, SmNode *pNode)
2460 {
2461 SmErrorDesc *pErrDesc = new SmErrorDesc;
2462
2463 pErrDesc->Type = Type;
2464 pErrDesc->pNode = pNode;
2465 pErrDesc->Text = String(SmResId(RID_ERR_IDENT));
2466
2467 sal_uInt16 nRID;
2468 switch (Type)
2469 {
2470 case PE_UNEXPECTED_CHAR: nRID = RID_ERR_UNEXPECTEDCHARACTER; break;
2471 case PE_LGROUP_EXPECTED: nRID = RID_ERR_LGROUPEXPECTED; break;
2472 case PE_RGROUP_EXPECTED: nRID = RID_ERR_RGROUPEXPECTED; break;
2473 case PE_LBRACE_EXPECTED: nRID = RID_ERR_LBRACEEXPECTED; break;
2474 case PE_RBRACE_EXPECTED: nRID = RID_ERR_RBRACEEXPECTED; break;
2475 case PE_FUNC_EXPECTED: nRID = RID_ERR_FUNCEXPECTED; break;
2476 case PE_UNOPER_EXPECTED: nRID = RID_ERR_UNOPEREXPECTED; break;
2477 case PE_BINOPER_EXPECTED: nRID = RID_ERR_BINOPEREXPECTED; break;
2478 case PE_SYMBOL_EXPECTED: nRID = RID_ERR_SYMBOLEXPECTED; break;
2479 case PE_IDENTIFIER_EXPECTED: nRID = RID_ERR_IDENTEXPECTED; break;
2480 case PE_POUND_EXPECTED: nRID = RID_ERR_POUNDEXPECTED; break;
2481 case PE_COLOR_EXPECTED: nRID = RID_ERR_COLOREXPECTED; break;
2482 case PE_RIGHT_EXPECTED: nRID = RID_ERR_RIGHTEXPECTED; break;
2483
2484 default:
2485 nRID = RID_ERR_UNKOWN;
2486 }
2487 pErrDesc->Text += SmResId(nRID);
2488
2489 m_aErrDescList.Insert(pErrDesc);
2490
2491 return (sal_uInt16) m_aErrDescList.GetPos(pErrDesc);
2492 }
2493
2494
NextError()2495 const SmErrorDesc *SmParser::NextError()
2496 {
2497 if (m_aErrDescList.Count())
2498 if (m_nCurError > 0) return m_aErrDescList.Seek(--m_nCurError);
2499 else
2500 {
2501 m_nCurError = 0;
2502 return m_aErrDescList.Seek(m_nCurError);
2503 }
2504 else return 0;
2505 }
2506
2507
PrevError()2508 const SmErrorDesc *SmParser::PrevError()
2509 {
2510 if (m_aErrDescList.Count())
2511 if (m_nCurError < (int) (m_aErrDescList.Count() - 1)) return m_aErrDescList.Seek(++m_nCurError);
2512 else
2513 {
2514 m_nCurError = (int) (m_aErrDescList.Count() - 1);
2515 return m_aErrDescList.Seek(m_nCurError);
2516 }
2517 else return 0;
2518 }
2519
2520
GetError(sal_uInt16 i)2521 const SmErrorDesc *SmParser::GetError(sal_uInt16 i)
2522 {
2523 return (/*i >= 0 &&*/ i < m_aErrDescList.Count())
2524 ? m_aErrDescList.Seek(i)
2525 : m_aErrDescList.Seek(m_nCurError);
2526 }
2527
2528
2529