1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: parse.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_starmath.hxx"
39 #include <com/sun/star/i18n/UnicodeType.hpp>
40 #include <i18npool/lang.h>
41 #include <unotools/charclass.hxx>
42 #include <svx/unolingu.hxx>
43 #include <svtools/syslocale.hxx>
46 #include "starmath.hrc"
56 using namespace ::com::sun::star
;
57 using namespace ::com::sun::star::i18n
;
59 ///////////////////////////////////////////////////////////////////////////
61 static inline BOOL
strnccmp(const String
&u1
, xub_StrLen nIdx
,
62 const sal_Char
*s2
, xub_StrLen nLen
)
64 return u1
.EqualsIgnoreCaseAscii( s2
, nIdx
, nLen
);
67 static const sal_Unicode aDelimiterTable
[] =
69 ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#',
70 '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(',
71 ')', '{', '}', '[', ']', '^', '_',
72 '\0' // end of list symbol
76 static inline BOOL
IsDigit( sal_Unicode cChar
)
78 return '0' <= cChar
&& cChar
<= '9';
81 ///////////////////////////////////////////////////////////////////////////
87 nGroup
= nCol
= nRow
= nLevel
= 0;
90 ///////////////////////////////////////////////////////////////////////////
92 struct SmTokenTableEntry
94 const sal_Char
* pIdent
;
96 sal_Unicode cMathChar
;
101 static const SmTokenTableEntry aTokenTable
[] =
103 // { "#", TPOUND, '\0', 0, 0 },
104 // { "##", TDPOUND, '\0', 0, 0 },
105 // { "&", TAND, MS_AND, TGPRODUCT, 0 },
106 // { "(", TLPARENT, MS_LPARENT, TGLBRACES, 5 }, //! 5 to continue expression
107 // { ")", TRPARENT, MS_RPARENT, TGRBRACES, 0 }, //! 0 to terminate expression
108 // { "*", TMULTIPLY, MS_MULTIPLY, TGPRODUCT, 0 },
109 // { "+", TPLUS, MS_PLUS, TGUNOPER | TGSUM, 5 },
110 // { "+-", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5 },
111 // { "-", TMINUS, MS_MINUS, TGUNOPER | TGSUM, 5 },
112 // { "-+", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5 },
113 // { ".", TPOINT, '\0', 0, 0 },
114 // { "/", TDIVIDEBY, MS_SLASH, TGPRODUCT, 0 },
115 // { "<", TLT, MS_LT, TGRELATION, 0 },
116 // { "<<", TLL, MS_LL, TGRELATION, 0 },
117 // { "<=", TLE, MS_LE, TGRELATION, 0 },
118 // { "<>", TNEQ, MS_NEQ, TGRELATION, 0},
119 // { "<?>", TPLACE, MS_PLACE, 0, 5 },
120 // { "=", TASSIGN, MS_ASSIGN, TGRELATION, 0},
121 // { ">", TGT, MS_GT, TGRELATION, 0 },
122 // { ">=", TGE, MS_GE, TGRELATION, 0 },
123 // { ">>", TGG, MS_GG, TGRELATION, 0 },
124 { "Im" , TIM
, MS_IM
, TGSTANDALONE
, 5 },
125 { "MZ23", TDEBUG
, '\0', TGATTRIBUT
, 0 },
126 { "Re" , TRE
, MS_RE
, TGSTANDALONE
, 5 },
127 { "abs", TABS
, '\0', TGUNOPER
, 13 },
128 { "arcosh", TACOSH
, '\0', TGFUNCTION
, 5 },
129 { "arcoth", TACOTH
, '\0', TGFUNCTION
, 5 },
130 { "acute", TACUTE
, MS_ACUTE
, TGATTRIBUT
, 5 },
131 { "aleph" , TALEPH
, MS_ALEPH
, TGSTANDALONE
, 5 },
132 { "alignb", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
133 { "alignc", TALIGNC
, '\0', TGALIGN
, 0},
134 { "alignl", TALIGNL
, '\0', TGALIGN
, 0},
135 { "alignm", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
136 { "alignr", TALIGNR
, '\0', TGALIGN
, 0},
137 { "alignt", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
138 { "and", TAND
, MS_AND
, TGPRODUCT
, 0},
139 { "approx", TAPPROX
, MS_APPROX
, TGRELATION
, 0},
140 { "arccos", TACOS
, '\0', TGFUNCTION
, 5},
141 { "arccot", TACOT
, '\0', TGFUNCTION
, 5},
142 { "arcsin", TASIN
, '\0', TGFUNCTION
, 5},
143 { "arctan", TATAN
, '\0', TGFUNCTION
, 5},
144 { "arsinh", TASINH
, '\0', TGFUNCTION
, 5},
145 { "artanh", TATANH
, '\0', TGFUNCTION
, 5},
146 { "backepsilon" , TBACKEPSILON
, MS_BACKEPSILON
, TGSTANDALONE
, 5},
147 { "bar", TBAR
, MS_BAR
, TGATTRIBUT
, 5},
148 { "binom", TBINOM
, '\0', 0, 5 },
149 { "black", TBLACK
, '\0', TGCOLOR
, 0},
150 { "blue", TBLUE
, '\0', TGCOLOR
, 0},
151 { "bold", TBOLD
, '\0', TGFONTATTR
, 5},
152 { "boper", TBOPER
, '\0', TGPRODUCT
, 0},
153 { "breve", TBREVE
, MS_BREVE
, TGATTRIBUT
, 5},
154 { "bslash", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
155 { "cdot", TCDOT
, MS_CDOT
, TGPRODUCT
, 0},
156 { "check", TCHECK
, MS_CHECK
, TGATTRIBUT
, 5},
157 { "circ" , TCIRC
, MS_CIRC
, TGSTANDALONE
, 5},
158 { "circle", TCIRCLE
, MS_CIRCLE
, TGATTRIBUT
, 5},
159 { "color", TCOLOR
, '\0', TGFONTATTR
, 5},
160 { "coprod", TCOPROD
, MS_COPROD
, TGOPER
, 5},
161 { "cos", TCOS
, '\0', TGFUNCTION
, 5},
162 { "cosh", TCOSH
, '\0', TGFUNCTION
, 5},
163 { "cot", TCOT
, '\0', TGFUNCTION
, 5},
164 { "coth", TCOTH
, '\0', TGFUNCTION
, 5},
165 { "csub", TCSUB
, '\0', TGPOWER
, 0},
166 { "csup", TCSUP
, '\0', TGPOWER
, 0},
167 { "cyan", TCYAN
, '\0', TGCOLOR
, 0},
168 { "dddot", TDDDOT
, MS_DDDOT
, TGATTRIBUT
, 5},
169 { "ddot", TDDOT
, MS_DDOT
, TGATTRIBUT
, 5},
170 { "def", TDEF
, MS_DEF
, TGRELATION
, 0},
171 { "div", TDIV
, MS_DIV
, TGPRODUCT
, 0},
172 { "divides", TDIVIDES
, MS_LINE
, TGRELATION
, 0},
173 { "dlarrow" , TDLARROW
, MS_DLARROW
, TGSTANDALONE
, 5},
174 { "dlrarrow" , TDLRARROW
, MS_DLRARROW
, TGSTANDALONE
, 5},
175 { "dot", TDOT
, MS_DOT
, TGATTRIBUT
, 5},
176 { "dotsaxis", TDOTSAXIS
, MS_DOTSAXIS
, TGSTANDALONE
, 5}, // 5 to continue expression
177 { "dotsdiag", TDOTSDIAG
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
178 { "dotsdown", TDOTSDOWN
, MS_DOTSDOWN
, TGSTANDALONE
, 5}, //
179 { "dotslow", TDOTSLOW
, MS_DOTSLOW
, TGSTANDALONE
, 5}, //
180 { "dotsup", TDOTSUP
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
181 { "dotsvert", TDOTSVERT
, MS_DOTSVERT
, TGSTANDALONE
, 5}, //
182 { "downarrow" , TDOWNARROW
, MS_DOWNARROW
, TGSTANDALONE
, 5},
183 { "drarrow" , TDRARROW
, MS_DRARROW
, TGSTANDALONE
, 5},
184 { "emptyset" , TEMPTYSET
, MS_EMPTYSET
, TGSTANDALONE
, 5},
185 { "equiv", TEQUIV
, MS_EQUIV
, TGRELATION
, 0},
186 { "exists", TEXISTS
, MS_EXISTS
, TGSTANDALONE
, 5},
187 { "exp", TEXP
, '\0', TGFUNCTION
, 5},
188 { "fact", TFACT
, MS_FACT
, TGUNOPER
, 5},
189 { "fixed", TFIXED
, '\0', TGFONT
, 0},
190 { "font", TFONT
, '\0', TGFONTATTR
, 5},
191 { "forall", TFORALL
, MS_FORALL
, TGSTANDALONE
, 5},
192 { "from", TFROM
, '\0', TGLIMIT
, 0},
193 { "func", TFUNC
, '\0', TGFUNCTION
, 5},
194 { "ge", TGE
, MS_GE
, TGRELATION
, 0},
195 { "geslant", TGESLANT
, MS_GESLANT
, TGRELATION
, 0 },
196 { "gg", TGG
, MS_GG
, TGRELATION
, 0},
197 { "grave", TGRAVE
, MS_GRAVE
, TGATTRIBUT
, 5},
198 { "green", TGREEN
, '\0', TGCOLOR
, 0},
199 { "gt", TGT
, MS_GT
, TGRELATION
, 0},
200 { "hat", THAT
, MS_HAT
, TGATTRIBUT
, 5},
201 { "hbar" , THBAR
, MS_HBAR
, TGSTANDALONE
, 5},
202 { "iiint", TIIINT
, MS_IIINT
, TGOPER
, 5},
203 { "iint", TIINT
, MS_IINT
, TGOPER
, 5},
204 { "in", TIN
, MS_IN
, TGRELATION
, 0},
205 { "infinity" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
206 { "infty" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
207 { "int", TINT
, MS_INT
, TGOPER
, 5},
208 { "intersection", TINTERSECT
, MS_INTERSECT
, TGPRODUCT
, 0},
209 { "ital", TITALIC
, '\0', TGFONTATTR
, 5},
210 { "italic", TITALIC
, '\0', TGFONTATTR
, 5},
211 { "lambdabar" , TLAMBDABAR
, MS_LAMBDABAR
, TGSTANDALONE
, 5},
212 { "langle", TLANGLE
, MS_LANGLE
, TGLBRACES
, 5},
213 { "lbrace", TLBRACE
, MS_LBRACE
, TGLBRACES
, 5},
214 { "lceil", TLCEIL
, MS_LCEIL
, TGLBRACES
, 5},
215 { "ldbracket", TLDBRACKET
, MS_LDBRACKET
, TGLBRACES
, 5},
216 { "ldline", TLDLINE
, MS_DLINE
, TGLBRACES
, 5},
217 { "le", TLE
, MS_LE
, TGRELATION
, 0},
218 { "left", TLEFT
, '\0', 0, 5},
219 { "leftarrow" , TLEFTARROW
, MS_LEFTARROW
, TGSTANDALONE
, 5},
220 { "leslant", TLESLANT
, MS_LESLANT
, TGRELATION
, 0 },
221 { "lfloor", TLFLOOR
, MS_LFLOOR
, TGLBRACES
, 5},
222 { "lim", TLIM
, '\0', TGOPER
, 5},
223 { "liminf", TLIMINF
, '\0', TGOPER
, 5},
224 { "limsup", TLIMSUP
, '\0', TGOPER
, 5},
225 { "lint", TLINT
, MS_LINT
, TGOPER
, 5},
226 { "ll", TLL
, MS_LL
, TGRELATION
, 0},
227 { "lline", TLLINE
, MS_LINE
, TGLBRACES
, 5},
228 { "llint", TLLINT
, MS_LLINT
, TGOPER
, 5},
229 { "lllint", TLLLINT
, MS_LLLINT
, TGOPER
, 5},
230 { "ln", TLN
, '\0', TGFUNCTION
, 5},
231 { "log", TLOG
, '\0', TGFUNCTION
, 5},
232 { "lsub", TLSUB
, '\0', TGPOWER
, 0},
233 { "lsup", TLSUP
, '\0', TGPOWER
, 0},
234 { "lt", TLT
, MS_LT
, TGRELATION
, 0},
235 { "magenta", TMAGENTA
, '\0', TGCOLOR
, 0},
236 { "matrix", TMATRIX
, '\0', 0, 5},
237 { "minusplus", TMINUSPLUS
, MS_MINUSPLUS
, TGUNOPER
| TGSUM
, 5},
238 { "mline", TMLINE
, MS_LINE
, 0, 0}, //! nicht in TGRBRACES, Level 0
239 { "nabla", TNABLA
, MS_NABLA
, TGSTANDALONE
, 5},
240 { "nbold", TNBOLD
, '\0', TGFONTATTR
, 5},
241 { "ndivides", TNDIVIDES
, MS_NDIVIDES
, TGRELATION
, 0},
242 { "neg", TNEG
, MS_NEG
, TGUNOPER
, 5 },
243 { "neq", TNEQ
, MS_NEQ
, TGRELATION
, 0},
244 { "newline", TNEWLINE
, '\0', 0, 0},
245 { "ni", TNI
, MS_NI
, TGRELATION
, 0},
246 { "nitalic", TNITALIC
, '\0', TGFONTATTR
, 5},
247 { "none", TNONE
, '\0', TGLBRACES
| TGRBRACES
, 0},
248 { "notin", TNOTIN
, MS_NOTIN
, TGRELATION
, 0},
249 { "nsubset", TNSUBSET
, MS_NSUBSET
, TGRELATION
, 0 },
250 { "nsupset", TNSUPSET
, MS_NSUPSET
, TGRELATION
, 0 },
251 { "nsubseteq", TNSUBSETEQ
, MS_NSUBSETEQ
, TGRELATION
, 0 },
252 { "nsupseteq", TNSUPSETEQ
, MS_NSUPSETEQ
, TGRELATION
, 0 },
253 { "nroot", TNROOT
, MS_SQRT
, TGUNOPER
, 5},
254 { "odivide", TODIVIDE
, MS_ODIVIDE
, TGPRODUCT
, 0},
255 { "odot", TODOT
, MS_ODOT
, TGPRODUCT
, 0},
256 { "ominus", TOMINUS
, MS_OMINUS
, TGSUM
, 0},
257 { "oper", TOPER
, '\0', TGOPER
, 5},
258 { "oplus", TOPLUS
, MS_OPLUS
, TGSUM
, 0},
259 { "or", TOR
, MS_OR
, TGSUM
, 0},
260 { "ortho", TORTHO
, MS_ORTHO
, TGRELATION
, 0},
261 { "otimes", TOTIMES
, MS_OTIMES
, TGPRODUCT
, 0},
262 { "over", TOVER
, '\0', TGPRODUCT
, 0},
263 { "overbrace", TOVERBRACE
, MS_OVERBRACE
, TGPRODUCT
, 5},
264 { "overline", TOVERLINE
, '\0', TGATTRIBUT
, 5},
265 { "overstrike", TOVERSTRIKE
, '\0', TGATTRIBUT
, 5},
266 { "owns", TNI
, MS_NI
, TGRELATION
, 0},
267 { "parallel", TPARALLEL
, MS_DLINE
, TGRELATION
, 0},
268 { "partial", TPARTIAL
, MS_PARTIAL
, TGSTANDALONE
, 5 },
269 { "phantom", TPHANTOM
, '\0', TGFONTATTR
, 5},
270 { "plusminus", TPLUSMINUS
, MS_PLUSMINUS
, TGUNOPER
| TGSUM
, 5},
271 { "prod", TPROD
, MS_PROD
, TGOPER
, 5},
272 { "prop", TPROP
, MS_PROP
, TGRELATION
, 0},
273 { "rangle", TRANGLE
, MS_RANGLE
, TGRBRACES
, 0}, //! 0 to terminate expression
274 { "rbrace", TRBRACE
, MS_RBRACE
, TGRBRACES
, 0}, //
275 { "rceil", TRCEIL
, MS_RCEIL
, TGRBRACES
, 0}, //
276 { "rdbracket", TRDBRACKET
, MS_RDBRACKET
, TGRBRACES
, 0}, //
277 { "rdline", TRDLINE
, MS_DLINE
, TGRBRACES
, 0}, //
278 { "red", TRED
, '\0', TGCOLOR
, 0},
279 { "rfloor", TRFLOOR
, MS_RFLOOR
, TGRBRACES
, 0}, //! 0 to terminate expression
280 { "right", TRIGHT
, '\0', 0, 0},
281 { "rightarrow" , TRIGHTARROW
, MS_RIGHTARROW
, TGSTANDALONE
, 5},
282 { "rline", TRLINE
, MS_LINE
, TGRBRACES
, 0}, //! 0 to terminate expression
283 { "rsub", TRSUB
, '\0', TGPOWER
, 0},
284 { "rsup", TRSUP
, '\0', TGPOWER
, 0},
285 { "sans", TSANS
, '\0', TGFONT
, 0},
286 { "serif", TSERIF
, '\0', TGFONT
, 0},
287 { "setC" , TSETC
, MS_SETC
, TGSTANDALONE
, 5},
288 { "setN" , TSETN
, MS_SETN
, TGSTANDALONE
, 5},
289 { "setQ" , TSETQ
, MS_SETQ
, TGSTANDALONE
, 5},
290 { "setR" , TSETR
, MS_SETR
, TGSTANDALONE
, 5},
291 { "setZ" , TSETZ
, MS_SETZ
, TGSTANDALONE
, 5},
292 { "setminus", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
293 { "sim", TSIM
, MS_SIM
, TGRELATION
, 0},
294 { "simeq", TSIMEQ
, MS_SIMEQ
, TGRELATION
, 0},
295 { "sin", TSIN
, '\0', TGFUNCTION
, 5},
296 { "sinh", TSINH
, '\0', TGFUNCTION
, 5},
297 { "size", TSIZE
, '\0', TGFONTATTR
, 5},
298 { "slash", TSLASH
, MS_SLASH
, TGPRODUCT
, 0 },
299 { "sqrt", TSQRT
, MS_SQRT
, TGUNOPER
, 5},
300 { "stack", TSTACK
, '\0', 0, 5},
301 { "sub", TRSUB
, '\0', TGPOWER
, 0},
302 { "subset", TSUBSET
, MS_SUBSET
, TGRELATION
, 0},
303 { "subseteq", TSUBSETEQ
, MS_SUBSETEQ
, TGRELATION
, 0},
304 { "sum", TSUM
, MS_SUM
, TGOPER
, 5},
305 { "sup", TRSUP
, '\0', TGPOWER
, 0},
306 { "supset", TSUPSET
, MS_SUPSET
, TGRELATION
, 0},
307 { "supseteq", TSUPSETEQ
, MS_SUPSETEQ
, TGRELATION
, 0},
308 { "tan", TTAN
, '\0', TGFUNCTION
, 5},
309 { "tanh", TTANH
, '\0', TGFUNCTION
, 5},
310 { "tilde", TTILDE
, MS_TILDE
, TGATTRIBUT
, 5},
311 { "times", TTIMES
, MS_TIMES
, TGPRODUCT
, 0},
312 { "to", TTO
, '\0', TGLIMIT
, 0},
313 { "toward", TTOWARD
, MS_RIGHTARROW
, TGRELATION
, 0},
314 { "transl", TTRANSL
, MS_TRANSL
, TGRELATION
, 0},
315 { "transr", TTRANSR
, MS_TRANSR
, TGRELATION
, 0},
316 { "underbrace", TUNDERBRACE
, MS_UNDERBRACE
, TGPRODUCT
, 5},
317 { "underline", TUNDERLINE
, '\0', TGATTRIBUT
, 5},
318 { "union", TUNION
, MS_UNION
, TGSUM
, 0},
319 { "uoper", TUOPER
, '\0', TGUNOPER
, 5},
320 { "uparrow" , TUPARROW
, MS_UPARROW
, TGSTANDALONE
, 5},
321 { "vec", TVEC
, MS_VEC
, TGATTRIBUT
, 5},
322 { "white", TWHITE
, '\0', TGCOLOR
, 0},
323 { "widebslash", TWIDEBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
324 { "widehat", TWIDEHAT
, MS_HAT
, TGATTRIBUT
, 5},
325 { "widetilde", TWIDETILDE
, MS_TILDE
, TGATTRIBUT
, 5},
326 { "wideslash", TWIDESLASH
, MS_SLASH
, TGPRODUCT
, 0 },
327 { "widevec", TWIDEVEC
, MS_VEC
, TGATTRIBUT
, 5},
328 { "wp" , TWP
, MS_WP
, TGSTANDALONE
, 5},
329 { "yellow", TYELLOW
, '\0', TGCOLOR
, 0},
330 // { "[", TLBRACKET, MS_LBRACKET, TGLBRACES, 5}, //! 5 to continue expression
331 // { "\\", TESCAPE, '\0', 0, 5},
332 // { "]", TRBRACKET, MS_RBRACKET, TGRBRACES, 0}, //! 0 to terminate expression
333 // { "^", TRSUP, '\0', TGPOWER, 0},
334 // { "_", TRSUB, '\0', TGPOWER, 0},
335 // { "`", TSBLANK, '\0', TGBLANK, 5},
336 // { "{", TLGROUP, MS_LBRACE, 0, 5}, //! 5 to continue expression
337 // { "|", TOR, MS_OR, TGSUM, 0},
338 // { "}", TRGROUP, MS_RBRACE, 0, 0}, //! 0 to terminate expression
339 // { "~", TBLANK, '\0', TGBLANK, 5},
340 { "", TEND
, '\0', 0, 0}
344 static const SmTokenTableEntry
* GetTokenTableEntry( const String
&rName
)
346 const SmTokenTableEntry
* pRes
= 0;
349 INT32 nEntries
= sizeof( aTokenTable
) / sizeof( aTokenTable
[0] );
350 for (INT32 i
= 0; i
< nEntries
; ++i
)
352 if (rName
.EqualsIgnoreCaseAscii( aTokenTable
[i
].pIdent
))
354 pRes
= &aTokenTable
[i
];
365 ///////////////////////////////////////////////////////////////////////////
369 BOOL
SmParser::IsDelimiter( const String
&rTxt
, xub_StrLen nPos
)
370 // returns 'TRUE' iff cChar is '\0' or a delimeter
372 DBG_ASSERT( nPos
<= rTxt
.Len(), "index out of range" );
374 sal_Unicode cChar
= rTxt
.GetChar( nPos
);
378 // check if 'cChar' is in the delimeter table
379 const sal_Unicode
*pDelim
= &aDelimiterTable
[0];
380 for ( ; *pDelim
!= 0; pDelim
++)
381 if (*pDelim
== cChar
)
384 BOOL bIsDelim
= *pDelim
!= 0;
386 INT16 nTypJp
= SM_MOD1()->GetSysLocale().GetCharClass().getType( rTxt
, nPos
);
387 bIsDelim
|= nTypJp
== com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR
||
388 nTypJp
== com::sun::star::i18n::UnicodeType::CONTROL
;
395 void SmParser::Insert(const String
&rText
, USHORT nPos
)
397 BufferString
.Insert(rText
, nPos
);
399 xub_StrLen nLen
= rText
.Len();
400 BufferIndex
= BufferIndex
+ nLen
;
401 nTokenIndex
= nTokenIndex
+ nLen
;
405 void SmParser::Replace( USHORT nPos
, USHORT nLen
, const String
&rText
)
407 DBG_ASSERT( nPos
+ nLen
<= BufferString
.Len(), "argument mismatch" );
409 BufferString
.Replace( nPos
, nLen
, rText
);
410 INT16 nChg
= rText
.Len() - nLen
;
411 BufferIndex
= BufferIndex
+ nChg
;
412 nTokenIndex
= nTokenIndex
+ nChg
;
416 // First character may be any alphabetic
417 const sal_Int32 coStartFlags
=
418 KParseTokens::ANY_LETTER_OR_NUMBER
|
419 KParseTokens::IGNORE_LEADING_WS
;
421 // Continuing characters may be any alphanumeric or dot.
422 const sal_Int32 coContFlags
=
423 ((coStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
)
424 | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING
;
426 // First character for numbers, may be any numeric or dot
427 const sal_Int32 coNumStartFlags
=
428 KParseTokens::ASC_DIGIT
|
429 KParseTokens::ASC_DOT
|
430 KParseTokens::IGNORE_LEADING_WS
;
431 // Continuing characters for numbers, may be any numeric or dot.
432 const sal_Int32 coNumContFlags
=
433 (coNumStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
;
435 void SmParser::NextToken()
437 static const String aEmptyStr
;
439 xub_StrLen nBufLen
= BufferString
.Len();
441 xub_StrLen nRealStart
;
443 BOOL bNumStart
= FALSE
;
444 CharClass
aCC(SM_MOD1()->GetSysLocale().GetCharClass().getLocale());
448 while (UnicodeType::SPACE_SEPARATOR
==
449 aCC
.getType( BufferString
, BufferIndex
))
452 sal_Int32 nStartFlags
= coStartFlags
;
453 sal_Int32 nContFlags
= coContFlags
;
454 sal_Unicode cFirstChar
= BufferString
.GetChar( BufferIndex
);
456 removed because of #i11752#
457 bNumStart = cFirstChar == '.' || ('0' <= cFirstChar && cFirstChar <= '9');
460 nStartFlags = coNumStartFlags;
461 nContFlags = coNumContFlags;
464 aRes
= aCC
.parseAnyToken( BufferString
, BufferIndex
,
465 nStartFlags
, aEmptyStr
,
466 nContFlags
, aEmptyStr
);
468 // #i45779# parse numbers correctly
469 // i.e. independent from the locale setting.
470 // (note that #i11752# remains fixed)
471 if ((aRes
.TokenType
& KParseType::IDENTNAME
) && IsDigit( cFirstChar
))
473 //! locale where '.' is decimal seperator!
474 static lang::Locale
aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US
) );
477 lang::Locale
aOldLoc( aCC
.getLocale() );
478 aCC
.setLocale( aDotLoc
);
479 aTmpRes
= aCC
.parsePredefinedToken(
480 KParseType::ASC_NUMBER
,
481 BufferString
, BufferIndex
,
482 KParseTokens::ASC_DIGIT
, aEmptyStr
,
483 KParseTokens::ASC_DIGIT
| KParseTokens::ASC_DOT
, aEmptyStr
);
484 aCC
.setLocale( aOldLoc
);
485 if (aTmpRes
.TokenType
& KParseType::ASC_NUMBER
)
486 aRes
.TokenType
= aTmpRes
.TokenType
;
489 nRealStart
= BufferIndex
+ sal::static_int_cast
< xub_StrLen
>(aRes
.LeadingWhiteSpace
);
490 BufferIndex
= nRealStart
;
493 if ( aRes
.TokenType
== 0 &&
494 nRealStart
< nBufLen
&&
495 '\n' == BufferString
.GetChar( nRealStart
) )
497 // keep data needed for tokens row and col entry up to date
499 BufferIndex
= ColOff
= nRealStart
+ 1;
502 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
504 String
aName( BufferString
.Copy( nRealStart
, 2 ));
505 if ( aName
.EqualsAscii( "%%" ))
508 BufferIndex
= nRealStart
+ 2;
509 while (BufferIndex
< nBufLen
&&
510 '\n' != BufferString
.GetChar( BufferIndex
))
518 // set index of current token
519 nTokenIndex
= BufferIndex
;
522 CurToken
.nCol
= nRealStart
- ColOff
+ 1;
524 BOOL bHandled
= TRUE
;
525 if (nRealStart
>= nBufLen
)
527 CurToken
.eType
= TEND
;
528 CurToken
.cMathChar
= '\0';
531 CurToken
.aText
.Erase();
533 else if ((aRes
.TokenType
& (KParseType::ASC_NUMBER
| KParseType::UNI_NUMBER
))
534 || (bNumStart
&& (aRes
.TokenType
& KParseType::IDENTNAME
)))
536 INT32 n
= aRes
.EndPos
- nRealStart
;
537 DBG_ASSERT( n
>= 0, "length < 0" );
538 CurToken
.eType
= TNUMBER
;
539 CurToken
.cMathChar
= '\0';
542 CurToken
.aText
= BufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) );
544 #if OSL_DEBUG_LEVEL > 1
545 if (!IsDelimiter( BufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
547 DBG_WARNING( "identifier really finished? (compatibility!)" );
551 else if (aRes
.TokenType
& KParseType::DOUBLE_QUOTE_STRING
)
553 CurToken
.eType
= TTEXT
;
554 CurToken
.cMathChar
= '\0';
557 CurToken
.aText
= aRes
.DequotedNameOrString
;
559 CurToken
.nCol
= nRealStart
- ColOff
+ 2;
561 else if (aRes
.TokenType
& KParseType::IDENTNAME
)
563 INT32 n
= aRes
.EndPos
- nRealStart
;
564 DBG_ASSERT( n
>= 0, "length < 0" );
565 String
aName( BufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) ) );
566 const SmTokenTableEntry
*pEntry
= GetTokenTableEntry( aName
);
570 CurToken
.eType
= pEntry
->eType
;
571 CurToken
.cMathChar
= pEntry
->cMathChar
;
572 CurToken
.nGroup
= pEntry
->nGroup
;
573 CurToken
.nLevel
= pEntry
->nLevel
;
574 CurToken
.aText
.AssignAscii( pEntry
->pIdent
);
578 CurToken
.eType
= TIDENT
;
579 CurToken
.cMathChar
= '\0';
582 CurToken
.aText
= aName
;
584 #if OSL_DEBUG_LEVEL > 1
585 if (!IsDelimiter( BufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
587 DBG_WARNING( "identifier really finished? (compatibility!)" );
592 else if (aRes
.TokenType
== 0 && '_' == BufferString
.GetChar( nRealStart
))
594 CurToken
.eType
= TRSUB
;
595 CurToken
.cMathChar
= '\0';
596 CurToken
.nGroup
= TGPOWER
;
598 CurToken
.aText
.AssignAscii( "_" );
600 aRes
.EndPos
= nRealStart
+ 1;
602 else if (aRes
.TokenType
& KParseType::BOOLEAN
)
604 sal_Int32
&rnEndPos
= aRes
.EndPos
;
605 String
aName( BufferString
.Copy( nRealStart
,
606 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ));
607 if (2 >= aName
.Len())
609 sal_Unicode ch
= aName
.GetChar( 0 );
614 if (BufferString
.Copy( nRealStart
, 2 ).
617 CurToken
.eType
= TLL
;
618 CurToken
.cMathChar
= MS_LL
;
619 CurToken
.nGroup
= TGRELATION
;
621 CurToken
.aText
.AssignAscii( "<<" );
623 rnEndPos
= nRealStart
+ 2;
625 else if (BufferString
.Copy( nRealStart
, 2 ).
628 CurToken
.eType
= TLE
;
629 CurToken
.cMathChar
= MS_LE
;
630 CurToken
.nGroup
= TGRELATION
;
632 CurToken
.aText
.AssignAscii( "<=" );
634 rnEndPos
= nRealStart
+ 2;
636 else if (BufferString
.Copy( nRealStart
, 2 ).
639 CurToken
.eType
= TNEQ
;
640 CurToken
.cMathChar
= MS_NEQ
;
641 CurToken
.nGroup
= TGRELATION
;
643 CurToken
.aText
.AssignAscii( "<>" );
645 rnEndPos
= nRealStart
+ 2;
647 else if (BufferString
.Copy( nRealStart
, 3 ).
648 EqualsAscii( "<?>" ))
650 CurToken
.eType
= TPLACE
;
651 CurToken
.cMathChar
= MS_PLACE
;
654 CurToken
.aText
.AssignAscii( "<?>" );
656 rnEndPos
= nRealStart
+ 3;
660 CurToken
.eType
= TLT
;
661 CurToken
.cMathChar
= MS_LT
;
662 CurToken
.nGroup
= TGRELATION
;
664 CurToken
.aText
.AssignAscii( "<" );
670 if (BufferString
.Copy( nRealStart
, 2 ).
673 CurToken
.eType
= TGE
;
674 CurToken
.cMathChar
= MS_GE
;
675 CurToken
.nGroup
= TGRELATION
;
677 CurToken
.aText
.AssignAscii( ">=" );
679 rnEndPos
= nRealStart
+ 2;
681 else if (BufferString
.Copy( nRealStart
, 2 ).
684 CurToken
.eType
= TGG
;
685 CurToken
.cMathChar
= MS_GG
;
686 CurToken
.nGroup
= TGRELATION
;
688 CurToken
.aText
.AssignAscii( ">>" );
690 rnEndPos
= nRealStart
+ 2;
694 CurToken
.eType
= TGT
;
695 CurToken
.cMathChar
= MS_GT
;
696 CurToken
.nGroup
= TGRELATION
;
698 CurToken
.aText
.AssignAscii( ">" );
707 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
709 sal_Int32
&rnEndPos
= aRes
.EndPos
;
710 String
aName( BufferString
.Copy( nRealStart
,
711 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ) );
713 if (1 == aName
.Len())
715 sal_Unicode ch
= aName
.GetChar( 0 );
720 //! modifies aRes.EndPos
722 DBG_ASSERT( rnEndPos
>= nBufLen
||
723 '%' != BufferString
.GetChar( sal::static_int_cast
< xub_StrLen
>(rnEndPos
) ),
724 "unexpected comment start" );
726 // get identifier of user-defined character
727 ParseResult aTmpRes
= aCC
.parseAnyToken(
728 BufferString
, rnEndPos
,
729 KParseTokens::ANY_LETTER
,
734 xub_StrLen nTmpStart
= sal::static_int_cast
< xub_StrLen
>(rnEndPos
+
735 aTmpRes
.LeadingWhiteSpace
);
737 // default setting fo the case that no identifier
738 // i.e. a valid symbol-name is following the '%'
740 CurToken
.eType
= TTEXT
;
741 CurToken
.cMathChar
= '\0';
744 CurToken
.aText
= String();
745 CurToken
.nRow
= sal::static_int_cast
< xub_StrLen
>(Row
);
746 CurToken
.nCol
= nTmpStart
- ColOff
+ 1;
748 if (aTmpRes
.TokenType
& KParseType::IDENTNAME
)
751 xub_StrLen n
= sal::static_int_cast
< xub_StrLen
>(aTmpRes
.EndPos
- nTmpStart
);
752 CurToken
.eType
= TSPECIAL
;
753 CurToken
.aText
= BufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTmpStart
), n
);
755 DBG_ASSERT( aTmpRes
.EndPos
> rnEndPos
,
756 "empty identifier" );
757 if (aTmpRes
.EndPos
> rnEndPos
)
758 rnEndPos
= aTmpRes
.EndPos
;
763 // if no symbol-name was found we start-over with
764 // finding the next token right afer the '%' sign.
765 // I.e. we leave rnEndPos unmodified.
770 CurToken
.eType
= TLBRACKET
;
771 CurToken
.cMathChar
= MS_LBRACKET
;
772 CurToken
.nGroup
= TGLBRACES
;
774 CurToken
.aText
.AssignAscii( "[" );
779 CurToken
.eType
= TESCAPE
;
780 CurToken
.cMathChar
= '\0';
783 CurToken
.aText
.AssignAscii( "\\" );
788 CurToken
.eType
= TRBRACKET
;
789 CurToken
.cMathChar
= MS_RBRACKET
;
790 CurToken
.nGroup
= TGRBRACES
;
792 CurToken
.aText
.AssignAscii( "]" );
797 CurToken
.eType
= TRSUP
;
798 CurToken
.cMathChar
= '\0';
799 CurToken
.nGroup
= TGPOWER
;
801 CurToken
.aText
.AssignAscii( "^" );
806 CurToken
.eType
= TSBLANK
;
807 CurToken
.cMathChar
= '\0';
808 CurToken
.nGroup
= TGBLANK
;
810 CurToken
.aText
.AssignAscii( "`" );
815 CurToken
.eType
= TLGROUP
;
816 CurToken
.cMathChar
= MS_LBRACE
;
819 CurToken
.aText
.AssignAscii( "{" );
824 CurToken
.eType
= TOR
;
825 CurToken
.cMathChar
= MS_OR
;
826 CurToken
.nGroup
= TGSUM
;
828 CurToken
.aText
.AssignAscii( "|" );
833 CurToken
.eType
= TRGROUP
;
834 CurToken
.cMathChar
= MS_RBRACE
;
837 CurToken
.aText
.AssignAscii( "}" );
842 CurToken
.eType
= TBLANK
;
843 CurToken
.cMathChar
= '\0';
844 CurToken
.nGroup
= TGBLANK
;
846 CurToken
.aText
.AssignAscii( "~" );
851 if (BufferString
.Copy( nRealStart
, 2 ).
854 CurToken
.eType
= TDPOUND
;
855 CurToken
.cMathChar
= '\0';
858 CurToken
.aText
.AssignAscii( "##" );
860 rnEndPos
= nRealStart
+ 2;
864 CurToken
.eType
= TPOUND
;
865 CurToken
.cMathChar
= '\0';
868 CurToken
.aText
.AssignAscii( "#" );
874 CurToken
.eType
= TAND
;
875 CurToken
.cMathChar
= MS_AND
;
876 CurToken
.nGroup
= TGPRODUCT
;
878 CurToken
.aText
.AssignAscii( "&" );
883 CurToken
.eType
= TLPARENT
;
884 CurToken
.cMathChar
= MS_LPARENT
;
885 CurToken
.nGroup
= TGLBRACES
;
886 CurToken
.nLevel
= 5; //! 0 to continue expression
887 CurToken
.aText
.AssignAscii( "(" );
892 CurToken
.eType
= TRPARENT
;
893 CurToken
.cMathChar
= MS_RPARENT
;
894 CurToken
.nGroup
= TGRBRACES
;
895 CurToken
.nLevel
= 0; //! 0 to terminate expression
896 CurToken
.aText
.AssignAscii( ")" );
901 CurToken
.eType
= TMULTIPLY
;
902 CurToken
.cMathChar
= MS_MULTIPLY
;
903 CurToken
.nGroup
= TGPRODUCT
;
905 CurToken
.aText
.AssignAscii( "*" );
910 if (BufferString
.Copy( nRealStart
, 2 ).
913 CurToken
.eType
= TPLUSMINUS
;
914 CurToken
.cMathChar
= MS_PLUSMINUS
;
915 CurToken
.nGroup
= TGUNOPER
| TGSUM
;
917 CurToken
.aText
.AssignAscii( "+-" );
919 rnEndPos
= nRealStart
+ 2;
923 CurToken
.eType
= TPLUS
;
924 CurToken
.cMathChar
= MS_PLUS
;
925 CurToken
.nGroup
= TGUNOPER
| TGSUM
;
927 CurToken
.aText
.AssignAscii( "+" );
933 if (BufferString
.Copy( nRealStart
, 2 ).
936 CurToken
.eType
= TMINUSPLUS
;
937 CurToken
.cMathChar
= MS_MINUSPLUS
;
938 CurToken
.nGroup
= TGUNOPER
| TGSUM
;
940 CurToken
.aText
.AssignAscii( "-+" );
942 rnEndPos
= nRealStart
+ 2;
946 CurToken
.eType
= TMINUS
;
947 CurToken
.cMathChar
= MS_MINUS
;
948 CurToken
.nGroup
= TGUNOPER
| TGSUM
;
950 CurToken
.aText
.AssignAscii( "-" );
956 // for compatibility with SO5.2
957 // texts like .34 ...56 ... h ...78..90
958 // will be treated as numbers
959 CurToken
.eType
= TNUMBER
;
960 CurToken
.cMathChar
= '\0';
964 xub_StrLen nTxtStart
= BufferIndex
;
968 cChar
= BufferString
.GetChar( ++BufferIndex
);
970 while ( cChar
== '.' || IsDigit( cChar
) );
972 CurToken
.aText
= BufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTxtStart
),
973 sal::static_int_cast
< xub_StrLen
>(BufferIndex
- nTxtStart
) );
974 aRes
.EndPos
= BufferIndex
;
979 CurToken
.eType
= TDIVIDEBY
;
980 CurToken
.cMathChar
= MS_SLASH
;
981 CurToken
.nGroup
= TGPRODUCT
;
983 CurToken
.aText
.AssignAscii( "/" );
988 CurToken
.eType
= TASSIGN
;
989 CurToken
.cMathChar
= MS_ASSIGN
;
990 CurToken
.nGroup
= TGRELATION
;
992 CurToken
.aText
.AssignAscii( "=" );
1005 CurToken
.eType
= TCHARACTER
;
1006 CurToken
.cMathChar
= '\0';
1007 CurToken
.nGroup
= 0;
1008 CurToken
.nLevel
= 5;
1009 CurToken
.aText
= BufferString
.Copy( nRealStart
, 1 );
1011 aRes
.EndPos
= nRealStart
+ 1;
1014 if (TEND
!= CurToken
.eType
)
1015 BufferIndex
= sal::static_int_cast
< xub_StrLen
>(aRes
.EndPos
);
1019 ////////////////////////////////////////
1024 void SmParser::Table()
1026 SmNodeArray LineArray
;
1029 while (CurToken
.eType
== TNEWLINE
)
1035 if (CurToken
.eType
!= TEND
)
1036 Error(PE_UNEXPECTED_CHAR
);
1038 ULONG n
= NodeStack
.Count();
1040 LineArray
.resize(n
);
1042 for (ULONG i
= 0; i
< n
; i
++)
1043 LineArray
[n
- (i
+ 1)] = NodeStack
.Pop();
1045 SmStructureNode
*pSNode
= new SmTableNode(CurToken
);
1046 pSNode
->SetSubNodes(LineArray
);
1047 NodeStack
.Push(pSNode
);
1051 void SmParser::Align()
1052 // parse alignment info (if any), then go on with rest of expression
1054 SmStructureNode
*pSNode
= 0;
1055 BOOL bNeedGroupClose
= FALSE
;
1057 if (TokenInGroup(TGALIGN
))
1059 if (CONVERT_40_TO_50
== GetConversion())
1060 // encapsulate expression to be aligned in group braces
1061 // (here group-open brace)
1062 { Insert('{', GetTokenIndex());
1063 bNeedGroupClose
= TRUE
;
1065 // get first valid align statement in sequence
1066 // (the dominant one in 4.0) and erase all others (especially old
1067 // discarded tokens) from command string.
1068 while (TokenInGroup(TGALIGN
))
1069 { if (TokenInGroup(TGDISCARDED
) || pSNode
)
1070 { BufferIndex
= GetTokenIndex();
1071 BufferString
.Erase(BufferIndex
, CurToken
.aText
.Len());
1074 pSNode
= new SmAlignNode(CurToken
);
1081 pSNode
= new SmAlignNode(CurToken
);
1085 // allow for just one align statement in 5.0
1086 if (CONVERT_40_TO_50
!= GetConversion() && TokenInGroup(TGALIGN
))
1087 { Error(PE_DOUBLE_ALIGN
);
1095 if (bNeedGroupClose
)
1096 Insert('}', GetTokenIndex());
1099 { pSNode
->SetSubNodes(NodeStack
.Pop(), 0);
1100 NodeStack
.Push(pSNode
);
1105 void SmParser::Line()
1108 SmNodeArray ExpressionArray
;
1110 ExpressionArray
.resize(n
);
1112 // start with single expression that may have an alignment statement
1113 // (and go on with expressions that must not have alignment
1114 // statements in 'while' loop below. See also 'Expression()'.)
1115 if (CurToken
.eType
!= TEND
&& CurToken
.eType
!= TNEWLINE
)
1117 ExpressionArray
.resize(++n
);
1118 ExpressionArray
[n
- 1] = NodeStack
.Pop();
1121 while (CurToken
.eType
!= TEND
&& CurToken
.eType
!= TNEWLINE
)
1122 { if (CONVERT_40_TO_50
!= GetConversion())
1126 ExpressionArray
.resize(++n
);
1127 ExpressionArray
[n
- 1] = NodeStack
.Pop();
1130 SmStructureNode
*pSNode
= new SmLineNode(CurToken
);
1131 pSNode
->SetSubNodes(ExpressionArray
);
1132 NodeStack
.Push(pSNode
);
1136 void SmParser::Expression()
1139 SmNodeArray RelationArray
;
1141 RelationArray
.resize(n
);
1144 RelationArray
.resize(++n
);
1145 RelationArray
[n
- 1] = NodeStack
.Pop();
1147 while (CurToken
.nLevel
>= 4)
1149 RelationArray
.resize(++n
);
1150 RelationArray
[n
- 1] = NodeStack
.Pop();
1153 SmStructureNode
*pSNode
= new SmExpressionNode(CurToken
);
1154 pSNode
->SetSubNodes(RelationArray
);
1155 NodeStack
.Push(pSNode
);
1159 void SmParser::Relation()
1162 while (TokenInGroup(TGRELATION
))
1164 SmStructureNode
*pSNode
= new SmBinHorNode(CurToken
);
1165 SmNode
*pFirst
= NodeStack
.Pop();
1168 SmNode
*pSecond
= NodeStack
.Pop();
1172 pSNode
->SetSubNodes(pFirst
, pSecond
, NodeStack
.Pop());
1173 NodeStack
.Push(pSNode
);
1178 void SmParser::Sum()
1181 while (TokenInGroup(TGSUM
))
1183 SmStructureNode
*pSNode
= new SmBinHorNode(CurToken
);
1184 SmNode
*pFirst
= NodeStack
.Pop();
1187 SmNode
*pSecond
= NodeStack
.Pop();
1191 pSNode
->SetSubNodes(pFirst
, pSecond
, NodeStack
.Pop());
1192 NodeStack
.Push(pSNode
);
1197 void SmParser::Product()
1201 while (TokenInGroup(TGPRODUCT
))
1202 { SmStructureNode
*pSNode
;
1203 SmNode
*pFirst
= NodeStack
.Pop(),
1205 BOOL bSwitchArgs
= FALSE
;
1207 SmTokenType eType
= CurToken
.eType
;
1211 pSNode
= new SmBinVerNode(CurToken
);
1212 pOper
= new SmRectangleNode(CurToken
);
1217 pSNode
= new SmBinHorNode(CurToken
);
1222 pOper
= NodeStack
.Pop();
1227 pSNode
= new SmVerticalBraceNode(CurToken
);
1228 pOper
= new SmMathSymbolNode(CurToken
);
1233 case TWIDEBACKSLASH
:
1236 SmBinDiagonalNode
*pSTmp
= new SmBinDiagonalNode(CurToken
);
1237 pSTmp
->SetAscending(eType
== TWIDESLASH
);
1240 pOper
= new SmPolyLineNode(CurToken
);
1248 pSNode
= new SmBinHorNode(CurToken
);
1251 pOper
= NodeStack
.Pop();
1257 //! vgl siehe SmBinDiagonalNode::Arrange
1258 pSNode
->SetSubNodes(pFirst
, NodeStack
.Pop(), pOper
);
1260 pSNode
->SetSubNodes(pFirst
, pOper
, NodeStack
.Pop());
1261 NodeStack
.Push(pSNode
);
1266 void SmParser::SubSup(ULONG nActiveGroup
)
1268 DBG_ASSERT(nActiveGroup
== TGPOWER
|| nActiveGroup
== TGLIMIT
,
1269 "Sm: falsche Tokengruppe");
1271 if (!TokenInGroup(nActiveGroup
))
1275 SmSubSupNode
*pNode
= new SmSubSupNode(CurToken
);
1276 //! Of course 'CurToken' ist just the first sub-/supscript token.
1277 //! It should be of no further interest. The positions of the
1278 //! sub-/supscripts will be identified by the corresponding subnodes
1279 //! index in the 'aSubNodes' array (enum value from 'SmSubSup').
1281 pNode
->SetUseLimits(nActiveGroup
== TGLIMIT
);
1283 // initialize subnodes array
1284 SmNodeArray aSubNodes
;
1285 aSubNodes
.resize(1 + SUBSUP_NUM_ENTRIES
);
1286 aSubNodes
[0] = NodeStack
.Pop();
1287 for (USHORT i
= 1; i
< aSubNodes
.size(); i
++)
1288 aSubNodes
[i
] = NULL
;
1290 // process all sub-/supscripts
1292 while (TokenInGroup(nActiveGroup
))
1293 { SmTokenType
eType (CurToken
.eType
);
1295 // skip sub-/supscript token
1298 // get sub-/supscript node on top of stack
1299 if (eType
== TFROM
|| eType
== TTO
)
1301 // parse limits in old 4.0 and 5.0 style
1308 { case TRSUB
: nIndex
= (int) RSUB
; break;
1309 case TRSUP
: nIndex
= (int) RSUP
; break;
1311 case TCSUB
: nIndex
= (int) CSUB
; break;
1313 case TCSUP
: nIndex
= (int) CSUP
; break;
1314 case TLSUB
: nIndex
= (int) LSUB
; break;
1315 case TLSUP
: nIndex
= (int) LSUP
; break;
1317 DBG_ASSERT(FALSE
, "Sm: unbekannter Fall");
1320 DBG_ASSERT(1 <= nIndex
&& nIndex
<= 1 + SUBSUP_NUM_ENTRIES
,
1321 "SmParser::Power() : sub-/supscript index falsch");
1323 // set sub-/supscript if not already done
1324 if (aSubNodes
[nIndex
] != NULL
)
1325 Error(PE_DOUBLE_SUBSUPSCRIPT
);
1326 aSubNodes
[nIndex
] = NodeStack
.Pop();
1329 pNode
->SetSubNodes(aSubNodes
);
1330 NodeStack
.Push(pNode
);
1334 void SmParser::OpSubSup()
1336 // push operator symbol
1337 NodeStack
.Push(new SmMathSymbolNode(CurToken
));
1338 // skip operator token
1340 // get sub- supscripts if any
1341 if (TokenInGroup(TGPOWER
))
1346 void SmParser::Power()
1348 // get body for sub- supscripts on top of stack
1355 void SmParser::Blank()
1357 DBG_ASSERT(TokenInGroup(TGBLANK
), "Sm : falsches Token");
1358 SmBlankNode
*pBlankNode
= new SmBlankNode(CurToken
);
1360 while (TokenInGroup(TGBLANK
))
1362 pBlankNode
->IncreaseBy(CurToken
);
1366 // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist
1367 if ( CurToken
.eType
== TNEWLINE
||
1368 (CurToken
.eType
== TEND
&& SM_MOD1()->GetConfig()->IsIgnoreSpacesRight()) )
1370 pBlankNode
->Clear();
1373 NodeStack
.Push(pBlankNode
);
1377 void SmParser::Term()
1379 switch (CurToken
.eType
)
1387 // allow for empty group
1388 if (CurToken
.eType
== TRGROUP
)
1389 { SmStructureNode
*pSNode
= new SmExpressionNode(CurToken
);
1390 pSNode
->SetSubNodes(NULL
, NULL
);
1391 NodeStack
.Push(pSNode
);
1397 if (CurToken
.eType
!= TRGROUP
)
1398 Error(PE_RGROUP_EXPECTED
);
1415 NodeStack
.Push(new SmTextNode(CurToken
, FNT_TEXT
));
1420 NodeStack
.Push(new SmTextNode(CurToken
, FNT_VARIABLE
));
1424 NodeStack
.Push(new SmTextNode(CurToken
, FNT_NUMBER
));
1461 NodeStack
.Push(new SmMathSymbolNode(CurToken
));
1466 NodeStack
.Push(new SmPlaceNode(CurToken
));
1487 if (TokenInGroup(TGLBRACES
))
1490 else if (TokenInGroup(TGOPER
))
1493 else if (TokenInGroup(TGUNOPER
))
1496 else if ( TokenInGroup(TGATTRIBUT
)
1497 || TokenInGroup(TGFONTATTR
))
1498 { SmStructureNodeArray aArray
;
1502 while (TRUE
== (bIsAttr
= TokenInGroup(TGATTRIBUT
))
1503 || TokenInGroup(TGFONTATTR
))
1504 { aArray
.resize(n
+ 1);
1511 // check if casting in following line is ok
1512 DBG_ASSERT(!NodeStack
.Top()->IsVisible(), "Sm : Ooops...");
1514 aArray
[n
] = (SmStructureNode
*) NodeStack
.Pop();
1520 SmNode
*pFirstNode
= NodeStack
.Pop();
1522 { aArray
[n
- 1]->SetSubNodes(0, pFirstNode
);
1523 pFirstNode
= aArray
[n
- 1];
1526 NodeStack
.Push(pFirstNode
);
1528 else if (TokenInGroup(TGFUNCTION
))
1529 { if (CONVERT_40_TO_50
!= GetConversion())
1532 else // encapsulate old 4.0 style parsing in braces
1534 // insert opening brace
1535 Insert('{', GetTokenIndex());
1538 // parse in 4.0 style
1542 SmNode
*pFunc
= NodeStack
.Pop();
1544 if (CurToken
.eType
== TLPARENT
)
1551 // insert closing brace
1552 Insert('}', GetTokenIndex());
1554 SmStructureNode
*pSNode
= new SmExpressionNode(pFunc
->GetToken());
1555 pSNode
->SetSubNodes(pFunc
, NodeStack
.Pop());
1556 NodeStack
.Push(pSNode
);
1560 Error(PE_UNEXPECTED_CHAR
);
1565 void SmParser::Escape()
1570 switch (CurToken
.eType
)
1571 { case TLPARENT
: cChar
= MS_LPARENT
; break;
1572 case TRPARENT
: cChar
= MS_RPARENT
; break;
1573 case TLBRACKET
: cChar
= MS_LBRACKET
; break;
1574 case TRBRACKET
: cChar
= MS_RBRACKET
; break;
1575 case TLDBRACKET
: cChar
= MS_LDBRACKET
; break;
1576 case TRDBRACKET
: cChar
= MS_RDBRACKET
; break;
1578 case TLGROUP
: cChar
= MS_LBRACE
; break;
1580 case TRGROUP
: cChar
= MS_RBRACE
; break;
1581 case TLANGLE
: cChar
= MS_LANGLE
; break;
1582 case TRANGLE
: cChar
= MS_RANGLE
; break;
1583 case TLCEIL
: cChar
= MS_LCEIL
; break;
1584 case TRCEIL
: cChar
= MS_RCEIL
; break;
1585 case TLFLOOR
: cChar
= MS_LFLOOR
; break;
1586 case TRFLOOR
: cChar
= MS_RFLOOR
; break;
1588 case TRLINE
: cChar
= MS_LINE
; break;
1590 case TRDLINE
: cChar
= MS_DLINE
; break;
1592 Error(PE_UNEXPECTED_TOKEN
);
1595 SmNode
*pNode
= new SmMathSymbolNode(CurToken
);
1596 NodeStack
.Push(pNode
);
1602 void SmParser::Operator()
1604 if (TokenInGroup(TGOPER
))
1605 { SmStructureNode
*pSNode
= new SmOperNode(CurToken
);
1607 // put operator on top of stack
1610 if (TokenInGroup(TGLIMIT
) || TokenInGroup(TGPOWER
))
1611 SubSup(CurToken
.nGroup
);
1612 SmNode
*pOperator
= NodeStack
.Pop();
1617 pSNode
->SetSubNodes(pOperator
, NodeStack
.Pop());
1618 NodeStack
.Push(pSNode
);
1623 void SmParser::Oper()
1625 SmTokenType
eType (CurToken
.eType
);
1626 SmNode
*pNode
= NULL
;
1639 pNode
= new SmMathSymbolNode(CurToken
);
1646 const sal_Char
* pLim
= 0;
1649 case TLIM
: pLim
= "lim"; break;
1650 case TLIMSUP
: pLim
= "lim sup"; break;
1651 case TLIMINF
: pLim
= "lim inf"; break;
1656 CurToken
.aText
.AssignAscii( pLim
);
1657 pNode
= new SmTextNode(CurToken
, FNT_TEXT
);
1663 pNode
= new SmMathSymbolNode(CurToken
);
1669 DBG_ASSERT(CurToken
.eType
== TSPECIAL
, "Sm: falsches Token");
1670 pNode
= new SmGlyphSpecialNode(CurToken
);
1674 DBG_ASSERT(0, "Sm: unbekannter Fall");
1676 NodeStack
.Push(pNode
);
1682 void SmParser::UnOper()
1684 DBG_ASSERT(TokenInGroup(TGUNOPER
), "Sm: falsches Token");
1686 SmToken aNodeToken
= CurToken
;
1687 SmTokenType eType
= CurToken
.eType
;
1688 BOOL bIsPostfix
= eType
== TFACT
;
1690 SmStructureNode
*pSNode
;
1705 pExtra
= NodeStack
.Pop();
1711 pOper
= NodeStack
.Pop();
1721 pOper
= NodeStack
.Pop();
1725 Error(PE_UNOPER_EXPECTED
);
1730 pArg
= NodeStack
.Pop();
1733 { pSNode
= new SmBraceNode(aNodeToken
);
1734 pSNode
->SetScaleMode(SCALE_HEIGHT
);
1736 // build nodes for left & right lines
1737 // (text, group, level of the used token are of no interrest here)
1738 // we'll use row & column of the keyword for abs
1739 aNodeToken
.eType
= TABS
;
1741 aNodeToken
.cMathChar
= MS_LINE
;
1742 SmNode
* pLeft
= new SmMathSymbolNode(aNodeToken
);
1744 aNodeToken
.cMathChar
= MS_LINE
;
1745 SmNode
* pRight
= new SmMathSymbolNode(aNodeToken
);
1747 pSNode
->SetSubNodes(pLeft
, pArg
, pRight
);
1749 else if (eType
== TSQRT
|| eType
== TNROOT
)
1750 { pSNode
= new SmRootNode(aNodeToken
);
1751 pOper
= new SmRootSymbolNode(aNodeToken
);
1752 pSNode
->SetSubNodes(pExtra
, pOper
, pArg
);
1755 { pSNode
= new SmUnHorNode(aNodeToken
);
1758 pSNode
->SetSubNodes(pArg
, pOper
);
1761 pSNode
->SetSubNodes(pOper
, pArg
);
1764 NodeStack
.Push(pSNode
);
1768 void SmParser::Attribut()
1770 DBG_ASSERT(TokenInGroup(TGATTRIBUT
), "Sm: falsche Tokengruppe");
1772 SmStructureNode
*pSNode
= new SmAttributNode(CurToken
);
1774 SmScaleMode eScaleMode
= SCALE_NONE
;
1776 // get appropriate node for the attribut itself
1777 switch (CurToken
.eType
)
1781 pAttr
= new SmRectangleNode(CurToken
);
1782 eScaleMode
= SCALE_WIDTH
;
1788 pAttr
= new SmMathSymbolNode(CurToken
);
1789 eScaleMode
= SCALE_WIDTH
;
1793 pAttr
= new SmMathSymbolNode(CurToken
);
1798 pSNode
->SetSubNodes(pAttr
, 0);
1799 pSNode
->SetScaleMode(eScaleMode
);
1800 NodeStack
.Push(pSNode
);
1804 void SmParser::FontAttribut()
1806 DBG_ASSERT(TokenInGroup(TGFONTATTR
), "Sm: falsche Tokengruppe");
1808 switch (CurToken
.eType
)
1815 NodeStack
.Push(new SmFontNode(CurToken
));
1832 DBG_ASSERT(0, "Sm: unbekannter Fall");
1837 void SmParser::Color()
1839 DBG_ASSERT(CurToken
.eType
== TCOLOR
, "Sm : Ooops...");
1841 // last color rules, get that one
1846 if (TokenInGroup(TGCOLOR
))
1847 { aToken
= CurToken
;
1851 Error(PE_COLOR_EXPECTED
);
1852 } while (CurToken
.eType
== TCOLOR
);
1854 NodeStack
.Push(new SmFontNode(aToken
));
1858 void SmParser::Font()
1860 DBG_ASSERT(CurToken
.eType
== TFONT
, "Sm : Ooops...");
1862 // last font rules, get that one
1867 if (TokenInGroup(TGFONT
))
1868 { aToken
= CurToken
;
1872 Error(PE_FONT_EXPECTED
);
1873 } while (CurToken
.eType
== TFONT
);
1875 NodeStack
.Push(new SmFontNode(aToken
));
1879 // gets number used as arguments in Math formulas (e.g. 'size' command)
1880 // Format: no negative numbers, must start with a digit, no exponent notation, ...
1881 BOOL
lcl_IsNumber(const UniString
& rText
)
1883 BOOL bPoint
= FALSE
;
1884 const sal_Unicode
* pBuffer
= rText
.GetBuffer();
1885 for(xub_StrLen nPos
= 0; nPos
< rText
.Len(); nPos
++, pBuffer
++)
1887 const sal_Unicode cChar
= *pBuffer
;
1895 else if ( !IsDigit( cChar
) )
1901 void SmParser::FontSize()
1903 DBG_ASSERT(CurToken
.eType
== TSIZE
, "Sm : Ooops...");
1906 SmFontNode
*pFontNode
= new SmFontNode(CurToken
);
1910 switch (CurToken
.eType
)
1912 case TNUMBER
: Type
= FNTSIZ_ABSOLUT
; break;
1913 case TPLUS
: Type
= FNTSIZ_PLUS
; break;
1914 case TMINUS
: Type
= FNTSIZ_MINUS
; break;
1915 case TMULTIPLY
: Type
= FNTSIZ_MULTIPLY
; break;
1916 case TDIVIDEBY
: Type
= FNTSIZ_DIVIDE
; break;
1920 Error(PE_SIZE_EXPECTED
);
1924 if (Type
!= FNTSIZ_ABSOLUT
)
1927 if (CurToken
.eType
!= TNUMBER
)
1930 Error(PE_SIZE_EXPECTED
);
1935 // get number argument
1936 Fraction
aValue( 1L );
1937 if (lcl_IsNumber( CurToken
.aText
))
1940 if ((fTmp
= CurToken
.aText
.ToDouble()) != 0.0)
1944 //!! keep the numerator and denominator from being to large
1945 //!! otherwise ongoing multiplications may result in overflows
1946 //!! (for example in SmNode::SetFontSize the font size calculated
1947 //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux
1948 //!! or ftmp = 1.11111111111111111... (11/9) on every platform.)
1949 if (aValue
.GetDenominator() > 1000)
1951 long nNum
= aValue
.GetNumerator();
1952 long nDenom
= aValue
.GetDenominator();
1953 while (nDenom
> 1000)
1958 aValue
= Fraction( nNum
, nDenom
);
1965 pFontNode
->SetSizeParameter(aValue
, Type
);
1966 NodeStack
.Push(pFontNode
);
1970 void SmParser::Brace()
1972 DBG_ASSERT(CurToken
.eType
== TLEFT
|| TokenInGroup(TGLBRACES
),
1973 "Sm: kein Klammer Ausdruck");
1975 SmStructureNode
*pSNode
= new SmBraceNode(CurToken
);
1979 SmScaleMode eScaleMode
= SCALE_NONE
;
1980 SmParseError eError
= PE_NONE
;
1982 if (CurToken
.eType
== TLEFT
)
1985 eScaleMode
= SCALE_HEIGHT
;
1987 // check for left bracket
1988 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
1990 pLeft
= new SmMathSymbolNode(CurToken
);
1994 pBody
= NodeStack
.Pop();
1996 if (CurToken
.eType
== TRIGHT
)
1999 // check for right bracket
2000 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
2002 pRight
= new SmMathSymbolNode(CurToken
);
2006 eError
= PE_RBRACE_EXPECTED
;
2009 eError
= PE_RIGHT_EXPECTED
;
2012 eError
= PE_LBRACE_EXPECTED
;
2016 if (TokenInGroup(TGLBRACES
))
2018 pLeft
= new SmMathSymbolNode(CurToken
);
2022 pBody
= NodeStack
.Pop();
2024 SmTokenType eExpectedType
= TUNKNOWN
;
2025 switch (pLeft
->GetToken().eType
)
2026 { case TLPARENT
: eExpectedType
= TRPARENT
; break;
2027 case TLBRACKET
: eExpectedType
= TRBRACKET
; break;
2028 case TLBRACE
: eExpectedType
= TRBRACE
; break;
2029 case TLDBRACKET
: eExpectedType
= TRDBRACKET
; break;
2030 case TLLINE
: eExpectedType
= TRLINE
; break;
2031 case TLDLINE
: eExpectedType
= TRDLINE
; break;
2032 case TLANGLE
: eExpectedType
= TRANGLE
; break;
2033 case TLFLOOR
: eExpectedType
= TRFLOOR
; break;
2034 case TLCEIL
: eExpectedType
= TRCEIL
; break;
2036 DBG_ASSERT(0, "Sm: unbekannter Fall");
2039 if (CurToken
.eType
== eExpectedType
)
2041 pRight
= new SmMathSymbolNode(CurToken
);
2045 eError
= PE_PARENT_MISMATCH
;
2048 eError
= PE_LBRACE_EXPECTED
;
2051 if (eError
== PE_NONE
)
2052 { DBG_ASSERT(pLeft
, "Sm: NULL pointer");
2053 DBG_ASSERT(pRight
, "Sm: NULL pointer");
2054 pSNode
->SetSubNodes(pLeft
, pBody
, pRight
);
2055 pSNode
->SetScaleMode(eScaleMode
);
2056 NodeStack
.Push(pSNode
);
2069 void SmParser::Bracebody(BOOL bIsLeftRight
)
2071 SmStructureNode
*pBody
= new SmBracebodyNode(CurToken
);
2080 if (CurToken
.eType
== TMLINE
)
2082 NodeStack
.Push(new SmMathSymbolNode(CurToken
));
2086 else if (CurToken
.eType
!= TRIGHT
)
2090 if (CurToken
.eType
!= TMLINE
&& CurToken
.eType
!= TRIGHT
)
2091 Error(PE_RIGHT_EXPECTED
);
2093 } while (CurToken
.eType
!= TEND
&& CurToken
.eType
!= TRIGHT
);
2099 if (CurToken
.eType
== TMLINE
)
2101 NodeStack
.Push(new SmMathSymbolNode(CurToken
));
2105 else if (!TokenInGroup(TGRBRACES
))
2109 if (CurToken
.eType
!= TMLINE
&& !TokenInGroup(TGRBRACES
))
2110 Error(PE_RBRACE_EXPECTED
);
2112 } while (CurToken
.eType
!= TEND
&& !TokenInGroup(TGRBRACES
));
2115 // build argument vector in parsing order
2116 aNodes
.resize(nNum
);
2117 for (USHORT i
= 0; i
< nNum
; i
++)
2118 aNodes
[nNum
- 1 - i
] = NodeStack
.Pop();
2120 pBody
->SetSubNodes(aNodes
);
2121 pBody
->SetScaleMode(bIsLeftRight
? SCALE_HEIGHT
: SCALE_NONE
);
2122 NodeStack
.Push(pBody
);
2126 void SmParser::Function()
2128 switch (CurToken
.eType
)
2131 NextToken(); // skip "FUNC"-statement
2153 NodeStack
.Push(new SmTextNode(CurToken
, FNT_FUNCTION
));
2158 Error(PE_FUNC_EXPECTED
);
2163 void SmParser::Binom()
2165 SmNodeArray ExpressionArray
;
2166 SmStructureNode
*pSNode
= new SmTableNode(CurToken
);
2173 ExpressionArray
.resize(2);
2175 for (int i
= 0; i
< 2; i
++)
2176 ExpressionArray
[2 - (i
+ 1)] = NodeStack
.Pop();
2178 pSNode
->SetSubNodes(ExpressionArray
);
2179 NodeStack
.Push(pSNode
);
2183 void SmParser::Stack()
2185 SmNodeArray ExpressionArray
;
2187 if (CurToken
.eType
== TLGROUP
)
2197 while (CurToken
.eType
== TPOUND
);
2199 ExpressionArray
.resize(n
);
2201 for (USHORT i
= 0; i
< n
; i
++)
2202 ExpressionArray
[n
- (i
+ 1)] = NodeStack
.Pop();
2204 if (CurToken
.eType
!= TRGROUP
)
2205 Error(PE_RGROUP_EXPECTED
);
2209 SmStructureNode
*pSNode
= new SmTableNode(CurToken
);
2210 pSNode
->SetSubNodes(ExpressionArray
);
2211 NodeStack
.Push(pSNode
);
2214 Error(PE_LGROUP_EXPECTED
);
2218 void SmParser::Matrix()
2220 SmNodeArray ExpressionArray
;
2223 if (CurToken
.eType
== TLGROUP
)
2233 while (CurToken
.eType
== TPOUND
);
2237 while (CurToken
.eType
== TDPOUND
)
2240 for (USHORT i
= 0; i
< c
; i
++)
2245 if (CurToken
.eType
== TPOUND
)
2250 Error(PE_POUND_EXPECTED
);
2259 ExpressionArray
.resize(nRC
);
2261 for (USHORT i
= 0; i
< (nRC
); i
++)
2262 ExpressionArray
[(nRC
) - (i
+ 1)] = NodeStack
.Pop();
2264 if (CurToken
.eType
!= TRGROUP
)
2265 Error(PE_RGROUP_EXPECTED
);
2269 SmMatrixNode
*pMNode
= new SmMatrixNode(CurToken
);
2270 pMNode
->SetSubNodes(ExpressionArray
);
2271 pMNode
->SetRowCol(r
, c
);
2272 NodeStack
.Push(pMNode
);
2275 Error(PE_LGROUP_EXPECTED
);
2279 void SmParser::Special()
2281 BOOL bReplace
= FALSE
;
2282 String
&rName
= CurToken
.aText
;
2285 if (CONVERT_NONE
== GetConversion())
2287 // conversion of symbol names for 6.0 (XML) file format
2288 // (name change on import / export.
2289 // UI uses localized names XML file format does not.)
2290 if (IsImportSymbolNames())
2292 const SmLocalizedSymbolData
&rLSD
= SM_MOD1()->GetLocSymbolData();
2293 aNewName
= rLSD
.GetUiSymbolName( rName
);
2296 else if (IsExportSymbolNames())
2298 const SmLocalizedSymbolData
&rLSD
= SM_MOD1()->GetLocSymbolData();
2299 aNewName
= rLSD
.GetExportSymbolName( rName
);
2303 else // 5.0 <-> 6.0 formula text (symbol name) conversion
2305 LanguageType nLanguage
= GetLanguage();
2306 SmLocalizedSymbolData
&rData
= SM_MOD1()->GetLocSymbolData();
2307 const ResStringArray
*pFrom
= 0;
2308 const ResStringArray
*pTo
= 0;
2309 if (CONVERT_50_TO_60
== GetConversion())
2311 pFrom
= rData
.Get50NamesArray( nLanguage
);
2312 pTo
= rData
.Get60NamesArray( nLanguage
);
2314 else if (CONVERT_60_TO_50
== GetConversion())
2316 pFrom
= rData
.Get60NamesArray( nLanguage
);
2317 pTo
= rData
.Get50NamesArray( nLanguage
);
2321 DBG_ASSERT( pFrom
->Count() == pTo
->Count(),
2322 "array length mismatch" );
2323 USHORT nCount
= sal::static_int_cast
< USHORT
>(pFrom
->Count());
2324 for (USHORT i
= 0; i
< nCount
; ++i
)
2326 if (pFrom
->GetString(i
) == rName
)
2328 aNewName
= pTo
->GetString(i
);
2334 // conversion arrays not found or (usually)
2335 // conversion not necessary
2338 if (bReplace
&& aNewName
.Len() && rName
!= aNewName
)
2340 Replace( GetTokenIndex() + 1, rName
.Len(), aNewName
);
2344 NodeStack
.Push(new SmSpecialNode(CurToken
));
2349 void SmParser::GlyphSpecial()
2351 NodeStack
.Push(new SmGlyphSpecialNode(CurToken
));
2356 void SmParser::Error(SmParseError eError
)
2358 SmStructureNode
*pSNode
= new SmExpressionNode(CurToken
);
2359 SmErrorNode
*pErr
= new SmErrorNode(eError
, CurToken
);
2360 pSNode
->SetSubNodes(pErr
, 0);
2362 //! put a structure node on the stack (instead of the error node itself)
2363 //! because sometimes such a node is expected in order to attach some
2365 NodeStack
.Push(pSNode
);
2367 AddError(eError
, pSNode
);
2376 SmParser::SmParser()
2378 eConversion
= CONVERT_NONE
;
2379 bImportSymNames
= bExportSymNames
= FALSE
;
2380 nLang
= Application::GetSettings().GetUILanguage();
2384 SmNode
*SmParser::Parse(const String
&rBuffer
)
2386 BufferString
= rBuffer
;
2387 BufferString
.ConvertLineEnd( LINEEND_LF
);
2394 for (USHORT i
= 0; i
< ErrDescList
.Count(); i
++)
2395 delete ErrDescList
.Remove(i
);
2397 ErrDescList
.Clear();
2401 SetLanguage( Application::GetSettings().GetUILanguage() );
2405 return NodeStack
.Pop();
2409 USHORT
SmParser::AddError(SmParseError Type
, SmNode
*pNode
)
2411 SmErrorDesc
*pErrDesc
= new SmErrorDesc
;
2413 pErrDesc
->Type
= Type
;
2414 pErrDesc
->pNode
= pNode
;
2415 pErrDesc
->Text
= String(SmResId(RID_ERR_IDENT
));
2420 case PE_UNEXPECTED_CHAR
: nRID
= RID_ERR_UNEXPECTEDCHARACTER
; break;
2421 case PE_LGROUP_EXPECTED
: nRID
= RID_ERR_LGROUPEXPECTED
; break;
2422 case PE_RGROUP_EXPECTED
: nRID
= RID_ERR_RGROUPEXPECTED
; break;
2423 case PE_LBRACE_EXPECTED
: nRID
= RID_ERR_LBRACEEXPECTED
; break;
2424 case PE_RBRACE_EXPECTED
: nRID
= RID_ERR_RBRACEEXPECTED
; break;
2425 case PE_FUNC_EXPECTED
: nRID
= RID_ERR_FUNCEXPECTED
; break;
2426 case PE_UNOPER_EXPECTED
: nRID
= RID_ERR_UNOPEREXPECTED
; break;
2427 case PE_BINOPER_EXPECTED
: nRID
= RID_ERR_BINOPEREXPECTED
; break;
2428 case PE_SYMBOL_EXPECTED
: nRID
= RID_ERR_SYMBOLEXPECTED
; break;
2429 case PE_IDENTIFIER_EXPECTED
: nRID
= RID_ERR_IDENTEXPECTED
; break;
2430 case PE_POUND_EXPECTED
: nRID
= RID_ERR_POUNDEXPECTED
; break;
2431 case PE_COLOR_EXPECTED
: nRID
= RID_ERR_COLOREXPECTED
; break;
2432 case PE_RIGHT_EXPECTED
: nRID
= RID_ERR_RIGHTEXPECTED
; break;
2435 nRID
= RID_ERR_UNKOWN
;
2437 pErrDesc
->Text
+= SmResId(nRID
);
2439 ErrDescList
.Insert(pErrDesc
);
2441 return (USHORT
) ErrDescList
.GetPos(pErrDesc
);
2445 const SmErrorDesc
*SmParser::NextError()
2447 if (ErrDescList
.Count())
2448 if (CurError
> 0) return ErrDescList
.Seek(--CurError
);
2452 return ErrDescList
.Seek(CurError
);
2458 const SmErrorDesc
*SmParser::PrevError()
2460 if (ErrDescList
.Count())
2461 if (CurError
< (int) (ErrDescList
.Count() - 1)) return ErrDescList
.Seek(++CurError
);
2464 CurError
= (int) (ErrDescList
.Count() - 1);
2465 return ErrDescList
.Seek(CurError
);
2471 const SmErrorDesc
*SmParser::GetError(USHORT i
)
2473 return (/*i >= 0 &&*/ i
< ErrDescList
.Count())
2474 ? ErrDescList
.Seek(i
)
2475 : ErrDescList
.Seek(CurError
);