1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
# ==================================================================================================================== #
# __ ___ _ ____ _ __ __ _ _ #
# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
# |_| |___/ #
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.
VHDL uses *names* to express cross-references from *usage locations* to *declarations*. Here, *names* are single or
combined identifiers. :mod:`Symbols <pyVHDLModel.Symbol>` are structures representing a *name* and a reference
(pointer) to the referenced vhdl language entity.
"""
from typing import List, Iterable, Optional as Nullable
from pyTooling.Decorators import export
from pyVHDLModel.Base import ModelEntity, ExpressionUnion
@export
class Name(ModelEntity):
"""``Name`` is the base-class for all *names* in the VHDL language model."""
_identifier: str
_normalizedIdentifier: str
_root: Nullable['Name'] # TODO: seams to be unused. There is no reverse linking, or?
_prefix: Nullable['Name']
def __init__(self, identifier: str, prefix: 'Name' = None):
super().__init__()
self._identifier = identifier
self._normalizedIdentifier = identifier.lower()
if prefix is None:
self._prefix = None
self._root = self
else:
self._prefix = prefix
self._root = prefix._root
@property
def Identifier(self) -> str:
"""
The identifier the name is referencing.
:returns: The referenced identifier.
"""
return self._identifier
@property
def NormalizedIdentifier(self) -> str:
"""
The normalized identifier the name is referencing.
:returns: The referenced identifier (normalized).
"""
return self._normalizedIdentifier
@property
def Root(self) -> 'Name':
"""
The root (left-most) element in a chain of names.
In case the name is a :class:`simple name <SimpleName>`, the root points to the name itself.
:returns: The name's root element.
"""
return self._root
@property
def Prefix(self) -> Nullable['Name']:
"""
The name's prefix in a chain of names.
:returns: The name left from current name, if not a simple name, otherwise ``None``.
"""
return self._prefix
@property
def HasPrefix(self) -> bool:
"""
Returns true, if the name has a prefix.
This is true for all names except :class:`simple names <SimpleName>`.
:returns: ``True``, if the name as a prefix.
"""
return self._prefix is not None
def __repr__(self) -> str:
return f"Name: '{self.__str__()}'"
def __str__(self) -> str:
return self._identifier
@export
class SimpleName(Name):
"""
A *simple name* is a name made from a single word.
For example, the entity name in an architecture declaration is a simple name, while the name of the architecture
itself is an identifier. The simple name references is again an identifier in the entity declaration, thus names
reference other (already) declared language entities.
"""
@export
class ParenthesisName(Name):
_associations: List
def __init__(self, prefix: Name, associations: Iterable):
super().__init__("", prefix)
self._associations = []
for association in associations:
self._associations.append(association)
association._parent = self
@property
def Associations(self) -> List:
return self._associations
def __str__(self) -> str:
return f"{self._prefix!s}({', '.join(str(a) for a in self._associations)})"
@export
class IndexedName(Name):
_indices: List[ExpressionUnion]
def __init__(self, prefix: Name, indices: Iterable[ExpressionUnion]):
super().__init__("", prefix)
self._indices = []
for index in indices:
self._indices.append(index)
index._parent = self
@property
def Indices(self) -> List[ExpressionUnion]:
return self._indices
def __str__(self) -> str:
return f"{self._prefix!s}({', '.join(str(i) for i in self._indices)})"
@export
class SlicedName(Name):
pass
@export
class SelectedName(Name):
"""
A *selected name* is a name made from multiple words separated by a dot (``.``).
For example, the library and entity name in a direct entity instantiation is a selected name. Here the entity
identifier is a selected name. The library identifier is a :class:`simple name <SimpleName>`, which is
referenced by the selected name via the :attr:`~pyVHDLModel.Name.Prefix` property.
"""
def __init__(self, identifier: str, prefix: Name):
super().__init__(identifier, prefix)
def __str__(self) -> str:
return f"{self._prefix!s}.{self._identifier}"
@export
class AttributeName(Name):
def __init__(self, identifier: str, prefix: Name):
super().__init__(identifier, prefix)
def __str__(self) -> str:
return f"{self._prefix!s}'{self._identifier}"
@export
class AllName(SelectedName):
"""
The *all name* represents the reserved word ``all`` used in names.
Most likely this name is used in use-statements.
"""
def __init__(self, prefix: Name):
super().__init__("all", prefix) # TODO: the case of 'ALL' is not preserved
@export
class OpenName(Name):
"""
The *open name* represents the reserved word ``open``.
Most likely this name is used in port associations.
"""
def __init__(self):
super().__init__("open") # TODO: the case of 'ALL' is not preserved
def __str__(self) -> str:
return "open"
|