Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / idl / source / prj / parser.cxx
blobbe948e8ec31fda426d5eaca0cb0c3c18ac97614e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sal/config.h>
22 #include <algorithm>
24 #include <parser.hxx>
25 #include <database.hxx>
26 #include <globals.hxx>
27 #include <osl/file.hxx>
29 void SvIdlParser::ReadSvIdl( const OUString & rPath )
31 rBase.SetPath(rPath); // only valid for this iteration
32 SvToken& rTok = rInStm.GetToken();
34 while( true )
36 rTok = rInStm.GetToken();
37 if( rTok.IsEof() )
38 return;
40 Read( SvHash_module() );
41 tools::SvRef<SvMetaModule> aModule = new SvMetaModule;
42 ReadModuleHeader(*aModule);
43 rBase.GetModuleList().push_back( aModule.get() );
47 void SvIdlParser::ReadModuleHeader(SvMetaModule& rModule)
49 OString aName = ReadIdentifier();
50 rModule.SetName( aName );
51 rBase.Push( &rModule ); // onto the context stack
52 ReadModuleBody(rModule);
53 rBase.GetStack().pop_back(); // remove from stack
56 void SvIdlParser::ReadModuleBody(SvMetaModule& rModule)
58 if( ReadIf( '[' ) )
60 while( true )
62 OString aSlotIdFile;
63 if( !ReadStringSvIdl( SvHash_SlotIdFile(), rInStm, aSlotIdFile ) )
64 break;
65 if( !rBase.ReadIdFile( aSlotIdFile ) )
67 throw SvParseException( rInStm, "cannot read file: " + aSlotIdFile );
69 ReadIfDelimiter();
71 Read( ']' );
74 if( !ReadIf( '{' ) )
75 return;
77 sal_uInt32 nBeginPos = 0;
78 while( nBeginPos != rInStm.Tell() )
80 nBeginPos = rInStm.Tell();
81 ReadModuleElement( rModule );
82 ReadIfDelimiter();
84 Read( '}' );
87 void SvIdlParser::ReadModuleElement( SvMetaModule& rModule )
89 if( ReadIf( SvHash_interface() ) )
91 ReadInterfaceOrShell(rModule, MetaTypeType::Interface);
93 else if( ReadIf( SvHash_shell() ) )
95 ReadInterfaceOrShell(rModule, MetaTypeType::Shell);
97 else if( ReadIf( SvHash_enum() ) )
99 ReadEnum();
101 else if( ReadIf( SvHash_item() ) )
103 ReadItem();
105 else if( ReadIf( SvHash_struct() ) )
107 ReadStruct();
109 else if( ReadIf( SvHash_include() ) )
111 ReadInclude(rModule);
113 else
115 tools::SvRef<SvMetaSlot> xSlot( new SvMetaSlot() );
117 if (ReadSlot(*xSlot))
119 if( xSlot->Test( rInStm ) )
121 // announce globally
122 rBase.AppendSlot( xSlot.get() );
128 void SvIdlParser::ReadInclude( SvMetaModule& rModule )
130 sal_uInt32 nTokPos = rInStm.Tell();
131 bool bOk = false;
132 OUString aFullName(OStringToOUString(ReadString(), RTL_TEXTENCODING_ASCII_US));
133 rBase.StartNewFile( aFullName );
134 osl::FileBase::RC searchError = osl::File::searchFileURL(aFullName, rBase.GetPath(), aFullName);
135 if( osl::FileBase::E_None != searchError )
137 OString aStr = "cannot find file:" +
138 OUStringToOString(aFullName, RTL_TEXTENCODING_UTF8);
139 throw SvParseException(aStr, rInStm.GetToken());
141 osl::FileBase::getSystemPathFromFileURL( aFullName, aFullName );
142 rBase.AddDepFile( aFullName );
143 SvTokenStream aTokStm( aFullName );
144 if( ERRCODE_NONE != aTokStm.GetStream().GetError() )
146 OString aStr = "cannot open file: " +
147 OUStringToOString(aFullName, RTL_TEXTENCODING_UTF8);
148 throw SvParseException(aStr, rInStm.GetToken());
150 // rescue error from old file
151 SvIdlError aOldErr = rBase.GetError();
152 // reset error
153 rBase.SetError( SvIdlError() );
155 try {
156 SvIdlParser aIncludeParser( rBase, aTokStm );
157 sal_uInt32 nBeginPos = 0xFFFFFFFF; // can not happen with Tell
158 while( nBeginPos != aTokStm.Tell() )
160 nBeginPos = aTokStm.Tell();
161 aIncludeParser.ReadModuleElement(rModule);
162 aTokStm.ReadIfDelimiter();
164 } catch (const SvParseException& ex) {
165 rBase.SetError(ex.aError);
166 rBase.WriteError(aTokStm);
168 bOk = aTokStm.GetToken().IsEof();
169 if( !bOk )
171 rBase.WriteError( aTokStm );
173 // recover error from old file
174 rBase.SetError( aOldErr );
175 if( !bOk )
176 rInStm.Seek( nTokPos );
179 void SvIdlParser::ReadStruct()
181 tools::SvRef<SvMetaType> xStruct(new SvMetaType() );
182 xStruct->SetType( MetaTypeType::Struct );
183 xStruct->SetName( ReadIdentifier() );
184 Read( '{' );
185 while( true )
187 tools::SvRef<SvMetaAttribute> xAttr( new SvMetaAttribute() );
188 xAttr->aType = ReadKnownType();
189 xAttr->SetName(ReadIdentifier());
190 xAttr->aSlotId.setString(ReadIdentifier());
191 sal_uLong n;
192 if( !rBase.FindId( xAttr->aSlotId.getString(), &n ) )
193 throw SvParseException( rInStm, "no value for identifier <" + xAttr->aSlotId.getString() + "> " );
194 xAttr->aSlotId.SetValue(n);
195 xStruct->GetAttrList().push_back( xAttr.get() );
196 if( !ReadIfDelimiter() )
197 break;
198 if( rInStm.GetToken().IsChar() && rInStm.GetToken().GetChar() == '}')
199 break;
201 Read( '}' );
202 ReadDelimiter();
203 // announce globally
204 rBase.GetTypeList().push_back( xStruct.get() );
207 void SvIdlParser::ReadItem()
209 tools::SvRef<SvMetaType> xItem(new SvMetaType() );
210 xItem->SetItem(true);
211 xItem->SetRef( ReadKnownType() );
212 xItem->SetName( ReadIdentifier() );
213 // announce globally
214 rBase.GetTypeList().push_back( xItem.get() );
217 void SvIdlParser::ReadEnum()
219 tools::SvRef<SvMetaTypeEnum> xEnum( new SvMetaTypeEnum() );
220 xEnum->SetType( MetaTypeType::Enum );
221 xEnum->SetName( ReadIdentifier() );
223 Read('{');
224 while( true )
226 ReadEnumValue( *xEnum );
227 if( !ReadIfDelimiter() )
228 break;
230 Read( '}' );
231 // announce globally
232 rBase.GetTypeList().push_back( xEnum.get() );
235 static OString getCommonSubPrefix(const OString &rA, const OString &rB)
237 sal_Int32 nMax = std::min(rA.getLength(), rB.getLength());
238 sal_Int32 nI = 0;
239 while (nI < nMax)
241 if (rA[nI] != rB[nI])
242 break;
243 ++nI;
245 return rA.copy(0, nI);
248 void SvIdlParser::ReadEnumValue( SvMetaTypeEnum& rEnum )
250 tools::SvRef<SvMetaEnumValue> aEnumVal = new SvMetaEnumValue();
251 aEnumVal->SetName( ReadIdentifier() );
252 if( rEnum.aEnumValueList.empty() )
254 // the first
255 rEnum.aPrefix = aEnumVal->GetName();
257 else
259 rEnum.aPrefix = getCommonSubPrefix(rEnum.aPrefix, aEnumVal->GetName());
261 rEnum.aEnumValueList.push_back( aEnumVal.get() );
264 void SvIdlParser::ReadInterfaceOrShell( SvMetaModule& rModule, MetaTypeType aMetaTypeType )
266 tools::SvRef<SvMetaClass> aClass( new SvMetaClass() );
268 aClass->SetType( aMetaTypeType );
270 aClass->SetName( ReadIdentifier() );
272 if( ReadIf( ':' ) )
274 aClass->aSuperClass = ReadKnownClass();
276 if( ReadIf( '{' ) )
278 sal_uInt32 nBeginPos = 0; // can not happen with Tell
279 while( nBeginPos != rInStm.Tell() )
281 nBeginPos = rInStm.Tell();
282 ReadInterfaceOrShellEntry(*aClass);
283 ReadIfDelimiter();
285 Read( '}' );
287 rModule.aClassList.push_back( aClass.get() );
288 // announce globally
289 rBase.GetClassList().push_back( aClass.get() );
292 void SvIdlParser::ReadInterfaceOrShellEntry(SvMetaClass& rClass)
294 if( ReadIf( SvHash_import() ) )
296 SvMetaClass * pClass = ReadKnownClass();
297 SvClassElement aEle(pClass);
298 SvToken& rTok = rInStm.GetToken();
299 if( rTok.IsString() )
301 aEle.SetPrefix( rTok.GetString() );
302 rInStm.GetToken_Next();
304 rClass.aClassElementList.push_back( aEle );
306 else
308 SvMetaType * pType = rBase.ReadKnownType( rInStm );
309 tools::SvRef<SvMetaAttribute> xAttr;
310 bool bOk = false;
311 if( !pType || pType->IsItem() )
313 xAttr = new SvMetaSlot( pType );
314 bOk = ReadSlot(static_cast<SvMetaSlot&>(*xAttr));
316 else
318 xAttr = new SvMetaAttribute( pType );
319 ReadInterfaceOrShellMethod(*xAttr);
320 bOk = true;
322 if( bOk )
323 bOk = xAttr->Test( rInStm );
324 if( bOk )
325 bOk = rClass.TestAttribute( rBase, rInStm, *xAttr );
326 if( bOk )
328 if( !xAttr->GetSlotId().IsSet() )
329 xAttr->SetSlotId( SvIdentifier(rBase.GetUniqueId()) );
330 rClass.aAttrList.push_back( xAttr.get() );
335 bool SvIdlParser::ReadSlot(SvMetaSlot& rSlot)
337 sal_uInt32 nTokPos = rInStm.Tell();
338 bool bOk = true;
340 SvMetaAttribute * pAttr = rBase.ReadKnownAttr( rInStm, rSlot.GetType() );
341 if( pAttr )
343 SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr );
344 if( !pKnownSlot )
345 throw SvParseException( rInStm, "attribute " + pAttr->GetName() + " is method or variable but not a slot" );
346 rSlot.SetRef( pKnownSlot );
347 rSlot.SetName( pKnownSlot->GetName() );
348 if( ReadIf( '[' ) )
350 sal_uInt32 nBeginPos = 0; // can not happen with Tell
351 while( nBeginPos != rInStm.Tell() )
353 nBeginPos = rInStm.Tell();
354 ReadSlotAttribute(rSlot);
355 ReadIfDelimiter();
357 Read( ']' );
360 else
362 bOk = rSlot.SvMetaAttribute::ReadSvIdl( rBase, rInStm );
363 SvMetaAttribute *pAttr2 = rBase.FindKnownAttr( rSlot.GetSlotId() );
364 if( pAttr2 )
366 SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr2 );
367 if( !pKnownSlot )
368 throw SvParseException( rInStm, "attribute " + pAttr2->GetName() + " is method or variable but not a slot" );
369 rSlot.SetRef( pKnownSlot );
370 // names may differ, because explicitly given
371 if ( pKnownSlot->GetName() != rSlot.GetName() )
372 throw SvParseException( rInStm, "Illegal definition!" );
376 if( !bOk )
377 rInStm.Seek( nTokPos );
379 return bOk;
382 void SvIdlParser::ReadSlotAttribute( SvMetaSlot& rSlot )
384 ReadIfIdAttribute(rSlot.aGroupId, SvHash_GroupId() );
385 ReadIfIdAttribute(rSlot.aExecMethod, SvHash_ExecMethod() );
386 ReadIfIdAttribute(rSlot.aStateMethod, SvHash_StateMethod() );
387 ReadStringSvIdl( SvHash_DisableFlags(), rInStm, rSlot.aDisableFlags );
388 ReadIfBoolAttribute(rSlot.aReadOnlyDoc, SvHash_ReadOnlyDoc() );
389 ReadIfBoolAttribute(rSlot.aExport, SvHash_Export() );
391 ReadIfBoolAttribute(rSlot.aToggle, SvHash_Toggle() );
392 ReadIfBoolAttribute(rSlot.aAutoUpdate, SvHash_AutoUpdate() );
393 ReadIfBoolAttribute(rSlot.aAsynchron, SvHash_Asynchron() );
394 ReadIfBoolAttribute(rSlot.aRecordAbsolute, SvHash_RecordAbsolute() );
396 if( ReadIfBoolAttribute(rSlot.aRecordPerItem, SvHash_RecordPerItem()) )
398 if (rSlot.aRecordPerSet.IsSet() || rSlot.aNoRecord.IsSet())
399 throw SvParseException(rInStm, "conflicting attributes");
400 rSlot.SetRecordPerItem( rSlot.aRecordPerItem );
402 if( ReadIfBoolAttribute(rSlot.aRecordPerSet, SvHash_RecordPerSet() ) )
404 if (rSlot.aRecordPerItem.IsSet() || rSlot.aNoRecord.IsSet())
405 throw SvParseException(rInStm, "conflicting attributes");
406 rSlot.SetRecordPerSet( rSlot.aRecordPerSet );
408 if( ReadIfBoolAttribute(rSlot.aNoRecord, SvHash_NoRecord() ) )
410 if (rSlot.aRecordPerItem.IsSet() || rSlot.aRecordPerSet.IsSet())
411 throw SvParseException(rInStm, "conflicting attributes");
412 rSlot.SetNoRecord( rSlot.aNoRecord );
415 ReadIfBoolAttribute(rSlot.aMenuConfig, SvHash_MenuConfig() );
416 ReadIfBoolAttribute(rSlot.aToolBoxConfig, SvHash_ToolBoxConfig() );
417 ReadIfBoolAttribute(rSlot.aAccelConfig, SvHash_AccelConfig() );
419 ReadIfBoolAttribute(rSlot.aFastCall, SvHash_FastCall() );
420 ReadIfBoolAttribute(rSlot.aContainer, SvHash_Container() );
423 void SvIdlParser::ReadInterfaceOrShellMethod( SvMetaAttribute& rAttr )
425 rAttr.SetName( ReadIdentifier() );
426 ReadSlotId( rAttr.aSlotId );
428 // read method arguments
429 Read( '(' );
430 tools::SvRef<SvMetaType> xT(new SvMetaType() );
431 xT->SetRef(rAttr.GetType() );
432 rAttr.aType = xT;
433 rAttr.aType->SetType( MetaTypeType::Method );
434 if (!ReadIf(')'))
436 while (true)
438 tools::SvRef<SvMetaAttribute> xParamAttr( new SvMetaAttribute() );
439 xParamAttr->aType = ReadKnownType();
440 xParamAttr->SetName( ReadIdentifier() );
441 ReadSlotId(xParamAttr->aSlotId);
442 rAttr.aType->GetAttrList().push_back( xParamAttr.get() );
443 if (!ReadIfDelimiter())
444 break;
446 Read(')');
450 void SvIdlParser::ReadSlotId(SvIdentifier& rSlotId)
452 rSlotId.setString( ReadIdentifier() );
453 sal_uLong n;
454 if( !rBase.FindId( rSlotId.getString(), &n ) )
455 throw SvParseException( rInStm, "no value for identifier <" + rSlotId.getString() + "> " );
456 rSlotId.SetValue(n);
459 SvMetaClass * SvIdlParser::ReadKnownClass()
461 OString aName(ReadIdentifier());
462 SvMetaClass* pClass = rBase.FindKnownClass( aName );
463 if( !pClass )
464 throw SvParseException( rInStm, "unknown class" );
465 return pClass;
468 SvMetaType * SvIdlParser::ReadKnownType()
470 OString aName = ReadIdentifier();
471 for( const auto& aType : rBase.GetTypeList() )
473 if( aType->GetName() == aName )
474 return aType;
476 throw SvParseException( rInStm, "wrong typedef: ");
479 bool SvIdlParser::ReadIfBoolAttribute( SvBOOL& rBool, SvStringHashEntry const * pName )
481 sal_uInt32 nTokPos = rInStm.Tell();
482 SvToken& rTok = rInStm.GetToken_Next();
484 if( rTok.Is( pName ) )
486 if( rInStm.ReadIf( '=' ) )
488 rTok = rInStm.GetToken();
489 if( !rTok.IsBool() )
490 throw SvParseException(rInStm, "xxx");
491 rBool = rTok.GetBool();
492 rInStm.GetToken_Next();
494 else
495 rBool = true; //default action set to TRUE
496 return true;
498 rInStm.Seek( nTokPos );
499 return false;
502 void SvIdlParser::ReadIfIdAttribute( SvIdentifier& rIdentifier, SvStringHashEntry const * pName )
504 sal_uInt32 nTokPos = rInStm.Tell();
505 SvToken& rTok = rInStm.GetToken_Next();
507 if( rTok.Is( pName ) )
509 if( rInStm.ReadIf( '=' ) )
511 rTok = rInStm.GetToken();
512 if( !rTok.IsIdentifier() )
513 throw SvParseException(rInStm, "expected identifier");
514 rIdentifier.setString(rTok.GetString());
515 rInStm.GetToken_Next();
518 else
519 rInStm.Seek( nTokPos );
522 void SvIdlParser::ReadDelimiter()
524 if( !ReadIfDelimiter() )
525 throw SvParseException(rInStm, "expected delimiter");
528 bool SvIdlParser::ReadIfDelimiter()
530 if( rInStm.GetToken().IsChar()
531 && (';' == rInStm.GetToken().GetChar()
532 || ',' == rInStm.GetToken().GetChar()) )
534 rInStm.GetToken_Next();
535 return true;
537 return false;
540 OString SvIdlParser::ReadIdentifier()
542 SvToken& rTok = rInStm.GetToken();
543 if( !rTok.IsIdentifier() )
544 throw SvParseException("expected identifier", rTok);
545 rInStm.GetToken_Next();
546 return rTok.GetString();
549 OString SvIdlParser::ReadString()
551 SvToken& rTok = rInStm.GetToken();
552 if( !rTok.IsString() )
553 throw SvParseException("expected string", rTok);
554 rInStm.GetToken_Next();
555 return rTok.GetString();
558 void SvIdlParser::Read(char cChar)
560 if( !ReadIf(cChar) )
561 throw SvParseException(rInStm, "expected char '" + OStringChar(cChar) + "'");
564 bool SvIdlParser::ReadIf(char cChar)
566 if( rInStm.GetToken().IsChar() && rInStm.GetToken().GetChar() == cChar )
568 rInStm.GetToken_Next();
569 return true;
571 return false;
574 void SvIdlParser::Read(SvStringHashEntry const * entry)
576 if( !rInStm.GetToken().Is(entry) )
577 throw SvParseException("expected " + entry->GetName(), rInStm.GetToken());
578 rInStm.GetToken_Next();
581 bool SvIdlParser::ReadIf(SvStringHashEntry const * entry)
583 if( rInStm.GetToken().Is(entry) )
585 rInStm.GetToken_Next();
586 return true;
588 return false;
590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */