/Users/ericb/Desktop/SRC680_m247/starmath/source/parse.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  OpenOffice.org - a multi-platform office productivity suite
00004  *
00005  *  $RCSfile: parse.cxx,v $
00006  *
00007  *  $Revision: 1.34 $
00008  *
00009  *  last change: $Author: hr $ $Date: 2007/08/02 13:54:04 $
00010  *
00011  *  The Contents of this file are made available subject to
00012  *  the terms of GNU Lesser General Public License Version 2.1.
00013  *
00014  *
00015  *    GNU Lesser General Public License Version 2.1
00016  *    =============================================
00017  *    Copyright 2005 by Sun Microsystems, Inc.
00018  *    901 San Antonio Road, Palo Alto, CA 94303, USA
00019  *
00020  *    This library is free software; you can redistribute it and/or
00021  *    modify it under the terms of the GNU Lesser General Public
00022  *    License version 2.1, as published by the Free Software Foundation.
00023  *
00024  *    This library is distributed in the hope that it will be useful,
00025  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027  *    Lesser General Public License for more details.
00028  *
00029  *    You should have received a copy of the GNU Lesser General Public
00030  *    License along with this library; if not, write to the Free Software
00031  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00032  *    MA  02111-1307  USA
00033  *
00034  ************************************************************************/
00035 
00036 // MARKER(update_precomp.py): autogen include statement, do not remove
00037 #include "precompiled_starmath.hxx"
00038 
00039 
00040 #include <stdio.h>
00041 
00042 #define SMDLL 1
00043 
00044 #include <com/sun/star/i18n/UnicodeType.hpp>
00045 
00046 #ifndef INCLUDED_I18NPOOL_LANG_H
00047 #include <i18npool/lang.h>
00048 #endif
00049 #ifndef _UNOTOOLS_CHARCLASS_HXX
00050 #include <unotools/charclass.hxx>
00051 #endif
00052 #ifndef _UNO_LINGU_HXX
00053 #include <svx/unolingu.hxx>
00054 #endif
00055 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
00056 #include <svtools/syslocale.hxx>
00057 #endif
00058 
00059 #ifndef PARSE_HXX
00060 #include "parse.hxx"
00061 #endif
00062 #ifndef _STARMATH_HRC
00063 #include "starmath.hrc"
00064 #endif
00065 #ifndef _SMDLL_HXX
00066 #include "smdll.hxx"
00067 #endif
00068 #ifndef _SMMOD_HXX
00069 #include "smmod.hxx"
00070 #endif
00071 #ifndef CONFIG_HXX
00072 #include "config.hxx"
00073 #endif
00074 
00075 #include "node.hxx"
00076 
00077 using namespace ::com::sun::star;
00078 using namespace ::com::sun::star::i18n;
00079 
00081 
00082 static inline BOOL strnccmp(const String &u1, xub_StrLen nIdx,
00083                                                         const sal_Char *s2, xub_StrLen nLen)
00084 {
00085         return u1.EqualsIgnoreCaseAscii( s2, nIdx, nLen );
00086 }
00087 
00088 static const sal_Unicode aDelimiterTable[] =
00089 {
00090         ' ',    '\t',   '\n',   '\r',   '+',    '-',    '*',    '/',    '=',    '#',
00091         '%',    '\\',   '"',    '~',    '`',    '>',    '<',    '&',    '|',    '(',
00092         ')',    '{',    '}',    '[',    ']',    '^',    '_',
00093         '\0'    // end of list symbol
00094 };
00095 
00096 
00097 static inline BOOL IsDigit( sal_Unicode cChar )
00098 {
00099         return '0' <= cChar && cChar <= '9';
00100 }
00101 
00103 
00104 SmToken::SmToken() :
00105         eType           (TUNKNOWN),
00106         cMathChar       ('\0')
00107 {
00108     nGroup = nCol = nRow = nLevel = 0;
00109 }
00110 
00112 
00113 struct SmTokenTableEntry
00114 {
00115         const sal_Char* pIdent;
00116         SmTokenType             eType;
00117         sal_Unicode             cMathChar;
00118         ULONG                   nGroup;
00119         USHORT                  nLevel;
00120 };
00121 
00122 static const SmTokenTableEntry aTokenTable[] =
00123 {
00124 //      { "#", TPOUND, '\0', 0, 0 },
00125 //      { "##", TDPOUND, '\0', 0, 0 },
00126 //      { "&", TAND, MS_AND, TGPRODUCT, 0 },
00127 //      { "(", TLPARENT, MS_LPARENT, TGLBRACES, 5 },    //! 5 to continue expression
00128 //      { ")", TRPARENT, MS_RPARENT, TGRBRACES, 0 },    //! 0 to terminate expression
00129 //      { "*", TMULTIPLY, MS_MULTIPLY, TGPRODUCT, 0 },
00130 //      { "+", TPLUS, MS_PLUS, TGUNOPER | TGSUM, 5 },
00131 //      { "+-", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5 },
00132 //      { "-", TMINUS, MS_MINUS, TGUNOPER | TGSUM, 5 },
00133 //      { "-+", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5 },
00134 //      { ".", TPOINT, '\0', 0, 0 },
00135 //      { "/", TDIVIDEBY, MS_SLASH, TGPRODUCT, 0 },
00136 //      { "<", TLT, MS_LT, TGRELATION, 0 },
00137 //      { "<<", TLL, MS_LL, TGRELATION, 0 },
00138 //      { "<=", TLE, MS_LE, TGRELATION, 0 },
00139 //      { "<>", TNEQ, MS_NEQ, TGRELATION, 0},
00140 //      { "<?>", TPLACE, MS_PLACE, 0, 5 },
00141 //      { "=", TASSIGN, MS_ASSIGN, TGRELATION, 0},
00142 //      { ">", TGT, MS_GT, TGRELATION, 0 },
00143 //      { ">=", TGE, MS_GE, TGRELATION, 0 },
00144 //      { ">>", TGG, MS_GG, TGRELATION, 0 },
00145         { "Im" , TIM, MS_IM, TGSTANDALONE, 5 },
00146         { "MZ23", TDEBUG, '\0', TGATTRIBUT, 0 },
00147         { "Re" , TRE, MS_RE, TGSTANDALONE, 5 },
00148         { "abs", TABS, '\0', TGUNOPER, 13 },
00149         { "arcosh", TACOSH, '\0', TGFUNCTION, 5 },
00150         { "arcoth", TACOTH, '\0', TGFUNCTION, 5 },
00151         { "acute", TACUTE, MS_ACUTE, TGATTRIBUT, 5 },
00152         { "aleph" , TALEPH, MS_ALEPH, TGSTANDALONE, 5 },
00153         { "alignb", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
00154         { "alignc", TALIGNC, '\0', TGALIGN, 0},
00155         { "alignl", TALIGNL, '\0', TGALIGN, 0},
00156         { "alignm", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
00157         { "alignr", TALIGNR, '\0', TGALIGN, 0},
00158         { "alignt", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0},
00159         { "and", TAND, MS_AND, TGPRODUCT, 0},
00160         { "approx", TAPPROX, MS_APPROX, TGRELATION, 0},
00161         { "arccos", TACOS, '\0', TGFUNCTION, 5},
00162         { "arccot", TACOT, '\0', TGFUNCTION, 5},
00163         { "arcsin", TASIN, '\0', TGFUNCTION, 5},
00164         { "arctan", TATAN, '\0', TGFUNCTION, 5},
00165         { "arsinh", TASINH, '\0', TGFUNCTION, 5},
00166         { "artanh", TATANH, '\0', TGFUNCTION, 5},
00167         { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TGSTANDALONE, 5},
00168         { "bar", TBAR, MS_BAR, TGATTRIBUT, 5},
00169         { "binom", TBINOM, '\0', 0, 5 },
00170         { "black", TBLACK, '\0', TGCOLOR, 0},
00171         { "blue", TBLUE, '\0', TGCOLOR, 0},
00172         { "bold", TBOLD, '\0', TGFONTATTR, 5},
00173         { "boper", TBOPER, '\0', TGPRODUCT, 0},
00174         { "breve", TBREVE, MS_BREVE, TGATTRIBUT, 5},
00175         { "bslash", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
00176         { "cdot", TCDOT, MS_CDOT, TGPRODUCT, 0},
00177         { "check", TCHECK, MS_CHECK, TGATTRIBUT, 5},
00178         { "circ" , TCIRC, MS_CIRC, TGSTANDALONE, 5},
00179         { "circle", TCIRCLE, MS_CIRCLE, TGATTRIBUT, 5},
00180         { "color", TCOLOR, '\0', TGFONTATTR, 5},
00181         { "coprod", TCOPROD, MS_COPROD, TGOPER, 5},
00182         { "cos", TCOS, '\0', TGFUNCTION, 5},
00183         { "cosh", TCOSH, '\0', TGFUNCTION, 5},
00184         { "cot", TCOT, '\0', TGFUNCTION, 5},
00185         { "coth", TCOTH, '\0', TGFUNCTION, 5},
00186         { "csub", TCSUB, '\0', TGPOWER, 0},
00187         { "csup", TCSUP, '\0', TGPOWER, 0},
00188         { "cyan", TCYAN, '\0', TGCOLOR, 0},
00189         { "dddot", TDDDOT, MS_DDDOT, TGATTRIBUT, 5},
00190         { "ddot", TDDOT, MS_DDOT, TGATTRIBUT, 5},
00191         { "def", TDEF, MS_DEF, TGRELATION, 0},
00192         { "div", TDIV, MS_DIV, TGPRODUCT, 0},
00193         { "divides", TDIVIDES, MS_LINE, TGRELATION, 0},
00194         { "dlarrow" , TDLARROW, MS_DLARROW, TGSTANDALONE, 5},
00195         { "dlrarrow" , TDLRARROW, MS_DLRARROW, TGSTANDALONE, 5},
00196         { "dot", TDOT, MS_DOT, TGATTRIBUT, 5},
00197         { "dotsaxis", TDOTSAXIS, MS_DOTSAXIS, TGSTANDALONE, 5}, // 5 to continue expression
00198         { "dotsdiag", TDOTSDIAG, MS_DOTSUP, TGSTANDALONE, 5},   //
00199         { "dotsdown", TDOTSDOWN, MS_DOTSDOWN, TGSTANDALONE, 5},  //
00200         { "dotslow", TDOTSLOW, MS_DOTSLOW, TGSTANDALONE, 5},    //
00201         { "dotsup", TDOTSUP, MS_DOTSUP, TGSTANDALONE, 5},      //
00202         { "dotsvert", TDOTSVERT, MS_DOTSVERT, TGSTANDALONE, 5}, //
00203         { "downarrow" , TDOWNARROW, MS_DOWNARROW, TGSTANDALONE, 5},
00204         { "drarrow" , TDRARROW, MS_DRARROW, TGSTANDALONE, 5},
00205         { "emptyset" , TEMPTYSET, MS_EMPTYSET, TGSTANDALONE, 5},
00206         { "equiv", TEQUIV, MS_EQUIV, TGRELATION, 0},
00207         { "exists", TEXISTS, MS_EXISTS, TGSTANDALONE, 5},
00208         { "exp", TEXP, '\0', TGFUNCTION, 5},
00209         { "fact", TFACT, MS_FACT, TGUNOPER, 5},
00210         { "fixed", TFIXED, '\0', TGFONT, 0},
00211         { "font", TFONT, '\0', TGFONTATTR, 5},
00212         { "forall", TFORALL, MS_FORALL, TGSTANDALONE, 5},
00213         { "from", TFROM, '\0', TGLIMIT, 0},
00214         { "func", TFUNC, '\0', TGFUNCTION, 5},
00215         { "ge", TGE, MS_GE, TGRELATION, 0},
00216         { "geslant", TGESLANT, MS_GESLANT, TGRELATION, 0 },
00217         { "gg", TGG, MS_GG, TGRELATION, 0},
00218         { "grave", TGRAVE, MS_GRAVE, TGATTRIBUT, 5},
00219         { "green", TGREEN, '\0', TGCOLOR, 0},
00220         { "gt", TGT, MS_GT, TGRELATION, 0},
00221         { "hat", THAT, MS_HAT, TGATTRIBUT, 5},
00222         { "hbar" , THBAR, MS_HBAR, TGSTANDALONE, 5},
00223         { "iiint", TIIINT, MS_IIINT, TGOPER, 5},
00224         { "iint", TIINT, MS_IINT, TGOPER, 5},
00225         { "in", TIN, MS_IN, TGRELATION, 0},
00226         { "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
00227         { "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5},
00228         { "int", TINT, MS_INT, TGOPER, 5},
00229         { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0},
00230         { "ital", TITALIC, '\0', TGFONTATTR, 5},
00231         { "italic", TITALIC, '\0', TGFONTATTR, 5},
00232         { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TGSTANDALONE, 5},
00233         { "langle", TLANGLE, MS_LANGLE, TGLBRACES, 5},
00234         { "lbrace", TLBRACE, MS_LBRACE, TGLBRACES, 5},
00235         { "lceil", TLCEIL, MS_LCEIL, TGLBRACES, 5},
00236         { "ldbracket", TLDBRACKET, MS_LDBRACKET, TGLBRACES, 5},
00237         { "ldline", TLDLINE, MS_DLINE, TGLBRACES, 5},
00238         { "le", TLE, MS_LE, TGRELATION, 0},
00239         { "left", TLEFT, '\0', 0, 5},
00240         { "leftarrow" , TLEFTARROW, MS_LEFTARROW, TGSTANDALONE, 5},
00241         { "leslant", TLESLANT, MS_LESLANT, TGRELATION, 0 },
00242         { "lfloor", TLFLOOR, MS_LFLOOR, TGLBRACES, 5},
00243         { "lim", TLIM, '\0', TGOPER, 5},
00244         { "liminf", TLIMINF, '\0', TGOPER, 5},
00245         { "limsup", TLIMSUP, '\0', TGOPER, 5},
00246         { "lint", TLINT, MS_LINT, TGOPER, 5},
00247         { "ll", TLL, MS_LL, TGRELATION, 0},
00248         { "lline", TLLINE, MS_LINE, TGLBRACES, 5},
00249         { "llint", TLLINT, MS_LLINT, TGOPER, 5},
00250         { "lllint", TLLLINT, MS_LLLINT, TGOPER, 5},
00251         { "ln", TLN, '\0', TGFUNCTION, 5},
00252         { "log", TLOG, '\0', TGFUNCTION, 5},
00253         { "lsub", TLSUB, '\0', TGPOWER, 0},
00254         { "lsup", TLSUP, '\0', TGPOWER, 0},
00255         { "lt", TLT, MS_LT, TGRELATION, 0},
00256         { "magenta", TMAGENTA, '\0', TGCOLOR, 0},
00257         { "matrix", TMATRIX, '\0', 0, 5},
00258         { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5},
00259         { "mline", TMLINE, MS_LINE, 0, 0},              
00260         { "nabla", TNABLA, MS_NABLA, TGSTANDALONE, 5},
00261         { "nbold", TNBOLD, '\0', TGFONTATTR, 5},
00262         { "ndivides", TNDIVIDES, MS_NDIVIDES, TGRELATION, 0},
00263         { "neg", TNEG, MS_NEG, TGUNOPER, 5 },
00264         { "neq", TNEQ, MS_NEQ, TGRELATION, 0},
00265         { "newline", TNEWLINE, '\0', 0, 0},
00266         { "ni", TNI, MS_NI, TGRELATION, 0},
00267         { "nitalic", TNITALIC, '\0', TGFONTATTR, 5},
00268         { "none", TNONE, '\0', TGLBRACES | TGRBRACES, 0},
00269         { "notin", TNOTIN, MS_NOTIN, TGRELATION, 0},
00270         { "nsubset", TNSUBSET, MS_NSUBSET, TGRELATION, 0 },
00271         { "nsupset", TNSUPSET, MS_NSUPSET, TGRELATION, 0 },
00272         { "nsubseteq", TNSUBSETEQ, MS_NSUBSETEQ, TGRELATION, 0 },
00273         { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TGRELATION, 0 },
00274         { "nroot", TNROOT, MS_SQRT, TGUNOPER, 5},
00275         { "odivide", TODIVIDE, MS_ODIVIDE, TGPRODUCT, 0},
00276         { "odot", TODOT, MS_ODOT, TGPRODUCT, 0},
00277         { "ominus", TOMINUS, MS_OMINUS, TGSUM, 0},
00278         { "oper", TOPER, '\0', TGOPER, 5},
00279         { "oplus", TOPLUS, MS_OPLUS, TGSUM, 0},
00280         { "or", TOR, MS_OR, TGSUM, 0},
00281         { "ortho", TORTHO, MS_ORTHO, TGRELATION, 0},
00282         { "otimes", TOTIMES, MS_OTIMES, TGPRODUCT, 0},
00283         { "over", TOVER, '\0', TGPRODUCT, 0},
00284         { "overbrace", TOVERBRACE, MS_OVERBRACE, TGPRODUCT, 5},
00285         { "overline", TOVERLINE, '\0', TGATTRIBUT, 5},
00286         { "overstrike", TOVERSTRIKE, '\0', TGATTRIBUT, 5},
00287         { "owns", TNI, MS_NI, TGRELATION, 0},
00288         { "parallel", TPARALLEL, MS_DLINE, TGRELATION, 0},
00289         { "partial", TPARTIAL, MS_PARTIAL, TGSTANDALONE, 5 },
00290         { "phantom", TPHANTOM, '\0', TGFONTATTR, 5},
00291         { "plusminus", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5},
00292         { "prod", TPROD, MS_PROD, TGOPER, 5},
00293         { "prop", TPROP, MS_PROP, TGRELATION, 0},
00294         { "rangle", TRANGLE, MS_RANGLE, TGRBRACES, 0},  
00295         { "rbrace", TRBRACE, MS_RBRACE, TGRBRACES, 0},  //
00296         { "rceil", TRCEIL, MS_RCEIL, TGRBRACES, 0},     //
00297         { "rdbracket", TRDBRACKET, MS_RDBRACKET, TGRBRACES, 0}, //
00298         { "rdline", TRDLINE, MS_DLINE, TGRBRACES, 0},   //
00299         { "red", TRED, '\0', TGCOLOR, 0},
00300         { "rfloor", TRFLOOR, MS_RFLOOR, TGRBRACES, 0},  
00301         { "right", TRIGHT, '\0', 0, 0},
00302         { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TGSTANDALONE, 5},
00303         { "rline", TRLINE, MS_LINE, TGRBRACES, 0},      
00304         { "rsub", TRSUB, '\0', TGPOWER, 0},
00305         { "rsup", TRSUP, '\0', TGPOWER, 0},
00306         { "sans", TSANS, '\0', TGFONT, 0},
00307         { "serif", TSERIF, '\0', TGFONT, 0},
00308         { "setC" , TSETC, MS_SETC, TGSTANDALONE, 5},
00309         { "setN" , TSETN, MS_SETN, TGSTANDALONE, 5},
00310         { "setQ" , TSETQ, MS_SETQ, TGSTANDALONE, 5},
00311         { "setR" , TSETR, MS_SETR, TGSTANDALONE, 5},
00312         { "setZ" , TSETZ, MS_SETZ, TGSTANDALONE, 5},
00313         { "setminus", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
00314         { "sim", TSIM, MS_SIM, TGRELATION, 0},
00315         { "simeq", TSIMEQ, MS_SIMEQ, TGRELATION, 0},
00316         { "sin", TSIN, '\0', TGFUNCTION, 5},
00317         { "sinh", TSINH, '\0', TGFUNCTION, 5},
00318         { "size", TSIZE, '\0', TGFONTATTR, 5},
00319         { "slash", TSLASH, MS_SLASH, TGPRODUCT, 0 },
00320         { "sqrt", TSQRT, MS_SQRT, TGUNOPER, 5},
00321         { "stack", TSTACK, '\0', 0, 5},
00322         { "sub", TRSUB, '\0', TGPOWER, 0},
00323         { "subset", TSUBSET, MS_SUBSET, TGRELATION, 0},
00324         { "subseteq", TSUBSETEQ, MS_SUBSETEQ, TGRELATION, 0},
00325         { "sum", TSUM, MS_SUM, TGOPER, 5},
00326         { "sup", TRSUP, '\0', TGPOWER, 0},
00327         { "supset", TSUPSET, MS_SUPSET, TGRELATION, 0},
00328         { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TGRELATION, 0},
00329         { "tan", TTAN, '\0', TGFUNCTION, 5},
00330         { "tanh", TTANH, '\0', TGFUNCTION, 5},
00331         { "tilde", TTILDE, MS_TILDE, TGATTRIBUT, 5},
00332         { "times", TTIMES, MS_TIMES, TGPRODUCT, 0},
00333         { "to", TTO, '\0', TGLIMIT, 0},
00334         { "toward", TTOWARD, MS_RIGHTARROW, TGRELATION, 0},
00335         { "transl", TTRANSL, MS_TRANSL, TGRELATION, 0},
00336         { "transr", TTRANSR, MS_TRANSR, TGRELATION, 0},
00337         { "underbrace", TUNDERBRACE, MS_UNDERBRACE, TGPRODUCT, 5},
00338         { "underline", TUNDERLINE, '\0', TGATTRIBUT, 5},
00339         { "union", TUNION, MS_UNION, TGSUM, 0},
00340         { "uoper", TUOPER, '\0', TGUNOPER, 5},
00341         { "uparrow" , TUPARROW, MS_UPARROW, TGSTANDALONE, 5},
00342         { "vec", TVEC, MS_VEC, TGATTRIBUT, 5},
00343         { "white", TWHITE, '\0', TGCOLOR, 0},
00344         { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 },
00345         { "widehat", TWIDEHAT, MS_HAT, TGATTRIBUT, 5},
00346         { "widetilde", TWIDETILDE, MS_TILDE, TGATTRIBUT, 5},
00347         { "wideslash", TWIDESLASH, MS_SLASH, TGPRODUCT, 0 },
00348         { "widevec", TWIDEVEC, MS_VEC, TGATTRIBUT, 5},
00349         { "wp" , TWP, MS_WP, TGSTANDALONE, 5},
00350         { "yellow", TYELLOW, '\0', TGCOLOR, 0},
00351 //      { "[", TLBRACKET, MS_LBRACKET, TGLBRACES, 5},   //! 5 to continue expression
00352 //      { "\\", TESCAPE, '\0', 0, 5},
00353 //      { "]", TRBRACKET, MS_RBRACKET, TGRBRACES, 0},   //! 0 to terminate expression
00354 //      { "^", TRSUP, '\0', TGPOWER, 0},
00355 //      { "_", TRSUB, '\0', TGPOWER, 0},
00356 //      { "`", TSBLANK, '\0', TGBLANK, 5},
00357 //      { "{", TLGROUP, MS_LBRACE, 0, 5},               //! 5 to continue expression
00358 //      { "|", TOR, MS_OR, TGSUM, 0},
00359 //      { "}", TRGROUP, MS_RBRACE, 0, 0},               //! 0 to terminate expression
00360 //      { "~", TBLANK, '\0', TGBLANK, 5},
00361         { "", TEND, '\0', 0, 0}
00362 };
00363 
00364 
00365 static const SmTokenTableEntry * GetTokenTableEntry( const String &rName )
00366 {
00367         const SmTokenTableEntry * pRes = 0;
00368         if (rName.Len())
00369         {
00370                 INT32 nEntries = sizeof( aTokenTable ) / sizeof( aTokenTable[0] );
00371                 for (INT32 i = 0;  i < nEntries;  ++i)
00372                 {
00373                         if (rName.EqualsIgnoreCaseAscii( aTokenTable[i].pIdent ))
00374                         {
00375                                 pRes = &aTokenTable[i];
00376                                 break;
00377                         }
00378                 }
00379 
00380         }
00381 
00382         return pRes;
00383 }
00384 
00385 
00387 
00388 #if OSL_DEBUG_LEVEL
00389 
00390 BOOL SmParser::IsDelimiter( const String &rTxt, xub_StrLen nPos )
00391         // returns 'TRUE' iff cChar is '\0' or a delimeter
00392 {
00393         DBG_ASSERT( nPos <= rTxt.Len(), "index out of range" );
00394 
00395         sal_Unicode cChar = rTxt.GetChar( nPos );
00396         if(!cChar)
00397                 return TRUE;
00398 
00399         // check if 'cChar' is in the delimeter table
00400         const sal_Unicode *pDelim = &aDelimiterTable[0];
00401         for ( ;  *pDelim != 0;  pDelim++)
00402                 if (*pDelim == cChar)
00403                         break;
00404 
00405         BOOL bIsDelim = *pDelim != 0;
00406 
00407         INT16 nTypJp = SM_MOD1()->GetSysLocale().GetCharClass().getType( rTxt, nPos );
00408         bIsDelim |= nTypJp == com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR ||
00409                                 nTypJp == com::sun::star::i18n::UnicodeType::CONTROL;
00410 
00411         return bIsDelim;
00412 }
00413 
00414 #endif
00415 
00416 void SmParser::Insert(const String &rText, USHORT nPos)
00417 {
00418         BufferString.Insert(rText, nPos);
00419 
00420         xub_StrLen  nLen = rText.Len();
00421     BufferIndex = BufferIndex + nLen;
00422     nTokenIndex = nTokenIndex + nLen;
00423 }
00424 
00425 
00426 void SmParser::Replace( USHORT nPos, USHORT nLen, const String &rText )
00427 {
00428     DBG_ASSERT( nPos + nLen <= BufferString.Len(), "argument mismatch" );
00429 
00430     BufferString.Replace( nPos, nLen, rText );
00431     INT16  nChg = rText.Len() - nLen;
00432     BufferIndex = BufferIndex + nChg;
00433     nTokenIndex = nTokenIndex + nChg;
00434 }
00435 
00436 
00437 // First character may be any alphabetic
00438 const sal_Int32 coStartFlags =
00439                 KParseTokens::ANY_LETTER_OR_NUMBER |
00440                 KParseTokens::IGNORE_LEADING_WS;
00441 
00442 // Continuing characters may be any alphanumeric or dot.
00443 const sal_Int32 coContFlags =
00444     ( coStartFlags | KParseTokens::ASC_DOT ) & ~KParseTokens::IGNORE_LEADING_WS
00445     | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING;
00446 
00447 // First character for numbers, may be any numeric or dot
00448 const sal_Int32 coNumStartFlags =
00449         KParseTokens::ASC_DIGIT |
00450         KParseTokens::ASC_DOT |
00451         KParseTokens::IGNORE_LEADING_WS;
00452 // Continuing characters for numbers, may be any numeric or dot.
00453 const sal_Int32 coNumContFlags =
00454     ( coNumStartFlags | KParseTokens::ASC_DOT ) & ~KParseTokens::IGNORE_LEADING_WS;
00455 
00456 void SmParser::NextToken()
00457 {
00458         static const String aEmptyStr;
00459 
00460         xub_StrLen      nBufLen = BufferString.Len();
00461         ParseResult     aRes;
00462         xub_StrLen      nRealStart;
00463         BOOL            bCont;
00464     BOOL        bNumStart = FALSE;
00465     CharClass   aCC(SM_MOD1()->GetSysLocale().GetCharClass().getLocale());
00466         do
00467         {
00468         // skip white spaces
00469         while (UnicodeType::SPACE_SEPARATOR ==
00470                         aCC.getType( BufferString, BufferIndex ))
00471            ++BufferIndex;
00472 
00473         sal_Int32 nStartFlags = coStartFlags;
00474         sal_Int32 nContFlags  = coContFlags;
00475         sal_Unicode cFirstChar = BufferString.GetChar( BufferIndex );
00476 /*
00477         removed because of #i11752#
00478         bNumStart = cFirstChar == '.' || ('0' <= cFirstChar && cFirstChar <= '9');
00479         if (bNumStart)
00480         {
00481             nStartFlags = coNumStartFlags;
00482             nContFlags  = coNumContFlags;
00483         }
00484 */
00485         aRes = aCC.parseAnyToken( BufferString, BufferIndex,
00486                                             nStartFlags, aEmptyStr,
00487                                             nContFlags, aEmptyStr );
00488 
00489         // #i45779# parse numbers correctly
00490         // i.e. independent from the locale setting.
00491         // (note that #i11752# remains fixed)
00492         if ((aRes.TokenType & KParseType::IDENTNAME) && IsDigit( cFirstChar ))
00493         {
00495             static lang::Locale aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US ) );
00496 
00497             ParseResult aTmpRes;
00498             lang::Locale aOldLoc( aCC.getLocale() );
00499             aCC.setLocale( aDotLoc );
00500             aTmpRes = aCC.parsePredefinedToken( 
00501                             KParseType::ASC_NUMBER,
00502                             BufferString, BufferIndex,
00503                             KParseTokens::ASC_DIGIT, aEmptyStr,
00504                             KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT, aEmptyStr );
00505             aCC.setLocale( aOldLoc );
00506             if (aTmpRes.TokenType & KParseType::ASC_NUMBER)
00507                 aRes.TokenType = aTmpRes.TokenType;
00508         }
00509 
00510         nRealStart = BufferIndex + sal::static_int_cast< xub_StrLen >(aRes.LeadingWhiteSpace);
00511         BufferIndex = nRealStart;
00512 
00513                 bCont = FALSE;
00514                 if ( aRes.TokenType == 0  &&
00515                                 nRealStart < nBufLen &&
00516                                 '\n' == BufferString.GetChar( nRealStart ) )
00517                 {
00518                         // keep data needed for tokens row and col entry up to date
00519                         ++Row;
00520                         BufferIndex = ColOff = nRealStart + 1;
00521                         bCont = TRUE;
00522                 }
00523                 else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
00524                 {
00525             String aName( BufferString.Copy( nRealStart, 2 ));
00526                         if ( aName.EqualsAscii( "%%" ))
00527                         {
00528                                 //SkipComment
00529                                 BufferIndex = nRealStart + 2;
00530                                 while (BufferIndex < nBufLen  &&
00531                                         '\n' != BufferString.GetChar( BufferIndex ))
00532                                         ++BufferIndex;
00533                                 bCont = TRUE;
00534                         }
00535                 }
00536 
00537         } while (bCont);
00538 
00539         // set index of current token
00540         nTokenIndex = BufferIndex;
00541 
00542         CurToken.nRow   = Row;
00543         CurToken.nCol   = nRealStart - ColOff + 1;
00544 
00545         BOOL bHandled = TRUE;
00546         if (nRealStart >= nBufLen)
00547         {
00548                 CurToken.eType     = TEND;
00549                 CurToken.cMathChar = '\0';
00550                 CurToken.nGroup    = 0;
00551                 CurToken.nLevel    = 0;
00552                 CurToken.aText.Erase();
00553         }
00554     else if ((aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER))
00555              || (bNumStart && (aRes.TokenType & KParseType::IDENTNAME)))
00556         {
00557                 INT32 n = aRes.EndPos - nRealStart;
00558                 DBG_ASSERT( n >= 0, "length < 0" );
00559                 CurToken.eType      = TNUMBER;
00560                 CurToken.cMathChar  = '\0';
00561                 CurToken.nGroup     = 0;
00562                 CurToken.nLevel     = 5;
00563         CurToken.aText      = BufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) );
00564 
00565 #if OSL_DEBUG_LEVEL > 1
00566         if (!IsDelimiter( BufferString, static_cast< xub_StrLen >(aRes.EndPos) ))
00567         {
00568             DBG_WARNING( "identifier really finished? (compatibility!)" );
00569         }
00570 #endif
00571         }
00572         else if (aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING)
00573         {
00574                 CurToken.eType      = TTEXT;
00575                 CurToken.cMathChar  = '\0';
00576                 CurToken.nGroup     = 0;
00577                 CurToken.nLevel     = 5;
00578                 CurToken.aText          = aRes.DequotedNameOrString;
00579                 CurToken.nRow       = Row;
00580                 CurToken.nCol       = nRealStart - ColOff + 2;
00581         }
00582         else if (aRes.TokenType & KParseType::IDENTNAME)
00583         {
00584                 INT32 n = aRes.EndPos - nRealStart;
00585                 DBG_ASSERT( n >= 0, "length < 0" );
00586         String aName( BufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ) );
00587                 const SmTokenTableEntry *pEntry = GetTokenTableEntry( aName );
00588 
00589                 if (pEntry)
00590                 {
00591                         CurToken.eType      = pEntry->eType;
00592                         CurToken.cMathChar  = pEntry->cMathChar;
00593                         CurToken.nGroup     = pEntry->nGroup;
00594                         CurToken.nLevel     = pEntry->nLevel;
00595                         CurToken.aText.AssignAscii( pEntry->pIdent );
00596                 }
00597                 else
00598                 {
00599                         CurToken.eType      = TIDENT;
00600                         CurToken.cMathChar  = '\0';
00601                         CurToken.nGroup     = 0;
00602                         CurToken.nLevel     = 5;
00603                         CurToken.aText      = aName;
00604 
00605 #if OSL_DEBUG_LEVEL > 1
00606             if (!IsDelimiter( BufferString, static_cast< xub_StrLen >(aRes.EndPos) ))
00607             {
00608                 DBG_WARNING( "identifier really finished? (compatibility!)" );
00609             }
00610 #endif
00611                 }
00612         }
00613         else if (aRes.TokenType == 0  &&  '_' == BufferString.GetChar( nRealStart ))
00614         {
00615                 CurToken.eType     = TRSUB;
00616                 CurToken.cMathChar = '\0';
00617                 CurToken.nGroup    = TGPOWER;
00618                 CurToken.nLevel    = 0;
00619                 CurToken.aText.AssignAscii( "_" );
00620 
00621                 aRes.EndPos = nRealStart + 1;
00622         }
00623         else if (aRes.TokenType & KParseType::BOOLEAN)
00624         {
00625                 sal_Int32   &rnEndPos = aRes.EndPos;
00626         String  aName( BufferString.Copy( nRealStart, 
00627                         sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ));
00628                 if (2 >= aName.Len())
00629                 {
00630                         sal_Unicode ch = aName.GetChar( 0 );
00631                         switch (ch)
00632                         {
00633                                 case '<':
00634                                         {
00635                                                 if (BufferString.Copy( nRealStart, 2 ).
00636                                                                 EqualsAscii( "<<" ))
00637                                                 {
00638                                                         CurToken.eType     = TLL;
00639                                                         CurToken.cMathChar = MS_LL;
00640                                                         CurToken.nGroup    = TGRELATION;
00641                                                         CurToken.nLevel    = 0;
00642                                                         CurToken.aText.AssignAscii( "<<" );
00643 
00644                                                         rnEndPos = nRealStart + 2;
00645                                                 }
00646                                                 else if (BufferString.Copy( nRealStart, 2 ).
00647                                                                 EqualsAscii( "<=" ))
00648                                                 {
00649                                                         CurToken.eType     = TLE;
00650                                                         CurToken.cMathChar = MS_LE;
00651                                                         CurToken.nGroup    = TGRELATION;
00652                                                         CurToken.nLevel    = 0;
00653                                                         CurToken.aText.AssignAscii( "<=" );
00654 
00655                                                         rnEndPos = nRealStart + 2;
00656                                                 }
00657                                                 else if (BufferString.Copy( nRealStart, 2 ).
00658                                                                 EqualsAscii( "<>" ))
00659                                                 {
00660                                                         CurToken.eType     = TNEQ;
00661                                                         CurToken.cMathChar = MS_NEQ;
00662                                                         CurToken.nGroup    = TGRELATION;
00663                                                         CurToken.nLevel    = 0;
00664                                                         CurToken.aText.AssignAscii( "<>" );
00665 
00666                                                         rnEndPos = nRealStart + 2;
00667                                                 }
00668                                                 else if (BufferString.Copy( nRealStart, 3 ).
00669                                                                 EqualsAscii( "<?>" ))
00670                                                 {
00671                                                         CurToken.eType     = TPLACE;
00672                                                         CurToken.cMathChar = MS_PLACE;
00673                                                         CurToken.nGroup    = 0;
00674                                                         CurToken.nLevel    = 5;
00675                                                         CurToken.aText.AssignAscii( "<?>" );
00676 
00677                                                         rnEndPos = nRealStart + 3;
00678                                                 }
00679                                                 else
00680                                                 {
00681                                                         CurToken.eType     = TLT;
00682                                                         CurToken.cMathChar = MS_LT;
00683                                                         CurToken.nGroup    = TGRELATION;
00684                                                         CurToken.nLevel    = 0;
00685                                                         CurToken.aText.AssignAscii( "<" );
00686                                                 }
00687                                         }
00688                                         break;
00689                                 case '>':
00690                                         {
00691                                                 if (BufferString.Copy( nRealStart, 2 ).
00692                                                                 EqualsAscii( ">=" ))
00693                                                 {
00694                                                         CurToken.eType     = TGE;
00695                                                         CurToken.cMathChar = MS_GE;
00696                                                         CurToken.nGroup    = TGRELATION;
00697                                                         CurToken.nLevel    = 0;
00698                                                         CurToken.aText.AssignAscii( ">=" );
00699 
00700                                                         rnEndPos = nRealStart + 2;
00701                                                 }
00702                                                 else if (BufferString.Copy( nRealStart, 2 ).
00703                                                                 EqualsAscii( ">>" ))
00704                                                 {
00705                                                         CurToken.eType     = TGG;
00706                                                         CurToken.cMathChar = MS_GG;
00707                                                         CurToken.nGroup    = TGRELATION;
00708                                                         CurToken.nLevel    = 0;
00709                                                         CurToken.aText.AssignAscii( ">>" );
00710 
00711                                                         rnEndPos = nRealStart + 2;
00712                                                 }
00713                                                 else
00714                                                 {
00715                                                         CurToken.eType     = TGT;
00716                                                         CurToken.cMathChar = MS_GT;
00717                                                         CurToken.nGroup    = TGRELATION;
00718                                                         CurToken.nLevel    = 0;
00719                                                         CurToken.aText.AssignAscii( ">" );
00720                                                 }
00721                                         }
00722                                         break;
00723                                 default:
00724                                         bHandled = FALSE;
00725                         }
00726                 }
00727         }
00728         else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR)
00729         {
00730                 sal_Int32   &rnEndPos = aRes.EndPos;
00731         String  aName( BufferString.Copy( nRealStart, 
00732                             sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ) );
00733 
00734                 if (1 == aName.Len())
00735                 {
00736                         sal_Unicode ch = aName.GetChar( 0 );
00737                         switch (ch)
00738                         {
00739                                 case '%':
00740                                         {
00742 
00743                                                 DBG_ASSERT( rnEndPos >= nBufLen  ||
00744                                     '%' != BufferString.GetChar( sal::static_int_cast< xub_StrLen >(rnEndPos) ),
00745                                                                 "unexpected comment start" );
00746 
00747                                                 // get identifier of user-defined character
00748                         ParseResult aTmpRes = aCC.parseAnyToken(
00749                                                                 BufferString, rnEndPos,
00750                                                                 KParseTokens::ANY_LETTER,
00751                                                                 aEmptyStr,
00752                                 coContFlags,
00753                                                                 aEmptyStr );
00754 
00755                         xub_StrLen nTmpStart = sal::static_int_cast< xub_StrLen >(rnEndPos +
00756                                                     aTmpRes.LeadingWhiteSpace);
00757 
00758                         // default setting fo the case that no identifier
00759                         // i.e. a valid symbol-name is following the '%'
00760                         // character
00761                         CurToken.eType      = TTEXT;
00762                         CurToken.cMathChar  = '\0';
00763                         CurToken.nGroup     = 0;
00764                         CurToken.nLevel     = 5;
00765                         CurToken.aText      = String();
00766                         CurToken.nRow       = sal::static_int_cast< xub_StrLen >(Row);
00767                         CurToken.nCol       = nTmpStart - ColOff + 1;
00768 
00769                         if (aTmpRes.TokenType & KParseType::IDENTNAME)
00770                         {
00771 
00772                             xub_StrLen n = sal::static_int_cast< xub_StrLen >(aTmpRes.EndPos - nTmpStart);
00773                             CurToken.eType      = TSPECIAL;
00774                             CurToken.aText      = BufferString.Copy( sal::static_int_cast< xub_StrLen >(nTmpStart), n );
00775 
00776                             DBG_ASSERT( aTmpRes.EndPos > rnEndPos,
00777                                     "empty identifier" );
00778                             if (aTmpRes.EndPos > rnEndPos)
00779                                 rnEndPos = aTmpRes.EndPos;
00780                             else
00781                                 ++rnEndPos;
00782                         }
00783 
00784                         // if no symbol-name was found we start-over with
00785                         // finding the next token right afer the '%' sign.
00786                         // I.e. we leave rnEndPos unmodified.
00787                                         }
00788                                         break;
00789                                 case '[':
00790                                         {
00791                                                 CurToken.eType     = TLBRACKET;
00792                                                 CurToken.cMathChar = MS_LBRACKET;
00793                                                 CurToken.nGroup    = TGLBRACES;
00794                                                 CurToken.nLevel    = 5;
00795                                                 CurToken.aText.AssignAscii( "[" );
00796                                         }
00797                                         break;
00798                                 case '\\':
00799                                         {
00800                                                 CurToken.eType     = TESCAPE;
00801                                                 CurToken.cMathChar = '\0';
00802                                                 CurToken.nGroup    = 0;
00803                                                 CurToken.nLevel    = 5;
00804                                                 CurToken.aText.AssignAscii( "\\" );
00805                                         }
00806                                         break;
00807                                 case ']':
00808                                         {
00809                                                 CurToken.eType     = TRBRACKET;
00810                                                 CurToken.cMathChar = MS_RBRACKET;
00811                                                 CurToken.nGroup    = TGRBRACES;
00812                                                 CurToken.nLevel    = 0;
00813                                                 CurToken.aText.AssignAscii( "]" );
00814                                         }
00815                                         break;
00816                                 case '^':
00817                                         {
00818                                                 CurToken.eType     = TRSUP;
00819                                                 CurToken.cMathChar = '\0';
00820                                                 CurToken.nGroup    = TGPOWER;
00821                                                 CurToken.nLevel    = 0;
00822                                                 CurToken.aText.AssignAscii( "^" );
00823                                         }
00824                                         break;
00825                                 case '`':
00826                                         {
00827                                                 CurToken.eType     = TSBLANK;
00828                                                 CurToken.cMathChar = '\0';
00829                                                 CurToken.nGroup    = TGBLANK;
00830                                                 CurToken.nLevel    = 5;
00831                                                 CurToken.aText.AssignAscii( "`" );
00832                                         }
00833                                         break;
00834                                 case '{':
00835                                         {
00836                                                 CurToken.eType     = TLGROUP;
00837                                                 CurToken.cMathChar = MS_LBRACE;
00838                                                 CurToken.nGroup    = 0;
00839                                                 CurToken.nLevel    = 5;
00840                                                 CurToken.aText.AssignAscii( "{" );
00841                                         }
00842                                         break;
00843                                 case '|':
00844                                         {
00845                                                 CurToken.eType     = TOR;
00846                                                 CurToken.cMathChar = MS_OR;
00847                                                 CurToken.nGroup    = TGSUM;
00848                                                 CurToken.nLevel    = 0;
00849                                                 CurToken.aText.AssignAscii( "|" );
00850                                         }
00851                                         break;
00852                                 case '}':
00853                                         {
00854                                                 CurToken.eType     = TRGROUP;
00855                                                 CurToken.cMathChar = MS_RBRACE;
00856                                                 CurToken.nGroup    = 0;
00857                                                 CurToken.nLevel    = 0;
00858                                                 CurToken.aText.AssignAscii( "}" );
00859                                         }
00860                                         break;
00861                                 case '~':
00862                                         {
00863                                                 CurToken.eType     = TBLANK;
00864                                                 CurToken.cMathChar = '\0';
00865                                                 CurToken.nGroup    = TGBLANK;
00866                                                 CurToken.nLevel    = 5;
00867                                                 CurToken.aText.AssignAscii( "~" );
00868                                         }
00869                                         break;
00870                                 case '#':
00871                                         {
00872                         if (BufferString.Copy( nRealStart, 2 ).
00873                                                                 EqualsAscii( "##" ))
00874                                                 {
00875                                                         CurToken.eType     = TDPOUND;
00876                                                         CurToken.cMathChar = '\0';
00877                                                         CurToken.nGroup    = 0;
00878                                                         CurToken.nLevel    = 0;
00879                                                         CurToken.aText.AssignAscii( "##" );
00880 
00881                                                         rnEndPos = nRealStart + 2;
00882                                                 }
00883                                                 else
00884                                                 {
00885                                                         CurToken.eType     = TPOUND;
00886                                                         CurToken.cMathChar = '\0';
00887                                                         CurToken.nGroup    = 0;
00888                                                         CurToken.nLevel    = 0;
00889                                                         CurToken.aText.AssignAscii( "#" );
00890                                                 }
00891                                         }
00892                                         break;
00893                                 case '&':
00894                                         {
00895                                                 CurToken.eType     = TAND;
00896                                                 CurToken.cMathChar = MS_AND;
00897                                                 CurToken.nGroup    = TGPRODUCT;
00898                                                 CurToken.nLevel    = 0;
00899                                                 CurToken.aText.AssignAscii( "&" );
00900                                         }
00901                                         break;
00902                                 case '(':
00903                                         {
00904                                                 CurToken.eType     = TLPARENT;
00905                                                 CurToken.cMathChar = MS_LPARENT;
00906                                                 CurToken.nGroup    = TGLBRACES;
00907                                                 CurToken.nLevel    = 5;         
00908                                                 CurToken.aText.AssignAscii( "(" );
00909                                         }
00910                                         break;
00911                                 case ')':
00912                                         {
00913                                                 CurToken.eType     = TRPARENT;
00914                                                 CurToken.cMathChar = MS_RPARENT;
00915                                                 CurToken.nGroup    = TGRBRACES;
00916                                                 CurToken.nLevel    = 0;         
00917                                                 CurToken.aText.AssignAscii( ")" );
00918                                         }
00919                                         break;
00920                                 case '*':
00921                                         {
00922                                                 CurToken.eType     = TMULTIPLY;
00923                                                 CurToken.cMathChar = MS_MULTIPLY;
00924                                                 CurToken.nGroup    = TGPRODUCT;
00925                                                 CurToken.nLevel    = 0;
00926                                                 CurToken.aText.AssignAscii( "*" );
00927                                         }
00928                                         break;
00929                                 case '+':
00930                                         {
00931                         if (BufferString.Copy( nRealStart, 2 ).
00932                                                                 EqualsAscii( "+-" ))
00933                                                 {
00934                                                         CurToken.eType     = TPLUSMINUS;
00935                                                         CurToken.cMathChar = MS_PLUSMINUS;
00936                                                         CurToken.nGroup    = TGUNOPER | TGSUM;
00937                                                         CurToken.nLevel    = 5;
00938                                                         CurToken.aText.AssignAscii( "+-" );
00939 
00940                                                         rnEndPos = nRealStart + 2;
00941                                                 }
00942                                                 else
00943                                                 {
00944                                                         CurToken.eType     = TPLUS;
00945                                                         CurToken.cMathChar = MS_PLUS;
00946                                                         CurToken.nGroup    = TGUNOPER | TGSUM;
00947                                                         CurToken.nLevel    = 5;
00948                                                         CurToken.aText.AssignAscii( "+" );
00949                                                 }
00950                                         }
00951                                         break;
00952                                 case '-':
00953                                         {
00954                         if (BufferString.Copy( nRealStart, 2 ).
00955                                                                 EqualsAscii( "-+" ))
00956                                                 {
00957                                                         CurToken.eType     = TMINUSPLUS;
00958                                                         CurToken.cMathChar = MS_MINUSPLUS;
00959                                                         CurToken.nGroup    = TGUNOPER | TGSUM;
00960                                                         CurToken.nLevel    = 5;
00961                                                         CurToken.aText.AssignAscii( "-+" );
00962 
00963                                                         rnEndPos = nRealStart + 2;
00964                                                 }
00965                                                 else
00966                                                 {
00967                                                         CurToken.eType     = TMINUS;
00968                                                         CurToken.cMathChar = MS_MINUS;
00969                                                         CurToken.nGroup    = TGUNOPER | TGSUM;
00970                                                         CurToken.nLevel    = 5;
00971                                                         CurToken.aText.AssignAscii( "-" );
00972                                                 }
00973                                         }
00974                                         break;
00975                                 case '.':
00976                                         {
00977                         // for compatibility with SO5.2
00978                         // texts like .34 ...56 ... h ...78..90
00979                         // will be treated as numbers
00980                         CurToken.eType     = TNUMBER;
00981                                                 CurToken.cMathChar = '\0';
00982                                                 CurToken.nGroup    = 0;
00983                         CurToken.nLevel    = 5;
00984 
00985                         xub_StrLen nTxtStart = BufferIndex;
00986                         sal_Unicode cChar;
00987                         do
00988                         {
00989                             cChar = BufferString.GetChar( ++BufferIndex );
00990                         }
00991                         while ( cChar == '.' || IsDigit( cChar ) );
00992 
00993                         CurToken.aText = BufferString.Copy( sal::static_int_cast< xub_StrLen >(nTxtStart), 
00994                                                             sal::static_int_cast< xub_StrLen >(BufferIndex - nTxtStart) );
00995                         aRes.EndPos = BufferIndex;
00996                                         }
00997                                         break;
00998                                 case '/':
00999                                         {
01000                                                 CurToken.eType     = TDIVIDEBY;
01001                                                 CurToken.cMathChar = MS_SLASH;
01002                                                 CurToken.nGroup    = TGPRODUCT;
01003                                                 CurToken.nLevel    = 0;
01004                                                 CurToken.aText.AssignAscii( "/" );
01005                                         }
01006                                         break;
01007                                 case '=':
01008                                         {
01009                                                 CurToken.eType     = TASSIGN;
01010                                                 CurToken.cMathChar = MS_ASSIGN;
01011                                                 CurToken.nGroup    = TGRELATION;
01012                                                 CurToken.nLevel    = 0;
01013                                                 CurToken.aText.AssignAscii( "=" );
01014                                         }
01015                                         break;
01016                                 default:
01017                                         bHandled = FALSE;
01018                         }
01019                 }
01020         }
01021         else
01022                 bHandled = FALSE;
01023 
01024         if (!bHandled)
01025         {
01026                 CurToken.eType      = TCHARACTER;
01027                 CurToken.cMathChar  = '\0';
01028                 CurToken.nGroup     = 0;
01029                 CurToken.nLevel     = 5;
01030         CurToken.aText      = BufferString.Copy( nRealStart, 1 );
01031 
01032                 aRes.EndPos = nRealStart + 1;
01033         }
01034 
01035         if (TEND != CurToken.eType)
01036         BufferIndex = sal::static_int_cast< xub_StrLen >(aRes.EndPos);
01037 }
01038 
01039 
01041 // grammar
01042 //
01043 
01044 
01045 void SmParser::Table()
01046 {
01047         SmNodeArray  LineArray;
01048 
01049         Line();
01050         while (CurToken.eType == TNEWLINE)
01051         {
01052                 NextToken();
01053                 Line();
01054         }
01055 
01056         if (CurToken.eType != TEND)
01057                 Error(PE_UNEXPECTED_CHAR);
01058 
01059         ULONG n = NodeStack.Count();
01060 
01061         LineArray.SetSize(n);
01062 
01063         for (ULONG i = 0; i < n; i++)
01064                 LineArray.Put(n - (i + 1), NodeStack.Pop());
01065 
01066         SmStructureNode *pSNode = new SmTableNode(CurToken);
01067         pSNode->SetSubNodes(LineArray);
01068         NodeStack.Push(pSNode);
01069 }
01070 
01071 
01072 void SmParser::Align()
01073         // parse alignment info (if any), then go on with rest of expression
01074 {
01075         SmStructureNode *pSNode = 0;
01076         BOOL    bNeedGroupClose = FALSE;
01077 
01078         if (TokenInGroup(TGALIGN))
01079         {
01080         if (CONVERT_40_TO_50 == GetConversion())
01081                         // encapsulate expression to be aligned in group braces
01082                         // (here group-open brace)
01083                 {       Insert('{', GetTokenIndex());
01084                         bNeedGroupClose = TRUE;
01085 
01086                         // get first valid align statement in sequence
01087                         // (the dominant one in 4.0) and erase all others (especially old
01088                         // discarded tokens) from command string.
01089                         while (TokenInGroup(TGALIGN))
01090                         {       if (TokenInGroup(TGDISCARDED) || pSNode)
01091                                 {   BufferIndex = GetTokenIndex();
01092                                         BufferString.Erase(BufferIndex, CurToken.aText.Len());
01093                                 }
01094                                 else
01095                                         pSNode = new SmAlignNode(CurToken);
01096 
01097                                 NextToken();
01098                         }
01099                 }
01100                 else
01101                 {
01102                         pSNode = new SmAlignNode(CurToken);
01103 
01104                         NextToken();
01105 
01106                         // allow for just one align statement in 5.0
01107             if (CONVERT_40_TO_50 != GetConversion() && TokenInGroup(TGALIGN))
01108                         {       Error(PE_DOUBLE_ALIGN);
01109                                 return;
01110                         }
01111                 }
01112         }
01113 
01114         Expression();
01115 
01116         if (bNeedGroupClose)
01117                 Insert('}', GetTokenIndex());
01118 
01119         if (pSNode)
01120         {       pSNode->SetSubNodes(NodeStack.Pop(), 0);
01121                 NodeStack.Push(pSNode);
01122         }
01123 }
01124 
01125 
01126 void SmParser::Line()
01127 {
01128         USHORT  n = 0;
01129         SmNodeArray  ExpressionArray;
01130 
01131         ExpressionArray.SetSize(n);
01132 
01133         // start with single expression that may have an alignment statement
01134         // (and go on with expressions that must not have alignment
01135         // statements in 'while' loop below. See also 'Expression()'.)
01136         if (CurToken.eType != TEND  &&  CurToken.eType != TNEWLINE)
01137         {       Align();
01138                 ExpressionArray.SetSize(++n);
01139                 ExpressionArray.Put(n - 1, NodeStack.Pop());
01140         }
01141 
01142         while (CurToken.eType != TEND  &&  CurToken.eType != TNEWLINE)
01143     {   if (CONVERT_40_TO_50 != GetConversion())
01144                         Expression();
01145                 else
01146                         Align();
01147                 ExpressionArray.SetSize(++n);
01148                 ExpressionArray.Put(n - 1, NodeStack.Pop());
01149         }
01150 
01151         SmStructureNode *pSNode = new SmLineNode(CurToken);
01152         pSNode->SetSubNodes(ExpressionArray);
01153         NodeStack.Push(pSNode);
01154 }
01155 
01156 
01157 void SmParser::Expression()
01158 {
01159         USHORT           n = 0;
01160         SmNodeArray  RelationArray;
01161 
01162         RelationArray.SetSize(n);
01163 
01164         Relation();
01165         RelationArray.SetSize(++n);
01166         RelationArray.Put(n - 1, NodeStack.Pop());
01167 
01168         while (CurToken.nLevel >= 4)
01169         {       Relation();
01170                 RelationArray.SetSize(++n);
01171                 RelationArray.Put(n - 1, NodeStack.Pop());
01172         }
01173 
01174         SmStructureNode *pSNode = new SmExpressionNode(CurToken);
01175         pSNode->SetSubNodes(RelationArray);
01176         NodeStack.Push(pSNode);
01177 }
01178 
01179 
01180 void SmParser::Relation()
01181 {
01182         Sum();
01183         while (TokenInGroup(TGRELATION))
01184         {
01185                 SmStructureNode *pSNode  = new SmBinHorNode(CurToken);
01186                 SmNode *pFirst = NodeStack.Pop();
01187 
01188                 OpSubSup();
01189                 SmNode *pSecond = NodeStack.Pop();
01190 
01191                 Sum();
01192 
01193                 pSNode->SetSubNodes(pFirst, pSecond, NodeStack.Pop());
01194                 NodeStack.Push(pSNode);
01195         }
01196 }
01197 
01198 
01199 void SmParser::Sum()
01200 {
01201         Product();
01202         while (TokenInGroup(TGSUM))
01203         {
01204                 SmStructureNode *pSNode  = new SmBinHorNode(CurToken);
01205                 SmNode *pFirst = NodeStack.Pop();
01206 
01207                 OpSubSup();
01208                 SmNode *pSecond = NodeStack.Pop();
01209 
01210                 Product();
01211 
01212                 pSNode->SetSubNodes(pFirst, pSecond, NodeStack.Pop());
01213                 NodeStack.Push(pSNode);
01214         }
01215 }
01216 
01217 
01218 void SmParser::Product()
01219 {
01220         Power();
01221 
01222         while (TokenInGroup(TGPRODUCT))
01223         {       SmStructureNode *pSNode;
01224                 SmNode *pFirst = NodeStack.Pop(),
01225                            *pOper;
01226                 BOOL bSwitchArgs = FALSE;
01227 
01228                 SmTokenType eType = CurToken.eType;
01229                 switch (eType)
01230                 {
01231                         case TOVER:
01232                                 pSNode = new SmBinVerNode(CurToken);
01233                                 pOper = new SmRectangleNode(CurToken);
01234                                 NextToken();
01235                                 break;
01236 
01237                         case TBOPER:
01238                                 pSNode = new SmBinHorNode(CurToken);
01239 
01240                                 NextToken();
01241 
01242                                 GlyphSpecial();
01243                                 pOper = NodeStack.Pop();
01244                                 break;
01245 
01246                         case TOVERBRACE :
01247                         case TUNDERBRACE :
01248                                 pSNode = new SmVerticalBraceNode(CurToken);
01249                                 pOper = new SmMathSymbolNode(CurToken);
01250 
01251                                 NextToken();
01252                                 break;
01253 
01254                         case TWIDEBACKSLASH:
01255                         case TWIDESLASH:
01256                         {
01257                                 SmBinDiagonalNode *pSTmp = new SmBinDiagonalNode(CurToken);
01258                                 pSTmp->SetAscending(eType == TWIDESLASH);
01259                                 pSNode = pSTmp;
01260 
01261                                 pOper = new SmPolyLineNode(CurToken);
01262                                 NextToken();
01263 
01264                                 bSwitchArgs =TRUE;
01265                                 break;
01266                         }
01267 
01268                         default:
01269                                 pSNode = new SmBinHorNode(CurToken);
01270 
01271                                 OpSubSup();
01272                                 pOper = NodeStack.Pop();
01273                 }
01274 
01275                 Power();
01276 
01277                 if (bSwitchArgs)
01279                         pSNode->SetSubNodes(pFirst, NodeStack.Pop(), pOper);
01280                 else
01281                         pSNode->SetSubNodes(pFirst, pOper, NodeStack.Pop());
01282                 NodeStack.Push(pSNode);
01283         }
01284 }
01285 
01286 
01287 void SmParser::SubSup(ULONG nActiveGroup)
01288 {
01289         DBG_ASSERT(nActiveGroup == TGPOWER  ||  nActiveGroup == TGLIMIT,
01290                            "Sm: falsche Tokengruppe");
01291 
01292         if (!TokenInGroup(nActiveGroup))
01293                 // already finish
01294                 return;
01295 
01296         SmSubSupNode *pNode = new SmSubSupNode(CurToken);
01301 
01302         pNode->SetUseLimits(nActiveGroup == TGLIMIT);
01303 
01304         // initialize subnodes array
01305         SmNodeArray  aSubNodes;
01306         aSubNodes.SetSize(1 + SUBSUP_NUM_ENTRIES);
01307         aSubNodes.Put(0, NodeStack.Pop());
01308         for (USHORT i = 1;  i < aSubNodes.GetSize();  i++)
01309                 aSubNodes.Put(i, NULL);
01310 
01311         // process all sub-/supscripts
01312     int  nIndex = 0;
01313         while (TokenInGroup(nActiveGroup))
01314         {       SmTokenType  eType (CurToken.eType);
01315 
01316                 // skip sub-/supscript token
01317                 NextToken();
01318 
01319                 // get sub-/supscript node on top of stack
01320                 if (eType == TFROM  ||  eType == TTO)
01321                 {
01322                         // parse limits in old 4.0 and 5.0 style
01323                         Relation();
01324                 }
01325                 else
01326                         Term();
01327 
01328                 switch (eType)
01329                 {       case TRSUB :    nIndex = (int) RSUB;    break;
01330                         case TRSUP :    nIndex = (int) RSUP;    break;
01331                         case TFROM :
01332                         case TCSUB :    nIndex = (int) CSUB;    break;
01333                         case TTO :
01334                         case TCSUP :    nIndex = (int) CSUP;    break;
01335                         case TLSUB :    nIndex = (int) LSUB;    break;
01336                         case TLSUP :    nIndex = (int) LSUP;    break;
01337                         default :
01338                                 DBG_ASSERT(FALSE, "Sm: unbekannter Fall");
01339                 }
01340                 nIndex++;
01341                 DBG_ASSERT(1 <= nIndex  &&      nIndex <= 1 + SUBSUP_NUM_ENTRIES,
01342                                    "SmParser::Power() : sub-/supscript index falsch")
01343 
01344                 // set sub-/supscript if not already done
01345                 if (aSubNodes.Get(nIndex) != NULL)
01346                         Error(PE_DOUBLE_SUBSUPSCRIPT);
01347                 aSubNodes.Put(nIndex, NodeStack.Pop());
01348         }
01349 
01350         pNode->SetSubNodes(aSubNodes);
01351         NodeStack.Push(pNode);
01352 }
01353 
01354 
01355 void SmParser::OpSubSup()
01356 {
01357         // push operator symbol
01358         NodeStack.Push(new SmMathSymbolNode(CurToken));
01359         // skip operator token
01360         NextToken();
01361         // get sub- supscripts if any
01362         if (TokenInGroup(TGPOWER))
01363                 SubSup(TGPOWER);
01364 }
01365 
01366 
01367 void SmParser::Power()
01368 {
01369         // get body for sub- supscripts on top of stack
01370         Term();
01371 
01372         SubSup(TGPOWER);
01373 }
01374 
01375 
01376 void SmParser::Blank()
01377 {
01378         DBG_ASSERT(TokenInGroup(TGBLANK), "Sm : falsches Token");
01379         SmBlankNode *pBlankNode = new SmBlankNode(CurToken);
01380 
01381         while (TokenInGroup(TGBLANK))
01382         {
01383                 pBlankNode->IncreaseBy(CurToken);
01384                 NextToken();
01385         }
01386 
01387         // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist
01388         if (CurToken.eType == TNEWLINE  ||  CurToken.eType == TEND
01389         &&  SM_MOD1()->GetConfig()->IsIgnoreSpacesRight())
01390                 pBlankNode->Clear();
01391 
01392         NodeStack.Push(pBlankNode);
01393 }
01394 
01395 
01396 void SmParser::Term()
01397 {
01398         switch (CurToken.eType)
01399         {       case TESCAPE :
01400                         Escape();
01401                         break;
01402 
01403                 case TLGROUP :
01404                         NextToken();
01405 
01406                         // allow for empty group
01407                         if (CurToken.eType == TRGROUP)
01408                         {       SmStructureNode *pSNode = new SmExpressionNode(CurToken);
01409                                 pSNode->SetSubNodes(NULL, NULL);
01410                                 NodeStack.Push(pSNode);
01411 
01412                                 NextToken();
01413                         }
01414                         else    // go as usual
01415                         {       Align();
01416                                 if (CurToken.eType != TRGROUP)
01417                                         Error(PE_RGROUP_EXPECTED);
01418                                 else
01419                                 {       NextToken();
01420                                 }
01421                         }
01422                         break;
01423 
01424                 case TLEFT :
01425                         Brace();
01426                         break;
01427 
01428                 case TBLANK :
01429                 case TSBLANK :
01430                         Blank();
01431                         break;
01432 
01433                 case TTEXT :
01434                         NodeStack.Push(new SmTextNode(CurToken, FNT_TEXT));
01435                         NextToken();
01436                         break;
01437                 case TIDENT :
01438                 case TCHARACTER :
01439                         NodeStack.Push(new SmTextNode(CurToken, FNT_VARIABLE));
01440                         NextToken();
01441                         break;
01442                 case TNUMBER :
01443                         NodeStack.Push(new SmTextNode(CurToken, FNT_NUMBER));
01444                         NextToken();
01445                         break;
01446 
01447                 case TLEFTARROW :
01448                 case TRIGHTARROW :
01449                 case TUPARROW :
01450                 case TDOWNARROW :
01451                 case TSETN :
01452                 case TSETZ :
01453                 case TSETQ :
01454                 case TSETR :
01455                 case TSETC :
01456                 case THBAR :
01457                 case TLAMBDABAR :
01458                 case TCIRC :
01459                 case TDRARROW :
01460                 case TDLARROW :
01461                 case TDLRARROW :
01462                 case TBACKEPSILON :
01463                 case TALEPH :
01464                 case TIM :
01465                 case TRE :
01466                 case TWP :
01467                 case TEMPTYSET :
01468                 case TINFINITY :
01469                 case TEXISTS :
01470                 case TFORALL :
01471                 case TPARTIAL :
01472                 case TNABLA :
01473                 case TTOWARD :
01474                 case TDOTSAXIS :
01475                 case TDOTSDIAG :
01476                 case TDOTSDOWN :
01477                 case TDOTSLOW :
01478                 case TDOTSUP :
01479                 case TDOTSVERT :
01480                         NodeStack.Push(new SmMathSymbolNode(CurToken));
01481                         NextToken();
01482                         break;
01483 
01484                 case TPLACE:
01485                         NodeStack.Push(new SmPlaceNode(CurToken));
01486                         NextToken();
01487                         break;
01488 
01489                 case TSPECIAL:
01490                         Special();
01491                         break;
01492 
01493                 case TBINOM:
01494                         Binom();
01495                         break;
01496 
01497                 case TSTACK:
01498                         Stack();
01499                         break;
01500 
01501                 case TMATRIX:
01502                         Matrix();
01503                         break;
01504 
01505                 default:
01506                         if (TokenInGroup(TGLBRACES))
01507                         {       Brace();
01508                         }
01509                         else if (TokenInGroup(TGOPER))
01510                         {       Operator();
01511                         }
01512                         else if (TokenInGroup(TGUNOPER))
01513                         {       UnOper();
01514                         }
01515                         else if (    TokenInGroup(TGATTRIBUT)
01516                                          ||  TokenInGroup(TGFONTATTR))
01517                         {       SmStructureNodeArray  aArray;
01518 
01519                                 BOOL    bIsAttr;
01520                                 USHORT  n = 0;
01521                 while (TRUE == (bIsAttr = TokenInGroup(TGATTRIBUT))
01522                                            ||  TokenInGroup(TGFONTATTR))
01523                                 {       aArray.SetSize(n + 1);
01524 
01525                                         if (bIsAttr)
01526                                                 Attribut();
01527                                         else
01528                                                 FontAttribut();
01529 
01530                                         // check if casting in following line is ok
01531                                         DBG_ASSERT(!NodeStack.Top()->IsVisible(), "Sm : Ooops...");
01532 
01533                                         aArray.Put(n, (SmStructureNode *) NodeStack.Pop());
01534                                         n++;
01535                                 }
01536 
01537                                 Power();
01538 
01539                                 SmNode *pFirstNode = NodeStack.Pop();
01540                                 while (n > 0)
01541                                 {       aArray.Get(n - 1)->SetSubNodes(0, pFirstNode);
01542                                         pFirstNode = aArray.Get(n - 1);
01543                                         n--;
01544                                 }
01545                                 NodeStack.Push(pFirstNode);
01546                         }
01547                         else if (TokenInGroup(TGFUNCTION))
01548             {   if (CONVERT_40_TO_50 != GetConversion())
01549                                 {       Function();
01550                                 }
01551                                 else    // encapsulate old 4.0 style parsing in braces
01552                                 {
01553                                         // insert opening brace
01554                                         Insert('{', GetTokenIndex());
01555 
01556                                         //
01557                                         // parse in 4.0 style
01558                                         //
01559                                         Function();
01560 
01561                                         SmNode *pFunc = NodeStack.Pop();
01562 
01563                                         if (CurToken.eType == TLPARENT)
01564                                         {       Term();
01565                                         }
01566                                         else
01567                                         {       Align();
01568                                         }
01569 
01570                                         // insert closing brace
01571                                         Insert('}', GetTokenIndex());
01572 
01573                                         SmStructureNode *pSNode = new SmExpressionNode(pFunc->GetToken());
01574                                         pSNode->SetSubNodes(pFunc, NodeStack.Pop());
01575                                         NodeStack.Push(pSNode);
01576                                 }
01577                         }
01578                         else
01579                                 Error(PE_UNEXPECTED_CHAR);
01580         }
01581 }
01582 
01583 
01584 void SmParser::Escape()
01585 {
01586         NextToken();
01587 
01588         sal_Unicode     cChar;
01589         switch (CurToken.eType)
01590         {       case TLPARENT :         cChar = MS_LPARENT;             break;
01591                 case TRPARENT :         cChar = MS_RPARENT;             break;
01592                 case TLBRACKET :        cChar = MS_LBRACKET;    break;
01593                 case TRBRACKET :        cChar = MS_RBRACKET;    break;
01594         case TLDBRACKET :   cChar = MS_LDBRACKET;   break;
01595         case TRDBRACKET :   cChar = MS_RDBRACKET;   break;
01596                 case TLBRACE :
01597                 case TLGROUP :          cChar = MS_LBRACE;              break;
01598                 case TRBRACE :
01599                 case TRGROUP :          cChar = MS_RBRACE;              break;
01600                 case TLANGLE :          cChar = MS_LANGLE;              break;
01601                 case TRANGLE :          cChar = MS_RANGLE;              break;
01602                 case TLCEIL :           cChar = MS_LCEIL;               break;
01603                 case TRCEIL :           cChar = MS_RCEIL;               break;
01604                 case TLFLOOR :          cChar = MS_LFLOOR;              break;
01605                 case TRFLOOR :          cChar = MS_RFLOOR;              break;
01606                 case TLLINE :
01607                 case TRLINE :           cChar = MS_LINE;                break;
01608                 case TLDLINE :
01609                 case TRDLINE :          cChar = MS_DLINE;               break;
01610                 default:
01611                         Error(PE_UNEXPECTED_TOKEN);
01612         }
01613 
01614         SmNode *pNode = new SmMathSymbolNode(CurToken);
01615         NodeStack.Push(pNode);
01616 
01617         NextToken();
01618 }
01619 
01620 
01621 void SmParser::Operator()
01622 {
01623         if (TokenInGroup(TGOPER))
01624         {       SmStructureNode *pSNode = new SmOperNode(CurToken);
01625 
01626                 // put operator on top of stack
01627                 Oper();
01628 
01629                 if (TokenInGroup(TGLIMIT) || TokenInGroup(TGPOWER))
01630                         SubSup(CurToken.nGroup);
01631                 SmNode *pOperator = NodeStack.Pop();
01632 
01633                 // get argument
01634                 Power();
01635 
01636                 pSNode->SetSubNodes(pOperator, NodeStack.Pop());
01637                 NodeStack.Push(pSNode);
01638         }
01639 }
01640 
01641 
01642 void SmParser::Oper()
01643 {
01644         SmTokenType  eType (CurToken.eType);
01645         SmNode      *pNode = NULL;
01646 
01647         switch (eType)
01648         {
01649                 case TSUM :
01650                 case TPROD :
01651                 case TCOPROD :
01652                 case TINT :
01653                 case TIINT :
01654                 case TIIINT :
01655                 case TLINT :
01656                 case TLLINT :
01657                 case TLLLINT :
01658                         pNode = new SmMathSymbolNode(CurToken);
01659                         break;
01660 
01661                 case TLIM :
01662                 case TLIMSUP :
01663                 case TLIMINF :
01664                         {
01665                                 const sal_Char* pLim = 0;
01666                                 switch (eType)
01667                                 {
01668                                         case TLIM :             pLim = "lim";           break;
01669                                         case TLIMSUP :  pLim = "lim sup";       break;
01670                                         case TLIMINF :  pLim = "lim inf";       break;
01671                     default:
01672                         break;
01673                                 }
01674                                 if( pLim )
01675                                         CurToken.aText.AssignAscii( pLim );
01676                                 pNode = new SmTextNode(CurToken, FNT_TEXT);
01677                         }
01678                         break;
01679 
01680                 case TOVERBRACE :
01681                 case TUNDERBRACE :
01682                                 pNode = new SmMathSymbolNode(CurToken);
01683                         break;
01684 
01685                 case TOPER :
01686                         NextToken();
01687 
01688                         DBG_ASSERT(CurToken.eType == TSPECIAL, "Sm: falsches Token");
01689                         pNode = new SmGlyphSpecialNode(CurToken);
01690                         break;
01691 
01692                 default :
01693                         DBG_ASSERT(0, "Sm: unbekannter Fall");
01694         }
01695         NodeStack.Push(pNode);
01696 
01697         NextToken();
01698 }
01699 
01700 
01701 void SmParser::UnOper()
01702 {
01703         DBG_ASSERT(TokenInGroup(TGUNOPER), "Sm: falsches Token");
01704 
01705         SmToken          aNodeToken = CurToken;
01706         SmTokenType  eType              = CurToken.eType;
01707         BOOL             bIsPostfix = eType == TFACT;
01708 
01709     SmStructureNode *pSNode;
01710     SmNode *pOper   = 0,
01711            *pExtra  = 0,
01712                    *pArg;
01713 
01714         switch (eType)
01715         {
01716                 case TABS :
01717                 case TSQRT :
01718                         NextToken();
01719                         break;
01720 
01721                 case TNROOT :
01722                         NextToken();
01723                         Power();
01724                         pExtra = NodeStack.Pop();
01725                         break;
01726 
01727                 case TUOPER :
01728                         NextToken();
01729                         GlyphSpecial();
01730                         pOper = NodeStack.Pop();
01731                         break;
01732 
01733                 case TPLUS :
01734                 case TMINUS :
01735                 case TPLUSMINUS :
01736                 case TMINUSPLUS :
01737                 case TNEG :
01738                 case TFACT :
01739                         OpSubSup();
01740                         pOper = NodeStack.Pop();
01741                         break;
01742 
01743                 default :
01744                         Error(PE_UNOPER_EXPECTED);
01745         }
01746 
01747         // get argument
01748         Power();
01749         pArg = NodeStack.Pop();
01750 
01751         if (eType == TABS)
01752         {       pSNode = new SmBraceNode(aNodeToken);
01753                 pSNode->SetScaleMode(SCALE_HEIGHT);
01754 
01755                 // build nodes for left & right lines
01756                 // (text, group, level of the used token are of no interrest here)
01757                 // we'll use row & column of the keyword for abs
01758                 aNodeToken.eType = TABS;
01759                 //
01760                 aNodeToken.cMathChar = MS_LINE;
01761                 SmNode* pLeft = new SmMathSymbolNode(aNodeToken);
01762                 //
01763                 aNodeToken.cMathChar = MS_LINE;
01764                 SmNode* pRight = new SmMathSymbolNode(aNodeToken);
01765 
01766                 pSNode->SetSubNodes(pLeft, pArg, pRight);
01767         }
01768         else if (eType == TSQRT  ||  eType == TNROOT)
01769         {       pSNode = new SmRootNode(aNodeToken);
01770                 pOper = new SmRootSymbolNode(aNodeToken);
01771                 pSNode->SetSubNodes(pExtra, pOper, pArg);
01772         }
01773         else
01774         {       pSNode = new SmUnHorNode(aNodeToken);
01775 
01776                 if (bIsPostfix)
01777                         pSNode->SetSubNodes(pArg, pOper);
01778                 else
01779                         // prefix operator
01780                         pSNode->SetSubNodes(pOper, pArg);
01781         }
01782 
01783         NodeStack.Push(pSNode);
01784 }
01785 
01786 
01787 void SmParser::Attribut()
01788 {
01789         DBG_ASSERT(TokenInGroup(TGATTRIBUT), "Sm: falsche Tokengruppe");
01790 
01791         SmStructureNode *pSNode = new SmAttributNode(CurToken);
01792         SmNode          *pAttr;
01793         SmScaleMode  eScaleMode = SCALE_NONE;
01794 
01795         // get appropriate node for the attribut itself
01796         switch (CurToken.eType)
01797         {       case TUNDERLINE :
01798                 case TOVERLINE :
01799                 case TOVERSTRIKE :
01800                         pAttr = new SmRectangleNode(CurToken);
01801                         eScaleMode = SCALE_WIDTH;
01802                         break;
01803 
01804                 case TWIDEVEC :
01805                 case TWIDEHAT :
01806                 case TWIDETILDE :
01807                         pAttr = new SmMathSymbolNode(CurToken);
01808                         eScaleMode = SCALE_WIDTH;
01809                         break;
01810 
01811                 default :
01812                         pAttr = new SmMathSymbolNode(CurToken);
01813         }
01814 
01815         NextToken();
01816 
01817         pSNode->SetSubNodes(pAttr, 0);
01818         pSNode->SetScaleMode(eScaleMode);
01819         NodeStack.Push(pSNode);
01820 }
01821 
01822 
01823 void SmParser::FontAttribut()
01824 {
01825         DBG_ASSERT(TokenInGroup(TGFONTATTR), "Sm: falsche Tokengruppe");
01826 
01827         switch (CurToken.eType)
01828         {
01829                 case TITALIC :
01830                 case TNITALIC :
01831                 case TBOLD :
01832                 case TNBOLD :
01833                 case TPHANTOM :
01834                         NodeStack.Push(new SmFontNode(CurToken));
01835                         NextToken();
01836                         break;
01837 
01838                 case TSIZE :
01839                         FontSize();
01840                         break;
01841 
01842                 case TFONT :
01843                         Font();
01844                         break;
01845 
01846                 case TCOLOR :
01847                         Color();
01848                         break;
01849 
01850                 default :
01851                         DBG_ASSERT(0, "Sm: unbekannter Fall");
01852         }
01853 }
01854 
01855 
01856 void SmParser::Color()
01857 {
01858         DBG_ASSERT(CurToken.eType == TCOLOR, "Sm : Ooops...");
01859 
01860         // last color rules, get that one
01861         SmToken  aToken;
01862         do
01863         {       NextToken();
01864 
01865                 if (TokenInGroup(TGCOLOR))
01866                 {       aToken = CurToken;
01867                         NextToken();
01868                 }
01869                 else
01870                         Error(PE_COLOR_EXPECTED);
01871         } while (CurToken.eType == TCOLOR);
01872 
01873         NodeStack.Push(new SmFontNode(aToken));
01874 }
01875 
01876 
01877 void SmParser::Font()
01878 {
01879         DBG_ASSERT(CurToken.eType == TFONT, "Sm : Ooops...");
01880 
01881         // last font rules, get that one
01882         SmToken  aToken;
01883         do
01884         {       NextToken();
01885 
01886                 if (TokenInGroup(TGFONT))
01887                 {       aToken = CurToken;
01888                         NextToken();
01889                 }
01890                 else
01891                         Error(PE_FONT_EXPECTED);
01892         } while (CurToken.eType == TFONT);
01893 
01894         NodeStack.Push(new SmFontNode(aToken));
01895 }
01896 
01897 
01898 // gets number used as arguments in Math formulas (e.g. 'size' command)
01899 // Format: no negative numbers, must start with a digit, no exponent notation, ...
01900 BOOL lcl_IsNumber(const UniString& rText)
01901 {
01902         BOOL bPoint = FALSE;
01903         const sal_Unicode* pBuffer = rText.GetBuffer();
01904         for(xub_StrLen nPos = 0; nPos < rText.Len(); nPos++, pBuffer++)
01905         {
01906                 const sal_Unicode cChar = *pBuffer;
01907                 if(cChar == '.')
01908                 {
01909                         if(bPoint)
01910                                 return FALSE;
01911                         else
01912                                 bPoint = TRUE;
01913                 }
01914         else if ( !IsDigit( cChar ) )
01915                         return FALSE;
01916         }
01917         return TRUE;
01918 }
01919 
01920 void SmParser::FontSize()
01921 {
01922         DBG_ASSERT(CurToken.eType == TSIZE, "Sm : Ooops...");
01923 
01924         USHORT     Type;
01925         SmFontNode *pFontNode = new SmFontNode(CurToken);
01926 
01927         NextToken();
01928 
01929         switch (CurToken.eType)
01930         {
01931                 case TNUMBER:   Type = FNTSIZ_ABSOLUT;  break;
01932                 case TPLUS:             Type = FNTSIZ_PLUS;             break;
01933                 case TMINUS:    Type = FNTSIZ_MINUS;    break;
01934                 case TMULTIPLY: Type = FNTSIZ_MULTIPLY; break;
01935                 case TDIVIDEBY: Type = FNTSIZ_DIVIDE;   break;
01936 
01937                 default:
01938                         delete pFontNode;
01939                         Error(PE_SIZE_EXPECTED);
01940                         return;
01941         }
01942 
01943         if (Type != FNTSIZ_ABSOLUT)
01944         {
01945                 NextToken();
01946                 if (CurToken.eType != TNUMBER)
01947                 {
01948                         delete pFontNode;
01949                         Error(PE_SIZE_EXPECTED);
01950                         return;
01951                 }
01952         }
01953 
01954         // get number argument
01955         Fraction  aValue( 1L );
01956     if (lcl_IsNumber( CurToken.aText ))
01957     {
01958         double    fTmp;
01959         if ((fTmp = CurToken.aText.ToDouble()) != 0.0)
01960         {
01961             aValue = fTmp;
01962 
01968             if (aValue.GetDenominator() > 1000)
01969             {
01970                 long nNum   = aValue.GetNumerator();
01971                 long nDenom = aValue.GetDenominator();
01972                 while (nDenom > 1000)
01973                 {
01974                     nNum    /= 10;
01975                     nDenom  /= 10;
01976                 }
01977                 aValue = Fraction( nNum, nDenom );
01978             }
01979         }
01980     }
01981 
01982         NextToken();
01983 
01984         pFontNode->SetSizeParameter(aValue, Type);
01985         NodeStack.Push(pFontNode);
01986 }
01987 
01988 
01989 void SmParser::Brace()
01990 {
01991         DBG_ASSERT(CurToken.eType == TLEFT  ||  TokenInGroup(TGLBRACES),
01992                 "Sm: kein Klammer Ausdruck");
01993 
01994         SmStructureNode *pSNode  = new SmBraceNode(CurToken);
01995         SmNode *pBody   = 0,
01996                    *pLeft   = 0,
01997                    *pRight  = 0;
01998         SmScaleMode   eScaleMode = SCALE_NONE;
01999         SmParseError  eError     = PE_NONE;
02000 
02001         if (CurToken.eType == TLEFT)
02002         {       NextToken();
02003 
02004                 eScaleMode = SCALE_HEIGHT;
02005 
02006                 // check for left bracket
02007                 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES))
02008                 {
02009                         pLeft = new SmMathSymbolNode(CurToken);
02010 
02011                         NextToken();
02012                         Bracebody(TRUE);
02013                         pBody = NodeStack.Pop();
02014 
02015                         if (CurToken.eType == TRIGHT)
02016                         {       NextToken();
02017 
02018                                 // check for right bracket
02019                                 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES))
02020                                 {
02021                                         pRight = new SmMathSymbolNode(CurToken);
02022                                         NextToken();
02023                                 }
02024                                 else
02025                                         eError = PE_RBRACE_EXPECTED;
02026                         }
02027                         else
02028                                 eError = PE_RIGHT_EXPECTED;
02029                 }
02030                 else
02031                         eError = PE_LBRACE_EXPECTED;
02032         }
02033         else
02034         {
02035                 if (TokenInGroup(TGLBRACES))
02036                 {
02037                         pLeft = new SmMathSymbolNode(CurToken);
02038 
02039                         NextToken();
02040                         Bracebody(FALSE);
02041                         pBody = NodeStack.Pop();
02042 
02043             SmTokenType  eExpectedType = TUNKNOWN;
02044                         switch (pLeft->GetToken().eType)
02045                         {       case TLPARENT :         eExpectedType = TRPARENT;       break;
02046                                 case TLBRACKET :        eExpectedType = TRBRACKET;      break;
02047                                 case TLBRACE :          eExpectedType = TRBRACE;        break;
02048                                 case TLDBRACKET :       eExpectedType = TRDBRACKET;     break;
02049                                 case TLLINE :           eExpectedType = TRLINE;         break;
02050                                 case TLDLINE :          eExpectedType = TRDLINE;        break;
02051                                 case TLANGLE :          eExpectedType = TRANGLE;        break;
02052                                 case TLFLOOR :          eExpectedType = TRFLOOR;        break;
02053                                 case TLCEIL :           eExpectedType = TRCEIL;         break;
02054                                 default :
02055                                         DBG_ASSERT(0, "Sm: unbekannter Fall");
02056                         }
02057 
02058                         if (CurToken.eType == eExpectedType)
02059                         {
02060                                 pRight = new SmMathSymbolNode(CurToken);
02061                                 NextToken();
02062                         }
02063                         else
02064                                 eError = PE_PARENT_MISMATCH;
02065                 }
02066                 else
02067                         eError = PE_LBRACE_EXPECTED;
02068         }
02069 
02070         if (eError == PE_NONE)
02071         {   DBG_ASSERT(pLeft,  "Sm: NULL pointer");
02072                 DBG_ASSERT(pRight, "Sm: NULL pointer");
02073                 pSNode->SetSubNodes(pLeft, pBody, pRight);
02074                 pSNode->SetScaleMode(eScaleMode);
02075                 NodeStack.Push(pSNode);
02076         }
02077         else
02078         {       delete pSNode;
02079                 delete pBody;
02080                 delete pLeft;
02081                 delete pRight;
02082 
02083                 Error(eError);
02084         }
02085 }
02086 
02087 
02088 void SmParser::Bracebody(BOOL bIsLeftRight)
02089 {
02090         SmStructureNode *pBody = new SmBracebodyNode(CurToken);
02091         SmNodeArray      aNodes;
02092         USHORT                   nNum = 0;
02093 
02094         // get body if any
02095         if (bIsLeftRight)
02096         {
02097                 do
02098                 {
02099                         if (CurToken.eType == TMLINE)
02100                         {
02101                                 NodeStack.Push(new SmMathSymbolNode(CurToken));
02102                 NextToken();
02103                                 nNum++;
02104                         }
02105                         else if (CurToken.eType != TRIGHT)
02106                         {       Align();
02107                                 nNum++;
02108 
02109                                 if (CurToken.eType != TMLINE  &&  CurToken.eType != TRIGHT)
02110                                         Error(PE_RIGHT_EXPECTED);
02111                         }
02112                 } while (CurToken.eType != TEND  &&  CurToken.eType != TRIGHT);
02113         }
02114         else
02115         {
02116                 do
02117                 {
02118                         if (CurToken.eType == TMLINE)
02119                         {
02120                                 NodeStack.Push(new SmMathSymbolNode(CurToken));
02121                                 NextToken();
02122                                 nNum++;
02123                         }
02124                         else if (!TokenInGroup(TGRBRACES))
02125                         {       Align();
02126                                 nNum++;
02127 
02128                                 if (CurToken.eType != TMLINE  &&  !TokenInGroup(TGRBRACES))
02129                                         Error(PE_RBRACE_EXPECTED);
02130                         }
02131                 } while (CurToken.eType != TEND  &&  !TokenInGroup(TGRBRACES));
02132         }
02133 
02134         // build argument vector in parsing order
02135         aNodes.SetSize(nNum);
02136         for (USHORT i = 0;  i < nNum;  i++)
02137                 aNodes.Put(nNum - 1 - i, NodeStack.Pop());
02138 
02139         pBody->SetSubNodes(aNodes);
02140         pBody->SetScaleMode(bIsLeftRight ? SCALE_HEIGHT : SCALE_NONE);
02141         NodeStack.Push(pBody);
02142 }
02143 
02144 
02145 void SmParser::Function()
02146 {
02147         switch (CurToken.eType)
02148         {
02149                 case TFUNC:
02150                         NextToken();    // skip "FUNC"-statement
02151                         // fall through
02152 
02153                 case TSIN :
02154                 case TCOS :
02155                 case TTAN :
02156                 case TCOT :
02157                 case TASIN :
02158                 case TACOS :
02159                 case TATAN :
02160                 case TACOT :
02161                 case TSINH :
02162                 case TCOSH :
02163                 case TTANH :
02164                 case TCOTH :
02165                 case TASINH :
02166                 case TACOSH :
02167                 case TATANH :
02168                 case TACOTH :
02169                 case TLN :
02170                 case TLOG :
02171                 case TEXP :
02172                         NodeStack.Push(new SmTextNode(CurToken, FNT_FUNCTION));
02173                         NextToken();
02174                         break;
02175 
02176                 default:
02177                         Error(PE_FUNC_EXPECTED);
02178         }
02179 }
02180 
02181 
02182 void SmParser::Binom()
02183 {
02184         SmNodeArray  ExpressionArray;
02185         SmStructureNode *pSNode = new SmTableNode(CurToken);
02186 
02187         NextToken();
02188 
02189         Sum();
02190         Sum();
02191 
02192         ExpressionArray.SetSize(2);
02193 
02194         for (int i = 0;  i < 2;  i++)
02195                 ExpressionArray.Put(2 - (i + 1), NodeStack.Pop());
02196 
02197         pSNode->SetSubNodes(ExpressionArray);
02198         NodeStack.Push(pSNode);
02199 }
02200 
02201 
02202 void SmParser::Stack()
02203 {
02204         SmNodeArray  ExpressionArray;
02205         NextToken();
02206         if (CurToken.eType == TLGROUP)
02207         {
02208                 USHORT n = 0;
02209 
02210                 do
02211                 {
02212                         NextToken();
02213                         Align();
02214                         n++;
02215                 }
02216                 while (CurToken.eType == TPOUND);
02217 
02218                 ExpressionArray.SetSize(n);
02219 
02220                 for (USHORT i = 0; i < n; i++)
02221                         ExpressionArray.Put(n - (i + 1), NodeStack.Pop());
02222 
02223                 if (CurToken.eType != TRGROUP)
02224                         Error(PE_RGROUP_EXPECTED);
02225 
02226                 NextToken();
02227 
02228                 SmStructureNode *pSNode = new SmTableNode(CurToken);
02229                 pSNode->SetSubNodes(ExpressionArray);
02230                 NodeStack.Push(pSNode);
02231         }
02232         else
02233                 Error(PE_LGROUP_EXPECTED);
02234 }
02235 
02236 
02237 void SmParser::Matrix()
02238 {
02239         SmNodeArray  ExpressionArray;
02240 
02241         NextToken();
02242         if (CurToken.eType == TLGROUP)
02243         {
02244                 USHORT c = 0;
02245 
02246                 do
02247                 {
02248                         NextToken();
02249                         Align();
02250                         c++;
02251                 }
02252                 while (CurToken.eType == TPOUND);
02253 
02254                 USHORT r = 1;
02255 
02256                 while (CurToken.eType == TDPOUND)
02257                 {
02258                         NextToken();
02259                         for (USHORT i = 0; i < c; i++)
02260                         {
02261                                 Align();
02262                                 if (i < (c - 1))
02263                                 {
02264                                         if (CurToken.eType == TPOUND)
02265                                         {
02266                                                 NextToken();
02267                                         }
02268                                         else
02269                                                 Error(PE_POUND_EXPECTED);
02270                                 }
02271                         }
02272 
02273                         r++;
02274                 }
02275 
02276                 long nRC = r * c;
02277 
02278                 ExpressionArray.SetSize(nRC);
02279 
02280                 for (USHORT i = 0; i < (nRC); i++)
02281                         ExpressionArray.Put((nRC) - (i + 1), NodeStack.Pop());
02282 
02283                 if (CurToken.eType != TRGROUP)
02284                         Error(PE_RGROUP_EXPECTED);
02285 
02286                 NextToken();
02287 
02288                 SmMatrixNode *pMNode = new SmMatrixNode(CurToken);
02289                 pMNode->SetSubNodes(ExpressionArray);
02290                 pMNode->SetRowCol(r, c);
02291                 NodeStack.Push(pMNode);
02292         }
02293         else
02294                 Error(PE_LGROUP_EXPECTED);
02295 }
02296 
02297 
02298 void SmParser::Special()
02299 {
02300     BOOL bReplace = FALSE;
02301     String &rName = CurToken.aText;
02302     String aNewName;
02303 
02304     if (CONVERT_NONE == GetConversion())
02305     {
02306         // conversion of symbol names for 6.0 (XML) file format
02307         // (name change on import / export.
02308         // UI uses localized names XML file format does not.)
02309         if (IsImportSymbolNames())
02310         {
02311             const SmLocalizedSymbolData &rLSD = SM_MOD1()->GetLocSymbolData();
02312             aNewName = rLSD.GetUiSymbolName( rName );
02313             bReplace = TRUE;
02314         }
02315         else if (IsExportSymbolNames())
02316         {
02317             const SmLocalizedSymbolData &rLSD = SM_MOD1()->GetLocSymbolData();
02318             aNewName = rLSD.GetExportSymbolName( rName );
02319             bReplace = TRUE;
02320         }
02321     }
02322     else    // 5.0 <-> 6.0 formula text (symbol name) conversion
02323     {
02324         LanguageType nLanguage = GetLanguage();
02325         SmLocalizedSymbolData &rData = SM_MOD1()->GetLocSymbolData();
02326         const ResStringArray *pFrom = 0;
02327         const ResStringArray *pTo   = 0;
02328         if (CONVERT_50_TO_60 == GetConversion())
02329         {
02330             pFrom = rData.Get50NamesArray( nLanguage );
02331             pTo   = rData.Get60NamesArray( nLanguage );
02332         }
02333         else if (CONVERT_60_TO_50 == GetConversion())
02334         {
02335             pFrom = rData.Get60NamesArray( nLanguage );
02336             pTo   = rData.Get50NamesArray( nLanguage );
02337         }
02338         if (pFrom  &&  pTo)
02339         {
02340             DBG_ASSERT( pFrom->Count() == pTo->Count(),
02341                     "array length mismatch" );
02342             USHORT nCount = sal::static_int_cast< USHORT >(pFrom->Count());
02343             for (USHORT i = 0;  i < nCount;  ++i)
02344             {
02345                 if (pFrom->GetString(i) == rName)
02346                 {
02347                     aNewName = pTo->GetString(i);
02348                     bReplace = TRUE;
02349                 }
02350             }
02351         }
02352         // else:
02353         // conversion arrays not found or (usually)
02354         // conversion not necessary
02355     }
02356 
02357     if (bReplace  &&  aNewName.Len()  &&  rName != aNewName)
02358     {
02359         Replace( GetTokenIndex() + 1, rName.Len(), aNewName );
02360         rName = aNewName;
02361     }
02362 
02363         NodeStack.Push(new SmSpecialNode(CurToken));
02364         NextToken();
02365 }
02366 
02367 
02368 void SmParser::GlyphSpecial()
02369 {
02370         NodeStack.Push(new SmGlyphSpecialNode(CurToken));
02371         NextToken();
02372 }
02373 
02374 
02375 void SmParser::Error(SmParseError eError)
02376 {
02377         SmStructureNode *pSNode = new SmExpressionNode(CurToken);
02378         SmErrorNode             *pErr   = new SmErrorNode(eError, CurToken);
02379         pSNode->SetSubNodes(pErr, 0);
02380 
02384         NodeStack.Push(pSNode);
02385 
02386         AddError(eError, pSNode);
02387 
02388         NextToken();
02389 }
02390 
02391 
02392 // end gramar
02393 
02394 
02395 SmParser::SmParser()
02396 {
02397     eConversion = CONVERT_NONE;
02398     bImportSymNames = bExportSymNames = FALSE;
02399     nLang = Application::GetSettings().GetUILanguage();
02400 }
02401 
02402 
02403 SmNode *SmParser::Parse(const String &rBuffer)
02404 {
02405         BufferString = rBuffer;
02406         BufferString.ConvertLineEnd( LINEEND_LF );
02407         BufferIndex  =
02408         nTokenIndex  = 0;
02409         Row              = 1;
02410         ColOff           = 0;
02411         CurError         = -1;
02412 
02413         for (USHORT i = 0;  i < ErrDescList.Count();  i++)
02414                 delete ErrDescList.Remove(i);
02415 
02416         ErrDescList.Clear();
02417 
02418         NodeStack.Clear();
02419 
02420     SetLanguage( Application::GetSettings().GetUILanguage() );
02421         NextToken();
02422         Table();
02423 
02424         return NodeStack.Pop();
02425 }
02426 
02427 
02428 USHORT SmParser::AddError(SmParseError Type, SmNode *pNode)
02429 {
02430         SmErrorDesc *pErrDesc = new SmErrorDesc;
02431 
02432         pErrDesc->Type  = Type;
02433         pErrDesc->pNode = pNode;
02434         pErrDesc->Text  = String(SmResId(RID_ERR_IDENT));
02435 
02436         USHORT  nRID;
02437         switch (Type)
02438         {
02439                 case PE_UNEXPECTED_CHAR:         nRID = RID_ERR_UNEXPECTEDCHARACTER;    break;
02440                 case PE_LGROUP_EXPECTED:         nRID = RID_ERR_LGROUPEXPECTED;                 break;
02441                 case PE_RGROUP_EXPECTED:         nRID = RID_ERR_RGROUPEXPECTED;                 break;
02442                 case PE_LBRACE_EXPECTED:         nRID = RID_ERR_LBRACEEXPECTED;                 break;
02443                 case PE_RBRACE_EXPECTED:         nRID = RID_ERR_RBRACEEXPECTED;                 break;
02444                 case PE_FUNC_EXPECTED:           nRID = RID_ERR_FUNCEXPECTED;                   break;
02445                 case PE_UNOPER_EXPECTED:         nRID = RID_ERR_UNOPEREXPECTED;                 break;
02446                 case PE_BINOPER_EXPECTED:        nRID = RID_ERR_BINOPEREXPECTED;                break;
02447                 case PE_SYMBOL_EXPECTED:         nRID = RID_ERR_SYMBOLEXPECTED;                 break;
02448                 case PE_IDENTIFIER_EXPECTED: nRID = RID_ERR_IDENTEXPECTED;                      break;
02449                 case PE_POUND_EXPECTED:          nRID = RID_ERR_POUNDEXPECTED;                  break;
02450                 case PE_COLOR_EXPECTED:          nRID = RID_ERR_COLOREXPECTED;                  break;
02451                 case PE_RIGHT_EXPECTED:          nRID = RID_ERR_RIGHTEXPECTED;                  break;
02452 
02453                 default:
02454                         nRID = RID_ERR_UNKOWN;
02455         }
02456         pErrDesc->Text += SmResId(nRID);
02457 
02458         ErrDescList.Insert(pErrDesc);
02459 
02460         return (USHORT) ErrDescList.GetPos(pErrDesc);
02461 }
02462 
02463 
02464 const SmErrorDesc  *SmParser::NextError()
02465 {
02466         if (ErrDescList.Count())
02467                 if (CurError > 0) return ErrDescList.Seek(--CurError);
02468                 else
02469                 {
02470                         CurError = 0;
02471                         return ErrDescList.Seek(CurError);
02472                 }
02473         else return 0;
02474 }
02475 
02476 
02477 const SmErrorDesc  *SmParser::PrevError()
02478 {
02479         if (ErrDescList.Count())
02480                 if (CurError < (int) (ErrDescList.Count() - 1)) return ErrDescList.Seek(++CurError);
02481                 else
02482                 {
02483                         CurError = (int) (ErrDescList.Count() - 1);
02484                         return ErrDescList.Seek(CurError);
02485                 }
02486         else return 0;
02487 }
02488 
02489 
02490 const SmErrorDesc  *SmParser::GetError(USHORT i)
02491 {
02492     return (/*i >= 0  &&*/  i < ErrDescList.Count())
02493                            ? ErrDescList.Seek(i)
02494                            : ErrDescList.Seek(CurError);
02495 }
02496 
02497 

Generated on Wed Feb 20 17:21:57 2008 for maths by  doxygen 1.5.1