1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <com/sun/star/i18n/UnicodeType.hpp>
23 #include <i18nlangtag/lang.h>
24 #include <unotools/charclass.hxx>
25 #include <editeng/unolingu.hxx>
26 #include <unotools/syslocale.hxx>
27 #include <sal/macros.h>
29 #include "starmath.hrc"
36 using namespace ::com::sun::star
;
37 using namespace ::com::sun::star::i18n
;
39 ///////////////////////////////////////////////////////////////////////////
42 template < typename T
>
43 T
* lcl_popOrZero( ::std::stack
<T
*> & rStack
)
47 T
* pTmp
= rStack
.top();
53 static const sal_Unicode aDelimiterTable
[] =
55 ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#',
56 '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(',
57 ')', '{', '}', '[', ']', '^', '_',
58 '\0' // end of list symbol
65 nGroup
= nCol
= nRow
= nLevel
= 0;
68 SmToken::SmToken(SmTokenType eTokenType
,
70 const sal_Char
* pText
,
71 sal_uLong nTokenGroup
,
72 sal_uInt16 nTokenLevel
) {
75 aText
= OUString::createFromAscii(pText
);
81 ///////////////////////////////////////////////////////////////////////////
84 static const SmTokenTableEntry aTokenTable
[] =
86 { "Im" , TIM
, MS_IM
, TGSTANDALONE
, 5 },
87 { "MZ23", TDEBUG
, '\0', TGATTRIBUT
, 0 },
88 { "Re" , TRE
, MS_RE
, TGSTANDALONE
, 5 },
89 { "abs", TABS
, '\0', TGUNOPER
, 13 },
90 { "arcosh", TACOSH
, '\0', TGFUNCTION
, 5 },
91 { "arcoth", TACOTH
, '\0', TGFUNCTION
, 5 },
92 { "acute", TACUTE
, MS_ACUTE
, TGATTRIBUT
, 5 },
93 { "aleph" , TALEPH
, MS_ALEPH
, TGSTANDALONE
, 5 },
94 { "alignb", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
95 { "alignc", TALIGNC
, '\0', TGALIGN
, 0},
96 { "alignl", TALIGNL
, '\0', TGALIGN
, 0},
97 { "alignm", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
98 { "alignr", TALIGNR
, '\0', TGALIGN
, 0},
99 { "alignt", TALIGNC
, '\0', TGALIGN
| TGDISCARDED
, 0},
100 { "and", TAND
, MS_AND
, TGPRODUCT
, 0},
101 { "approx", TAPPROX
, MS_APPROX
, TGRELATION
, 0},
102 { "arccos", TACOS
, '\0', TGFUNCTION
, 5},
103 { "arccot", TACOT
, '\0', TGFUNCTION
, 5},
104 { "arcsin", TASIN
, '\0', TGFUNCTION
, 5},
105 { "arctan", TATAN
, '\0', TGFUNCTION
, 5},
106 { "arsinh", TASINH
, '\0', TGFUNCTION
, 5},
107 { "artanh", TATANH
, '\0', TGFUNCTION
, 5},
108 { "backepsilon" , TBACKEPSILON
, MS_BACKEPSILON
, TGSTANDALONE
, 5},
109 { "bar", TBAR
, MS_BAR
, TGATTRIBUT
, 5},
110 { "binom", TBINOM
, '\0', 0, 5 },
111 { "black", TBLACK
, '\0', TGCOLOR
, 0},
112 { "blue", TBLUE
, '\0', TGCOLOR
, 0},
113 { "bold", TBOLD
, '\0', TGFONTATTR
, 5},
114 { "boper", TBOPER
, '\0', TGPRODUCT
, 0},
115 { "breve", TBREVE
, MS_BREVE
, TGATTRIBUT
, 5},
116 { "bslash", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
117 { "cdot", TCDOT
, MS_CDOT
, TGPRODUCT
, 0},
118 { "check", TCHECK
, MS_CHECK
, TGATTRIBUT
, 5},
119 { "circ" , TCIRC
, MS_CIRC
, TGSTANDALONE
, 5},
120 { "circle", TCIRCLE
, MS_CIRCLE
, TGATTRIBUT
, 5},
121 { "color", TCOLOR
, '\0', TGFONTATTR
, 5},
122 { "coprod", TCOPROD
, MS_COPROD
, TGOPER
, 5},
123 { "cos", TCOS
, '\0', TGFUNCTION
, 5},
124 { "cosh", TCOSH
, '\0', TGFUNCTION
, 5},
125 { "cot", TCOT
, '\0', TGFUNCTION
, 5},
126 { "coth", TCOTH
, '\0', TGFUNCTION
, 5},
127 { "csub", TCSUB
, '\0', TGPOWER
, 0},
128 { "csup", TCSUP
, '\0', TGPOWER
, 0},
129 { "cyan", TCYAN
, '\0', TGCOLOR
, 0},
130 { "dddot", TDDDOT
, MS_DDDOT
, TGATTRIBUT
, 5},
131 { "ddot", TDDOT
, MS_DDOT
, TGATTRIBUT
, 5},
132 { "def", TDEF
, MS_DEF
, TGRELATION
, 0},
133 { "div", TDIV
, MS_DIV
, TGPRODUCT
, 0},
134 { "divides", TDIVIDES
, MS_LINE
, TGRELATION
, 0},
135 { "dlarrow" , TDLARROW
, MS_DLARROW
, TGSTANDALONE
, 5},
136 { "dlrarrow" , TDLRARROW
, MS_DLRARROW
, TGSTANDALONE
, 5},
137 { "dot", TDOT
, MS_DOT
, TGATTRIBUT
, 5},
138 { "dotsaxis", TDOTSAXIS
, MS_DOTSAXIS
, TGSTANDALONE
, 5}, // 5 to continue expression
139 { "dotsdiag", TDOTSDIAG
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
140 { "dotsdown", TDOTSDOWN
, MS_DOTSDOWN
, TGSTANDALONE
, 5}, //
141 { "dotslow", TDOTSLOW
, MS_DOTSLOW
, TGSTANDALONE
, 5}, //
142 { "dotsup", TDOTSUP
, MS_DOTSUP
, TGSTANDALONE
, 5}, //
143 { "dotsvert", TDOTSVERT
, MS_DOTSVERT
, TGSTANDALONE
, 5}, //
144 { "downarrow" , TDOWNARROW
, MS_DOWNARROW
, TGSTANDALONE
, 5},
145 { "drarrow" , TDRARROW
, MS_DRARROW
, TGSTANDALONE
, 5},
146 { "emptyset" , TEMPTYSET
, MS_EMPTYSET
, TGSTANDALONE
, 5},
147 { "equiv", TEQUIV
, MS_EQUIV
, TGRELATION
, 0},
148 { "exists", TEXISTS
, MS_EXISTS
, TGSTANDALONE
, 5},
149 { "notexists", TNOTEXISTS
, MS_NOTEXISTS
, TGSTANDALONE
, 5},
150 { "exp", TEXP
, '\0', TGFUNCTION
, 5},
151 { "fact", TFACT
, MS_FACT
, TGUNOPER
, 5},
152 { "fixed", TFIXED
, '\0', TGFONT
, 0},
153 { "font", TFONT
, '\0', TGFONTATTR
, 5},
154 { "forall", TFORALL
, MS_FORALL
, TGSTANDALONE
, 5},
155 { "from", TFROM
, '\0', TGLIMIT
, 0},
156 { "func", TFUNC
, '\0', TGFUNCTION
, 5},
157 { "ge", TGE
, MS_GE
, TGRELATION
, 0},
158 { "geslant", TGESLANT
, MS_GESLANT
, TGRELATION
, 0 },
159 { "gg", TGG
, MS_GG
, TGRELATION
, 0},
160 { "grave", TGRAVE
, MS_GRAVE
, TGATTRIBUT
, 5},
161 { "green", TGREEN
, '\0', TGCOLOR
, 0},
162 { "gt", TGT
, MS_GT
, TGRELATION
, 0},
163 { "hat", THAT
, MS_HAT
, TGATTRIBUT
, 5},
164 { "hbar" , THBAR
, MS_HBAR
, TGSTANDALONE
, 5},
165 { "iiint", TIIINT
, MS_IIINT
, TGOPER
, 5},
166 { "iint", TIINT
, MS_IINT
, TGOPER
, 5},
167 { "in", TIN
, MS_IN
, TGRELATION
, 0},
168 { "infinity" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
169 { "infty" , TINFINITY
, MS_INFINITY
, TGSTANDALONE
, 5},
170 { "int", TINT
, MS_INT
, TGOPER
, 5},
171 { "intersection", TINTERSECT
, MS_INTERSECT
, TGPRODUCT
, 0},
172 { "ital", TITALIC
, '\0', TGFONTATTR
, 5},
173 { "italic", TITALIC
, '\0', TGFONTATTR
, 5},
174 { "lambdabar" , TLAMBDABAR
, MS_LAMBDABAR
, TGSTANDALONE
, 5},
175 { "langle", TLANGLE
, MS_LANGLE
, TGLBRACES
, 5},
176 { "lbrace", TLBRACE
, MS_LBRACE
, TGLBRACES
, 5},
177 { "lceil", TLCEIL
, MS_LCEIL
, TGLBRACES
, 5},
178 { "ldbracket", TLDBRACKET
, MS_LDBRACKET
, TGLBRACES
, 5},
179 { "ldline", TLDLINE
, MS_DLINE
, TGLBRACES
, 5},
180 { "le", TLE
, MS_LE
, TGRELATION
, 0},
181 { "left", TLEFT
, '\0', 0, 5},
182 { "leftarrow" , TLEFTARROW
, MS_LEFTARROW
, TGSTANDALONE
, 5},
183 { "leslant", TLESLANT
, MS_LESLANT
, TGRELATION
, 0 },
184 { "lfloor", TLFLOOR
, MS_LFLOOR
, TGLBRACES
, 5},
185 { "lim", TLIM
, '\0', TGOPER
, 5},
186 { "liminf", TLIMINF
, '\0', TGOPER
, 5},
187 { "limsup", TLIMSUP
, '\0', TGOPER
, 5},
188 { "lint", TLINT
, MS_LINT
, TGOPER
, 5},
189 { "ll", TLL
, MS_LL
, TGRELATION
, 0},
190 { "lline", TLLINE
, MS_LINE
, TGLBRACES
, 5},
191 { "llint", TLLINT
, MS_LLINT
, TGOPER
, 5},
192 { "lllint", TLLLINT
, MS_LLLINT
, TGOPER
, 5},
193 { "ln", TLN
, '\0', TGFUNCTION
, 5},
194 { "log", TLOG
, '\0', TGFUNCTION
, 5},
195 { "lsub", TLSUB
, '\0', TGPOWER
, 0},
196 { "lsup", TLSUP
, '\0', TGPOWER
, 0},
197 { "lt", TLT
, MS_LT
, TGRELATION
, 0},
198 { "magenta", TMAGENTA
, '\0', TGCOLOR
, 0},
199 { "matrix", TMATRIX
, '\0', 0, 5},
200 { "minusplus", TMINUSPLUS
, MS_MINUSPLUS
, TGUNOPER
| TGSUM
, 5},
201 { "mline", TMLINE
, MS_LINE
, 0, 0}, //! nicht in TGRBRACES, Level 0
202 { "nabla", TNABLA
, MS_NABLA
, TGSTANDALONE
, 5},
203 { "nbold", TNBOLD
, '\0', TGFONTATTR
, 5},
204 { "ndivides", TNDIVIDES
, MS_NDIVIDES
, TGRELATION
, 0},
205 { "neg", TNEG
, MS_NEG
, TGUNOPER
, 5 },
206 { "neq", TNEQ
, MS_NEQ
, TGRELATION
, 0},
207 { "newline", TNEWLINE
, '\0', 0, 0},
208 { "ni", TNI
, MS_NI
, TGRELATION
, 0},
209 { "nitalic", TNITALIC
, '\0', TGFONTATTR
, 5},
210 { "none", TNONE
, '\0', TGLBRACES
| TGRBRACES
, 0},
211 { "nospace", TNOSPACE
, '\0', TGSTANDALONE
, 5},
212 { "notin", TNOTIN
, MS_NOTIN
, TGRELATION
, 0},
213 { "nroot", TNROOT
, MS_SQRT
, TGUNOPER
, 5},
214 { "nsubset", TNSUBSET
, MS_NSUBSET
, TGRELATION
, 0 },
215 { "nsupset", TNSUPSET
, MS_NSUPSET
, TGRELATION
, 0 },
216 { "nsubseteq", TNSUBSETEQ
, MS_NSUBSETEQ
, TGRELATION
, 0 },
217 { "nsupseteq", TNSUPSETEQ
, MS_NSUPSETEQ
, TGRELATION
, 0 },
218 { "odivide", TODIVIDE
, MS_ODIVIDE
, TGPRODUCT
, 0},
219 { "odot", TODOT
, MS_ODOT
, TGPRODUCT
, 0},
220 { "ominus", TOMINUS
, MS_OMINUS
, TGSUM
, 0},
221 { "oper", TOPER
, '\0', TGOPER
, 5},
222 { "oplus", TOPLUS
, MS_OPLUS
, TGSUM
, 0},
223 { "or", TOR
, MS_OR
, TGSUM
, 0},
224 { "ortho", TORTHO
, MS_ORTHO
, TGRELATION
, 0},
225 { "otimes", TOTIMES
, MS_OTIMES
, TGPRODUCT
, 0},
226 { "over", TOVER
, '\0', TGPRODUCT
, 0},
227 { "overbrace", TOVERBRACE
, MS_OVERBRACE
, TGPRODUCT
, 5},
228 { "overline", TOVERLINE
, '\0', TGATTRIBUT
, 5},
229 { "overstrike", TOVERSTRIKE
, '\0', TGATTRIBUT
, 5},
230 { "owns", TNI
, MS_NI
, TGRELATION
, 0},
231 { "parallel", TPARALLEL
, MS_DLINE
, TGRELATION
, 0},
232 { "partial", TPARTIAL
, MS_PARTIAL
, TGSTANDALONE
, 5 },
233 { "phantom", TPHANTOM
, '\0', TGFONTATTR
, 5},
234 { "plusminus", TPLUSMINUS
, MS_PLUSMINUS
, TGUNOPER
| TGSUM
, 5},
235 { "prec", TPRECEDES
, MS_PRECEDES
, TGRELATION
, 0 },
236 { "preccurlyeq", TPRECEDESEQUAL
, MS_PRECEDESEQUAL
, TGRELATION
, 0 },
237 { "precsim", TPRECEDESEQUIV
, MS_PRECEDESEQUIV
, TGRELATION
, 0 },
238 { "nprec", TNOTPRECEDES
, MS_NOTPRECEDES
, TGRELATION
, 0 },
239 { "prod", TPROD
, MS_PROD
, TGOPER
, 5},
240 { "prop", TPROP
, MS_PROP
, TGRELATION
, 0},
241 { "rangle", TRANGLE
, MS_RANGLE
, TGRBRACES
, 0}, //! 0 to terminate expression
242 { "rbrace", TRBRACE
, MS_RBRACE
, TGRBRACES
, 0}, //
243 { "rceil", TRCEIL
, MS_RCEIL
, TGRBRACES
, 0}, //
244 { "rdbracket", TRDBRACKET
, MS_RDBRACKET
, TGRBRACES
, 0}, //
245 { "rdline", TRDLINE
, MS_DLINE
, TGRBRACES
, 0}, //
246 { "red", TRED
, '\0', TGCOLOR
, 0},
247 { "rfloor", TRFLOOR
, MS_RFLOOR
, TGRBRACES
, 0}, //! 0 to terminate expression
248 { "right", TRIGHT
, '\0', 0, 0},
249 { "rightarrow" , TRIGHTARROW
, MS_RIGHTARROW
, TGSTANDALONE
, 5},
250 { "rline", TRLINE
, MS_LINE
, TGRBRACES
, 0}, //! 0 to terminate expression
251 { "rsub", TRSUB
, '\0', TGPOWER
, 0},
252 { "rsup", TRSUP
, '\0', TGPOWER
, 0},
253 { "sans", TSANS
, '\0', TGFONT
, 0},
254 { "serif", TSERIF
, '\0', TGFONT
, 0},
255 { "setC" , TSETC
, MS_SETC
, TGSTANDALONE
, 5},
256 { "setN" , TSETN
, MS_SETN
, TGSTANDALONE
, 5},
257 { "setQ" , TSETQ
, MS_SETQ
, TGSTANDALONE
, 5},
258 { "setR" , TSETR
, MS_SETR
, TGSTANDALONE
, 5},
259 { "setZ" , TSETZ
, MS_SETZ
, TGSTANDALONE
, 5},
260 { "setminus", TBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
261 { "sim", TSIM
, MS_SIM
, TGRELATION
, 0},
262 { "simeq", TSIMEQ
, MS_SIMEQ
, TGRELATION
, 0},
263 { "sin", TSIN
, '\0', TGFUNCTION
, 5},
264 { "sinh", TSINH
, '\0', TGFUNCTION
, 5},
265 { "size", TSIZE
, '\0', TGFONTATTR
, 5},
266 { "slash", TSLASH
, MS_SLASH
, TGPRODUCT
, 0 },
267 { "sqrt", TSQRT
, MS_SQRT
, TGUNOPER
, 5},
268 { "stack", TSTACK
, '\0', 0, 5},
269 { "sub", TRSUB
, '\0', TGPOWER
, 0},
270 { "subset", TSUBSET
, MS_SUBSET
, TGRELATION
, 0},
271 { "succ", TSUCCEEDS
, MS_SUCCEEDS
, TGRELATION
, 0 },
272 { "succcurlyeq", TSUCCEEDSEQUAL
, MS_SUCCEEDSEQUAL
, TGRELATION
, 0 },
273 { "succsim", TSUCCEEDSEQUIV
, MS_SUCCEEDSEQUIV
, TGRELATION
, 0 },
274 { "nsucc", TNOTSUCCEEDS
, MS_NOTSUCCEEDS
, TGRELATION
, 0 },
275 { "subseteq", TSUBSETEQ
, MS_SUBSETEQ
, TGRELATION
, 0},
276 { "sum", TSUM
, MS_SUM
, TGOPER
, 5},
277 { "sup", TRSUP
, '\0', TGPOWER
, 0},
278 { "supset", TSUPSET
, MS_SUPSET
, TGRELATION
, 0},
279 { "supseteq", TSUPSETEQ
, MS_SUPSETEQ
, TGRELATION
, 0},
280 { "tan", TTAN
, '\0', TGFUNCTION
, 5},
281 { "tanh", TTANH
, '\0', TGFUNCTION
, 5},
282 { "tilde", TTILDE
, MS_TILDE
, TGATTRIBUT
, 5},
283 { "times", TTIMES
, MS_TIMES
, TGPRODUCT
, 0},
284 { "to", TTO
, '\0', TGLIMIT
, 0},
285 { "toward", TTOWARD
, MS_RIGHTARROW
, TGRELATION
, 0},
286 { "transl", TTRANSL
, MS_TRANSL
, TGRELATION
, 0},
287 { "transr", TTRANSR
, MS_TRANSR
, TGRELATION
, 0},
288 { "underbrace", TUNDERBRACE
, MS_UNDERBRACE
, TGPRODUCT
, 5},
289 { "underline", TUNDERLINE
, '\0', TGATTRIBUT
, 5},
290 { "union", TUNION
, MS_UNION
, TGSUM
, 0},
291 { "uoper", TUOPER
, '\0', TGUNOPER
, 5},
292 { "uparrow" , TUPARROW
, MS_UPARROW
, TGSTANDALONE
, 5},
293 { "vec", TVEC
, MS_VEC
, TGATTRIBUT
, 5},
294 { "white", TWHITE
, '\0', TGCOLOR
, 0},
295 { "widebslash", TWIDEBACKSLASH
, MS_BACKSLASH
, TGPRODUCT
, 0 },
296 { "widehat", TWIDEHAT
, MS_HAT
, TGATTRIBUT
, 5},
297 { "widetilde", TWIDETILDE
, MS_TILDE
, TGATTRIBUT
, 5},
298 { "wideslash", TWIDESLASH
, MS_SLASH
, TGPRODUCT
, 0 },
299 { "widevec", TWIDEVEC
, MS_VEC
, TGATTRIBUT
, 5},
300 { "wp" , TWP
, MS_WP
, TGSTANDALONE
, 5},
301 { "yellow", TYELLOW
, '\0', TGCOLOR
, 0},
302 { "", TEND
, '\0', 0, 0}
305 const SmTokenTableEntry
* SmParser::GetTokenTableEntry( const String
&rName
)
307 const SmTokenTableEntry
* pRes
= 0;
310 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aTokenTable
); ++i
)
312 if (rName
.EqualsIgnoreCaseAscii( aTokenTable
[i
].pIdent
))
314 pRes
= &aTokenTable
[i
];
324 ///////////////////////////////////////////////////////////////////////////
326 #if OSL_DEBUG_LEVEL > 1
328 bool SmParser::IsDelimiter( const String
&rTxt
, xub_StrLen nPos
)
329 // returns 'true' iff cChar is '\0' or a delimeter
331 OSL_ENSURE( nPos
<= rTxt
.Len(), "index out of range" );
333 sal_Unicode cChar
= rTxt
.GetChar( nPos
);
337 // check if 'cChar' is in the delimeter table
338 const sal_Unicode
*pDelim
= &aDelimiterTable
[0];
339 for ( ; *pDelim
!= 0; pDelim
++)
340 if (*pDelim
== cChar
)
344 sal_Int16 nTypJp
= SM_MOD()->GetSysLocale().GetCharClass().getType( rTxt
, nPos
);
345 bool bIsDelim
= (*pDelim
!= 0 ||
346 nTypJp
== com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR
||
347 nTypJp
== com::sun::star::i18n::UnicodeType::CONTROL
);
354 void SmParser::Insert(const String
&rText
, sal_uInt16 nPos
)
356 m_aBufferString
.Insert(rText
, nPos
);
358 xub_StrLen nLen
= rText
.Len();
359 m_nBufferIndex
= m_nBufferIndex
+ nLen
;
360 m_nTokenIndex
= m_nTokenIndex
+ nLen
;
364 void SmParser::Replace( sal_uInt16 nPos
, sal_uInt16 nLen
, const String
&rText
)
366 OSL_ENSURE( nPos
+ nLen
<= m_aBufferString
.Len(), "argument mismatch" );
368 m_aBufferString
.Replace( nPos
, nLen
, rText
);
369 sal_Int16 nChg
= rText
.Len() - nLen
;
370 m_nBufferIndex
= m_nBufferIndex
+ nChg
;
371 m_nTokenIndex
= m_nTokenIndex
+ nChg
;
375 // First character may be any alphabetic
376 const sal_Int32 coStartFlags
=
377 KParseTokens::ANY_LETTER_OR_NUMBER
|
378 KParseTokens::IGNORE_LEADING_WS
;
380 // Continuing characters may be any alphanumeric or dot.
381 const sal_Int32 coContFlags
=
382 ((coStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
)
383 | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING
;
385 // First character for numbers, may be any numeric or dot
386 const sal_Int32 coNumStartFlags
=
387 KParseTokens::ASC_DIGIT
|
388 KParseTokens::ASC_DOT
|
389 KParseTokens::IGNORE_LEADING_WS
;
390 // Continuing characters for numbers, may be any numeric or dot.
391 const sal_Int32 coNumContFlags
=
392 (coNumStartFlags
| KParseTokens::ASC_DOT
) & ~KParseTokens::IGNORE_LEADING_WS
;
394 void SmParser::NextToken()
396 static const String aEmptyStr
;
398 xub_StrLen nBufLen
= m_aBufferString
.Len();
400 xub_StrLen nRealStart
;
402 bool bNumStart
= false;
403 CharClass
aCC(SM_MOD()->GetSysLocale().GetLanguageTag());
407 while (UnicodeType::SPACE_SEPARATOR
==
408 aCC
.getType( m_aBufferString
, m_nBufferIndex
))
411 sal_Int32 nStartFlags
= coStartFlags
;
412 sal_Int32 nContFlags
= coContFlags
;
413 sal_Unicode cFirstChar
= m_aBufferString
.GetChar( m_nBufferIndex
);
414 aRes
= aCC
.parseAnyToken( m_aBufferString
, m_nBufferIndex
,
415 nStartFlags
, aEmptyStr
,
416 nContFlags
, aEmptyStr
);
418 // #i45779# parse numbers correctly
419 // i.e. independent from the locale setting.
420 // (note that #i11752# remains fixed)
421 if ((aRes
.TokenType
& KParseType::IDENTNAME
) && CharClass::isAsciiDigit( cFirstChar
))
424 LanguageTag
aOldLoc( aCC
.getLanguageTag() );
425 aCC
.setLanguageTag( LanguageTag( m_aDotLoc
));
426 aTmpRes
= aCC
.parsePredefinedToken(
427 KParseType::ASC_NUMBER
,
428 m_aBufferString
, m_nBufferIndex
,
429 KParseTokens::ASC_DIGIT
, aEmptyStr
,
430 KParseTokens::ASC_DIGIT
| KParseTokens::ASC_DOT
, aEmptyStr
);
431 aCC
.setLanguageTag( aOldLoc
);
432 if (aTmpRes
.TokenType
& KParseType::ASC_NUMBER
)
433 aRes
.TokenType
= aTmpRes
.TokenType
;
436 nRealStart
= m_nBufferIndex
+ sal::static_int_cast
< xub_StrLen
>(aRes
.LeadingWhiteSpace
);
437 m_nBufferIndex
= nRealStart
;
440 if ( aRes
.TokenType
== 0 &&
441 nRealStart
< nBufLen
&&
442 '\n' == m_aBufferString
.GetChar( nRealStart
) )
444 // keep data needed for tokens row and col entry up to date
446 m_nBufferIndex
= m_nColOff
= nRealStart
+ 1;
449 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
451 String
aName( m_aBufferString
.Copy( nRealStart
, 2 ));
452 if ( aName
.EqualsAscii( "%%" ))
455 m_nBufferIndex
= nRealStart
+ 2;
456 while (m_nBufferIndex
< nBufLen
&&
457 '\n' != m_aBufferString
.GetChar( m_nBufferIndex
))
465 // set index of current token
466 m_nTokenIndex
= m_nBufferIndex
;
468 m_aCurToken
.nRow
= m_Row
;
469 m_aCurToken
.nCol
= nRealStart
- m_nColOff
+ 1;
471 bool bHandled
= true;
472 if (nRealStart
>= nBufLen
)
474 m_aCurToken
.eType
= TEND
;
475 m_aCurToken
.cMathChar
= '\0';
476 m_aCurToken
.nGroup
= 0;
477 m_aCurToken
.nLevel
= 0;
478 m_aCurToken
.aText
= "";
480 else if ((aRes
.TokenType
& (KParseType::ASC_NUMBER
| KParseType::UNI_NUMBER
))
481 || (bNumStart
&& (aRes
.TokenType
& KParseType::IDENTNAME
)))
483 sal_Int32 n
= aRes
.EndPos
- nRealStart
;
484 OSL_ENSURE( n
>= 0, "length < 0" );
485 m_aCurToken
.eType
= TNUMBER
;
486 m_aCurToken
.cMathChar
= '\0';
487 m_aCurToken
.nGroup
= 0;
488 m_aCurToken
.nLevel
= 5;
489 m_aCurToken
.aText
= m_aBufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) );
491 #if OSL_DEBUG_LEVEL > 1
492 if (!IsDelimiter( m_aBufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
494 OSL_FAIL( "identifier really finished? (compatibility!)" );
498 else if (aRes
.TokenType
& KParseType::DOUBLE_QUOTE_STRING
)
500 m_aCurToken
.eType
= TTEXT
;
501 m_aCurToken
.cMathChar
= '\0';
502 m_aCurToken
.nGroup
= 0;
503 m_aCurToken
.nLevel
= 5;
504 m_aCurToken
.aText
= aRes
.DequotedNameOrString
;
505 m_aCurToken
.nRow
= m_Row
;
506 m_aCurToken
.nCol
= nRealStart
- m_nColOff
+ 2;
508 else if (aRes
.TokenType
& KParseType::IDENTNAME
)
510 sal_Int32 n
= aRes
.EndPos
- nRealStart
;
511 OSL_ENSURE( n
>= 0, "length < 0" );
512 String
aName( m_aBufferString
.Copy( nRealStart
, sal::static_int_cast
< xub_StrLen
>(n
) ) );
513 const SmTokenTableEntry
*pEntry
= GetTokenTableEntry( aName
);
517 m_aCurToken
.eType
= pEntry
->eType
;
518 m_aCurToken
.cMathChar
= pEntry
->cMathChar
;
519 m_aCurToken
.nGroup
= pEntry
->nGroup
;
520 m_aCurToken
.nLevel
= pEntry
->nLevel
;
521 m_aCurToken
.aText
= OUString::createFromAscii( pEntry
->pIdent
);
525 m_aCurToken
.eType
= TIDENT
;
526 m_aCurToken
.cMathChar
= '\0';
527 m_aCurToken
.nGroup
= 0;
528 m_aCurToken
.nLevel
= 5;
529 m_aCurToken
.aText
= aName
;
531 #if OSL_DEBUG_LEVEL > 1
532 if (!IsDelimiter( m_aBufferString
, static_cast< xub_StrLen
>(aRes
.EndPos
) ))
534 OSL_FAIL( "identifier really finished? (compatibility!)" );
539 else if (aRes
.TokenType
== 0 && '_' == m_aBufferString
.GetChar( nRealStart
))
541 m_aCurToken
.eType
= TRSUB
;
542 m_aCurToken
.cMathChar
= '\0';
543 m_aCurToken
.nGroup
= TGPOWER
;
544 m_aCurToken
.nLevel
= 0;
545 m_aCurToken
.aText
= "_";
547 aRes
.EndPos
= nRealStart
+ 1;
549 else if (aRes
.TokenType
& KParseType::BOOLEAN
)
551 sal_Int32
&rnEndPos
= aRes
.EndPos
;
552 String
aName( m_aBufferString
.Copy( nRealStart
,
553 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ));
554 if (2 >= aName
.Len())
556 sal_Unicode ch
= aName
.GetChar( 0 );
561 if (m_aBufferString
.Copy( nRealStart
, 2 ).
564 m_aCurToken
.eType
= TLL
;
565 m_aCurToken
.cMathChar
= MS_LL
;
566 m_aCurToken
.nGroup
= TGRELATION
;
567 m_aCurToken
.nLevel
= 0;
568 m_aCurToken
.aText
= "<<";
570 rnEndPos
= nRealStart
+ 2;
572 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
575 m_aCurToken
.eType
= TLE
;
576 m_aCurToken
.cMathChar
= MS_LE
;
577 m_aCurToken
.nGroup
= TGRELATION
;
578 m_aCurToken
.nLevel
= 0;
579 m_aCurToken
.aText
= "<=";
581 rnEndPos
= nRealStart
+ 2;
583 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
586 m_aCurToken
.eType
= TNEQ
;
587 m_aCurToken
.cMathChar
= MS_NEQ
;
588 m_aCurToken
.nGroup
= TGRELATION
;
589 m_aCurToken
.nLevel
= 0;
590 m_aCurToken
.aText
= "<>";
592 rnEndPos
= nRealStart
+ 2;
594 else if (m_aBufferString
.Copy( nRealStart
, 3 ).
595 EqualsAscii( "<?>" ))
597 m_aCurToken
.eType
= TPLACE
;
598 m_aCurToken
.cMathChar
= MS_PLACE
;
599 m_aCurToken
.nGroup
= 0;
600 m_aCurToken
.nLevel
= 5;
601 m_aCurToken
.aText
= "<?>";
603 rnEndPos
= nRealStart
+ 3;
607 m_aCurToken
.eType
= TLT
;
608 m_aCurToken
.cMathChar
= MS_LT
;
609 m_aCurToken
.nGroup
= TGRELATION
;
610 m_aCurToken
.nLevel
= 0;
611 m_aCurToken
.aText
= "<";
617 if (m_aBufferString
.Copy( nRealStart
, 2 ).
620 m_aCurToken
.eType
= TGE
;
621 m_aCurToken
.cMathChar
= MS_GE
;
622 m_aCurToken
.nGroup
= TGRELATION
;
623 m_aCurToken
.nLevel
= 0;
624 m_aCurToken
.aText
= ">=";
626 rnEndPos
= nRealStart
+ 2;
628 else if (m_aBufferString
.Copy( nRealStart
, 2 ).
631 m_aCurToken
.eType
= TGG
;
632 m_aCurToken
.cMathChar
= MS_GG
;
633 m_aCurToken
.nGroup
= TGRELATION
;
634 m_aCurToken
.nLevel
= 0;
635 m_aCurToken
.aText
= ">>";
637 rnEndPos
= nRealStart
+ 2;
641 m_aCurToken
.eType
= TGT
;
642 m_aCurToken
.cMathChar
= MS_GT
;
643 m_aCurToken
.nGroup
= TGRELATION
;
644 m_aCurToken
.nLevel
= 0;
645 m_aCurToken
.aText
= ">";
654 else if (aRes
.TokenType
& KParseType::ONE_SINGLE_CHAR
)
656 sal_Int32
&rnEndPos
= aRes
.EndPos
;
657 String
aName( m_aBufferString
.Copy( nRealStart
,
658 sal::static_int_cast
< xub_StrLen
>(rnEndPos
- nRealStart
) ) );
660 if (1 == aName
.Len())
662 sal_Unicode ch
= aName
.GetChar( 0 );
667 //! modifies aRes.EndPos
669 OSL_ENSURE( rnEndPos
>= nBufLen
||
670 '%' != m_aBufferString
.GetChar( sal::static_int_cast
< xub_StrLen
>(rnEndPos
) ),
671 "unexpected comment start" );
673 // get identifier of user-defined character
674 ParseResult aTmpRes
= aCC
.parseAnyToken(
675 m_aBufferString
, rnEndPos
,
676 KParseTokens::ANY_LETTER
,
681 xub_StrLen nTmpStart
= sal::static_int_cast
< xub_StrLen
>(rnEndPos
+
682 aTmpRes
.LeadingWhiteSpace
);
684 // default setting for the case that no identifier
685 // i.e. a valid symbol-name is following the '%'
687 m_aCurToken
.eType
= TTEXT
;
688 m_aCurToken
.cMathChar
= '\0';
689 m_aCurToken
.nGroup
= 0;
690 m_aCurToken
.nLevel
= 5;
691 m_aCurToken
.aText
= String();
692 m_aCurToken
.nRow
= sal::static_int_cast
< xub_StrLen
>(m_Row
);
693 m_aCurToken
.nCol
= nTmpStart
- m_nColOff
;
695 if (aTmpRes
.TokenType
& KParseType::IDENTNAME
)
698 xub_StrLen n
= sal::static_int_cast
< xub_StrLen
>(aTmpRes
.EndPos
- nTmpStart
);
699 m_aCurToken
.eType
= TSPECIAL
;
700 m_aCurToken
.aText
= m_aBufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTmpStart
-1), n
+1 );
702 OSL_ENSURE( aTmpRes
.EndPos
> rnEndPos
,
703 "empty identifier" );
704 if (aTmpRes
.EndPos
> rnEndPos
)
705 rnEndPos
= aTmpRes
.EndPos
;
710 // if no symbol-name was found we start-over with
711 // finding the next token right afer the '%' sign.
712 // I.e. we leave rnEndPos unmodified.
717 m_aCurToken
.eType
= TLBRACKET
;
718 m_aCurToken
.cMathChar
= MS_LBRACKET
;
719 m_aCurToken
.nGroup
= TGLBRACES
;
720 m_aCurToken
.nLevel
= 5;
721 m_aCurToken
.aText
= "[";
726 m_aCurToken
.eType
= TESCAPE
;
727 m_aCurToken
.cMathChar
= '\0';
728 m_aCurToken
.nGroup
= 0;
729 m_aCurToken
.nLevel
= 5;
730 m_aCurToken
.aText
= "\\";
735 m_aCurToken
.eType
= TRBRACKET
;
736 m_aCurToken
.cMathChar
= MS_RBRACKET
;
737 m_aCurToken
.nGroup
= TGRBRACES
;
738 m_aCurToken
.nLevel
= 0;
739 m_aCurToken
.aText
= "]";
744 m_aCurToken
.eType
= TRSUP
;
745 m_aCurToken
.cMathChar
= '\0';
746 m_aCurToken
.nGroup
= TGPOWER
;
747 m_aCurToken
.nLevel
= 0;
748 m_aCurToken
.aText
= "^";
753 m_aCurToken
.eType
= TSBLANK
;
754 m_aCurToken
.cMathChar
= '\0';
755 m_aCurToken
.nGroup
= TGBLANK
;
756 m_aCurToken
.nLevel
= 5;
757 m_aCurToken
.aText
= "`";
762 m_aCurToken
.eType
= TLGROUP
;
763 m_aCurToken
.cMathChar
= MS_LBRACE
;
764 m_aCurToken
.nGroup
= 0;
765 m_aCurToken
.nLevel
= 5;
766 m_aCurToken
.aText
= "{";
771 m_aCurToken
.eType
= TOR
;
772 m_aCurToken
.cMathChar
= MS_OR
;
773 m_aCurToken
.nGroup
= TGSUM
;
774 m_aCurToken
.nLevel
= 0;
775 m_aCurToken
.aText
= "|";
780 m_aCurToken
.eType
= TRGROUP
;
781 m_aCurToken
.cMathChar
= MS_RBRACE
;
782 m_aCurToken
.nGroup
= 0;
783 m_aCurToken
.nLevel
= 0;
784 m_aCurToken
.aText
= "}";
789 m_aCurToken
.eType
= TBLANK
;
790 m_aCurToken
.cMathChar
= '\0';
791 m_aCurToken
.nGroup
= TGBLANK
;
792 m_aCurToken
.nLevel
= 5;
793 m_aCurToken
.aText
= "~";
798 if (m_aBufferString
.Copy( nRealStart
, 2 ).
801 m_aCurToken
.eType
= TDPOUND
;
802 m_aCurToken
.cMathChar
= '\0';
803 m_aCurToken
.nGroup
= 0;
804 m_aCurToken
.nLevel
= 0;
805 m_aCurToken
.aText
= "##";
807 rnEndPos
= nRealStart
+ 2;
811 m_aCurToken
.eType
= TPOUND
;
812 m_aCurToken
.cMathChar
= '\0';
813 m_aCurToken
.nGroup
= 0;
814 m_aCurToken
.nLevel
= 0;
815 m_aCurToken
.aText
= "#";
821 m_aCurToken
.eType
= TAND
;
822 m_aCurToken
.cMathChar
= MS_AND
;
823 m_aCurToken
.nGroup
= TGPRODUCT
;
824 m_aCurToken
.nLevel
= 0;
825 m_aCurToken
.aText
= "&";
830 m_aCurToken
.eType
= TLPARENT
;
831 m_aCurToken
.cMathChar
= MS_LPARENT
;
832 m_aCurToken
.nGroup
= TGLBRACES
;
833 m_aCurToken
.nLevel
= 5; //! 0 to continue expression
834 m_aCurToken
.aText
= "(";
839 m_aCurToken
.eType
= TRPARENT
;
840 m_aCurToken
.cMathChar
= MS_RPARENT
;
841 m_aCurToken
.nGroup
= TGRBRACES
;
842 m_aCurToken
.nLevel
= 0; //! 0 to terminate expression
843 m_aCurToken
.aText
= ")";
848 m_aCurToken
.eType
= TMULTIPLY
;
849 m_aCurToken
.cMathChar
= MS_MULTIPLY
;
850 m_aCurToken
.nGroup
= TGPRODUCT
;
851 m_aCurToken
.nLevel
= 0;
852 m_aCurToken
.aText
= "*";
857 if (m_aBufferString
.Copy( nRealStart
, 2 ).
860 m_aCurToken
.eType
= TPLUSMINUS
;
861 m_aCurToken
.cMathChar
= MS_PLUSMINUS
;
862 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
863 m_aCurToken
.nLevel
= 5;
864 m_aCurToken
.aText
= "+-";
866 rnEndPos
= nRealStart
+ 2;
870 m_aCurToken
.eType
= TPLUS
;
871 m_aCurToken
.cMathChar
= MS_PLUS
;
872 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
873 m_aCurToken
.nLevel
= 5;
874 m_aCurToken
.aText
= "+";
880 if (m_aBufferString
.Copy( nRealStart
, 2 ).
883 m_aCurToken
.eType
= TMINUSPLUS
;
884 m_aCurToken
.cMathChar
= MS_MINUSPLUS
;
885 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
886 m_aCurToken
.nLevel
= 5;
887 m_aCurToken
.aText
= "-+";
889 rnEndPos
= nRealStart
+ 2;
893 m_aCurToken
.eType
= TMINUS
;
894 m_aCurToken
.cMathChar
= MS_MINUS
;
895 m_aCurToken
.nGroup
= TGUNOPER
| TGSUM
;
896 m_aCurToken
.nLevel
= 5;
897 m_aCurToken
.aText
= "-";
903 // for compatibility with SO5.2
904 // texts like .34 ...56 ... h ...78..90
905 // will be treated as numbers
906 m_aCurToken
.eType
= TNUMBER
;
907 m_aCurToken
.cMathChar
= '\0';
908 m_aCurToken
.nGroup
= 0;
909 m_aCurToken
.nLevel
= 5;
911 xub_StrLen nTxtStart
= m_nBufferIndex
;
915 cChar
= m_aBufferString
.GetChar( ++m_nBufferIndex
);
917 while ( cChar
== '.' || CharClass::isAsciiDigit( cChar
) );
919 m_aCurToken
.aText
= m_aBufferString
.Copy( sal::static_int_cast
< xub_StrLen
>(nTxtStart
),
920 sal::static_int_cast
< xub_StrLen
>(m_nBufferIndex
- nTxtStart
) );
921 aRes
.EndPos
= m_nBufferIndex
;
926 m_aCurToken
.eType
= TDIVIDEBY
;
927 m_aCurToken
.cMathChar
= MS_SLASH
;
928 m_aCurToken
.nGroup
= TGPRODUCT
;
929 m_aCurToken
.nLevel
= 0;
930 m_aCurToken
.aText
= "/";
935 m_aCurToken
.eType
= TASSIGN
;
936 m_aCurToken
.cMathChar
= MS_ASSIGN
;
937 m_aCurToken
.nGroup
= TGRELATION
;
938 m_aCurToken
.nLevel
= 0;
939 m_aCurToken
.aText
= "=";
952 m_aCurToken
.eType
= TCHARACTER
;
953 m_aCurToken
.cMathChar
= '\0';
954 m_aCurToken
.nGroup
= 0;
955 m_aCurToken
.nLevel
= 5;
956 m_aCurToken
.aText
= m_aBufferString
.Copy( nRealStart
, 1 );
958 aRes
.EndPos
= nRealStart
+ 1;
961 if (TEND
!= m_aCurToken
.eType
)
962 m_nBufferIndex
= sal::static_int_cast
< xub_StrLen
>(aRes
.EndPos
);
966 ////////////////////////////////////////
971 void SmParser::Table()
973 SmNodeArray LineArray
;
976 while (m_aCurToken
.eType
== TNEWLINE
)
982 if (m_aCurToken
.eType
!= TEND
)
983 Error(PE_UNEXPECTED_CHAR
);
985 sal_uLong n
= m_aNodeStack
.size();
989 for (sal_uLong i
= 0; i
< n
; i
++)
991 LineArray
[n
- (i
+ 1)] = m_aNodeStack
.top();
995 SmStructureNode
*pSNode
= new SmTableNode(m_aCurToken
);
996 pSNode
->SetSubNodes(LineArray
);
997 m_aNodeStack
.push(pSNode
);
1001 void SmParser::Align()
1002 // parse alignment info (if any), then go on with rest of expression
1004 SmStructureNode
*pSNode
= 0;
1005 bool bNeedGroupClose
= false;
1007 if (TokenInGroup(TGALIGN
))
1009 if (CONVERT_40_TO_50
== GetConversion())
1010 // encapsulate expression to be aligned in group braces
1011 // (here group-open brace)
1012 { Insert(OUString('{'), GetTokenIndex());
1013 bNeedGroupClose
= true;
1015 // get first valid align statement in sequence
1016 // (the dominant one in 4.0) and erase all others (especially old
1017 // discarded tokens) from command string.
1018 while (TokenInGroup(TGALIGN
))
1020 if (TokenInGroup(TGDISCARDED
) || pSNode
)
1022 m_nBufferIndex
= GetTokenIndex();
1023 m_aBufferString
.Erase(m_nBufferIndex
, m_aCurToken
.aText
.getLength());
1026 pSNode
= new SmAlignNode(m_aCurToken
);
1033 pSNode
= new SmAlignNode(m_aCurToken
);
1037 // allow for just one align statement in 5.0
1038 if (CONVERT_40_TO_50
!= GetConversion() && TokenInGroup(TGALIGN
))
1040 Error(PE_DOUBLE_ALIGN
);
1049 if (bNeedGroupClose
)
1050 Insert(OUString('}'), GetTokenIndex());
1054 pSNode
->SetSubNodes(lcl_popOrZero(m_aNodeStack
), 0);
1055 m_aNodeStack
.push(pSNode
);
1060 void SmParser::Line()
1063 SmNodeArray ExpressionArray
;
1065 ExpressionArray
.resize(n
);
1067 // start with single expression that may have an alignment statement
1068 // (and go on with expressions that must not have alignment
1069 // statements in 'while' loop below. See also 'Expression()'.)
1070 if (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TNEWLINE
)
1072 ExpressionArray
.resize(++n
);
1073 ExpressionArray
[n
- 1] = lcl_popOrZero(m_aNodeStack
);
1076 while (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TNEWLINE
)
1077 { if (CONVERT_40_TO_50
!= GetConversion())
1081 ExpressionArray
.resize(++n
);
1082 ExpressionArray
[n
- 1] = lcl_popOrZero(m_aNodeStack
);
1085 //If there's no expression, add an empty one.
1086 //this is to avoid a formula tree without any caret
1087 //positions, in visual formula editor.
1088 if(ExpressionArray
.empty())
1089 ExpressionArray
.push_back(new SmExpressionNode(SmToken()));
1091 SmStructureNode
*pSNode
= new SmLineNode(m_aCurToken
);
1092 pSNode
->SetSubNodes(ExpressionArray
);
1093 m_aNodeStack
.push(pSNode
);
1097 void SmParser::Expression()
1099 bool bUseExtraSpaces
= true;
1100 if (!m_aNodeStack
.empty())
1102 SmNode
*pNode
= m_aNodeStack
.top();
1104 if (pNode
->GetToken().eType
== TNOSPACE
)
1105 bUseExtraSpaces
= false;
1107 m_aNodeStack
.push(pNode
); // push the node from above again (now to be used as argument to this current 'nospace' node)
1111 SmNodeArray RelationArray
;
1113 RelationArray
.resize(n
);
1116 RelationArray
.resize(++n
);
1117 RelationArray
[n
- 1] = lcl_popOrZero(m_aNodeStack
);
1119 while (m_aCurToken
.nLevel
>= 4)
1121 RelationArray
.resize(++n
);
1122 RelationArray
[n
- 1] = lcl_popOrZero(m_aNodeStack
);
1125 SmExpressionNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
1126 pSNode
->SetSubNodes(RelationArray
);
1127 pSNode
->SetUseExtraSpaces(bUseExtraSpaces
);
1128 m_aNodeStack
.push(pSNode
);
1132 void SmParser::Relation()
1135 while (TokenInGroup(TGRELATION
))
1137 SmStructureNode
*pSNode
= new SmBinHorNode(m_aCurToken
);
1138 SmNode
*pFirst
= lcl_popOrZero(m_aNodeStack
);
1141 SmNode
*pSecond
= lcl_popOrZero(m_aNodeStack
);
1145 pSNode
->SetSubNodes(pFirst
, pSecond
, lcl_popOrZero(m_aNodeStack
));
1146 m_aNodeStack
.push(pSNode
);
1151 void SmParser::Sum()
1154 while (TokenInGroup(TGSUM
))
1156 SmStructureNode
*pSNode
= new SmBinHorNode(m_aCurToken
);
1157 SmNode
*pFirst
= lcl_popOrZero(m_aNodeStack
);
1160 SmNode
*pSecond
= lcl_popOrZero(m_aNodeStack
);
1164 pSNode
->SetSubNodes(pFirst
, pSecond
, lcl_popOrZero(m_aNodeStack
));
1165 m_aNodeStack
.push(pSNode
);
1170 void SmParser::Product()
1174 while (TokenInGroup(TGPRODUCT
))
1175 { SmStructureNode
*pSNode
;
1176 SmNode
*pFirst
= lcl_popOrZero(m_aNodeStack
),
1178 bool bSwitchArgs
= false;
1180 SmTokenType eType
= m_aCurToken
.eType
;
1184 pSNode
= new SmBinVerNode(m_aCurToken
);
1185 pOper
= new SmRectangleNode(m_aCurToken
);
1190 pSNode
= new SmBinHorNode(m_aCurToken
);
1194 //Let the glyph node know it's a binary operation
1195 m_aCurToken
.eType
= TBOPER
;
1196 m_aCurToken
.nGroup
= TGPRODUCT
;
1199 pOper
= lcl_popOrZero(m_aNodeStack
);
1204 pSNode
= new SmVerticalBraceNode(m_aCurToken
);
1205 pOper
= new SmMathSymbolNode(m_aCurToken
);
1210 case TWIDEBACKSLASH
:
1213 SmBinDiagonalNode
*pSTmp
= new SmBinDiagonalNode(m_aCurToken
);
1214 pSTmp
->SetAscending(eType
== TWIDESLASH
);
1217 pOper
= new SmPolyLineNode(m_aCurToken
);
1225 pSNode
= new SmBinHorNode(m_aCurToken
);
1228 pOper
= lcl_popOrZero(m_aNodeStack
);
1235 //! vgl siehe SmBinDiagonalNode::Arrange
1236 pSNode
->SetSubNodes(pFirst
, lcl_popOrZero(m_aNodeStack
), pOper
);
1240 pSNode
->SetSubNodes(pFirst
, pOper
, lcl_popOrZero(m_aNodeStack
));
1242 m_aNodeStack
.push(pSNode
);
1247 void SmParser::SubSup(sal_uLong nActiveGroup
)
1249 OSL_ENSURE(nActiveGroup
== TGPOWER
|| nActiveGroup
== TGLIMIT
,
1250 "Sm: wrong token group");
1252 if (!TokenInGroup(nActiveGroup
))
1256 SmSubSupNode
*pNode
= new SmSubSupNode(m_aCurToken
);
1257 //! Of course 'm_aCurToken' is just the first sub-/supscript token.
1258 //! It should be of no further interest. The positions of the
1259 //! sub-/supscripts will be identified by the corresponding subnodes
1260 //! index in the 'aSubNodes' array (enum value from 'SmSubSup').
1262 pNode
->SetUseLimits(nActiveGroup
== TGLIMIT
);
1264 // initialize subnodes array
1265 SmNodeArray aSubNodes
;
1266 aSubNodes
.resize(1 + SUBSUP_NUM_ENTRIES
);
1267 aSubNodes
[0] = lcl_popOrZero(m_aNodeStack
);
1268 for (sal_uInt16 i
= 1; i
< aSubNodes
.size(); i
++)
1269 aSubNodes
[i
] = NULL
;
1271 // process all sub-/supscripts
1273 while (TokenInGroup(nActiveGroup
))
1274 { SmTokenType
eType (m_aCurToken
.eType
);
1276 // skip sub-/supscript token
1279 // get sub-/supscript node on top of stack
1280 if (eType
== TFROM
|| eType
== TTO
)
1282 // parse limits in old 4.0 and 5.0 style
1289 { case TRSUB
: nIndex
= (int) RSUB
; break;
1290 case TRSUP
: nIndex
= (int) RSUP
; break;
1292 case TCSUB
: nIndex
= (int) CSUB
; break;
1294 case TCSUP
: nIndex
= (int) CSUP
; break;
1295 case TLSUB
: nIndex
= (int) LSUB
; break;
1296 case TLSUP
: nIndex
= (int) LSUP
; break;
1298 OSL_FAIL("Sm: unknown case");
1301 OSL_ENSURE(1 <= nIndex
&& nIndex
<= 1 + SUBSUP_NUM_ENTRIES
,
1302 "SmParser::Power() : sub-/supscript index falsch");
1304 // set sub-/supscript if not already done
1305 if (aSubNodes
[nIndex
] != NULL
)
1306 Error(PE_DOUBLE_SUBSUPSCRIPT
);
1307 aSubNodes
[nIndex
] = lcl_popOrZero(m_aNodeStack
);
1310 pNode
->SetSubNodes(aSubNodes
);
1311 m_aNodeStack
.push(pNode
);
1315 void SmParser::OpSubSup()
1317 // push operator symbol
1318 m_aNodeStack
.push(new SmMathSymbolNode(m_aCurToken
));
1319 // skip operator token
1321 // get sub- supscripts if any
1322 if (TokenInGroup(TGPOWER
))
1327 void SmParser::Power()
1329 // get body for sub- supscripts on top of stack
1336 void SmParser::Blank()
1338 OSL_ENSURE(TokenInGroup(TGBLANK
), "Sm : wrong token");
1339 SmBlankNode
*pBlankNode
= new SmBlankNode(m_aCurToken
);
1341 while (TokenInGroup(TGBLANK
))
1343 pBlankNode
->IncreaseBy(m_aCurToken
);
1347 // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist
1348 if ( m_aCurToken
.eType
== TNEWLINE
||
1349 (m_aCurToken
.eType
== TEND
&& SM_MOD()->GetConfig()->IsIgnoreSpacesRight()) )
1351 pBlankNode
->Clear();
1354 m_aNodeStack
.push(pBlankNode
);
1358 void SmParser::Term()
1360 switch (m_aCurToken
.eType
)
1369 bool bNoSpace
= m_aCurToken
.eType
== TNOSPACE
;
1370 if (bNoSpace
) // push 'no space' node and continue to parse expression
1372 m_aNodeStack
.push(new SmExpressionNode(m_aCurToken
));
1375 if (m_aCurToken
.eType
!= TLGROUP
)
1377 m_aNodeStack
.pop(); // get rid of the 'no space' node pushed above
1384 // allow for empty group
1385 if (m_aCurToken
.eType
== TRGROUP
)
1387 if (bNoSpace
) // get rid of the 'no space' node pushed above
1389 SmStructureNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
1390 pSNode
->SetSubNodes(NULL
, NULL
);
1391 m_aNodeStack
.push(pSNode
);
1398 if (m_aCurToken
.eType
!= TRGROUP
)
1399 Error(PE_RGROUP_EXPECTED
);
1417 m_aNodeStack
.push(new SmTextNode(m_aCurToken
, FNT_TEXT
));
1422 m_aNodeStack
.push(new SmTextNode(m_aCurToken
, FNT_VARIABLE
));
1426 m_aNodeStack
.push(new SmTextNode(m_aCurToken
, FNT_NUMBER
));
1464 m_aNodeStack
.push(new SmMathSymbolNode(m_aCurToken
));
1469 m_aNodeStack
.push(new SmPlaceNode(m_aCurToken
));
1490 if (TokenInGroup(TGLBRACES
))
1493 else if (TokenInGroup(TGOPER
))
1496 else if (TokenInGroup(TGUNOPER
))
1499 else if ( TokenInGroup(TGATTRIBUT
)
1500 || TokenInGroup(TGFONTATTR
))
1501 { SmStructureNodeArray aArray
;
1505 while (true == (bIsAttr
= TokenInGroup(TGATTRIBUT
))
1506 || TokenInGroup(TGFONTATTR
))
1507 { aArray
.resize(n
+ 1);
1514 SmNode
* pTmp
= lcl_popOrZero(m_aNodeStack
);
1516 // check if casting in following line is ok
1517 OSL_ENSURE(pTmp
&& !pTmp
->IsVisible(), "Sm : Ooops...");
1519 aArray
[n
] = (SmStructureNode
*) pTmp
;
1525 SmNode
*pFirstNode
= lcl_popOrZero(m_aNodeStack
);
1527 { aArray
[n
- 1]->SetSubNodes(0, pFirstNode
);
1528 pFirstNode
= aArray
[n
- 1];
1531 m_aNodeStack
.push(pFirstNode
);
1533 else if (TokenInGroup(TGFUNCTION
))
1534 { if (CONVERT_40_TO_50
!= GetConversion())
1537 else // encapsulate old 4.0 style parsing in braces
1539 // insert opening brace
1540 Insert(OUString('{'), GetTokenIndex());
1543 // parse in 4.0 style
1547 SmNode
*pFunc
= lcl_popOrZero(m_aNodeStack
);
1549 if (m_aCurToken
.eType
== TLPARENT
)
1556 // insert closing brace
1557 Insert(OUString('}'), GetTokenIndex());
1559 SmStructureNode
*pSNode
= new SmExpressionNode(pFunc
->GetToken());
1560 pSNode
->SetSubNodes(pFunc
, lcl_popOrZero(m_aNodeStack
));
1561 m_aNodeStack
.push(pSNode
);
1565 Error(PE_UNEXPECTED_CHAR
);
1570 void SmParser::Escape()
1574 switch (m_aCurToken
.eType
)
1598 Error(PE_UNEXPECTED_TOKEN
);
1601 SmNode
*pNode
= new SmMathSymbolNode(m_aCurToken
);
1602 m_aNodeStack
.push(pNode
);
1608 void SmParser::Operator()
1610 if (TokenInGroup(TGOPER
))
1611 { SmStructureNode
*pSNode
= new SmOperNode(m_aCurToken
);
1613 // put operator on top of stack
1616 if (TokenInGroup(TGLIMIT
) || TokenInGroup(TGPOWER
))
1617 SubSup(m_aCurToken
.nGroup
);
1618 SmNode
*pOperator
= lcl_popOrZero(m_aNodeStack
);
1623 pSNode
->SetSubNodes(pOperator
, lcl_popOrZero(m_aNodeStack
));
1624 m_aNodeStack
.push(pSNode
);
1629 void SmParser::Oper()
1631 SmTokenType
eType (m_aCurToken
.eType
);
1632 SmNode
*pNode
= NULL
;
1645 pNode
= new SmMathSymbolNode(m_aCurToken
);
1652 const sal_Char
* pLim
= 0;
1655 case TLIM
: pLim
= "lim"; break;
1656 case TLIMSUP
: pLim
= "lim sup"; break;
1657 case TLIMINF
: pLim
= "lim inf"; break;
1662 m_aCurToken
.aText
= OUString::createFromAscii(pLim
);
1663 pNode
= new SmTextNode(m_aCurToken
, FNT_TEXT
);
1669 pNode
= new SmMathSymbolNode(m_aCurToken
);
1675 OSL_ENSURE(m_aCurToken
.eType
== TSPECIAL
, "Sm: wrong token");
1676 pNode
= new SmGlyphSpecialNode(m_aCurToken
);
1680 OSL_FAIL("Sm: unknown case");
1682 m_aNodeStack
.push(pNode
);
1688 void SmParser::UnOper()
1690 OSL_ENSURE(TokenInGroup(TGUNOPER
), "Sm: wrong token");
1692 SmToken aNodeToken
= m_aCurToken
;
1693 SmTokenType eType
= m_aCurToken
.eType
;
1694 bool bIsPostfix
= eType
== TFACT
;
1696 SmStructureNode
*pSNode
;
1711 pExtra
= lcl_popOrZero(m_aNodeStack
);
1716 //Let the glyph know what it is...
1717 m_aCurToken
.eType
= TUOPER
;
1718 m_aCurToken
.nGroup
= TGUNOPER
;
1720 pOper
= lcl_popOrZero(m_aNodeStack
);
1730 pOper
= lcl_popOrZero(m_aNodeStack
);
1734 Error(PE_UNOPER_EXPECTED
);
1739 pArg
= lcl_popOrZero(m_aNodeStack
);
1742 { pSNode
= new SmBraceNode(aNodeToken
);
1743 pSNode
->SetScaleMode(SCALE_HEIGHT
);
1745 // build nodes for left & right lines
1746 // (text, group, level of the used token are of no interrest here)
1747 // we'll use row & column of the keyword for abs
1748 aNodeToken
.eType
= TABS
;
1750 aNodeToken
.cMathChar
= MS_LINE
;
1751 SmNode
* pLeft
= new SmMathSymbolNode(aNodeToken
);
1753 aNodeToken
.cMathChar
= MS_LINE
;
1754 SmNode
* pRight
= new SmMathSymbolNode(aNodeToken
);
1756 pSNode
->SetSubNodes(pLeft
, pArg
, pRight
);
1758 else if (eType
== TSQRT
|| eType
== TNROOT
)
1759 { pSNode
= new SmRootNode(aNodeToken
);
1760 pOper
= new SmRootSymbolNode(aNodeToken
);
1761 pSNode
->SetSubNodes(pExtra
, pOper
, pArg
);
1764 { pSNode
= new SmUnHorNode(aNodeToken
);
1767 pSNode
->SetSubNodes(pArg
, pOper
);
1770 pSNode
->SetSubNodes(pOper
, pArg
);
1773 m_aNodeStack
.push(pSNode
);
1777 void SmParser::Attribut()
1779 OSL_ENSURE(TokenInGroup(TGATTRIBUT
), "Sm: wrong token group");
1781 SmStructureNode
*pSNode
= new SmAttributNode(m_aCurToken
);
1783 SmScaleMode eScaleMode
= SCALE_NONE
;
1785 // get appropriate node for the attribut itself
1786 switch (m_aCurToken
.eType
)
1790 pAttr
= new SmRectangleNode(m_aCurToken
);
1791 eScaleMode
= SCALE_WIDTH
;
1797 pAttr
= new SmMathSymbolNode(m_aCurToken
);
1798 eScaleMode
= SCALE_WIDTH
;
1802 pAttr
= new SmMathSymbolNode(m_aCurToken
);
1807 pSNode
->SetSubNodes(pAttr
, 0);
1808 pSNode
->SetScaleMode(eScaleMode
);
1809 m_aNodeStack
.push(pSNode
);
1813 void SmParser::FontAttribut()
1815 OSL_ENSURE(TokenInGroup(TGFONTATTR
), "Sm: wrong token group");
1817 switch (m_aCurToken
.eType
)
1824 m_aNodeStack
.push(new SmFontNode(m_aCurToken
));
1841 OSL_FAIL("Sm: unknown case");
1846 void SmParser::Color()
1848 OSL_ENSURE(m_aCurToken
.eType
== TCOLOR
, "Sm : Ooops...");
1850 // last color rules, get that one
1855 if (TokenInGroup(TGCOLOR
))
1856 { aToken
= m_aCurToken
;
1860 Error(PE_COLOR_EXPECTED
);
1861 } while (m_aCurToken
.eType
== TCOLOR
);
1863 m_aNodeStack
.push(new SmFontNode(aToken
));
1867 void SmParser::Font()
1869 OSL_ENSURE(m_aCurToken
.eType
== TFONT
, "Sm : Ooops...");
1871 // last font rules, get that one
1876 if (TokenInGroup(TGFONT
))
1877 { aToken
= m_aCurToken
;
1881 Error(PE_FONT_EXPECTED
);
1882 } while (m_aCurToken
.eType
== TFONT
);
1884 m_aNodeStack
.push(new SmFontNode(aToken
));
1888 // gets number used as arguments in Math formulas (e.g. 'size' command)
1889 // Format: no negative numbers, must start with a digit, no exponent notation, ...
1890 static bool lcl_IsNumber(const OUString
& rText
)
1892 bool bPoint
= false;
1893 const sal_Unicode
* pBuffer
= rText
.getStr();
1894 for(sal_Int32 nPos
= 0; nPos
< rText
.getLength(); nPos
++, pBuffer
++)
1896 const sal_Unicode cChar
= *pBuffer
;
1904 else if ( !CharClass::isAsciiDigit( cChar
) )
1910 void SmParser::FontSize()
1912 OSL_ENSURE(m_aCurToken
.eType
== TSIZE
, "Sm : Ooops...");
1915 SmFontNode
*pFontNode
= new SmFontNode(m_aCurToken
);
1919 switch (m_aCurToken
.eType
)
1921 case TNUMBER
: Type
= FNTSIZ_ABSOLUT
; break;
1922 case TPLUS
: Type
= FNTSIZ_PLUS
; break;
1923 case TMINUS
: Type
= FNTSIZ_MINUS
; break;
1924 case TMULTIPLY
: Type
= FNTSIZ_MULTIPLY
; break;
1925 case TDIVIDEBY
: Type
= FNTSIZ_DIVIDE
; break;
1929 Error(PE_SIZE_EXPECTED
);
1933 if (Type
!= FNTSIZ_ABSOLUT
)
1936 if (m_aCurToken
.eType
!= TNUMBER
)
1939 Error(PE_SIZE_EXPECTED
);
1944 // get number argument
1945 Fraction
aValue( 1L );
1946 if (lcl_IsNumber( m_aCurToken
.aText
))
1948 double fTmp
= OUString(m_aCurToken
.aText
).toDouble();
1953 //!! keep the numerator and denominator from being to large
1954 //!! otherwise ongoing multiplications may result in overflows
1955 //!! (for example in SmNode::SetFontSize the font size calculated
1956 //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux
1957 //!! or ftmp = 1.11111111111111111... (11/9) on every platform.)
1958 if (aValue
.GetDenominator() > 1000)
1960 long nNum
= aValue
.GetNumerator();
1961 long nDenom
= aValue
.GetDenominator();
1962 while (nDenom
> 1000)
1967 aValue
= Fraction( nNum
, nDenom
);
1974 pFontNode
->SetSizeParameter(aValue
, Type
);
1975 m_aNodeStack
.push(pFontNode
);
1979 void SmParser::Brace()
1981 OSL_ENSURE(m_aCurToken
.eType
== TLEFT
|| TokenInGroup(TGLBRACES
),
1982 "Sm: kein Klammer Ausdruck");
1984 SmStructureNode
*pSNode
= new SmBraceNode(m_aCurToken
);
1988 SmScaleMode eScaleMode
= SCALE_NONE
;
1989 SmParseError eError
= PE_NONE
;
1991 if (m_aCurToken
.eType
== TLEFT
)
1994 eScaleMode
= SCALE_HEIGHT
;
1996 // check for left bracket
1997 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
1999 pLeft
= new SmMathSymbolNode(m_aCurToken
);
2003 pBody
= lcl_popOrZero(m_aNodeStack
);
2005 if (m_aCurToken
.eType
== TRIGHT
)
2008 // check for right bracket
2009 if (TokenInGroup(TGLBRACES
) || TokenInGroup(TGRBRACES
))
2011 pRight
= new SmMathSymbolNode(m_aCurToken
);
2015 eError
= PE_RBRACE_EXPECTED
;
2018 eError
= PE_RIGHT_EXPECTED
;
2021 eError
= PE_LBRACE_EXPECTED
;
2025 if (TokenInGroup(TGLBRACES
))
2027 pLeft
= new SmMathSymbolNode(m_aCurToken
);
2031 pBody
= lcl_popOrZero(m_aNodeStack
);
2033 SmTokenType eExpectedType
= TUNKNOWN
;
2034 switch (pLeft
->GetToken().eType
)
2035 { case TLPARENT
: eExpectedType
= TRPARENT
; break;
2036 case TLBRACKET
: eExpectedType
= TRBRACKET
; break;
2037 case TLBRACE
: eExpectedType
= TRBRACE
; break;
2038 case TLDBRACKET
: eExpectedType
= TRDBRACKET
; break;
2039 case TLLINE
: eExpectedType
= TRLINE
; break;
2040 case TLDLINE
: eExpectedType
= TRDLINE
; break;
2041 case TLANGLE
: eExpectedType
= TRANGLE
; break;
2042 case TLFLOOR
: eExpectedType
= TRFLOOR
; break;
2043 case TLCEIL
: eExpectedType
= TRCEIL
; break;
2045 OSL_FAIL("Sm: unknown case");
2048 if (m_aCurToken
.eType
== eExpectedType
)
2050 pRight
= new SmMathSymbolNode(m_aCurToken
);
2054 eError
= PE_PARENT_MISMATCH
;
2057 eError
= PE_LBRACE_EXPECTED
;
2060 if (eError
== PE_NONE
)
2061 { OSL_ENSURE(pLeft
, "Sm: NULL pointer");
2062 OSL_ENSURE(pRight
, "Sm: NULL pointer");
2063 pSNode
->SetSubNodes(pLeft
, pBody
, pRight
);
2064 pSNode
->SetScaleMode(eScaleMode
);
2065 m_aNodeStack
.push(pSNode
);
2078 void SmParser::Bracebody(bool bIsLeftRight
)
2080 SmStructureNode
*pBody
= new SmBracebodyNode(m_aCurToken
);
2082 sal_uInt16 nNum
= 0;
2089 if (m_aCurToken
.eType
== TMLINE
)
2091 m_aNodeStack
.push(new SmMathSymbolNode(m_aCurToken
));
2095 else if (m_aCurToken
.eType
!= TRIGHT
)
2099 if (m_aCurToken
.eType
!= TMLINE
&& m_aCurToken
.eType
!= TRIGHT
)
2100 Error(PE_RIGHT_EXPECTED
);
2102 } while (m_aCurToken
.eType
!= TEND
&& m_aCurToken
.eType
!= TRIGHT
);
2108 if (m_aCurToken
.eType
== TMLINE
)
2110 m_aNodeStack
.push(new SmMathSymbolNode(m_aCurToken
));
2114 else if (!TokenInGroup(TGRBRACES
))
2118 if (m_aCurToken
.eType
!= TMLINE
&& !TokenInGroup(TGRBRACES
))
2119 Error(PE_RBRACE_EXPECTED
);
2121 } while (m_aCurToken
.eType
!= TEND
&& !TokenInGroup(TGRBRACES
));
2124 // build argument vector in parsing order
2125 aNodes
.resize(nNum
);
2126 for (sal_uInt16 i
= 0; i
< nNum
; i
++)
2128 aNodes
[nNum
- 1 - i
] = lcl_popOrZero(m_aNodeStack
);
2131 pBody
->SetSubNodes(aNodes
);
2132 pBody
->SetScaleMode(bIsLeftRight
? SCALE_HEIGHT
: SCALE_NONE
);
2133 m_aNodeStack
.push(pBody
);
2137 void SmParser::Function()
2139 switch (m_aCurToken
.eType
)
2142 NextToken(); // skip "FUNC"-statement
2164 m_aNodeStack
.push(new SmTextNode(m_aCurToken
, FNT_FUNCTION
));
2169 Error(PE_FUNC_EXPECTED
);
2174 void SmParser::Binom()
2176 SmNodeArray ExpressionArray
;
2177 SmStructureNode
*pSNode
= new SmTableNode(m_aCurToken
);
2184 ExpressionArray
.resize(2);
2186 for (int i
= 0; i
< 2; i
++)
2188 ExpressionArray
[2 - (i
+ 1)] = lcl_popOrZero(m_aNodeStack
);
2191 pSNode
->SetSubNodes(ExpressionArray
);
2192 m_aNodeStack
.push(pSNode
);
2196 void SmParser::Stack()
2198 SmNodeArray ExpressionArray
;
2200 if (m_aCurToken
.eType
== TLGROUP
)
2210 while (m_aCurToken
.eType
== TPOUND
);
2212 ExpressionArray
.resize(n
);
2214 for (sal_uInt16 i
= 0; i
< n
; i
++)
2216 ExpressionArray
[n
- (i
+ 1)] = lcl_popOrZero(m_aNodeStack
);
2219 if (m_aCurToken
.eType
!= TRGROUP
)
2220 Error(PE_RGROUP_EXPECTED
);
2224 //We need to let the table node know it context
2225 //it's used in SmNodeToTextVisitor
2226 SmToken aTok
= m_aCurToken
;
2227 aTok
.eType
= TSTACK
;
2228 SmStructureNode
*pSNode
= new SmTableNode(aTok
);
2229 pSNode
->SetSubNodes(ExpressionArray
);
2230 m_aNodeStack
.push(pSNode
);
2233 Error(PE_LGROUP_EXPECTED
);
2237 void SmParser::Matrix()
2239 SmNodeArray ExpressionArray
;
2242 if (m_aCurToken
.eType
== TLGROUP
)
2252 while (m_aCurToken
.eType
== TPOUND
);
2256 while (m_aCurToken
.eType
== TDPOUND
)
2259 for (sal_uInt16 i
= 0; i
< c
; i
++)
2264 if (m_aCurToken
.eType
== TPOUND
)
2269 Error(PE_POUND_EXPECTED
);
2278 ExpressionArray
.resize(nRC
);
2280 for (sal_uInt16 i
= 0; i
< (nRC
); i
++)
2282 ExpressionArray
[(nRC
) - (i
+ 1)] = lcl_popOrZero(m_aNodeStack
);
2285 if (m_aCurToken
.eType
!= TRGROUP
)
2286 Error(PE_RGROUP_EXPECTED
);
2290 SmMatrixNode
*pMNode
= new SmMatrixNode(m_aCurToken
);
2291 pMNode
->SetSubNodes(ExpressionArray
);
2292 pMNode
->SetRowCol(r
, c
);
2293 m_aNodeStack
.push(pMNode
);
2296 Error(PE_LGROUP_EXPECTED
);
2300 void SmParser::Special()
2302 bool bReplace
= false;
2303 OUString
&rName
= m_aCurToken
.aText
;
2306 if (CONVERT_NONE
== GetConversion())
2308 // conversion of symbol names for 6.0 (XML) file format
2309 // (name change on import / export.
2310 // UI uses localized names XML file format does not.)
2311 if (!rName
.isEmpty() && rName
[0] == '%')
2313 if (IsImportSymbolNames())
2315 const SmLocalizedSymbolData
&rLSD
= SM_MOD()->GetLocSymbolData();
2316 aNewName
= rLSD
.GetUiSymbolName(rName
.copy(1));
2319 else if (IsExportSymbolNames())
2321 const SmLocalizedSymbolData
&rLSD
= SM_MOD()->GetLocSymbolData();
2322 aNewName
= rLSD
.GetExportSymbolName(rName
.copy(1));
2326 if (!aNewName
.isEmpty())
2327 aNewName
= "%" + aNewName
;
2329 else // 5.0 <-> 6.0 formula text (symbol name) conversion
2331 LanguageType nLanguage
= GetLanguage();
2332 SmLocalizedSymbolData
&rData
= SM_MOD()->GetLocSymbolData();
2333 const ResStringArray
*pFrom
= 0;
2334 const ResStringArray
*pTo
= 0;
2335 if (CONVERT_50_TO_60
== GetConversion())
2337 pFrom
= rData
.Get50NamesArray( nLanguage
);
2338 pTo
= rData
.Get60NamesArray( nLanguage
);
2340 else if (CONVERT_60_TO_50
== GetConversion())
2342 pFrom
= rData
.Get60NamesArray( nLanguage
);
2343 pTo
= rData
.Get50NamesArray( nLanguage
);
2347 OSL_ENSURE( pFrom
->Count() == pTo
->Count(),
2348 "array length mismatch" );
2349 sal_uInt16 nCount
= sal::static_int_cast
< sal_uInt16
>(pFrom
->Count());
2350 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
2352 if (pFrom
->GetString(i
).equals(rName
))
2354 aNewName
= pTo
->GetString(i
);
2360 // conversion arrays not found or (usually)
2361 // conversion not necessary
2364 if (bReplace
&& !aNewName
.isEmpty() && rName
!= aNewName
)
2366 Replace(GetTokenIndex(), rName
.getLength(), aNewName
);
2370 // add symbol name to list of used symbols
2371 const OUString
aSymbolName(m_aCurToken
.aText
.copy(1));
2372 if (!aSymbolName
.isEmpty())
2373 AddToUsedSymbols( aSymbolName
);
2375 m_aNodeStack
.push(new SmSpecialNode(m_aCurToken
));
2380 void SmParser::GlyphSpecial()
2382 m_aNodeStack
.push(new SmGlyphSpecialNode(m_aCurToken
));
2387 void SmParser::Error(SmParseError eError
)
2389 SmStructureNode
*pSNode
= new SmExpressionNode(m_aCurToken
);
2390 SmErrorNode
*pErr
= new SmErrorNode(eError
, m_aCurToken
);
2391 pSNode
->SetSubNodes(pErr
, 0);
2393 //! put a structure node on the stack (instead of the error node itself)
2394 //! because sometimes such a node is expected in order to attach some
2396 m_aNodeStack
.push(pSNode
);
2398 AddError(eError
, pSNode
);
2407 SmParser::SmParser()
2408 : m_aDotLoc( LanguageTag( LANGUAGE_ENGLISH_US
).getLocale() )
2410 m_eConversion
= CONVERT_NONE
;
2411 bImportSymNames
= m_bExportSymNames
= false;
2412 m_nLang
= Application::GetSettings().GetUILanguageTag().getLanguageType();
2415 SmNode
*SmParser::Parse(const String
&rBuffer
)
2419 m_aBufferString
= convertLineEnd(rBuffer
, LINEEND_LF
);
2426 for ( size_t i
= 0, n
= m_aErrDescList
.size(); i
< n
; ++i
)
2427 delete m_aErrDescList
[ i
];
2428 m_aErrDescList
.clear();
2430 while ( !m_aNodeStack
.empty() )
2433 SetLanguage( Application::GetSettings().GetUILanguageTag().getLanguageType() );
2437 SmNode
* result
= lcl_popOrZero(m_aNodeStack
);
2441 SmNode
*SmParser::ParseExpression(const OUString
&rBuffer
)
2443 m_aBufferString
= convertLineEnd(rBuffer
, LINEEND_LF
);
2450 for ( size_t i
= 0, n
= m_aErrDescList
.size(); i
< n
; ++i
)
2451 delete m_aErrDescList
[ i
];
2452 m_aErrDescList
.clear();
2454 while ( !m_aNodeStack
.empty() )
2457 SetLanguage( Application::GetSettings().GetUILanguageTag().getLanguageType() );
2461 SmNode
* result
= lcl_popOrZero(m_aNodeStack
);
2466 size_t SmParser::AddError(SmParseError Type
, SmNode
*pNode
)
2468 SmErrorDesc
*pErrDesc
= new SmErrorDesc
;
2470 pErrDesc
->Type
= Type
;
2471 pErrDesc
->pNode
= pNode
;
2472 pErrDesc
->Text
= String(SmResId(RID_ERR_IDENT
));
2477 case PE_UNEXPECTED_CHAR
: nRID
= RID_ERR_UNEXPECTEDCHARACTER
; break;
2478 case PE_LGROUP_EXPECTED
: nRID
= RID_ERR_LGROUPEXPECTED
; break;
2479 case PE_RGROUP_EXPECTED
: nRID
= RID_ERR_RGROUPEXPECTED
; break;
2480 case PE_LBRACE_EXPECTED
: nRID
= RID_ERR_LBRACEEXPECTED
; break;
2481 case PE_RBRACE_EXPECTED
: nRID
= RID_ERR_RBRACEEXPECTED
; break;
2482 case PE_FUNC_EXPECTED
: nRID
= RID_ERR_FUNCEXPECTED
; break;
2483 case PE_UNOPER_EXPECTED
: nRID
= RID_ERR_UNOPEREXPECTED
; break;
2484 case PE_BINOPER_EXPECTED
: nRID
= RID_ERR_BINOPEREXPECTED
; break;
2485 case PE_SYMBOL_EXPECTED
: nRID
= RID_ERR_SYMBOLEXPECTED
; break;
2486 case PE_IDENTIFIER_EXPECTED
: nRID
= RID_ERR_IDENTEXPECTED
; break;
2487 case PE_POUND_EXPECTED
: nRID
= RID_ERR_POUNDEXPECTED
; break;
2488 case PE_COLOR_EXPECTED
: nRID
= RID_ERR_COLOREXPECTED
; break;
2489 case PE_RIGHT_EXPECTED
: nRID
= RID_ERR_RIGHTEXPECTED
; break;
2492 nRID
= RID_ERR_UNKNOWN
;
2494 pErrDesc
->Text
+= SM_RESSTR(nRID
);
2496 m_aErrDescList
.push_back( pErrDesc
);
2498 return m_aErrDescList
.size()-1;
2502 const SmErrorDesc
*SmParser::NextError()
2504 if ( !m_aErrDescList
.empty() )
2505 if (m_nCurError
> 0) return m_aErrDescList
[ --m_nCurError
];
2509 return m_aErrDescList
[ m_nCurError
];
2515 const SmErrorDesc
*SmParser::PrevError()
2517 if ( !m_aErrDescList
.empty() )
2518 if (m_nCurError
< (int) (m_aErrDescList
.size() - 1)) return m_aErrDescList
[ ++m_nCurError
];
2521 m_nCurError
= (int) (m_aErrDescList
.size() - 1);
2522 return m_aErrDescList
[ m_nCurError
];
2528 const SmErrorDesc
*SmParser::GetError(size_t i
)
2530 if ( i
< m_aErrDescList
.size() )
2531 return m_aErrDescList
[ i
];
2533 if ( (size_t)m_nCurError
< m_aErrDescList
.size() )
2534 return m_aErrDescList
[ m_nCurError
];
2539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */