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