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
22 #include "charptrless.h"
23 #include "Shapes_Ast_decls.h"
34 /* Memory management notice: The const char * strings used in NamespacePath, Identifier, and PlacedIdentifier
35 * will not be deallocated when no longer in use. This is by design, since the number of such strings should be remain
36 * fixed once the AST has been built up. Duplication of strings is avoided to some extent by the reference-counted
37 * NamespacePath objects.
39 * If memory leaking turns out to be a problem, one should consider replacing const char * by std::string or
40 * RefCountPtr< const char * >.
43 typedef std::list
< const char * > NamespacePath
;
44 extern const RefCountPtr
< const Ast::NamespacePath
> THE_EMPTY_NAMESPACE_PATH
;
46 int compare( const Ast::NamespacePath
& path1
, const Ast::NamespacePath
& path2
);
47 // bool operator < ( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 );
49 class NamespaceReference
52 enum Base
{ ABSOLUTE
, LOCAL
, RELATIVE
};
55 RefCountPtr
< const Ast::NamespacePath
> path_
;
58 : base_( ABSOLUTE
), path_( NullPtr
< const Ast::NamespacePath
>( ) )
60 NamespaceReference( Base base
, const RefCountPtr
< const Ast::NamespacePath
> & path
)
61 : base_( base
), path_( path
)
63 NamespaceReference( Base base
, Ast::NamespacePath
* path
) /* Transfers ownership. */
64 : base_( base
), path_( path
)
66 Base
base( ) const { return base_
; }
67 const Ast::NamespacePath
& path( ) const { return *path_
; }
68 RefCountPtr
< const Ast::NamespacePath
> pathRef( ) const { return path_
; }
69 void show( std::ostream
& os
, bool showAbsoluteMark
= true ) const;
72 /* A LookinPathStack holds the namespaces that have been explicitly listed to be looked in when looking up identifiers.
73 * The stack is to be traversed from top to bottom when looking up identifiers.
77 RefCountPtr
< const Ast::NamespacePath
> car_
; /* Resolved at the point where the look-in is added. */
78 RefCountPtr
< const LookinPathStack
> cdr_
;
80 LookinPathStack( const RefCountPtr
< const Ast::NamespacePath
> & car
, const RefCountPtr
< const LookinPathStack
> & cdr
)
81 : car_( car
), cdr_( cdr
)
83 RefCountPtr
< const Ast::NamespacePath
> car( ) const { return car_
; }
84 RefCountPtr
< const LookinPathStack
> cdr( ) const { return cdr_
; }
89 RefCountPtr
< const NamespacePath
> lexicalPath_
;
90 RefCountPtr
< const NamespacePath
> encapsulationPath_
;
91 RefCountPtr
< const LookinPathStack
> lookinStack_
;
92 RefCountPtr
< const char > privateName_
;
94 SearchContext( const RefCountPtr
< const NamespacePath
> & lexicalPath
, const RefCountPtr
< const NamespacePath
> & encapsulationPath
, const RefCountPtr
< const LookinPathStack
> & lookinStack
, const RefCountPtr
< const char > & privateName
)
95 : lexicalPath_( lexicalPath
), encapsulationPath_( encapsulationPath
), lookinStack_( lookinStack
), privateName_( privateName
)
97 SearchContext( const RefCountPtr
< const NamespacePath
> & lexicalPath
, const RefCountPtr
< const char > & privateName
)
98 : lexicalPath_( lexicalPath
), encapsulationPath_( Ast::THE_EMPTY_NAMESPACE_PATH
), lookinStack_( NullPtr
< const LookinPathStack
>( ) ), privateName_( privateName
)
100 const RefCountPtr
< const NamespacePath
> & lexicalPath( ) const { return lexicalPath_
; }
101 const RefCountPtr
< const NamespacePath
> & encapsulationPath( ) const { return encapsulationPath_
; }
102 const RefCountPtr
< const LookinPathStack
> & lookinStack( ) const { return lookinStack_
; }
103 const RefCountPtr
< const char > & privateName( ) const { return privateName_
; }
104 bool insidePrivateNamespace( ) const { return privateName_
== NullPtr
< const char >( ); }
105 bool insideEncapsulationNamespace( ) const;
107 static RefCountPtr
< const char > makePrivateName( size_t i
);
108 static RefCountPtr
< const char > makeEncapsulationName( size_t i
);
109 static bool isEncapsulationName( const char * name
);
112 extern const RefCountPtr
< const Ast::SearchContext
> THE_EMPTY_SEARCH_CONTEXT
;
114 class PlacedIdentifier
;
119 /* The type of identifier is not stored in the identifier, as that would have a substantial impact on the
120 * memory consumption considering the uniquitous use of identifiers in a program. The identifier type only
121 * matters when displaying the identifier back to the user, and then the type has to be provided by the caller.
123 enum Type
{ VARIABLE
, STATE
, DYNAMIC_VARIABLE
, DYNAMIC_STATE
, TYPE
};
126 RefCountPtr
< const SearchContext
> searchContext_
; /* Used also for absolute identifiers, in case they use a namespace alias that expands to a relative path. */
127 NamespaceReference namespaceRef_
;
128 const char * simpleId_
; /* Will not be deallocated, see memory management note above! */
131 Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, Ast::NamespaceReference::Base base
, NamespacePath
* path
, const char * simpleId
); /* Transfers ownership of path. */
132 Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, Ast::NamespaceReference::Base base
, const RefCountPtr
< const Ast::NamespacePath
> & path
, const char * simpleId
);
133 Identifier( const RefCountPtr
< const SearchContext
> & searchContext
, const NamespaceReference
& namespaceRef
, const char * simpleId
);
134 Identifier( const Identifier
& orig
);
137 const SearchContext
& searchContext( ) const { return *searchContext_
; }
138 NamespaceReference::Base
base( ) const { return namespaceRef_
.base( ); }
139 const NamespacePath
& path( ) const { return namespaceRef_
.path( ); }
140 const char * simpleId( ) const { return simpleId_
; }
142 /* Be careful when using the following destructive conversion functions!
143 * *this will be unusable after calling these, and should be destroyed.
145 Ast::PlacedIdentifier
* place( const Ast::SourceLocation
& loc
); /* Reinterprets the identifier as a placed (LHS) identifier. Always returns a new PlacedIdentifier, but will report an error if the conversion is unnatural. */
146 const char * strip( const Ast::SourceLocation
& loc
); /* Extracts the simple identifier. */
147 RefCountPtr
< const char > refstrip( const Ast::SourceLocation
& loc
); /* Warning! This will pass ownership to the reference counted result. Must not be used if there exist other references to the simpleId_ memory! */
149 void show( std::ostream
& os
, Ast::Identifier::Type type
, bool showAbsoluteMark
= true ) const;
150 void debugShow( std::ostream
& os
) const;
152 /* Warning! Comparison only takes the explicit part of the identifier into account. The search path
153 * is not used in the comparison, but absolute paths will precede relative paths.
155 bool operator < ( const Identifier
& other
) const;
157 static const char * identifierPrefix( Type type
);
160 class IdentifierPtrLess
163 bool operator () ( const Ast::Identifier
* id1
, const Ast::Identifier
* id2
) const
169 /* A placed identifier belongs to the current environment, expressed using only a simple identifier.
170 * That is, it is an absolute identifier, but looks like a relative identifier. Due to the risk
171 * of initial misinterpretation of a simple identifier in the scanner, there are methods that the parser
172 * can use for converting to the other possible types of token values.
173 * It is typically the left hand side of a binding statement.
175 class PlacedIdentifier
177 RefCountPtr
< const NamespacePath
> absolutePath_
;
178 const char * simpleId_
; /* Will not be deallocated, see memory management note above! */
180 PlacedIdentifier( const RefCountPtr
< const NamespacePath
> & absolutePath
, const char * simpleId
);
181 PlacedIdentifier( NamespacePath
* absolutePath
, const char * simpleId
); /* Transfers ownership of absolutePath. */
182 PlacedIdentifier( const NamespacePath
& absolutePath
, const char * simpleId
);
183 PlacedIdentifier( const PlacedIdentifier
& orig
);
184 ~PlacedIdentifier( );
186 const NamespacePath
& absolutePath( ) const { return *absolutePath_
; }
187 const RefCountPtr
< const NamespacePath
> & absolutePathRef( ) const { return absolutePath_
; }
188 const char * simpleId( ) const { return simpleId_
; }
190 Ast::PlacedIdentifier
* clone( ) const;
191 Ast::Identifier
* newAbsolute( ) const;
193 /* Be careful when using the following destructive conversion functions!
194 * *this will be unusable after calling these, and should be destroyed.
196 const char * strip( ); /* Extracts the simple identifier. */
197 RefCountPtr
< const char > refstrip( ); /* Warning! This will pass ownership to the reference counted result. Must not be used if there exist other references to the simpleId_ memory! */
199 /* Since it should be clear from the context that this is a placed identifier, a leading "::" is _not_ shown to reduce clutter.
201 void show( std::ostream
& os
, Ast::Identifier::Type type
) const;
203 bool operator < ( const PlacedIdentifier
& other
) const;
206 class PlacedIdentifierPtrLess
209 bool operator () ( const Ast::PlacedIdentifier
* id1
, const Ast::PlacedIdentifier
* id2
) const