1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2014 Henrik Tidefelt
19 #include "identifier.h"
20 #include "sourcelocation.h"
24 #include "environment.h"
25 #include "shapesexceptions.h"
27 using namespace Shapes
;
30 const RefCountPtr
< const Ast::NamespacePath
> Ast::THE_EMPTY_NAMESPACE_PATH( new Ast::NamespacePath( ) );
31 const RefCountPtr
< const Ast::SearchContext
> Ast::THE_EMPTY_SEARCH_CONTEXT( new Ast::SearchContext( Ast::THE_EMPTY_NAMESPACE_PATH
, RefCountPtr
< const char >( NullPtr
< const char >( ) ) ) );
35 Ast::compare( const Ast::NamespacePath
& path1
, const Ast::NamespacePath
& path2
)
37 if( path1
.size( ) < path2
.size( ) )
39 if( path1
.size( ) > path2
.size( ) )
42 Ast::NamespacePath::const_iterator i1
= path1
.begin( );
43 Ast::NamespacePath::const_iterator i2
= path2
.begin( );
44 Ast::NamespacePath::const_iterator end1
= path1
.end( );
45 for( ; i1
!= end1
; ++i1
, ++i2
){
46 int cmp
= strcmp( *i1
, *i2
);
57 //Ast::operator < ( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 )
59 // return compare( path1, path2 ) < 0;
64 Ast::NamespaceReference::show( std::ostream
& os
, bool showAbsoluteMark
) const
68 if( showAbsoluteMark
)
69 os
<< Interaction::NAMESPACE_SEPARATOR
;
72 os
<< Interaction::ENCAPSULATION_MARK
;
78 Ast::NamespacePath::const_iterator i
= path_
->begin( );
79 for( ; i
!= path_
->end( ) && Ast::SearchContext::isEncapsulationName( *i
); ++i
)
81 if( i
!= path_
->end( ) ){
83 for( ++i
; i
!= path_
->end( ); ++i
){
84 if( ! Ast::SearchContext::isEncapsulationName( *i
) )
85 os
<< Interaction::NAMESPACE_SEPARATOR
<< *i
;
92 Ast::SearchContext::insideEncapsulationNamespace( ) const
94 if( lexicalPath_
->empty( ) )
96 /* An alternative condition that could be used below:
97 * lexicalPath_.size( ) == encapsulationPath_.size( )
98 * However, list<>::size is not constant time, so a name-based condition is used instead.
100 return isEncapsulationName( lexicalPath_
->back( ) );
104 RefCountPtr
< const char >
105 Ast::SearchContext::makePrivateName( size_t i
)
107 std::ostringstream oss
;
109 return strrefdup( oss
);
113 RefCountPtr
< const char >
114 Ast::SearchContext::makeEncapsulationName( size_t i
)
116 std::ostringstream oss
;
118 return strrefdup( oss
);
123 Ast::SearchContext::isEncapsulationName( const char * name
)
125 return name
[0] == '^';
129 Ast::Identifier::Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, Ast::NamespaceReference::Base base
, Ast::NamespacePath
* path
, const char * simpleId
)
130 : searchContext_( searchContext
), namespaceRef_( base
, path
), simpleId_( simpleId
)
133 Ast::Identifier::Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, Ast::NamespaceReference::Base base
, const RefCountPtr
< const Ast::NamespacePath
> & path
, const char * simpleId
)
134 : searchContext_( searchContext
), namespaceRef_( base
, path
), simpleId_( simpleId
)
137 Ast::Identifier::Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, const NamespaceReference
& namespaceRef
, const char * simpleId
)
138 : searchContext_( searchContext
), namespaceRef_( namespaceRef
), simpleId_( simpleId
)
141 Ast::Identifier::Identifier( const Ast::Identifier
& orig
)
142 : searchContext_( orig
.searchContext_
), namespaceRef_( orig
.namespaceRef_
), simpleId_( orig
.simpleId_
)
145 Ast::Identifier::~Identifier( )
147 /* Note that we intentionally allow simpleId_ to leak here, see memory management note in identifier.h.
151 Ast::PlacedIdentifier
*
152 Ast::Identifier::place( const Ast::SourceLocation
& loc
)
154 if( namespaceRef_
.base( ) != Ast::NamespaceReference::RELATIVE
|| namespaceRef_
.path( ).size( ) != 0 ){
155 Ast::theAnalysisErrorsList
.push_back( new Exceptions::ScannerError( loc
, strrefdup( "Expected simple identifier." ) ) );
157 Ast::PlacedIdentifier
* res
= new Ast::PlacedIdentifier( searchContext_
->lexicalPath( ), simpleId_
);
163 Ast::Identifier::strip( const Ast::SourceLocation
& loc
)
165 if( namespaceRef_
.base( ) != Ast::NamespaceReference::RELATIVE
|| namespaceRef_
.path( ).size( ) != 0 ){
166 Ast::theAnalysisErrorsList
.push_back( new Exceptions::ScannerError( loc
, strrefdup( "Expected simple identifier." ) ) );
168 const char * res
= simpleId_
;
173 RefCountPtr
< const char >
174 Ast::Identifier::refstrip( const Ast::SourceLocation
& loc
)
176 if( namespaceRef_
.base( ) != Ast::NamespaceReference::RELATIVE
|| namespaceRef_
.path( ).size( ) != 0 ){
177 Ast::theAnalysisErrorsList
.push_back( new Exceptions::ScannerError( loc
, strrefdup( "Expected simple identifier." ) ) );
179 RefCountPtr
< const char > res( simpleId_
);
185 Ast::Identifier::show( std::ostream
& os
, Type type
, bool showAbsoluteMark
) const
187 namespaceRef_
.show( os
, showAbsoluteMark
);
188 if( ! namespaceRef_
.path( ).empty( ) )
189 os
<< Interaction::NAMESPACE_SEPARATOR
;
190 os
<< identifierPrefix( type
) << simpleId_
;
194 Ast::Identifier::debugShow( std::ostream
& os
) const
196 os
<< "Identifier: " ;
197 if( namespaceRef_
.base( ) == Ast::NamespaceReference::ABSOLUTE
){
198 os
<< Interaction::NAMESPACE_SEPARATOR
;
201 for( Ast::NamespacePath::const_iterator i
= searchContext_
->lexicalPath( )->begin( ); i
!= searchContext_
->lexicalPath( )->end( ); ++i
){
202 os
<< *i
<< Interaction::NAMESPACE_SEPARATOR
;
207 if( namespaceRef_
.base( ) == Ast::NamespaceReference::LOCAL
)
208 os
<< Interaction::ENCAPSULATION_MARK
;
210 for( Ast::NamespacePath::const_iterator i
= namespaceRef_
.path( ).begin( ); i
!= namespaceRef_
.path( ).end( ); ++i
){
211 os
<< *i
<< Interaction::NAMESPACE_SEPARATOR
;
219 Ast::Identifier::operator < ( const Ast::Identifier
& other
) const
221 if( base( ) < other
.base( ) ){
224 if( base( ) > other
.base( ) ){
228 Ast::NamespacePath::const_iterator i1
= namespaceRef_
.path( ).begin( );
229 Ast::NamespacePath::const_iterator end1
= namespaceRef_
.path( ).end( );
230 Ast::NamespacePath::const_iterator i2
= other
.namespaceRef_
.path( ).begin( );
231 Ast::NamespacePath::const_iterator end2
= other
.namespaceRef_
.path( ).end( );
233 while( i1
!= end1
&& i2
!= end2
)
235 int cmp
= strcmp( *i1
, *i2
);
249 return strcmp( simpleId_
, other
.simpleId_
) < 0;
253 Ast::Identifier::identifierPrefix( Type type
)
260 return Interaction::STATE_PREFIX
;
261 case DYNAMIC_VARIABLE
:
262 return Interaction::DYNAMIC_VARIABLE_PREFIX
;
264 return Interaction::DYNAMIC_STATE_PREFIX
;
272 Ast::PlacedIdentifier::PlacedIdentifier( const RefCountPtr
< const NamespacePath
> & absolutePath
, const char * simpleId
)
273 : absolutePath_( absolutePath
), simpleId_( simpleId
)
276 Ast::PlacedIdentifier::PlacedIdentifier( Ast::NamespacePath
* absolutePath
, const char * simpleId
)
277 : absolutePath_( absolutePath
), simpleId_( simpleId
)
280 Ast::PlacedIdentifier::PlacedIdentifier( const Ast::NamespacePath
& absolutePath
, const char * simpleId
)
281 : absolutePath_( absolutePath
), simpleId_( simpleId
)
284 Ast::PlacedIdentifier::PlacedIdentifier( const Ast::PlacedIdentifier
& orig
)
285 : absolutePath_( orig
.absolutePath_
), simpleId_( orig
.simpleId_
)
288 Ast::PlacedIdentifier::~PlacedIdentifier( )
290 /* Note that we intentionally allow simpleId_ to leak here, see memory management note in identifier.h.
294 Ast::PlacedIdentifier
*
295 Ast::PlacedIdentifier::clone( ) const
297 /* Here we use that the simpleId_ is not going to be deallocated, so we can share with the constructed object.
299 return new Ast::PlacedIdentifier( absolutePath_
, simpleId_
);
303 Ast::PlacedIdentifier::newAbsolute( ) const
305 /* Here we use that the simpleId_ is not going to be deallocated, so we can share with the constructed object.
307 return new Ast::Identifier( Ast::THE_EMPTY_SEARCH_CONTEXT
, Ast::NamespaceReference::ABSOLUTE
, absolutePath_
, simpleId_
);
311 Ast::PlacedIdentifier::strip( )
313 const char * res
= simpleId_
;
318 RefCountPtr
< const char >
319 Ast::PlacedIdentifier::refstrip( )
321 RefCountPtr
< const char > res( simpleId_
);
327 Ast::PlacedIdentifier::show( std::ostream
& os
, Ast::Identifier::Type type
) const
329 for( Ast::NamespacePath::const_iterator i
= absolutePath( ).begin( ); i
!= absolutePath( ).end( ); ++i
){
330 if( ! Ast::SearchContext::isEncapsulationName( *i
) )
331 os
<< *i
<< Interaction::NAMESPACE_SEPARATOR
;
334 os
<< Ast::Identifier::identifierPrefix( type
) << simpleId_
;
338 Ast::PlacedIdentifier::operator < ( const Ast::PlacedIdentifier
& other
) const
340 Ast::NamespacePath::const_iterator i1
= absolutePath( ).begin( );
341 Ast::NamespacePath::const_iterator end1
= absolutePath( ).end( );
342 Ast::NamespacePath::const_iterator i2
= other
.absolutePath( ).begin( );
343 Ast::NamespacePath::const_iterator end2
= other
.absolutePath( ).end( );
345 while( i1
!= end1
&& i2
!= end2
)
347 int cmp
= strcmp( *i1
, *i2
);
361 return strcmp( simpleId_
, other
.simpleId_
) < 0;