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 .
20 #include <basic/sberrors.hxx>
21 #include <basic/sbxmeth.hxx>
22 #include <basic/sbmod.hxx>
23 #include <basic/sbstar.hxx>
24 #include <basic/sbx.hxx>
26 #include <com/sun/star/script/ModuleType.hpp>
27 #include <rtl/character.hxx>
29 struct SbiParseStack
{ // "Stack" for statement-blocks
30 SbiParseStack
* pNext
; // Chain
31 SbiExprNode
* pWithVar
;
33 sal_uInt32 nChain
; // JUMP-Chain
40 void( SbiParser::*Func
)();
41 bool bMain
; // true: OK outside the SUB
42 bool bSubr
; // true: OK inside the SUB
50 const SbiStatement StmntTable
[] = {
51 { ATTRIBUTE
, &SbiParser::Attribute
, Y
, Y
, }, // ATTRIBUTE
52 { CALL
, &SbiParser::Call
, N
, Y
, }, // CALL
53 { CLOSE
, &SbiParser::Close
, N
, Y
, }, // CLOSE
54 { CONST_
, &SbiParser::Dim
, Y
, Y
, }, // CONST
55 { DECLARE
, &SbiParser::Declare
, Y
, N
, }, // DECLARE
56 { DEFBOOL
, &SbiParser::DefXXX
, Y
, N
, }, // DEFBOOL
57 { DEFCUR
, &SbiParser::DefXXX
, Y
, N
, }, // DEFCUR
58 { DEFDATE
, &SbiParser::DefXXX
, Y
, N
, }, // DEFDATE
59 { DEFDBL
, &SbiParser::DefXXX
, Y
, N
, }, // DEFDBL
60 { DEFERR
, &SbiParser::DefXXX
, Y
, N
, }, // DEFERR
61 { DEFINT
, &SbiParser::DefXXX
, Y
, N
, }, // DEFINT
62 { DEFLNG
, &SbiParser::DefXXX
, Y
, N
, }, // DEFLNG
63 { DEFOBJ
, &SbiParser::DefXXX
, Y
, N
, }, // DEFOBJ
64 { DEFSNG
, &SbiParser::DefXXX
, Y
, N
, }, // DEFSNG
65 { DEFSTR
, &SbiParser::DefXXX
, Y
, N
, }, // DEFSTR
66 { DEFVAR
, &SbiParser::DefXXX
, Y
, N
, }, // DEFVAR
67 { DIM
, &SbiParser::Dim
, Y
, Y
, }, // DIM
68 { DO
, &SbiParser::DoLoop
, N
, Y
, }, // DO
69 { ELSE
, &SbiParser::NoIf
, N
, Y
, }, // ELSE
70 { ELSEIF
, &SbiParser::NoIf
, N
, Y
, }, // ELSEIF
71 { ENDIF
, &SbiParser::NoIf
, N
, Y
, }, // ENDIF
72 { END
, &SbiParser::Stop
, N
, Y
, }, // END
73 { ENUM
, &SbiParser::Enum
, Y
, N
, }, // TYPE
74 { ERASE
, &SbiParser::Erase
, N
, Y
, }, // ERASE
75 { ERROR_
, &SbiParser::ErrorStmnt
, N
, Y
, }, // ERROR
76 { EXIT
, &SbiParser::Exit
, N
, Y
, }, // EXIT
77 { FOR
, &SbiParser::For
, N
, Y
, }, // FOR
78 { FUNCTION
, &SbiParser::SubFunc
, Y
, N
, }, // FUNCTION
79 { GOSUB
, &SbiParser::Goto
, N
, Y
, }, // GOSUB
80 { GLOBAL
, &SbiParser::Dim
, Y
, N
, }, // GLOBAL
81 { GOTO
, &SbiParser::Goto
, N
, Y
, }, // GOTO
82 { IF
, &SbiParser::If
, N
, Y
, }, // IF
83 { IMPLEMENTS
, &SbiParser::Implements
, Y
, N
, }, // IMPLEMENTS
84 { INPUT
, &SbiParser::Input
, N
, Y
, }, // INPUT
85 { LET
, &SbiParser::Assign
, N
, Y
, }, // LET
86 { LINE
, &SbiParser::Line
, N
, Y
, }, // LINE, -> LINE INPUT (#i92642)
87 { LINEINPUT
,&SbiParser::LineInput
, N
, Y
, }, // LINE INPUT
88 { LOOP
, &SbiParser::BadBlock
, N
, Y
, }, // LOOP
89 { LSET
, &SbiParser::LSet
, N
, Y
, }, // LSET
90 { NAME
, &SbiParser::Name
, N
, Y
, }, // NAME
91 { NEXT
, &SbiParser::BadBlock
, N
, Y
, }, // NEXT
92 { ON
, &SbiParser::On
, N
, Y
, }, // ON
93 { OPEN
, &SbiParser::Open
, N
, Y
, }, // OPEN
94 { OPTION
, &SbiParser::Option
, Y
, N
, }, // OPTION
95 { PRINT
, &SbiParser::Print
, N
, Y
, }, // PRINT
96 { PRIVATE
, &SbiParser::Dim
, Y
, N
, }, // PRIVATE
97 { PROPERTY
, &SbiParser::SubFunc
, Y
, N
, }, // FUNCTION
98 { PUBLIC
, &SbiParser::Dim
, Y
, N
, }, // PUBLIC
99 { REDIM
, &SbiParser::ReDim
, N
, Y
, }, // DIM
100 { RESUME
, &SbiParser::Resume
, N
, Y
, }, // RESUME
101 { RETURN
, &SbiParser::Return
, N
, Y
, }, // RETURN
102 { RSET
, &SbiParser::RSet
, N
, Y
, }, // RSET
103 { SELECT
, &SbiParser::Select
, N
, Y
, }, // SELECT
104 { SET
, &SbiParser::Set
, N
, Y
, }, // SET
105 { STATIC
, &SbiParser::Static
, Y
, Y
, }, // STATIC
106 { STOP
, &SbiParser::Stop
, N
, Y
, }, // STOP
107 { SUB
, &SbiParser::SubFunc
, Y
, N
, }, // SUB
108 { TYPE
, &SbiParser::Type
, Y
, N
, }, // TYPE
109 { UNTIL
, &SbiParser::BadBlock
, N
, Y
, }, // UNTIL
110 { WHILE
, &SbiParser::While
, N
, Y
, }, // WHILE
111 { WEND
, &SbiParser::BadBlock
, N
, Y
, }, // WEND
112 { WITH
, &SbiParser::With
, N
, Y
, }, // WITH
113 { WRITE
, &SbiParser::Write
, N
, Y
, }, // WRITE
115 { NIL
, nullptr, N
, N
}
118 SbiParser::SbiParser( StarBASIC
* pb
, SbModule
* pm
)
119 : SbiTokenizer( pm
->GetSource32(), pb
),
126 bSingleLineIf(false),
127 bCodeCompleting(false),
128 aGlobals( aGblStrings
, SbGLOBAL
, this ),
129 aPublics( aGblStrings
, SbPUBLIC
, this ),
130 aRtlSyms( aGblStrings
, SbRTL
, this ),
135 bClassModule
= ( pm
->GetModuleType() == css::script::ModuleType::CLASS
);
137 for(SbxDataType
& eDefType
: eDefTypes
)
138 eDefType
= SbxVARIANT
; // no explicit default type
140 aPublics
.SetParent( &aGlobals
);
141 aGlobals
.SetParent( &aRtlSyms
);
144 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
146 rTypeArray
= new SbxArray
; // array for user defined types
147 rEnumArray
= new SbxArray
; // array for Enum types
148 bVBASupportOn
= pm
->IsVBASupport();
150 EnableCompatibility();
154 SbiParser::~SbiParser() { }
156 // part of the runtime-library?
157 SbiSymDef
* SbiParser::CheckRTLForSym(const OUString
& rSym
, SbxDataType eType
)
159 SbxVariable
* pVar
= GetBasic()->GetRtl()->Find(rSym
, SbxClassType::DontCare
);
163 if (SbxMethod
* pMethod
= dynamic_cast<SbxMethod
*>(pVar
))
165 SbiProcDef
* pProc_
= aRtlSyms
.AddProc( rSym
);
166 if (pMethod
->IsRuntimeFunction())
168 pProc_
->SetType( pMethod
->GetRuntimeFunctionReturnType() );
172 pProc_
->SetType( pVar
->GetType() );
178 SbiSymDef
* pDef
= aRtlSyms
.AddSym(rSym
);
179 pDef
->SetType(eType
);
183 // close global chain
185 bool SbiParser::HasGlobalCode()
187 if( bGblDefs
&& nGblChain
)
189 aGen
.BackChain( nGblChain
);
190 aGen
.Gen( SbiOpcode::LEAVE_
);
196 void SbiParser::OpenBlock( SbiToken eTok
, SbiExprNode
* pVar
)
198 SbiParseStack
* p
= new SbiParseStack
;
199 p
->eExitTok
= (eTok
== GET
|| eTok
== LET
|| eTok
== SET
) ? PROPERTY
: eTok
; // #i109051
201 p
->pWithVar
= pWithVar
;
206 // #29955 service the for-loop level
211 void SbiParser::CloseBlock()
216 SbiParseStack
* p
= pStack
;
218 // #29955 service the for-loop level
219 if( p
->eExitTok
== FOR
)
222 aGen
.BackChain( p
->nChain
);
224 pWithVar
= p
->pWithVar
;
230 void SbiParser::Exit()
232 SbiToken eTok
= Next();
233 for( SbiParseStack
* p
= pStack
; p
; p
= p
->pNext
)
235 if (eTok
== p
->eExitTok
)
237 p
->nChain
= aGen
.Gen( SbiOpcode::JUMP_
, p
->nChain
);
242 Error( ERRCODE_BASIC_EXPECTED
, pStack
->eExitTok
);
244 Error( ERRCODE_BASIC_BAD_EXIT
);
247 bool SbiParser::TestSymbol()
250 if( eCurTok
== SYMBOL
)
254 Error( ERRCODE_BASIC_SYMBOL_EXPECTED
);
259 bool SbiParser::TestToken( SbiToken t
)
267 Error( ERRCODE_BASIC_EXPECTED
, t
);
273 bool SbiParser::TestComma()
275 SbiToken eTok
= Peek();
281 else if( eTok
!= COMMA
)
283 Error( ERRCODE_BASIC_EXPECTED
, COMMA
);
291 void SbiParser::TestEoln()
293 if( !IsEoln( Next() ) )
295 Error( ERRCODE_BASIC_EXPECTED
, EOLN
);
296 while( !IsEoln( Next() ) ) {}
301 void SbiParser::StmntBlock( SbiToken eEnd
)
303 SbiToken xe
= eEndTok
;
305 while( !bAbort
&& Parse() ) {}
309 Error( ERRCODE_BASIC_BAD_BLOCK
, eEnd
);
314 void SbiParser::SetCodeCompleting( bool b
)
320 bool SbiParser::Parse()
322 if( bAbort
) return false;
326 bErrorIsSymbol
= false;
328 bErrorIsSymbol
= true;
332 // AB #33133: If no sub has been created before,
333 // the global chain must be closed here!
334 // AB #40689: Due to the new static-handling there
335 // can be another nGblChain, so ask for it before.
336 if( bNewGblDefs
&& nGblChain
== 0 )
337 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
342 if( IsEoln( eCurTok
) )
347 if( !bSingleLineIf
&& MayBeLabel( true ) )
351 Error( ERRCODE_BASIC_NOT_IN_MAIN
, aSym
);
353 pProc
->GetLabels().Define( aSym
);
356 if( IsEoln( eCurTok
) )
363 if( eCurTok
== eEndTok
||
364 ( bVBASupportOn
&& // #i109075
365 (eCurTok
== ENDFUNC
|| eCurTok
== ENDPROPERTY
|| eCurTok
== ENDSUB
) &&
366 (eEndTok
== ENDFUNC
|| eEndTok
== ENDPROPERTY
|| eEndTok
== ENDSUB
) ) )
380 // In vba it's possible to do Error.foobar ( even if it results in
382 if ( eCurTok
== ERROR_
&& IsVBASupportOn() ) // we probably need to define a subset of keywords where this madness applies e.g. if ( IsVBASupportOn() && SymbolCanBeRedined( eCurTok ) )
384 SbiTokenizer
tokens( *this );
386 if ( tokens
.Peek() == DOT
)
392 // if there's a symbol, it's either a variable (LET)
393 // or a SUB-procedure (CALL without brackets)
394 // DOT for assignments in the WITH-block: .A=5
395 if( eCurTok
== SYMBOL
|| eCurTok
== DOT
)
398 Error( ERRCODE_BASIC_EXPECTED
, SUB
);
401 // for correct line and column...
414 const SbiStatement
* p
;
415 for( p
= StmntTable
; p
->eTok
!= NIL
; p
++ )
416 if( p
->eTok
== eCurTok
)
420 if( !pProc
&& !p
->bMain
)
421 Error( ERRCODE_BASIC_NOT_IN_MAIN
, eCurTok
);
422 else if( pProc
&& !p
->bSubr
)
423 Error( ERRCODE_BASIC_NOT_IN_SUBR
, eCurTok
);
426 // AB #41606/#40689: Due to the new static-handling there
427 // can be another nGblChain, so ask for it before.
428 if( bNewGblDefs
&& nGblChain
== 0 &&
429 ( eCurTok
== SUB
|| eCurTok
== FUNCTION
|| eCurTok
== PROPERTY
) )
431 nGblChain
= aGen
.Gen( SbiOpcode::JUMP_
, 0 );
434 // statement-opcode at the beginning of a sub, too, please
435 if( ( p
->bSubr
&& (eCurTok
!= STATIC
|| Peek() == SUB
|| Peek() == FUNCTION
) ) ||
436 eCurTok
== SUB
|| eCurTok
== FUNCTION
)
438 (this->*( p
->Func
) )();
439 ErrCode nSbxErr
= SbxBase::GetError();
442 SbxBase::ResetError();
448 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
451 // test for the statement's end -
452 // might also be an ELSE, as there must not necessary be a : before the ELSE!
457 if( !IsEos() && eCurTok
!= ELSE
)
459 // if the parsing has been aborted, jump over to the ":"
460 Error( ERRCODE_BASIC_UNEXPECTED
, eCurTok
);
461 while( !IsEos() ) Next();
464 // The parser aborts at the end, the
465 // next token has not been fetched yet!
470 SbiExprNode
* SbiParser::GetWithVar()
475 SbiParseStack
* p
= pStack
;
478 // LoopVar can at the moment only be for with
487 // assignment or subroutine call
489 void SbiParser::Symbol( const KeywordSymbolInfo
* pKeywordSymbolInfo
)
491 SbiExprMode eMode
= bVBASupportOn
? EXPRMODE_STANDALONE
: EXPRMODE_STANDARD
;
492 SbiExpression
aVar( this, SbSYMBOL
, eMode
, pKeywordSymbolInfo
);
494 bool bEQ
= ( Peek() == EQ
);
495 if( !bEQ
&& bVBASupportOn
&& aVar
.IsBracket() )
496 Error( ERRCODE_BASIC_EXPECTED
, u
"="_ustr
);
498 RecursiveMode eRecMode
= ( bEQ
? PREVENT_CALL
: FORCE_CALL
);
499 bool bSpecialMidHandling
= false;
500 SbiSymDef
* pDef
= aVar
.GetRealVar();
501 if( bEQ
&& pDef
&& pDef
->GetScope() == SbRTL
)
503 OUString aRtlName
= pDef
->GetName();
504 if( aRtlName
.equalsIgnoreAsciiCase("Mid") )
506 SbiExprNode
* pExprNode
= aVar
.GetExprNode();
507 if( pExprNode
&& pExprNode
->GetNodeType() == SbxVARVAL
)
509 SbiExprList
* pPar
= pExprNode
->GetParameters();
510 short nParCount
= pPar
? pPar
->GetSize() : 0;
511 if( nParCount
== 2 || nParCount
== 3 )
514 pPar
->addExpression( std::make_unique
<SbiExpression
>( this, -1, SbxLONG
) );
517 pPar
->addExpression( std::make_unique
<SbiExpression
>( this ) );
519 bSpecialMidHandling
= true;
524 aVar
.Gen( eRecMode
);
525 if( bSpecialMidHandling
)
530 aGen
.Gen( SbiOpcode::GET_
);
534 // so it must be an assignment!
535 if( !aVar
.IsLvalue() )
536 Error( ERRCODE_BASIC_LVALUE_EXPECTED
);
538 SbiExpression
aExpr( this );
540 SbiOpcode eOp
= SbiOpcode::PUT_
;
543 if( pDef
->GetConstDef() )
544 Error( ERRCODE_BASIC_DUPLICATE_DEF
, pDef
->GetName() );
545 if( pDef
->GetType() == SbxOBJECT
)
547 eOp
= SbiOpcode::SET_
;
548 if( pDef
->GetTypeId() )
550 aGen
.Gen( SbiOpcode::SETCLASS_
, pDef
->GetTypeId() );
554 else if (auto nLen
= pDef
->GetLen()) // Dim s As String * 123 ' 123 -> nLen
556 aGen
.Gen(SbiOpcode::PAD_
, nLen
);
564 void SbiParser::Assign()
566 SbiExpression
aLvalue( this, SbLVALUE
);
568 SbiExpression
aExpr( this );
571 if (SbiSymDef
* pDef
= aLvalue
.GetRealVar())
573 if( pDef
->GetConstDef() )
574 Error( ERRCODE_BASIC_DUPLICATE_DEF
, pDef
->GetName() );
575 if (auto nLen
= pDef
->GetLen()) // Dim s As String * 123 ' 123 -> nLen
577 aGen
.Gen( SbiOpcode::PAD_
, nLen
);
580 aGen
.Gen( SbiOpcode::PUT_
);
583 // assignments of an object-variable
585 void SbiParser::Set()
587 SbiExpression
aLvalue( this, SbLVALUE
);
588 SbxDataType eType
= aLvalue
.GetType();
589 if( eType
!= SbxOBJECT
&& eType
!= SbxEMPTY
&& eType
!= SbxVARIANT
)
590 Error( ERRCODE_BASIC_INVALID_OBJECT
);
592 SbiSymDef
* pDef
= aLvalue
.GetRealVar();
593 if( pDef
->GetConstDef() )
594 Error( ERRCODE_BASIC_DUPLICATE_DEF
, pDef
->GetName() );
596 SbiToken eTok
= Peek();
600 SbiSymDef
aTypeDef( u
""_ustr
);
601 TypeDecl( aTypeDef
, true );
604 aGen
.Gen( SbiOpcode::CREATE_
, pDef
->GetId(), aTypeDef
.GetTypeId() );
605 aGen
.Gen( SbiOpcode::SETCLASS_
, pDef
->GetTypeId() );
609 SbiExpression
aExpr( this );
612 // It's a good idea to distinguish between
613 // set something = another &
614 // something = another
615 // ( it's necessary for vba objects where set is object
616 // specific and also doesn't involve processing default params )
617 if( pDef
->GetTypeId() )
620 aGen
.Gen( SbiOpcode::VBASETCLASS_
, pDef
->GetTypeId() );
622 aGen
.Gen( SbiOpcode::SETCLASS_
, pDef
->GetTypeId() );
627 aGen
.Gen( SbiOpcode::VBASET_
);
629 aGen
.Gen( SbiOpcode::SET_
);
635 void SbiParser::LSet()
637 SbiExpression
aLvalue( this, SbLVALUE
);
638 if( aLvalue
.GetType() != SbxSTRING
)
640 Error( ERRCODE_BASIC_INVALID_OBJECT
);
643 SbiSymDef
* pDef
= aLvalue
.GetRealVar();
644 if( pDef
&& pDef
->GetConstDef() )
646 Error( ERRCODE_BASIC_DUPLICATE_DEF
, pDef
->GetName() );
648 SbiExpression
aExpr( this );
651 aGen
.Gen( SbiOpcode::LSET_
);
655 void SbiParser::RSet()
657 SbiExpression
aLvalue( this, SbLVALUE
);
658 if( aLvalue
.GetType() != SbxSTRING
)
660 Error( ERRCODE_BASIC_INVALID_OBJECT
);
663 SbiSymDef
* pDef
= aLvalue
.GetRealVar();
664 if( pDef
&& pDef
->GetConstDef() )
665 Error( ERRCODE_BASIC_DUPLICATE_DEF
, pDef
->GetName() );
666 SbiExpression
aExpr( this );
669 aGen
.Gen( SbiOpcode::RSET_
);
672 // DEFINT, DEFLNG, DEFSNG, DEFDBL, DEFSTR and so on
674 void SbiParser::DefXXX()
676 sal_Unicode ch1
, ch2
;
677 SbxDataType t
= SbxDataType( eCurTok
- DEFINT
+ SbxINTEGER
);
681 if( Next() != SYMBOL
) break;
682 ch1
= rtl::toAsciiUpperCase(aSym
[0]);
684 if( Peek() == MINUS
)
687 if( Next() != SYMBOL
) Error( ERRCODE_BASIC_SYMBOL_EXPECTED
);
690 ch2
= rtl::toAsciiUpperCase(aSym
[0]);
693 Error( ERRCODE_BASIC_SYNTAX
);
699 ch1
-= 'A'; ch2
-= 'A';
700 for (; ch1
<= ch2
; ch1
++) eDefTypes
[ ch1
] = t
;
701 if( !TestComma() ) break;
707 void SbiParser::Stop()
709 aGen
.Gen( SbiOpcode::STOP_
);
710 Peek(); // #35694: only Peek(), so that EOL is recognized in Single-Line-If
715 void SbiParser::Implements()
719 Error( ERRCODE_BASIC_UNEXPECTED
, IMPLEMENTS
);
724 if( eCurTok
!= SYMBOL
)
726 Error( ERRCODE_BASIC_SYMBOL_EXPECTED
);
730 OUString aImplementedIface
= aSym
;
734 OUString
aDotStr( '.' );
735 while( Peek() == DOT
)
737 aImplementedIface
+= aDotStr
;
739 SbiToken ePeekTok
= Peek();
740 if( ePeekTok
== SYMBOL
|| IsKwd( ePeekTok
) )
743 aImplementedIface
+= aSym
;
748 Error( ERRCODE_BASIC_SYMBOL_EXPECTED
);
753 aIfaceVector
.push_back( aImplementedIface
);
756 void SbiParser::EnableCompatibility()
765 void SbiParser::Option()
770 bExplicit
= true; break;
772 if( Next() == NUMBER
&& ( nVal
== 0 || nVal
== 1 ) )
774 nBase
= static_cast<short>(nVal
);
777 Error( ERRCODE_BASIC_EXPECTED
, u
"0/1"_ustr
);
781 OUString aString
= SbiTokenizer::Symbol(Next());
782 if( !aString
.equalsIgnoreAsciiCase("Module") )
784 Error( ERRCODE_BASIC_EXPECTED
, u
"Module"_ustr
);
790 SbiToken eTok
= Next();
794 else if( eTok
== SYMBOL
&& GetSym().equalsIgnoreAsciiCase("text") )
799 Error( ERRCODE_BASIC_EXPECTED
, u
"Text/Binary"_ustr
);
804 EnableCompatibility();
809 aGen
.GetModule().SetModuleType( css::script::ModuleType::CLASS
);
811 case VBASUPPORT
: // Option VBASupport used to override the module mode ( in fact this must reset the mode
812 if( Next() == NUMBER
)
814 if ( nVal
== 1 || nVal
== 0 )
816 bVBASupportOn
= ( nVal
== 1 );
819 EnableCompatibility();
821 // if the module setting is different
822 // reset it to what the Option tells us
823 if ( bVBASupportOn
!= aGen
.GetModule().IsVBASupport() )
825 aGen
.GetModule().SetVBASupport( bVBASupportOn
);
830 Error( ERRCODE_BASIC_EXPECTED
, u
"0/1"_ustr
);
833 Error( ERRCODE_BASIC_BAD_OPTION
, eCurTok
);
837 static void addStringConst( SbiSymPool
& rPool
, const OUString
& pSym
, const OUString
& rStr
)
839 SbiConstDef
* pConst
= new SbiConstDef( pSym
);
840 pConst
->SetType( SbxSTRING
);
845 static void addNumericConst(SbiSymPool
& rPool
, const OUString
& pSym
, double nVal
)
847 SbiConstDef
* pConst
= new SbiConstDef(pSym
);
848 pConst
->Set(nVal
, SbxDOUBLE
);
852 void SbiParser::AddConstants()
854 // tdf#153543 - shell constants
855 // See https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/shell-constants
856 addNumericConst(aPublics
, u
"vbHide"_ustr
, 0);
857 addNumericConst(aPublics
, u
"vbNormalFocus"_ustr
, 1);
858 addNumericConst(aPublics
, u
"vbMinimizedFocus"_ustr
, 2);
859 addNumericConst(aPublics
, u
"vbMaximizedFocus"_ustr
, 3);
860 addNumericConst(aPublics
, u
"vbNormalNoFocus"_ustr
, 4);
861 addNumericConst(aPublics
, u
"vbMinimizedNoFocus"_ustr
, 6);
863 // tdf#131563 - add vba color constants
864 // See https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/color-constants
865 addNumericConst(aPublics
, u
"vbBlack"_ustr
, 0x0);
866 addNumericConst(aPublics
, u
"vbRed"_ustr
, 0xFF);
867 addNumericConst(aPublics
, u
"vbGreen"_ustr
, 0xFF00);
868 addNumericConst(aPublics
, u
"vbYellow"_ustr
, 0xFFFF);
869 addNumericConst(aPublics
, u
"vbBlue"_ustr
, 0xFF0000);
870 addNumericConst(aPublics
, u
"vbMagenta"_ustr
, 0xFF00FF);
871 addNumericConst(aPublics
, u
"vbCyan"_ustr
, 0xFFFF00);
872 addNumericConst(aPublics
, u
"vbWhite"_ustr
, 0xFFFFFF);
874 // #113063 Create constant RTL symbols
875 addStringConst( aPublics
, u
"vbCr"_ustr
, u
"\x0D"_ustr
);
876 addStringConst( aPublics
, u
"vbCrLf"_ustr
, u
"\x0D\x0A"_ustr
);
877 addStringConst( aPublics
, u
"vbFormFeed"_ustr
, u
"\x0C"_ustr
);
878 addStringConst( aPublics
, u
"vbLf"_ustr
, u
"\x0A"_ustr
);
880 addStringConst( aPublics
, "vbNewLine", "\x0D\x0A" );
882 addStringConst( aPublics
, u
"vbNewLine"_ustr
, u
"\x0A"_ustr
);
884 addStringConst( aPublics
, u
"vbNullString"_ustr
, u
""_ustr
);
885 addStringConst( aPublics
, u
"vbTab"_ustr
, u
"\x09"_ustr
);
886 addStringConst( aPublics
, u
"vbVerticalTab"_ustr
, u
"\x0B"_ustr
);
888 addStringConst( aPublics
, u
"vbNullChar"_ustr
, OUString(u
'\0') );
893 void SbiParser::ErrorStmnt()
895 SbiExpression
aPar( this );
897 aGen
.Gen( SbiOpcode::ERROR_
);
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */