1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_starmath.hxx"
36 #include <com/sun/star/i18n/UnicodeType.hpp>
37 #include <i18npool/lang.h>
38 #include <unotools/charclass.hxx>
39 #include <editeng/unolingu.hxx>
40 #include <unotools/syslocale.hxx>
43 #include "starmath.hrc"
53 using namespace ::com::sun::star
;
54 using namespace ::com::sun::star::i18n
;
56 ///////////////////////////////////////////////////////////////////////////
58 static inline sal_Bool
strnccmp(const String
&u1
, xub_StrLen nIdx
,
59 const sal_Char
*s2
, xub_StrLen nLen
)
61 return u1
.EqualsIgnoreCaseAscii( s2
, nIdx
, nLen
);
64 static const sal_Unicode aDelimiterTable
[] =
66 ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#',
67 '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(',
68 ')', '{', '}', '[', ']', '^', '_',
69 '\0' // end of list symbol
73 static inline sal_Bool
IsDigit( sal_Unicode cChar
)
75 return '0' <= cChar
&& cChar
<= '9';
78 ///////////////////////////////////////////////////////////////////////////
84 nGroup
= nCol
= nRow
= nLevel
= 0;
87 ///////////////////////////////////////////////////////////////////////////
89 struct SmTokenTableEntry
91 const sal_Char
* pIdent
;
93 sal_Unicode cMathChar
;
98 static const SmTokenTableEntry aTokenTable
[] =
100 // { "#", TPOUND, '\0', 0, 0 },
101 // { "##", TDPOUND, '\0', 0, 0 },
102 // { "&", TAND, MS_AND, TGPRODUCT, 0 },
103 // { "(", TLPARENT, MS_LPARENT, TGLBRACES, 5 }, //! 5 to continue expression
104 // { ")", TRPARENT, MS_RPARENT, TGRBRACES, 0 }, //! 0 to terminate expression
105 // { "*", TMULTIPLY, MS_MULTIPLY, TGPRODUCT, 0 },
106 // { "+", TPLUS, MS_PLUS, TGUNOPER | TGSUM, 5 },
107 // { "+-", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5 },
108 // { "-", TMINUS, MS_MINUS, TGUNOPER | TGSUM, 5 },
109 // { "-+", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5 },
110 // { ".", TPOINT, '\0', 0, 0 },
111 // { "/", TDIVIDEBY, MS_SLASH, TGPRODUCT, 0 },
112 // { "<", TLT, MS_LT, TGRELATION, 0 },
113 // { "<<", TLL, MS_LL, TGRELATION, 0 },
114 // { "<=", TLE, MS_LE, TGRELATION, 0 },
115 // { "<>", TNEQ, MS_NEQ, TGRELATION, 0},
116 // { "<?>", TPLACE, MS_PLACE, 0, 5 },
117 // { "=", TASSIGN, MS_ASSIGN, TGRELATION, 0},
118 // { ">", TGT, MS_GT, TGRELATION, 0 },
119 // { ">=", TGE, MS_GE, TGRELATION, 0 },
120 // { ">>", TGG, MS_GG, TGRELATION, 0 },
121 { "Im" , TIM
, MS_IM
, TGSTANDALONE
, 5 },
122 { "MZ23", TDEBUG
, '\0', TGATTRIBUT
, 0 },
123 { "Re" , TRE
, MS_RE
, TGSTANDALONE
, 5 },
124 { "abs", TABS
, '\0', TGUNOPER
, 13 },
125 { "arcosh", TACOSH
, '\0', TGFUNCTION
, 5 },
126 { "arcoth", TACOTH
, '\0', TGFUNCTION
, 5 },
127 { "acute", TACUTE
, MS_ACUTE
, TGATTRIBUT
, 5 },
128 { "aleph" , TALEPH
, MS_ALEPH
, TGSTANDALONE
, 5 },
129 { "alignb", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
130 { "alignc", TALIGNC
, '\0', TGALIGN
, 0},
131 { "alignl", TALIGNL
, '\0', TGALIGN
, 0},
132 { "alignm", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
133 { "alignr", TALIGNR
, '\0', TGALIGN
, 0},
134 { "alignt", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
135 { "and", TAND
, MS_AND
, TGPRODUCT
, 0},
136 { "approx", TAPPROX
, MS_APPROX
, TGRELATION
, 0},
137 { "arccos", TACOS
, '\0', TGFUNCTION
, 5},
138 { "arccot", TACOT
, '\0', TGFUNCTION
, 5},
139 { "arcsin", TASIN
, '\0', TGFUNCTION
, 5},
140 { "arctan", TATAN
, '\0', TGFUNCTION
, 5},
141 { "arsinh", TASINH
, '\0', TGFUNCTION
, 5},
142 { "artanh", TATANH
, '\0', TGFUNCTION
, 5},
143 { "backepsilon" , TBACKEPSILON
, MS_BACKEPSILON
, TGSTANDALONE
, 5},
144 { "bar", TBAR
, MS_BAR
, TGATTRIBUT
, 5},
145 { "binom", TBINOM
, '\0', 0, 5 },
146 { "black", TBLACK
, '\0', TGCOLOR
, 0},
147 { "blue", TBLUE
, '\0', TGCOLOR
, 0},
148 { "bold", TBOLD
, '\0', TGFONTATTR
, 5},
149 { "boper", TBOPER
, '\0', TGPRODUCT
, 0},
150 { "breve", TBREVE
, MS_BREVE
, TGATTRIBUT
, 5},
151 { "bslash", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
152 { "cdot", TCDOT
, MS_CDOT
, TGPRODUCT
, 0},
153 { "check", TCHECK
, MS_CHECK
, TGATTRIBUT
, 5},
154 { "circ" , TCIRC
, MS_CIRC
, TGSTANDALONE
, 5},
155 { "circle", TCIRCLE
, MS_CIRCLE
, TGATTRIBUT
, 5},
156 { "color", TCOLOR
, '\0', TGFONTATTR
, 5},
157 { "coprod", TCOPROD
, MS_COPROD
, TGOPER
, 5},
158 { "cos", TCOS
, '\0', TGFUNCTION
, 5},
159 { "cosh", TCOSH
, '\0', TGFUNCTION
, 5},
160 { "cot", TCOT
, '\0', TGFUNCTION
, 5},
161 { "coth", TCOTH
, '\0', TGFUNCTION
, 5},
162 { "csub", TCSUB
, '\0', TGPOWER
, 0},
163 { "csup", TCSUP
, '\0', TGPOWER
, 0},
164 { "cyan", TCYAN
, '\0', TGCOLOR
, 0},
165 { "dddot", TDDDOT
, MS_DDDOT
, TGATTRIBUT
, 5},
166 { "ddot", TDDOT
, MS_DDOT
, TGATTRIBUT
, 5},
167 { "def", TDEF
, MS_DEF
, TGRELATION
, 0},
168 { "div", TDIV
, MS_DIV
, TGPRODUCT
, 0},
169 { "divides", TDIVIDES
, MS_LINE
, TGRELATION
, 0},
170 { "dlarrow" , TDLARROW
, MS_DLARROW
, TGSTANDALONE
, 5},
171 { "dlrarrow" , TDLRARROW
, MS_DLRARROW
, TGSTANDALONE
, 5},
172 { "dot", TDOT
, MS_DOT
, TGATTRIBUT
, 5},
173 { "dotsaxis", TDOTSAXIS
, MS_DOTSAXIS
, TGSTANDALONE
, 5}, // 5 to continue expression
174 { "dotsdiag", TDOTSDIAG
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
175 { "dotsdown", TDOTSDOWN
, MS_DOTSDOWN
, TGSTANDALONE
, 5}, //
176 { "dotslow", TDOTSLOW
, MS_DOTSLOW
, TGSTANDALONE
, 5}, //
177 { "dotsup", TDOTSUP
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
178 { "dotsvert", TDOTSVERT
, MS_DOTSVERT
, TGSTANDALONE
, 5}, //
179 { "downarrow" , TDOWNARROW
, MS_DOWNARROW
, TGSTANDALONE
, 5},
180 { "drarrow" , TDRARROW
, MS_DRARROW
, TGSTANDALONE
, 5},
181 { "emptyset" , TEMPTYSET
, MS_EMPTYSET
, TGSTANDALONE
, 5},
182 { "equiv", TEQUIV
, MS_EQUIV
, TGRELATION
, 0},
183 { "exists", TEXISTS
, MS_EXISTS
, TGSTANDALONE
, 5},
184 { "exp", TEXP
, '\0', TGFUNCTION
, 5},
185 { "fact", TFACT
, MS_FACT
, TGUNOPER
, 5},
186 { "fixed", TFIXED
, '\0', TGFONT
, 0},
187 { "font", TFONT
, '\0', TGFONTATTR
, 5},
188 { "forall", TFORALL
, MS_FORALL
, TGSTANDALONE
, 5},
189 { "from", TFROM
, '\0', TGLIMIT
, 0},
190 { "func", TFUNC
, '\0', TGFUNCTION
, 5},
191 { "ge", TGE
, MS_GE
, TGRELATION
, 0},
192 { "geslant", TGESLANT
, MS_GESLANT
, TGRELATION
, 0 },
193 { "gg", TGG
, MS_GG
, TGRELATION
, 0},
194 { "grave", TGRAVE
, MS_GRAVE
, TGATTRIBUT
, 5},
195 { "green", TGREEN
, '\0', TGCOLOR
, 0},
196 { "gt", TGT
, MS_GT
, TGRELATION
, 0},
197 { "hat", THAT
, MS_HAT
, TGATTRIBUT
, 5},
198 { "hbar" , THBAR
, MS_HBAR
, TGSTANDALONE
, 5},
199 { "iiint", TIIINT
, MS_IIINT
, TGOPER
, 5},
200 { "iint", TIINT
, MS_IINT
, TGOPER
, 5},
201 { "in", TIN
, MS_IN
, TGRELATION
, 0},
202 { "infinity" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
203 { "infty" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
204 { "int", TINT
, MS_INT
, TGOPER
, 5},
205 { "intersection", TINTERSECT
, MS_INTERSECT
, TGPRODUCT
, 0},
206 { "ital", TITALIC
, '\0', TGFONTATTR
, 5},
207 { "italic", TITALIC
, '\0', TGFONTATTR
, 5},
208 { "lambdabar" , TLAMBDABAR
, MS_LAMBDABAR
, TGSTANDALONE
, 5},
209 { "langle", TLANGLE
, MS_LANGLE
, TGLBRACES
, 5},
210 { "lbrace", TLBRACE
, MS_LBRACE
, TGLBRACES
, 5},
211 { "lceil", TLCEIL
, MS_LCEIL
, TGLBRACES
, 5},
212 { "ldbracket", TLDBRACKET
, MS_LDBRACKET
, TGLBRACES
, 5},
213 { "ldline", TLDLINE
, MS_DLINE
, TGLBRACES
, 5},
214 { "le", TLE
, MS_LE
, TGRELATION
, 0},
215 { "left", TLEFT
, '\0', 0, 5},
216 { "leftarrow" , TLEFTARROW
, MS_LEFTARROW
, TGSTANDALONE
, 5},
217 { "leslant", TLESLANT
, MS_LESLANT
, TGRELATION
, 0 },
218 { "lfloor", TLFLOOR
, MS_LFLOOR
, TGLBRACES
, 5},
219 { "lim", TLIM
, '\0', TGOPER
, 5},
220 { "liminf", TLIMINF
, '\0', TGOPER
, 5},
221 { "limsup", TLIMSUP
, '\0', TGOPER
, 5},
222 { "lint", TLINT
, MS_LINT
, TGOPER
, 5},
223 { "ll", TLL
, MS_LL
, TGRELATION
, 0},
224 { "lline", TLLINE
, MS_LINE
, TGLBRACES
, 5},
225 { "llint", TLLINT
, MS_LLINT
, TGOPER
, 5},
226 { "lllint", TLLLINT
, MS_LLLINT
, TGOPER
, 5},
227 { "ln", TLN
, '\0', TGFUNCTION
, 5},
228 { "log", TLOG
, '\0', TGFUNCTION
, 5},
229 { "lsub", TLSUB
, '\0', TGPOWER
, 0},
230 { "lsup", TLSUP
, '\0', TGPOWER
, 0},
231 { "lt", TLT
, MS_LT
, TGRELATION
, 0},
232 { "magenta", TMAGENTA
, '\0', TGCOLOR
, 0},
233 { "matrix", TMATRIX
, '\0', 0, 5},
234 { "minusplus", TMINUSPLUS
, MS_MINUSPLUS
, TGUNOPER
| TGSUM
, 5},
235 { "mline", TMLINE
, MS_LINE
, 0, 0}, //! nicht in TGRBRACES, Level 0
236 { "nabla", TNABLA
, MS_NABLA
, TGSTANDALONE
, 5},
237 { "nbold", TNBOLD
, '\0', TGFONTATTR
, 5},
238 { "ndivides", TNDIVIDES
, MS_NDIVIDES
, TGRELATION
, 0},
239 { "neg", TNEG
, MS_NEG
, TGUNOPER
, 5 },
240 { "neq", TNEQ
, MS_NEQ
, TGRELATION
, 0},
241 { "newline", TNEWLINE
, '\0', 0, 0},
242 { "ni", TNI
, MS_NI
, TGRELATION
, 0},
243 { "nitalic", TNITALIC
, '\0', TGFONTATTR
, 5},
244 { "none", TNONE
, '\0', TGLBRACES
| TGRBRACES
, 0},
245 { "nospace", TNOSPACE
, '\0', TGSTANDALONE
, 5},
246 { "notin", TNOTIN
, MS_NOTIN
, TGRELATION
, 0},
247 { "nroot", TNROOT
, MS_SQRT
, TGUNOPER
, 5},
248 { "nsubset", TNSUBSET
, MS_NSUBSET
, TGRELATION
, 0 },
249 { "nsupset", TNSUPSET
, MS_NSUPSET
, TGRELATION
, 0 },
250 { "nsubseteq", TNSUBSETEQ
, MS_NSUBSETEQ
, TGRELATION
, 0 },
251 { "nsupseteq", TNSUPSETEQ
, MS_NSUPSETEQ
, TGRELATION
, 0 },
252 { "odivide", TODIVIDE
, MS_ODIVIDE
, TGPRODUCT
, 0},
253 { "odot", TODOT
, MS_ODOT
, TGPRODUCT
, 0},
254 { "ominus", TOMINUS
, MS_OMINUS
, TGSUM
, 0},
255 { "oper", TOPER
, '\0', TGOPER
, 5},
256 { "oplus", TOPLUS
, MS_OPLUS
, TGSUM
, 0},
257 { "or", TOR
, MS_OR
, TGSUM
, 0},
258 { "ortho", TORTHO
, MS_ORTHO
, TGRELATION
, 0},
259 { "otimes", TOTIMES
, MS_OTIMES
, TGPRODUCT
, 0},
260 { "over", TOVER
, '\0', TGPRODUCT
, 0},
261 { "overbrace", TOVERBRACE
, MS_OVERBRACE
, TGPRODUCT
, 5},
262 { "overline", TOVERLINE
, '\0', TGATTRIBUT
, 5},
263 { "overstrike", TOVERSTRIKE
, '\0', TGATTRIBUT
, 5},
264 { "owns", TNI
, MS_NI
, TGRELATION
, 0},
265 { "parallel", TPARALLEL
, MS_DLINE
, TGRELATION
, 0},
266 { "partial", TPARTIAL
, MS_PARTIAL
, TGSTANDALONE
, 5 },
267 { "phantom", TPHANTOM
, '\0', TGFONTATTR
, 5},
268 { "plusminus", TPLUSMINUS
, MS_PLUSMINUS
, TGUNOPER
| TGSUM
, 5},
269 { "prod", TPROD
, MS_PROD
, TGOPER
, 5},
270 { "prop", TPROP
, MS_PROP
, TGRELATION
, 0},
271 { "rangle", TRANGLE
, MS_RANGLE
, TGRBRACES
, 0}, //! 0 to terminate expression
272 { "rbrace", TRBRACE
, MS_RBRACE
, TGRBRACES
, 0}, //
273 { "rceil", TRCEIL
, MS_RCEIL
, TGRBRACES
, 0}, //
274 { "rdbracket", TRDBRACKET
, MS_RDBRACKET
, TGRBRACES
, 0}, //
275 { "rdline", TRDLINE
, MS_DLINE
, TGRBRACES
, 0}, //
276 { "red", TRED
, '\0', TGCOLOR
, 0},
277 { "rfloor", TRFLOOR
, MS_RFLOOR
, TGRBRACES
, 0}, //! 0 to terminate expression
278 { "right", TRIGHT
, '\0', 0, 0},
279 { "rightarrow" , TRIGHTARROW
, MS_RIGHTARROW
, TGSTANDALONE
, 5},
280 { "rline", TRLINE
, MS_LINE
, TGRBRACES
, 0}, //! 0 to terminate expression
281 { "rsub", TRSUB
, '\0', TGPOWER
, 0},
282 { "rsup", TRSUP
, '\0', TGPOWER
, 0},
283 { "sans", TSANS
, '\0', TGFONT
, 0},
284 { "serif", TSERIF
, '\0', TGFONT
, 0},
285 { "setC" , TSETC
, MS_SETC
, TGSTANDALONE
, 5},
286 { "setN" , TSETN
, MS_SETN
, TGSTANDALONE
, 5},
287 { "setQ" , TSETQ
, MS_SETQ
, TGSTANDALONE
, 5},
288 { "setR" , TSETR
, MS_SETR
, TGSTANDALONE
, 5},
289 { "setZ" , TSETZ
, MS_SETZ
, TGSTANDALONE
, 5},
290 { "setminus", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
291 { "sim", TSIM
, MS_SIM
, TGRELATION
, 0},
292 { "simeq", TSIMEQ
, MS_SIMEQ
, TGRELATION
, 0},
293 { "sin", TSIN
, '\0', TGFUNCTION
, 5},
294 { "sinh", TSINH
, '\0', TGFUNCTION
, 5},
295 { "size", TSIZE
, '\0', TGFONTATTR
, 5},
296 { "slash", TSLASH
, MS_SLASH
, TGPRODUCT
, 0 },
297 { "sqrt", TSQRT
, MS_SQRT
, TGUNOPER
, 5},
298 { "stack", TSTACK
, '\0', 0, 5},
299 { "sub", TRSUB
, '\0', TGPOWER
, 0},
300 { "subset", TSUBSET
, MS_SUBSET
, TGRELATION
, 0},
301 { "subseteq", TSUBSETEQ
, MS_SUBSETEQ
, TGRELATION
, 0},
302 { "sum", TSUM
, MS_SUM
, TGOPER
, 5},
303 { "sup", TRSUP
, '\0', TGPOWER
, 0},
304 { "supset", TSUPSET
, MS_SUPSET
, TGRELATION
, 0},
305 { "supseteq", TSUPSETEQ
, MS_SUPSETEQ
, TGRELATION
, 0},
306 { "tan", TTAN
, '\0', TGFUNCTION
, 5},
307 { "tanh", TTANH
, '\0', TGFUNCTION
, 5},
308 { "tilde", TTILDE
, MS_TILDE
, TGATTRIBUT
, 5},
309 { "times", TTIMES
, MS_TIMES
, TGPRODUCT
, 0},
310 { "to", TTO
, '\0', TGLIMIT
, 0},
311 { "toward", TTOWARD
, MS_RIGHTARROW
, TGRELATION
, 0},
312 { "transl", TTRANSL
, MS_TRANSL
, TGRELATION
, 0},
313 { "transr", TTRANSR
, MS_TRANSR
, TGRELATION
, 0},
314 { "underbrace", TUNDERBRACE
, MS_UNDERBRACE
, TGPRODUCT
, 5},
315 { "underline", TUNDERLINE
, '\0', TGATTRIBUT
, 5},
316 { "union", TUNION
, MS_UNION
, TGSUM
, 0},
317 { "uoper", TUOPER
, '\0', TGUNOPER
, 5},
318 { "uparrow" , TUPARROW
, MS_UPARROW
, TGSTANDALONE
, 5},
319 { "vec", TVEC
, MS_VEC
, TGATTRIBUT
, 5},
320 { "white", TWHITE
, '\0', TGCOLOR
, 0},
321 { "widebslash", TWIDEBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
322 { "widehat", TWIDEHAT
, MS_HAT
, TGATTRIBUT
, 5},
323 { "widetilde", TWIDETILDE
, MS_TILDE
, TGATTRIBUT
, 5},
324 { "wideslash", TWIDESLASH
, MS_SLASH
, TGPRODUCT
, 0 },
325 { "widevec", TWIDEVEC
, MS_VEC
, TGATTRIBUT
, 5},
326 { "wp" , TWP
, MS_WP
, TGSTANDALONE
, 5},
327 { "yellow", TYELLOW
, '\0', TGCOLOR
, 0},
328 // { "[", TLBRACKET, MS_LBRACKET, TGLBRACES, 5}, //! 5 to continue expression
329 // { "\\", TESCAPE, '\0', 0, 5},
330 // { "]", TRBRACKET, MS_RBRACKET, TGRBRACES, 0}, //! 0 to terminate expression
331 // { "^", TRSUP, '\0', TGPOWER, 0},
332 // { "_", TRSUB, '\0', TGPOWER, 0},
333 // { "`", TSBLANK, '\0', TGBLANK, 5},
334 // { "{", TLGROUP, MS_LBRACE, 0, 5}, //! 5 to continue expression
335 // { "|", TOR, MS_OR, TGSUM, 0},
336 // { "}", TRGROUP, MS_RBRACE, 0, 0}, //! 0 to terminate expression
337 // { "~", TBLANK, '\0', TGBLANK, 5},
338 { "", TEND
, '\0', 0, 0}
342 static const SmTokenTableEntry
* GetTokenTableEntry( const String
&rName
)
344 const SmTokenTableEntry
* pRes
= 0;
347 sal_Int32 nEntries
= sizeof( aTokenTable
) / sizeof( aTokenTable
[0] );
348 for (sal_Int32 i
= 0; i
< nEntries
; ++i
)
350 if (rName
.EqualsIgnoreCaseAscii( aTokenTable
[i
].pIdent
))
352 pRes
= &aTokenTable
[i
];
363 ///////////////////////////////////////////////////////////////////////////
367 sal_Bool
SmParser::IsDelimiter( const String
&rTxt
, xub_StrLen nPos
)
368 // returns 'sal_True' iff cChar is '\0' or a delimeter
370 DBG_ASSERT( nPos
<= rTxt
.Len(), "index out of range" );
372 sal_Unicode cChar
= rTxt
.GetChar( nPos
);
376 // check if 'cChar' is in the delimeter table
377 const sal_Unicode
*pDelim
= &aDelimiterTable
[0];
378 for ( ; *pDelim
!= 0; pDelim
++)
379 if (*pDelim
== cChar
)
382 sal_Bool bIsDelim
= *pDelim
!= 0;
384 sal_Int16 nTypJp
= SM_MOD()->GetSysLocale().GetCharClass().getType( rTxt
, nPos
);
385 bIsDelim
|= nTypJp
== com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR
||
386 nTypJp
== com::sun::star::i18n::UnicodeType::CONTROL
;
393 void SmParser::Insert(const String
&rText
, sal_uInt16 nPos
)
395 m_aBufferString
.Insert(rText
, nPos
);
397 xub_StrLen nLen
= rText
.Len();
398 m_nBufferIndex
= m_nBufferIndex
+ nLen
;
399 m_nTokenIndex
= m_nTokenIndex
+ nLen
;
403 void SmParser::Replace( sal_uInt16 nPos
, sal_uInt16 nLen
, const String
&rText
)
405 DBG_ASSERT( nPos
+ nLen
<= m_aBufferString
.Len(), "argument mismatch" );
407 m_aBufferString
.Replace( nPos
, nLen
, rText
);
408 sal_Int16 nChg
= rText
.Len() - nLen
;
409 m_nBufferIndex
= m_nBufferIndex
+ nChg
;
410 m_nTokenIndex
= m_nTokenIndex
+ nChg
;
414 // First character may be any alphabetic
415 const sal_Int32 coStartFlags
=
416 KParseTokens::ANY_LETTER_OR_NUMBER
|
417 KParseTokens::IGNORE_LEADING_WS
;
419 // Continuing characters may be any alphanumeric or dot.
420 const sal_Int32 coContFlags
=
421 ((coStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
)
422 | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING
;
424 // First character for numbers, may be any numeric or dot
425 const sal_Int32 coNumStartFlags
=
426 KParseTokens::ASC_DIGIT
|
427 KParseTokens::ASC_DOT
|
428 KParseTokens::IGNORE_LEADING_WS
;
429 // Continuing characters for numbers, may be any numeric or dot.
430 const sal_Int32 coNumContFlags
=
431 (coNumStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
;
433 void SmParser::NextToken()
435 static const String aEmptyStr
;
437 xub_StrLen nBufLen
= m_aBufferString
.Len();
439 xub_StrLen nRealStart
;
441 sal_Bool bNumStart
= sal_False
;
442 CharClass
aCC(SM_MOD()->GetSysLocale().GetCharClass().getLocale());
446 while (UnicodeType::SPACE_SEPARATOR
==
447 aCC
.getType( m_aBufferString
, m_nBufferIndex
))
450 sal_Int32 nStartFlags
= coStartFlags
;
451 sal_Int32 nContFlags
= coContFlags
;
452 sal_Unicode cFirstChar
= m_aBufferString
.GetChar( m_nBufferIndex
);
454 removed because of #i11752#
455 bNumStart = cFirstChar == '.' || ('0' <= cFirstChar && cFirstChar <= '9');
458 nStartFlags = coNumStartFlags;
459 nContFlags = coNumContFlags;
462 aRes
= aCC
.parseAnyToken( m_aBufferString
, m_nBufferIndex
,
463 nStartFlags
, aEmptyStr
,
464 nContFlags
, aEmptyStr
);
466 // #i45779# parse numbers correctly
467 // i.e. independent from the locale setting.
468 // (note that #i11752# remains fixed)
469 if ((aRes
.TokenType
& KParseType::IDENTNAME
) && IsDigit( cFirstChar
))
471 //! locale where '.' is decimal seperator!
472 static lang::Locale
aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US
) );
475 lang::Locale
aOldLoc( aCC
.getLocale() );
476 aCC
.setLocale( aDotLoc
);
477 aTmpRes
= aCC
.parsePredefinedToken(
478 KParseType::ASC_NUMBER
,
479 m_aBufferString
, m_nBufferIndex
,
480 KParseTokens::ASC_DIGIT
, aEmptyStr
,
481 KParseTokens::ASC_DIGIT
| KParseTokens::ASC_DOT
, aEmptyStr
);
482 aCC
.setLocale( aOldLoc
);
483 if (aTmpRes
.TokenType
& KParseType::ASC_NUMBER
)
484 aRes
.TokenType
= aTmpRes
.TokenType
;
487 nRealStart
= m_nBufferIndex
+ sal::static_int_cast
< xub_StrLen
>(aRes
.LeadingWhiteSpace
);
488 m_nBufferIndex
= nRealStart
;
491 if ( aRes
.TokenType
== 0 &&
492 nRealStart
< nBufLen
&&
493 '\n' == m_aBufferString
.GetChar( nRealStart
) )
495 // keep data needed for tokens row and col entry up to date
497 m_nBufferIndex
= m_nColOff
= nRealStart
+ 1;
500 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
502 String
aName( m_aBufferString
.Copy( nRealStart
, 2 ));
503 if ( aName
.EqualsAscii( "%%" ))
506 m_nBufferIndex
= nRealStart
+ 2;
507 while (m_nBufferIndex
< nBufLen
&&
508 '\n' != m_aBufferString
.GetChar( m_nBufferIndex
))
516 // set index of current token
517 m_nTokenIndex
= m_nBufferIndex
;
519 m_aCurToken
.nRow
= m_Row
;
520 m_aCurToken
.nCol
= nRealStart
- m_nColOff
+ 1;
522 sal_Bool bHandled
= sal_True
;
523 if (nRealStart
>= nBufLen
)
525 m_aCurToken
.eType
= TEND
;
526 m_aCurToken
.cMathChar
= '\0';
527 m_aCurToken
.nGroup
= 0;
528 m_aCurToken
.nLevel
= 0;
529 m_aCurToken
.aText
.Erase();
531 else if ((aRes
.TokenType
& (KParseType::ASC_NUMBER
| KParseType::UNI_NUMBER
))
532 || (bNumStart
&& (aRes
.TokenType
& KParseType::IDENTNAME
)))
534 sal_Int32 n
= aRes
.EndPos
- nRealStart
;
535 DBG_ASSERT( n
>= 0, "length < 0" );
536 m_aCurToken
.eType
= TNUMBER
;
537 m_aCurToken
.cMathChar
= '\0';
538 m_aCurToken
.nGroup
= 0;
539 m_aCurToken
.nLevel
= 5;
540 m_aCurToken
.aText
= m_aBufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) );
542 #if OSL_DEBUG_LEVEL > 1
543 if (!IsDelimiter( m_aBufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
545 DBG_WARNING( "identifier really finished? (compatibility!)" );
549 else if (aRes
.TokenType
& KParseType::DOUBLE_QUOTE_STRING
)
551 m_aCurToken
.eType
= TTEXT
;
552 m_aCurToken
.cMathChar
= '\0';
553 m_aCurToken
.nGroup
= 0;
554 m_aCurToken
.nLevel
= 5;
555 m_aCurToken
.aText
= aRes
.DequotedNameOrString
;
556 m_aCurToken
.nRow
= m_Row
;
557 m_aCurToken
.nCol
= nRealStart
- m_nColOff
+ 2;
559 else if (aRes
.TokenType
& KParseType::IDENTNAME
)
561 sal_Int32 n
= aRes
.EndPos
- nRealStart
;
562 DBG_ASSERT( n
>= 0, "length < 0" );
563 String
aName( m_aBufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) ) );
564 const SmTokenTableEntry
*pEntry
= GetTokenTableEntry( aName
);
568 m_aCurToken
.eType
= pEntry
->eType
;
569 m_aCurToken
.cMathChar
= pEntry
->cMathChar
;
570 m_aCurToken
.nGroup
= pEntry
->nGroup
;
571 m_aCurToken
.nLevel
= pEntry
->nLevel
;
572 m_aCurToken
.aText
.AssignAscii( pEntry
->pIdent
);
576 m_aCurToken
.eType
= TIDENT
;
577 m_aCurToken
.cMathChar
= '\0';
578 m_aCurToken
.nGroup
= 0;
579 m_aCurToken
.nLevel
= 5;
580 m_aCurToken
.aText
= aName
;
582 #if OSL_DEBUG_LEVEL > 1
583 if (!IsDelimiter( m_aBufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
585 DBG_WARNING( "identifier really finished? (compatibility!)" );
590 else if (aRes
.TokenType
== 0 && '_' == m_aBufferString
.GetChar( nRealStart
))
592 m_aCurToken
.eType
= TRSUB
;
593 m_aCurToken
.cMathChar
= '\0';
594 m_aCurToken
.nGroup
= TGPOWER
;
595 m_aCurToken
.nLevel
= 0;
596 m_aCurToken
.aText
.AssignAscii( "_" );
598 aRes
.EndPos
= nRealStart
+ 1;
600 else if (aRes
.TokenType
& KParseType::BOOLEAN
)
602 sal_Int32
&rnEndPos
= aRes
.EndPos
;
603 String
aName( m_aBufferString
.Copy( nRealStart
,
604 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ));
605 if (2 >= aName
.Len())
607 sal_Unicode ch
= aName
.GetChar( 0 );
612 if (m_aBufferString
.Copy( nRealStart
, 2 ).
615 m_aCurToken
.eType
= TLL
;
616 m_aCurToken
.cMathChar
= MS_LL
;
617 m_aCurToken
.nGroup
= TGRELATION
;
618 m_aCurToken
.nLevel
= 0;
619 m_aCurToken
.aText
.AssignAscii( "<<" );
621 rnEndPos
= nRealStart
+ 2;
623 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
626 m_aCurToken
.eType
= TLE
;
627 m_aCurToken
.cMathChar
= MS_LE
;
628 m_aCurToken
.nGroup
= TGRELATION
;
629 m_aCurToken
.nLevel
= 0;
630 m_aCurToken
.aText
.AssignAscii( "<=" );
632 rnEndPos
= nRealStart
+ 2;
634 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
637 m_aCurToken
.eType
= TNEQ
;
638 m_aCurToken
.cMathChar
= MS_NEQ
;
639 m_aCurToken
.nGroup
= TGRELATION
;
640 m_aCurToken
.nLevel
= 0;
641 m_aCurToken
.aText
.AssignAscii( "<>" );
643 rnEndPos
= nRealStart
+ 2;
645 else if (m_aBufferString
.Copy( nRealStart
, 3 ).
646 EqualsAscii( "<?>" ))
648 m_aCurToken
.eType
= TPLACE
;
649 m_aCurToken
.cMathChar
= MS_PLACE
;
650 m_aCurToken
.nGroup
= 0;
651 m_aCurToken
.nLevel
= 5;
652 m_aCurToken
.aText
.AssignAscii( "<?>" );
654 rnEndPos
= nRealStart
+ 3;
658 m_aCurToken
.eType
= TLT
;
659 m_aCurToken
.cMathChar
= MS_LT
;
660 m_aCurToken
.nGroup
= TGRELATION
;
661 m_aCurToken
.nLevel
= 0;
662 m_aCurToken
.aText
.AssignAscii( "<" );
668 if (m_aBufferString
.Copy( nRealStart
, 2 ).
671 m_aCurToken
.eType
= TGE
;
672 m_aCurToken
.cMathChar
= MS_GE
;
673 m_aCurToken
.nGroup
= TGRELATION
;
674 m_aCurToken
.nLevel
= 0;
675 m_aCurToken
.aText
.AssignAscii( ">=" );
677 rnEndPos
= nRealStart
+ 2;
679 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
682 m_aCurToken
.eType
= TGG
;
683 m_aCurToken
.cMathChar
= MS_GG
;
684 m_aCurToken
.nGroup
= TGRELATION
;
685 m_aCurToken
.nLevel
= 0;
686 m_aCurToken
.aText
.AssignAscii( ">>" );
688 rnEndPos
= nRealStart
+ 2;
692 m_aCurToken
.eType
= TGT
;
693 m_aCurToken
.cMathChar
= MS_GT
;
694 m_aCurToken
.nGroup
= TGRELATION
;
695 m_aCurToken
.nLevel
= 0;
696 m_aCurToken
.aText
.AssignAscii( ">" );
701 bHandled
= sal_False
;
705 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
707 sal_Int32
&rnEndPos
= aRes
.EndPos
;
708 String
aName( m_aBufferString
.Copy( nRealStart
,
709 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ) );
711 if (1 == aName
.Len())
713 sal_Unicode ch
= aName
.GetChar( 0 );
718 //! modifies aRes.EndPos
720 DBG_ASSERT( rnEndPos
>= nBufLen
||
721 '%' != m_aBufferString
.GetChar( sal::static_int_cast
< xub_StrLen
>(rnEndPos
) ),
722 "unexpected comment start" );
724 // get identifier of user-defined character
725 ParseResult aTmpRes
= aCC
.parseAnyToken(
726 m_aBufferString
, rnEndPos
,
727 KParseTokens::ANY_LETTER
,
732 xub_StrLen nTmpStart
= sal::static_int_cast
< xub_StrLen
>(rnEndPos
+
733 aTmpRes
.LeadingWhiteSpace
);
735 // default setting for the case that no identifier
736 // i.e. a valid symbol-name is following the '%'
738 m_aCurToken
.eType
= TTEXT
;
739 m_aCurToken
.cMathChar
= '\0';
740 m_aCurToken
.nGroup
= 0;
741 m_aCurToken
.nLevel
= 5;
742 m_aCurToken
.aText
= String();
743 m_aCurToken
.nRow
= sal::static_int_cast
< xub_StrLen
>(m_Row
);
744 m_aCurToken
.nCol
= nTmpStart
- m_nColOff
;
746 if (aTmpRes
.TokenType
& KParseType::IDENTNAME
)
749 xub_StrLen n
= sal::static_int_cast
< xub_StrLen
>(aTmpRes
.EndPos
- nTmpStart
);
750 m_aCurToken
.eType
= TSPECIAL
;
751 m_aCurToken
.aText
= m_aBufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTmpStart
-1), n
+1 );
753 DBG_ASSERT( aTmpRes
.EndPos
> rnEndPos
,
754 "empty identifier" );
755 if (aTmpRes
.EndPos
> rnEndPos
)
756 rnEndPos
= aTmpRes
.EndPos
;
761 // if no symbol-name was found we start-over with
762 // finding the next token right afer the '%' sign.
763 // I.e. we leave rnEndPos unmodified.
768 m_aCurToken
.eType
= TLBRACKET
;
769 m_aCurToken
.cMathChar
= MS_LBRACKET
;
770 m_aCurToken
.nGroup
= TGLBRACES
;
771 m_aCurToken
.nLevel
= 5;
772 m_aCurToken
.aText
.AssignAscii( "[" );
777 m_aCurToken
.eType
= TESCAPE
;
778 m_aCurToken
.cMathChar
= '\0';
779 m_aCurToken
.nGroup
= 0;
780 m_aCurToken
.nLevel
= 5;
781 m_aCurToken
.aText
.AssignAscii( "\\" );
786 m_aCurToken
.eType
= TRBRACKET
;
787 m_aCurToken
.cMathChar
= MS_RBRACKET
;
788 m_aCurToken
.nGroup
= TGRBRACES
;
789 m_aCurToken
.nLevel
= 0;
790 m_aCurToken
.aText
.AssignAscii( "]" );
795 m_aCurToken
.eType
= TRSUP
;
796 m_aCurToken
.cMathChar
= '\0';
797 m_aCurToken
.nGroup
= TGPOWER
;
798 m_aCurToken
.nLevel
= 0;
799 m_aCurToken
.aText
.AssignAscii( "^" );
804 m_aCurToken
.eType
= TSBLANK
;
805 m_aCurToken
.cMathChar
= '\0';
806 m_aCurToken
.nGroup
= TGBLANK
;
807 m_aCurToken
.nLevel
= 5;
808 m_aCurToken
.aText
.AssignAscii( "`" );
813 m_aCurToken
.eType
= TLGROUP
;
814 m_aCurToken
.cMathChar
= MS_LBRACE
;
815 m_aCurToken
.nGroup
= 0;
816 m_aCurToken
.nLevel
= 5;
817 m_aCurToken
.aText
.AssignAscii( "{" );
822 m_aCurToken
.eType
= TOR
;
823 m_aCurToken
.cMathChar
= MS_OR
;
824 m_aCurToken
.nGroup
= TGSUM
;
825 m_aCurToken
.nLevel
= 0;
826 m_aCurToken
.aText
.AssignAscii( "|" );
831 m_aCurToken
.eType
= TRGROUP
;
832 m_aCurToken
.cMathChar
= MS_RBRACE
;
833 m_aCurToken
.nGroup
= 0;
834 m_aCurToken
.nLevel
= 0;
835 m_aCurToken
.aText
.AssignAscii( "}" );
840 m_aCurToken
.eType
= TBLANK
;
841 m_aCurToken
.cMathChar
= '\0';
842 m_aCurToken
.nGroup
= TGBLANK
;
843 m_aCurToken
.nLevel
= 5;
844 m_aCurToken
.aText
.AssignAscii( "~" );
849 if (m_aBufferString
.Copy( nRealStart
, 2 ).
852 m_aCurToken
.eType
= TDPOUND
;
853 m_aCurToken
.cMathChar
= '\0';
854 m_aCurToken
.nGroup
= 0;
855 m_aCurToken
.nLevel
= 0;
856 m_aCurToken
.aText
.AssignAscii( "##" );
858 rnEndPos
= nRealStart
+ 2;
862 m_aCurToken
.eType
= TPOUND
;
863 m_aCurToken
.cMathChar
= '\0';
864 m_aCurToken
.nGroup
= 0;
865 m_aCurToken
.nLevel
= 0;
866 m_aCurToken
.aText
.AssignAscii( "#" );
872 m_aCurToken
.eType
= TAND
;
873 m_aCurToken
.cMathChar
= MS_AND
;
874 m_aCurToken
.nGroup
= TGPRODUCT
;
875 m_aCurToken
.nLevel
= 0;
876 m_aCurToken
.aText
.AssignAscii( "&" );
881 m_aCurToken
.eType
= TLPARENT
;
882 m_aCurToken
.cMathChar
= MS_LPARENT
;
883 m_aCurToken
.nGroup
= TGLBRACES
;
884 m_aCurToken
.nLevel
= 5; //! 0 to continue expression
885 m_aCurToken
.aText
.AssignAscii( "(" );
890 m_aCurToken
.eType
= TRPARENT
;
891 m_aCurToken
.cMathChar
= MS_RPARENT
;
892 m_aCurToken
.nGroup
= TGRBRACES
;
893 m_aCurToken
.nLevel
= 0; //! 0 to terminate expression
894 m_aCurToken
.aText
.AssignAscii( ")" );
899 m_aCurToken
.eType
= TMULTIPLY
;
900 m_aCurToken
.cMathChar
= MS_MULTIPLY
;
901 m_aCurToken
.nGroup
= TGPRODUCT
;
902 m_aCurToken
.nLevel
= 0;
903 m_aCurToken
.aText
.AssignAscii( "*" );
908 if (m_aBufferString
.Copy( nRealStart
, 2 ).
911 m_aCurToken
.eType
= TPLUSMINUS
;
912 m_aCurToken
.cMathChar
= MS_PLUSMINUS
;
913 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
914 m_aCurToken
.nLevel
= 5;
915 m_aCurToken
.aText
.AssignAscii( "+-" );
917 rnEndPos
= nRealStart
+ 2;
921 m_aCurToken
.eType
= TPLUS
;
922 m_aCurToken
.cMathChar
= MS_PLUS
;
923 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
924 m_aCurToken
.nLevel
= 5;
925 m_aCurToken
.aText
.AssignAscii( "+" );
931 if (m_aBufferString
.Copy( nRealStart
, 2 ).
934 m_aCurToken
.eType
= TMINUSPLUS
;
935 m_aCurToken
.cMathChar
= MS_MINUSPLUS
;
936 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
937 m_aCurToken
.nLevel
= 5;
938 m_aCurToken
.aText
.AssignAscii( "-+" );
940 rnEndPos
= nRealStart
+ 2;
944 m_aCurToken
.eType
= TMINUS
;
945 m_aCurToken
.cMathChar
= MS_MINUS
;
946 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
947 m_aCurToken
.nLevel
= 5;
948 m_aCurToken
.aText
.AssignAscii( "-" );
954 // for compatibility with SO5.2
955 // texts like .34 ...56 ... h ...78..90
956 // will be treated as numbers
957 m_aCurToken
.eType
= TNUMBER
;
958 m_aCurToken
.cMathChar
= '\0';
959 m_aCurToken
.nGroup
= 0;
960 m_aCurToken
.nLevel
= 5;
962 xub_StrLen nTxtStart
= m_nBufferIndex
;
966 cChar
= m_aBufferString
.GetChar( ++m_nBufferIndex
);
968 while ( cChar
== '.' || IsDigit( cChar
) );
970 m_aCurToken
.aText
= m_aBufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTxtStart
),
971 sal::static_int_cast
< xub_StrLen
>(m_nBufferIndex
- nTxtStart
) );
972 aRes
.EndPos
= m_nBufferIndex
;
977 m_aCurToken
.eType
= TDIVIDEBY
;
978 m_aCurToken
.cMathChar
= MS_SLASH
;
979 m_aCurToken
.nGroup
= TGPRODUCT
;
980 m_aCurToken
.nLevel
= 0;
981 m_aCurToken
.aText
.AssignAscii( "/" );
986 m_aCurToken
.eType
= TASSIGN
;
987 m_aCurToken
.cMathChar
= MS_ASSIGN
;
988 m_aCurToken
.nGroup
= TGRELATION
;
989 m_aCurToken
.nLevel
= 0;
990 m_aCurToken
.aText
.AssignAscii( "=" );
994 bHandled
= sal_False
;
999 bHandled
= sal_False
;
1003 m_aCurToken
.eType
= TCHARACTER
;
1004 m_aCurToken
.cMathChar
= '\0';
1005 m_aCurToken
.nGroup
= 0;
1006 m_aCurToken
.nLevel
= 5;
1007 m_aCurToken
.aText
= m_aBufferString
.Copy( nRealStart
, 1 );
1009 aRes
.EndPos
= nRealStart
+ 1;
1012 if (TEND
!= m_aCurToken
.eType
)
1013 m_nBufferIndex
= sal::static_int_cast
< xub_StrLen
>(aRes
.EndPos
);
1017 ////////////////////////////////////////
1022 void SmParser::Table()
1024 SmNodeArray LineArray
;
1027 while (m_aCurToken
.eType
== TNEWLINE
)
1033 if (m_aCurToken
.eType
!= TEND
)
1034 Error(PE_UNEXPECTED_CHAR
);
1036 sal_uLong n
= m_aNodeStack
.Count();
1038 LineArray
.resize(n
);
1040 for (sal_uLong i
= 0; i
< n
; i
++)
1041 LineArray
[n
- (i
+ 1)] = m_aNodeStack
.Pop();
1043 SmStructureNode
*pSNode
= new SmTableNode(m_aCurToken
);
1044 pSNode
->SetSubNodes(LineArray
);
1045 m_aNodeStack
.Push(pSNode
);
1049 void SmParser::Align()
1050 // parse alignment info (if any), then go on with rest of expression
1052 SmStructureNode
*pSNode
= 0;
1053 sal_Bool bNeedGroupClose
= sal_False
;
1055 if (TokenInGroup(TGALIGN
))
1057 if (CONVERT_40_TO_50
== GetConversion())
1058 // encapsulate expression to be aligned in group braces
1059 // (here group-open brace)
1060 { Insert('{', GetTokenIndex());
1061 bNeedGroupClose
= sal_True
;
1063 // get first valid align statement in sequence
1064 // (the dominant one in 4.0) and erase all others (especially old
1065 // discarded tokens) from command string.
1066 while (TokenInGroup(TGALIGN
))
1068 if (TokenInGroup(TGDISCARDED
) || pSNode
)
1070 m_nBufferIndex
= GetTokenIndex();
1071 m_aBufferString
.Erase(m_nBufferIndex
, m_aCurToken
.aText
.Len());
1074 pSNode
= new SmAlignNode(m_aCurToken
);
1081 pSNode
= new SmAlignNode(m_aCurToken
);
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(m_aNodeStack
.Pop(), 0);
1100 m_aNodeStack
.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 (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TNEWLINE
)
1117 ExpressionArray
.resize(++n
);
1118 ExpressionArray
[n
- 1] = m_aNodeStack
.Pop();
1121 while (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TNEWLINE
)
1122 { if (CONVERT_40_TO_50
!= GetConversion())
1126 ExpressionArray
.resize(++n
);
1127 ExpressionArray
[n
- 1] = m_aNodeStack
.Pop();
1130 SmStructureNode
*pSNode
= new SmLineNode(m_aCurToken
);
1131 pSNode
->SetSubNodes(ExpressionArray
);
1132 m_aNodeStack
.Push(pSNode
);
1136 void SmParser::Expression()
1138 sal_Bool bUseExtraSpaces
= sal_True
;
1139 SmNode
*pNode
= m_aNodeStack
.Pop();
1142 if (pNode
->GetToken().eType
== TNOSPACE
)
1143 bUseExtraSpaces
= sal_False
;
1145 m_aNodeStack
.Push(pNode
); // push the node from above again (now to be used as argument to this current 'nospace' node)
1149 SmNodeArray RelationArray
;
1151 RelationArray
.resize(n
);
1154 RelationArray
.resize(++n
);
1155 RelationArray
[n
- 1] = m_aNodeStack
.Pop();
1157 while (m_aCurToken
.nLevel
>= 4)
1159 RelationArray
.resize(++n
);
1160 RelationArray
[n
- 1] = m_aNodeStack
.Pop();
1163 SmExpressionNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
1164 pSNode
->SetSubNodes(RelationArray
);
1165 pSNode
->SetUseExtraSpaces(bUseExtraSpaces
);
1166 m_aNodeStack
.Push(pSNode
);
1170 void SmParser::Relation()
1173 while (TokenInGroup(TGRELATION
))
1175 SmStructureNode
*pSNode
= new SmBinHorNode(m_aCurToken
);
1176 SmNode
*pFirst
= m_aNodeStack
.Pop();
1179 SmNode
*pSecond
= m_aNodeStack
.Pop();
1183 pSNode
->SetSubNodes(pFirst
, pSecond
, m_aNodeStack
.Pop());
1184 m_aNodeStack
.Push(pSNode
);
1189 void SmParser::Sum()
1192 while (TokenInGroup(TGSUM
))
1194 SmStructureNode
*pSNode
= new SmBinHorNode(m_aCurToken
);
1195 SmNode
*pFirst
= m_aNodeStack
.Pop();
1198 SmNode
*pSecond
= m_aNodeStack
.Pop();
1202 pSNode
->SetSubNodes(pFirst
, pSecond
, m_aNodeStack
.Pop());
1203 m_aNodeStack
.Push(pSNode
);
1208 void SmParser::Product()
1212 while (TokenInGroup(TGPRODUCT
))
1213 { SmStructureNode
*pSNode
;
1214 SmNode
*pFirst
= m_aNodeStack
.Pop(),
1216 sal_Bool bSwitchArgs
= sal_False
;
1218 SmTokenType eType
= m_aCurToken
.eType
;
1222 pSNode
= new SmBinVerNode(m_aCurToken
);
1223 pOper
= new SmRectangleNode(m_aCurToken
);
1228 pSNode
= new SmBinHorNode(m_aCurToken
);
1233 pOper
= m_aNodeStack
.Pop();
1238 pSNode
= new SmVerticalBraceNode(m_aCurToken
);
1239 pOper
= new SmMathSymbolNode(m_aCurToken
);
1244 case TWIDEBACKSLASH
:
1247 SmBinDiagonalNode
*pSTmp
= new SmBinDiagonalNode(m_aCurToken
);
1248 pSTmp
->SetAscending(eType
== TWIDESLASH
);
1251 pOper
= new SmPolyLineNode(m_aCurToken
);
1254 bSwitchArgs
=sal_True
;
1259 pSNode
= new SmBinHorNode(m_aCurToken
);
1262 pOper
= m_aNodeStack
.Pop();
1268 //! vgl siehe SmBinDiagonalNode::Arrange
1269 pSNode
->SetSubNodes(pFirst
, m_aNodeStack
.Pop(), pOper
);
1271 pSNode
->SetSubNodes(pFirst
, pOper
, m_aNodeStack
.Pop());
1272 m_aNodeStack
.Push(pSNode
);
1277 void SmParser::SubSup(sal_uLong nActiveGroup
)
1279 DBG_ASSERT(nActiveGroup
== TGPOWER
|| nActiveGroup
== TGLIMIT
,
1280 "Sm: falsche Tokengruppe");
1282 if (!TokenInGroup(nActiveGroup
))
1286 SmSubSupNode
*pNode
= new SmSubSupNode(m_aCurToken
);
1287 //! Of course 'm_aCurToken' is just the first sub-/supscript token.
1288 //! It should be of no further interest. The positions of the
1289 //! sub-/supscripts will be identified by the corresponding subnodes
1290 //! index in the 'aSubNodes' array (enum value from 'SmSubSup').
1292 pNode
->SetUseLimits(nActiveGroup
== TGLIMIT
);
1294 // initialize subnodes array
1295 SmNodeArray aSubNodes
;
1296 aSubNodes
.resize(1 + SUBSUP_NUM_ENTRIES
);
1297 aSubNodes
[0] = m_aNodeStack
.Pop();
1298 for (sal_uInt16 i
= 1; i
< aSubNodes
.size(); i
++)
1299 aSubNodes
[i
] = NULL
;
1301 // process all sub-/supscripts
1303 while (TokenInGroup(nActiveGroup
))
1304 { SmTokenType
eType (m_aCurToken
.eType
);
1306 // skip sub-/supscript token
1309 // get sub-/supscript node on top of stack
1310 if (eType
== TFROM
|| eType
== TTO
)
1312 // parse limits in old 4.0 and 5.0 style
1319 { case TRSUB
: nIndex
= (int) RSUB
; break;
1320 case TRSUP
: nIndex
= (int) RSUP
; break;
1322 case TCSUB
: nIndex
= (int) CSUB
; break;
1324 case TCSUP
: nIndex
= (int) CSUP
; break;
1325 case TLSUB
: nIndex
= (int) LSUB
; break;
1326 case TLSUP
: nIndex
= (int) LSUP
; break;
1328 DBG_ASSERT(sal_False
, "Sm: unbekannter Fall");
1331 DBG_ASSERT(1 <= nIndex
&& nIndex
<= 1 + SUBSUP_NUM_ENTRIES
,
1332 "SmParser::Power() : sub-/supscript index falsch");
1334 // set sub-/supscript if not already done
1335 if (aSubNodes
[nIndex
] != NULL
)
1336 Error(PE_DOUBLE_SUBSUPSCRIPT
);
1337 aSubNodes
[nIndex
] = m_aNodeStack
.Pop();
1340 pNode
->SetSubNodes(aSubNodes
);
1341 m_aNodeStack
.Push(pNode
);
1345 void SmParser::OpSubSup()
1347 // push operator symbol
1348 m_aNodeStack
.Push(new SmMathSymbolNode(m_aCurToken
));
1349 // skip operator token
1351 // get sub- supscripts if any
1352 if (TokenInGroup(TGPOWER
))
1357 void SmParser::Power()
1359 // get body for sub- supscripts on top of stack
1366 void SmParser::Blank()
1368 DBG_ASSERT(TokenInGroup(TGBLANK
), "Sm : falsches Token");
1369 SmBlankNode
*pBlankNode
= new SmBlankNode(m_aCurToken
);
1371 while (TokenInGroup(TGBLANK
))
1373 pBlankNode
->IncreaseBy(m_aCurToken
);
1377 // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist
1378 if ( m_aCurToken
.eType
== TNEWLINE
||
1379 (m_aCurToken
.eType
== TEND
&& SM_MOD()->GetConfig()->IsIgnoreSpacesRight()) )
1381 pBlankNode
->Clear();
1384 m_aNodeStack
.Push(pBlankNode
);
1388 void SmParser::Term()
1390 switch (m_aCurToken
.eType
)
1399 bool bNoSpace
= m_aCurToken
.eType
== TNOSPACE
;
1400 if (bNoSpace
) // push 'no space' node and continue to parse expression
1402 m_aNodeStack
.Push(new SmExpressionNode(m_aCurToken
));
1405 if (m_aCurToken
.eType
!= TLGROUP
)
1407 m_aNodeStack
.Pop(); // get rid of the 'no space' node pushed above
1414 // allow for empty group
1415 if (m_aCurToken
.eType
== TRGROUP
)
1417 if (bNoSpace
) // get rid of the 'no space' node pushed above
1419 SmStructureNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
1420 pSNode
->SetSubNodes(NULL
, NULL
);
1421 m_aNodeStack
.Push(pSNode
);
1428 if (m_aCurToken
.eType
!= TRGROUP
)
1429 Error(PE_RGROUP_EXPECTED
);
1447 m_aNodeStack
.Push(new SmTextNode(m_aCurToken
, FNT_TEXT
));
1452 m_aNodeStack
.Push(new SmTextNode(m_aCurToken
, FNT_VARIABLE
));
1456 m_aNodeStack
.Push(new SmTextNode(m_aCurToken
, FNT_NUMBER
));
1493 m_aNodeStack
.Push(new SmMathSymbolNode(m_aCurToken
));
1498 m_aNodeStack
.Push(new SmPlaceNode(m_aCurToken
));
1519 if (TokenInGroup(TGLBRACES
))
1522 else if (TokenInGroup(TGOPER
))
1525 else if (TokenInGroup(TGUNOPER
))
1528 else if ( TokenInGroup(TGATTRIBUT
)
1529 || TokenInGroup(TGFONTATTR
))
1530 { SmStructureNodeArray aArray
;
1534 while (sal_True
== (bIsAttr
= TokenInGroup(TGATTRIBUT
))
1535 || TokenInGroup(TGFONTATTR
))
1536 { aArray
.resize(n
+ 1);
1543 // check if casting in following line is ok
1544 DBG_ASSERT(!m_aNodeStack
.Top()->IsVisible(), "Sm : Ooops...");
1546 aArray
[n
] = (SmStructureNode
*) m_aNodeStack
.Pop();
1552 SmNode
*pFirstNode
= m_aNodeStack
.Pop();
1554 { aArray
[n
- 1]->SetSubNodes(0, pFirstNode
);
1555 pFirstNode
= aArray
[n
- 1];
1558 m_aNodeStack
.Push(pFirstNode
);
1560 else if (TokenInGroup(TGFUNCTION
))
1561 { if (CONVERT_40_TO_50
!= GetConversion())
1564 else // encapsulate old 4.0 style parsing in braces
1566 // insert opening brace
1567 Insert('{', GetTokenIndex());
1570 // parse in 4.0 style
1574 SmNode
*pFunc
= m_aNodeStack
.Pop();
1576 if (m_aCurToken
.eType
== TLPARENT
)
1583 // insert closing brace
1584 Insert('}', GetTokenIndex());
1586 SmStructureNode
*pSNode
= new SmExpressionNode(pFunc
->GetToken());
1587 pSNode
->SetSubNodes(pFunc
, m_aNodeStack
.Pop());
1588 m_aNodeStack
.Push(pSNode
);
1592 Error(PE_UNEXPECTED_CHAR
);
1597 void SmParser::Escape()
1602 switch (m_aCurToken
.eType
)
1603 { case TLPARENT
: cChar
= MS_LPARENT
; break;
1604 case TRPARENT
: cChar
= MS_RPARENT
; break;
1605 case TLBRACKET
: cChar
= MS_LBRACKET
; break;
1606 case TRBRACKET
: cChar
= MS_RBRACKET
; break;
1607 case TLDBRACKET
: cChar
= MS_LDBRACKET
; break;
1608 case TRDBRACKET
: cChar
= MS_RDBRACKET
; break;
1610 case TLGROUP
: cChar
= MS_LBRACE
; break;
1612 case TRGROUP
: cChar
= MS_RBRACE
; break;
1613 case TLANGLE
: cChar
= MS_LANGLE
; break;
1614 case TRANGLE
: cChar
= MS_RANGLE
; break;
1615 case TLCEIL
: cChar
= MS_LCEIL
; break;
1616 case TRCEIL
: cChar
= MS_RCEIL
; break;
1617 case TLFLOOR
: cChar
= MS_LFLOOR
; break;
1618 case TRFLOOR
: cChar
= MS_RFLOOR
; break;
1620 case TRLINE
: cChar
= MS_LINE
; break;
1622 case TRDLINE
: cChar
= MS_DLINE
; break;
1624 Error(PE_UNEXPECTED_TOKEN
);
1627 SmNode
*pNode
= new SmMathSymbolNode(m_aCurToken
);
1628 m_aNodeStack
.Push(pNode
);
1634 void SmParser::Operator()
1636 if (TokenInGroup(TGOPER
))
1637 { SmStructureNode
*pSNode
= new SmOperNode(m_aCurToken
);
1639 // put operator on top of stack
1642 if (TokenInGroup(TGLIMIT
) || TokenInGroup(TGPOWER
))
1643 SubSup(m_aCurToken
.nGroup
);
1644 SmNode
*pOperator
= m_aNodeStack
.Pop();
1649 pSNode
->SetSubNodes(pOperator
, m_aNodeStack
.Pop());
1650 m_aNodeStack
.Push(pSNode
);
1655 void SmParser::Oper()
1657 SmTokenType
eType (m_aCurToken
.eType
);
1658 SmNode
*pNode
= NULL
;
1671 pNode
= new SmMathSymbolNode(m_aCurToken
);
1678 const sal_Char
* pLim
= 0;
1681 case TLIM
: pLim
= "lim"; break;
1682 case TLIMSUP
: pLim
= "lim sup"; break;
1683 case TLIMINF
: pLim
= "lim inf"; break;
1688 m_aCurToken
.aText
.AssignAscii( pLim
);
1689 pNode
= new SmTextNode(m_aCurToken
, FNT_TEXT
);
1695 pNode
= new SmMathSymbolNode(m_aCurToken
);
1701 DBG_ASSERT(m_aCurToken
.eType
== TSPECIAL
, "Sm: falsches Token");
1702 pNode
= new SmGlyphSpecialNode(m_aCurToken
);
1706 DBG_ASSERT(0, "Sm: unbekannter Fall");
1708 m_aNodeStack
.Push(pNode
);
1714 void SmParser::UnOper()
1716 DBG_ASSERT(TokenInGroup(TGUNOPER
), "Sm: falsches Token");
1718 SmToken aNodeToken
= m_aCurToken
;
1719 SmTokenType eType
= m_aCurToken
.eType
;
1720 sal_Bool bIsPostfix
= eType
== TFACT
;
1722 SmStructureNode
*pSNode
;
1737 pExtra
= m_aNodeStack
.Pop();
1743 pOper
= m_aNodeStack
.Pop();
1753 pOper
= m_aNodeStack
.Pop();
1757 Error(PE_UNOPER_EXPECTED
);
1762 pArg
= m_aNodeStack
.Pop();
1765 { pSNode
= new SmBraceNode(aNodeToken
);
1766 pSNode
->SetScaleMode(SCALE_HEIGHT
);
1768 // build nodes for left & right lines
1769 // (text, group, level of the used token are of no interrest here)
1770 // we'll use row & column of the keyword for abs
1771 aNodeToken
.eType
= TABS
;
1773 aNodeToken
.cMathChar
= MS_LINE
;
1774 SmNode
* pLeft
= new SmMathSymbolNode(aNodeToken
);
1776 aNodeToken
.cMathChar
= MS_LINE
;
1777 SmNode
* pRight
= new SmMathSymbolNode(aNodeToken
);
1779 pSNode
->SetSubNodes(pLeft
, pArg
, pRight
);
1781 else if (eType
== TSQRT
|| eType
== TNROOT
)
1782 { pSNode
= new SmRootNode(aNodeToken
);
1783 pOper
= new SmRootSymbolNode(aNodeToken
);
1784 pSNode
->SetSubNodes(pExtra
, pOper
, pArg
);
1787 { pSNode
= new SmUnHorNode(aNodeToken
);
1790 pSNode
->SetSubNodes(pArg
, pOper
);
1793 pSNode
->SetSubNodes(pOper
, pArg
);
1796 m_aNodeStack
.Push(pSNode
);
1800 void SmParser::Attribut()
1802 DBG_ASSERT(TokenInGroup(TGATTRIBUT
), "Sm: falsche Tokengruppe");
1804 SmStructureNode
*pSNode
= new SmAttributNode(m_aCurToken
);
1806 SmScaleMode eScaleMode
= SCALE_NONE
;
1808 // get appropriate node for the attribut itself
1809 switch (m_aCurToken
.eType
)
1813 pAttr
= new SmRectangleNode(m_aCurToken
);
1814 eScaleMode
= SCALE_WIDTH
;
1820 pAttr
= new SmMathSymbolNode(m_aCurToken
);
1821 eScaleMode
= SCALE_WIDTH
;
1825 pAttr
= new SmMathSymbolNode(m_aCurToken
);
1830 pSNode
->SetSubNodes(pAttr
, 0);
1831 pSNode
->SetScaleMode(eScaleMode
);
1832 m_aNodeStack
.Push(pSNode
);
1836 void SmParser::FontAttribut()
1838 DBG_ASSERT(TokenInGroup(TGFONTATTR
), "Sm: falsche Tokengruppe");
1840 switch (m_aCurToken
.eType
)
1847 m_aNodeStack
.Push(new SmFontNode(m_aCurToken
));
1864 DBG_ASSERT(0, "Sm: unbekannter Fall");
1869 void SmParser::Color()
1871 DBG_ASSERT(m_aCurToken
.eType
== TCOLOR
, "Sm : Ooops...");
1873 // last color rules, get that one
1878 if (TokenInGroup(TGCOLOR
))
1879 { aToken
= m_aCurToken
;
1883 Error(PE_COLOR_EXPECTED
);
1884 } while (m_aCurToken
.eType
== TCOLOR
);
1886 m_aNodeStack
.Push(new SmFontNode(aToken
));
1890 void SmParser::Font()
1892 DBG_ASSERT(m_aCurToken
.eType
== TFONT
, "Sm : Ooops...");
1894 // last font rules, get that one
1899 if (TokenInGroup(TGFONT
))
1900 { aToken
= m_aCurToken
;
1904 Error(PE_FONT_EXPECTED
);
1905 } while (m_aCurToken
.eType
== TFONT
);
1907 m_aNodeStack
.Push(new SmFontNode(aToken
));
1911 // gets number used as arguments in Math formulas (e.g. 'size' command)
1912 // Format: no negative numbers, must start with a digit, no exponent notation, ...
1913 sal_Bool
lcl_IsNumber(const UniString
& rText
)
1915 sal_Bool bPoint
= sal_False
;
1916 const sal_Unicode
* pBuffer
= rText
.GetBuffer();
1917 for(xub_StrLen nPos
= 0; nPos
< rText
.Len(); nPos
++, pBuffer
++)
1919 const sal_Unicode cChar
= *pBuffer
;
1927 else if ( !IsDigit( cChar
) )
1933 void SmParser::FontSize()
1935 DBG_ASSERT(m_aCurToken
.eType
== TSIZE
, "Sm : Ooops...");
1938 SmFontNode
*pFontNode
= new SmFontNode(m_aCurToken
);
1942 switch (m_aCurToken
.eType
)
1944 case TNUMBER
: Type
= FNTSIZ_ABSOLUT
; break;
1945 case TPLUS
: Type
= FNTSIZ_PLUS
; break;
1946 case TMINUS
: Type
= FNTSIZ_MINUS
; break;
1947 case TMULTIPLY
: Type
= FNTSIZ_MULTIPLY
; break;
1948 case TDIVIDEBY
: Type
= FNTSIZ_DIVIDE
; break;
1952 Error(PE_SIZE_EXPECTED
);
1956 if (Type
!= FNTSIZ_ABSOLUT
)
1959 if (m_aCurToken
.eType
!= TNUMBER
)
1962 Error(PE_SIZE_EXPECTED
);
1967 // get number argument
1968 Fraction
aValue( 1L );
1969 if (lcl_IsNumber( m_aCurToken
.aText
))
1972 if ((fTmp
= m_aCurToken
.aText
.ToDouble()) != 0.0)
1976 //!! keep the numerator and denominator from being to large
1977 //!! otherwise ongoing multiplications may result in overflows
1978 //!! (for example in SmNode::SetFontSize the font size calculated
1979 //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux
1980 //!! or ftmp = 1.11111111111111111... (11/9) on every platform.)
1981 if (aValue
.GetDenominator() > 1000)
1983 long nNum
= aValue
.GetNumerator();
1984 long nDenom
= aValue
.GetDenominator();
1985 while (nDenom
> 1000)
1990 aValue
= Fraction( nNum
, nDenom
);
1997 pFontNode
->SetSizeParameter(aValue
, Type
);
1998 m_aNodeStack
.Push(pFontNode
);
2002 void SmParser::Brace()
2004 DBG_ASSERT(m_aCurToken
.eType
== TLEFT
|| TokenInGroup(TGLBRACES
),
2005 "Sm: kein Klammer Ausdruck");
2007 SmStructureNode
*pSNode
= new SmBraceNode(m_aCurToken
);
2011 SmScaleMode eScaleMode
= SCALE_NONE
;
2012 SmParseError eError
= PE_NONE
;
2014 if (m_aCurToken
.eType
== TLEFT
)
2017 eScaleMode
= SCALE_HEIGHT
;
2019 // check for left bracket
2020 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
2022 pLeft
= new SmMathSymbolNode(m_aCurToken
);
2025 Bracebody(sal_True
);
2026 pBody
= m_aNodeStack
.Pop();
2028 if (m_aCurToken
.eType
== TRIGHT
)
2031 // check for right bracket
2032 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
2034 pRight
= new SmMathSymbolNode(m_aCurToken
);
2038 eError
= PE_RBRACE_EXPECTED
;
2041 eError
= PE_RIGHT_EXPECTED
;
2044 eError
= PE_LBRACE_EXPECTED
;
2048 if (TokenInGroup(TGLBRACES
))
2050 pLeft
= new SmMathSymbolNode(m_aCurToken
);
2053 Bracebody(sal_False
);
2054 pBody
= m_aNodeStack
.Pop();
2056 SmTokenType eExpectedType
= TUNKNOWN
;
2057 switch (pLeft
->GetToken().eType
)
2058 { case TLPARENT
: eExpectedType
= TRPARENT
; break;
2059 case TLBRACKET
: eExpectedType
= TRBRACKET
; break;
2060 case TLBRACE
: eExpectedType
= TRBRACE
; break;
2061 case TLDBRACKET
: eExpectedType
= TRDBRACKET
; break;
2062 case TLLINE
: eExpectedType
= TRLINE
; break;
2063 case TLDLINE
: eExpectedType
= TRDLINE
; break;
2064 case TLANGLE
: eExpectedType
= TRANGLE
; break;
2065 case TLFLOOR
: eExpectedType
= TRFLOOR
; break;
2066 case TLCEIL
: eExpectedType
= TRCEIL
; break;
2068 DBG_ASSERT(0, "Sm: unbekannter Fall");
2071 if (m_aCurToken
.eType
== eExpectedType
)
2073 pRight
= new SmMathSymbolNode(m_aCurToken
);
2077 eError
= PE_PARENT_MISMATCH
;
2080 eError
= PE_LBRACE_EXPECTED
;
2083 if (eError
== PE_NONE
)
2084 { DBG_ASSERT(pLeft
, "Sm: NULL pointer");
2085 DBG_ASSERT(pRight
, "Sm: NULL pointer");
2086 pSNode
->SetSubNodes(pLeft
, pBody
, pRight
);
2087 pSNode
->SetScaleMode(eScaleMode
);
2088 m_aNodeStack
.Push(pSNode
);
2101 void SmParser::Bracebody(sal_Bool bIsLeftRight
)
2103 SmStructureNode
*pBody
= new SmBracebodyNode(m_aCurToken
);
2105 sal_uInt16 nNum
= 0;
2112 if (m_aCurToken
.eType
== TMLINE
)
2114 m_aNodeStack
.Push(new SmMathSymbolNode(m_aCurToken
));
2118 else if (m_aCurToken
.eType
!= TRIGHT
)
2122 if (m_aCurToken
.eType
!= TMLINE
&& m_aCurToken
.eType
!= TRIGHT
)
2123 Error(PE_RIGHT_EXPECTED
);
2125 } while (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TRIGHT
);
2131 if (m_aCurToken
.eType
== TMLINE
)
2133 m_aNodeStack
.Push(new SmMathSymbolNode(m_aCurToken
));
2137 else if (!TokenInGroup(TGRBRACES
))
2141 if (m_aCurToken
.eType
!= TMLINE
&& !TokenInGroup(TGRBRACES
))
2142 Error(PE_RBRACE_EXPECTED
);
2144 } while (m_aCurToken
.eType
!= TEND
&& !TokenInGroup(TGRBRACES
));
2147 // build argument vector in parsing order
2148 aNodes
.resize(nNum
);
2149 for (sal_uInt16 i
= 0; i
< nNum
; i
++)
2150 aNodes
[nNum
- 1 - i
] = m_aNodeStack
.Pop();
2152 pBody
->SetSubNodes(aNodes
);
2153 pBody
->SetScaleMode(bIsLeftRight
? SCALE_HEIGHT
: SCALE_NONE
);
2154 m_aNodeStack
.Push(pBody
);
2158 void SmParser::Function()
2160 switch (m_aCurToken
.eType
)
2163 NextToken(); // skip "FUNC"-statement
2185 m_aNodeStack
.Push(new SmTextNode(m_aCurToken
, FNT_FUNCTION
));
2190 Error(PE_FUNC_EXPECTED
);
2195 void SmParser::Binom()
2197 SmNodeArray ExpressionArray
;
2198 SmStructureNode
*pSNode
= new SmTableNode(m_aCurToken
);
2205 ExpressionArray
.resize(2);
2207 for (int i
= 0; i
< 2; i
++)
2208 ExpressionArray
[2 - (i
+ 1)] = m_aNodeStack
.Pop();
2210 pSNode
->SetSubNodes(ExpressionArray
);
2211 m_aNodeStack
.Push(pSNode
);
2215 void SmParser::Stack()
2217 SmNodeArray ExpressionArray
;
2219 if (m_aCurToken
.eType
== TLGROUP
)
2229 while (m_aCurToken
.eType
== TPOUND
);
2231 ExpressionArray
.resize(n
);
2233 for (sal_uInt16 i
= 0; i
< n
; i
++)
2234 ExpressionArray
[n
- (i
+ 1)] = m_aNodeStack
.Pop();
2236 if (m_aCurToken
.eType
!= TRGROUP
)
2237 Error(PE_RGROUP_EXPECTED
);
2241 SmStructureNode
*pSNode
= new SmTableNode(m_aCurToken
);
2242 pSNode
->SetSubNodes(ExpressionArray
);
2243 m_aNodeStack
.Push(pSNode
);
2246 Error(PE_LGROUP_EXPECTED
);
2250 void SmParser::Matrix()
2252 SmNodeArray ExpressionArray
;
2255 if (m_aCurToken
.eType
== TLGROUP
)
2265 while (m_aCurToken
.eType
== TPOUND
);
2269 while (m_aCurToken
.eType
== TDPOUND
)
2272 for (sal_uInt16 i
= 0; i
< c
; i
++)
2277 if (m_aCurToken
.eType
== TPOUND
)
2282 Error(PE_POUND_EXPECTED
);
2291 ExpressionArray
.resize(nRC
);
2293 for (sal_uInt16 i
= 0; i
< (nRC
); i
++)
2294 ExpressionArray
[(nRC
) - (i
+ 1)] = m_aNodeStack
.Pop();
2296 if (m_aCurToken
.eType
!= TRGROUP
)
2297 Error(PE_RGROUP_EXPECTED
);
2301 SmMatrixNode
*pMNode
= new SmMatrixNode(m_aCurToken
);
2302 pMNode
->SetSubNodes(ExpressionArray
);
2303 pMNode
->SetRowCol(r
, c
);
2304 m_aNodeStack
.Push(pMNode
);
2307 Error(PE_LGROUP_EXPECTED
);
2311 void SmParser::Special()
2313 sal_Bool bReplace
= sal_False
;
2314 String
&rName
= m_aCurToken
.aText
;
2317 if (CONVERT_NONE
== GetConversion())
2319 // conversion of symbol names for 6.0 (XML) file format
2320 // (name change on import / export.
2321 // UI uses localized names XML file format does not.)
2322 if( rName
.Len() && rName
.GetChar( 0 ) == sal_Unicode( '%' ) )
2324 if (IsImportSymbolNames())
2326 const SmLocalizedSymbolData
&rLSD
= SM_MOD()->GetLocSymbolData();
2327 aNewName
= rLSD
.GetUiSymbolName( rName
.Copy( 1 ) );
2328 bReplace
= sal_True
;
2330 else if (IsExportSymbolNames())
2332 const SmLocalizedSymbolData
&rLSD
= SM_MOD()->GetLocSymbolData();
2333 aNewName
= rLSD
.GetExportSymbolName( rName
.Copy( 1 ) );
2334 bReplace
= sal_True
;
2337 if( aNewName
.Len() )
2338 aNewName
.Insert( '%', 0 );
2340 else // 5.0 <-> 6.0 formula text (symbol name) conversion
2342 LanguageType nLanguage
= GetLanguage();
2343 SmLocalizedSymbolData
&rData
= SM_MOD()->GetLocSymbolData();
2344 const ResStringArray
*pFrom
= 0;
2345 const ResStringArray
*pTo
= 0;
2346 if (CONVERT_50_TO_60
== GetConversion())
2348 pFrom
= rData
.Get50NamesArray( nLanguage
);
2349 pTo
= rData
.Get60NamesArray( nLanguage
);
2351 else if (CONVERT_60_TO_50
== GetConversion())
2353 pFrom
= rData
.Get60NamesArray( nLanguage
);
2354 pTo
= rData
.Get50NamesArray( nLanguage
);
2358 DBG_ASSERT( pFrom
->Count() == pTo
->Count(),
2359 "array length mismatch" );
2360 sal_uInt16 nCount
= sal::static_int_cast
< sal_uInt16
>(pFrom
->Count());
2361 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
2363 if (pFrom
->GetString(i
) == rName
)
2365 aNewName
= pTo
->GetString(i
);
2366 bReplace
= sal_True
;
2371 // conversion arrays not found or (usually)
2372 // conversion not necessary
2375 if (bReplace
&& aNewName
.Len() && rName
!= aNewName
)
2377 Replace( GetTokenIndex(), rName
.Len(), aNewName
);
2381 // add symbol name to list of used symbols
2382 const String
aSymbolName( m_aCurToken
.aText
.Copy( 1 ) );
2383 if (aSymbolName
.Len() > 0 )
2384 AddToUsedSymbols( aSymbolName
);
2386 m_aNodeStack
.Push(new SmSpecialNode(m_aCurToken
));
2391 void SmParser::GlyphSpecial()
2393 m_aNodeStack
.Push(new SmGlyphSpecialNode(m_aCurToken
));
2398 void SmParser::Error(SmParseError eError
)
2400 SmStructureNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
2401 SmErrorNode
*pErr
= new SmErrorNode(eError
, m_aCurToken
);
2402 pSNode
->SetSubNodes(pErr
, 0);
2404 //! put a structure node on the stack (instead of the error node itself)
2405 //! because sometimes such a node is expected in order to attach some
2407 m_aNodeStack
.Push(pSNode
);
2409 AddError(eError
, pSNode
);
2418 SmParser::SmParser()
2420 m_eConversion
= CONVERT_NONE
;
2421 m_bImportSymNames
= m_bExportSymNames
= sal_False
;
2422 m_nLang
= Application::GetSettings().GetUILanguage();
2426 SmNode
*SmParser::Parse(const String
&rBuffer
)
2430 m_aBufferString
= rBuffer
;
2431 m_aBufferString
.ConvertLineEnd( LINEEND_LF
);
2438 for (sal_uInt16 i
= 0; i
< m_aErrDescList
.Count(); i
++)
2439 delete m_aErrDescList
.Remove(i
);
2441 m_aErrDescList
.Clear();
2443 m_aNodeStack
.Clear();
2445 SetLanguage( Application::GetSettings().GetUILanguage() );
2449 return m_aNodeStack
.Pop();
2453 sal_uInt16
SmParser::AddError(SmParseError Type
, SmNode
*pNode
)
2455 SmErrorDesc
*pErrDesc
= new SmErrorDesc
;
2457 pErrDesc
->Type
= Type
;
2458 pErrDesc
->pNode
= pNode
;
2459 pErrDesc
->Text
= String(SmResId(RID_ERR_IDENT
));
2464 case PE_UNEXPECTED_CHAR
: nRID
= RID_ERR_UNEXPECTEDCHARACTER
; break;
2465 case PE_LGROUP_EXPECTED
: nRID
= RID_ERR_LGROUPEXPECTED
; break;
2466 case PE_RGROUP_EXPECTED
: nRID
= RID_ERR_RGROUPEXPECTED
; break;
2467 case PE_LBRACE_EXPECTED
: nRID
= RID_ERR_LBRACEEXPECTED
; break;
2468 case PE_RBRACE_EXPECTED
: nRID
= RID_ERR_RBRACEEXPECTED
; break;
2469 case PE_FUNC_EXPECTED
: nRID
= RID_ERR_FUNCEXPECTED
; break;
2470 case PE_UNOPER_EXPECTED
: nRID
= RID_ERR_UNOPEREXPECTED
; break;
2471 case PE_BINOPER_EXPECTED
: nRID
= RID_ERR_BINOPEREXPECTED
; break;
2472 case PE_SYMBOL_EXPECTED
: nRID
= RID_ERR_SYMBOLEXPECTED
; break;
2473 case PE_IDENTIFIER_EXPECTED
: nRID
= RID_ERR_IDENTEXPECTED
; break;
2474 case PE_POUND_EXPECTED
: nRID
= RID_ERR_POUNDEXPECTED
; break;
2475 case PE_COLOR_EXPECTED
: nRID
= RID_ERR_COLOREXPECTED
; break;
2476 case PE_RIGHT_EXPECTED
: nRID
= RID_ERR_RIGHTEXPECTED
; break;
2479 nRID
= RID_ERR_UNKOWN
;
2481 pErrDesc
->Text
+= SmResId(nRID
);
2483 m_aErrDescList
.Insert(pErrDesc
);
2485 return (sal_uInt16
) m_aErrDescList
.GetPos(pErrDesc
);
2489 const SmErrorDesc
*SmParser::NextError()
2491 if (m_aErrDescList
.Count())
2492 if (m_nCurError
> 0) return m_aErrDescList
.Seek(--m_nCurError
);
2496 return m_aErrDescList
.Seek(m_nCurError
);
2502 const SmErrorDesc
*SmParser::PrevError()
2504 if (m_aErrDescList
.Count())
2505 if (m_nCurError
< (int) (m_aErrDescList
.Count() - 1)) return m_aErrDescList
.Seek(++m_nCurError
);
2508 m_nCurError
= (int) (m_aErrDescList
.Count() - 1);
2509 return m_aErrDescList
.Seek(m_nCurError
);
2515 const SmErrorDesc
*SmParser::GetError(sal_uInt16 i
)
2517 return (/*i >= 0 &&*/ i
< m_aErrDescList
.Count())
2518 ? m_aErrDescList
.Seek(i
)
2519 : m_aErrDescList
.Seek(m_nCurError
);