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 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 69 static inline sal_Bool IsDigit( sal_Unicode cChar ) 70 { 71 return '0' <= cChar && cChar <= '9'; 72 } 73 74 /////////////////////////////////////////////////////////////////////////// 75 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1363 void SmParser::Power() 1364 { 1365 // get body for sub- supscripts on top of stack 1366 Term(); 1367 1368 SubSup(TGPOWER); 1369 } 1370 1371 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 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 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 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 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 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 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 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 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 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, ... 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 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 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 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 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 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 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 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 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 2397 void SmParser::GlyphSpecial() 2398 { 2399 m_aNodeStack.Push(new SmGlyphSpecialNode(m_aCurToken)); 2400 NextToken(); 2401 } 2402 2403 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 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 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 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 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 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 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