fb0deeb916bb53fd5dfe0e11294c15d6d05dc598
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / event / metadata / DeclarationScope.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal and others
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors: Matthew Khouzam - Initial Design and Grammar
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.ctf.core.event.metadata;
14
15 import java.util.Arrays;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
23 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
24 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
25 import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
26 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
27
28 /**
29 * <b><u>DeclarationScope</u></b>
30 * <p>
31 * A DeclarationScope keeps track of the various CTF declarations for a given
32 * scope.
33 *
34 * TODO: The notion of "symbols" and the notion of "scope" are misused in this
35 * parser, which leads to inefficient tree management. It should be cleaned up.
36 *
37 * @author Matthew Khouzam
38 * @author Simon Marchi
39 * @since 1.1
40 *
41 */
42 public class DeclarationScope {
43
44 // ------------------------------------------------------------------------
45 // Attributes
46 // ------------------------------------------------------------------------
47
48 private DeclarationScope fParentScope;
49 private @NonNull Map<String, DeclarationScope> fChildren = new HashMap<>();
50
51 private final Map<String, StructDeclaration> fStructs = new HashMap<>();
52 private final Map<String, EnumDeclaration> fEnums = new HashMap<>();
53 private final Map<String, VariantDeclaration> fVariants = new HashMap<>();
54 private final Map<String, IDeclaration> fTypes = new HashMap<>();
55 private final Map<String, IDeclaration> fIdentifiers = new HashMap<>();
56 private String fName;
57
58 // ------------------------------------------------------------------------
59 // Constructors
60 // ------------------------------------------------------------------------
61
62 /**
63 * Creates a declaration scope with no parent.
64 */
65 public DeclarationScope() {
66 }
67
68 /**
69 * Creates a declaration scope with the specified parent.
70 *
71 * @param parentScope
72 * The parent of the newly created scope.
73 * @param name
74 * scope name
75 */
76 public DeclarationScope(DeclarationScope parentScope, String name) {
77 fParentScope = parentScope;
78 fName = name;
79 if (parentScope != null) {
80 parentScope.registerChild(name, this);
81 }
82 }
83
84 private void registerChild(String name, DeclarationScope declarationScope) {
85 fChildren.put(name, declarationScope);
86 }
87
88 // ------------------------------------------------------------------------
89 // Getters/Setters/Predicates
90 // ------------------------------------------------------------------------
91
92 /**
93 * Returns the parent of the current scope.
94 *
95 * @return The parent scope.
96 */
97 public DeclarationScope getParentScope() {
98 return fParentScope;
99 }
100
101 /**
102 * Sets the name of the scope
103 *
104 * @param name
105 * the name
106 */
107 public void setName(String name) {
108 if (hasParent()) {
109 fParentScope.fChildren.remove(fName);
110 fParentScope.fChildren.put(name, this);
111 fName = name;
112 }
113 }
114
115 // ------------------------------------------------------------------------
116 // Registration operations
117 // ------------------------------------------------------------------------
118
119 /**
120 * Registers a type declaration.
121 *
122 * @param name
123 * The name of the type.
124 * @param declaration
125 * The type declaration.
126 * @throws ParseException
127 * if a type with the same name has already been defined.
128 */
129 public void registerType(String name, IDeclaration declaration)
130 throws ParseException {
131 /* Check if the type has been defined in the current scope */
132 if (fTypes.containsKey(name)) {
133 throw new ParseException("Type has already been defined:" + name); //$NON-NLS-1$
134 }
135
136 /* Add it to the register. */
137 fTypes.put(name, declaration);
138 }
139
140 /**
141 * Registers an identifier declaration.
142 *
143 * @param name
144 * name of the identifier
145 * @param declaration
146 * the identfier's declaration
147 * @throws ParseException
148 * if an identifier with the same name has already been defined.
149 */
150 public void registerIdentifier(String name, IDeclaration declaration) throws ParseException {
151 /* Check if the type has been defined in the current scope */
152 if (fIdentifiers.containsKey(name)) {
153 throw new ParseException("Identifier has already been defined:" + name); //$NON-NLS-1$
154 }
155
156 /* Add it to the register. */
157 fIdentifiers.put(name, declaration);
158 }
159
160 /**
161 * Registers a struct declaration.
162 *
163 * @param name
164 * The name of the struct.
165 * @param declaration
166 * The declaration of the struct.
167 * @throws ParseException
168 * if a struct with the same name has already been registered.
169 */
170 public void registerStruct(String name, StructDeclaration declaration)
171 throws ParseException {
172 /* Check if the struct has been defined in the current scope. */
173 if (fStructs.containsKey(name)) {
174 throw new ParseException("Struct has already been defined:" + name); //$NON-NLS-1$
175 }
176
177 /* Add it to the register. */
178 fStructs.put(name, declaration);
179
180 /* It also defined a new type, so add it to the type declarations. */
181 String structPrefix = "struct "; //$NON-NLS-1$
182 registerType(structPrefix + name, declaration);
183 }
184
185 /**
186 * Registers an enum declaration.
187 *
188 * @param name
189 * The name of the enum.
190 * @param declaration
191 * The declaration of the enum.
192 * @throws ParseException
193 * if an enum with the same name has already been registered.
194 */
195 public void registerEnum(String name, EnumDeclaration declaration)
196 throws ParseException {
197 /* Check if the enum has been defined in the current scope. */
198 if (lookupEnum(name) != null) {
199 throw new ParseException("Enum has already been defined:" + name); //$NON-NLS-1$
200 }
201
202 /* Add it to the register. */
203 fEnums.put(name, declaration);
204
205 /* It also defined a new type, so add it to the type declarations. */
206 String enumPrefix = "enum "; //$NON-NLS-1$
207 registerType(enumPrefix + name, declaration);
208 }
209
210 /**
211 * Registers a variant declaration.
212 *
213 * @param name
214 * The name of the variant.
215 * @param declaration
216 * The declaration of the variant.
217 * @throws ParseException
218 * if a variant with the same name has already been registered.
219 */
220 public void registerVariant(String name, VariantDeclaration declaration)
221 throws ParseException {
222 /* Check if the variant has been defined in the current scope. */
223 final VariantDeclaration lookupVariant = lookupVariant(name);
224 if (declaration.equals(lookupVariant)) {
225 return;
226 }
227 if (lookupVariant != null) {
228 throw new ParseException("Variant has already been defined:" + name); //$NON-NLS-1$
229 }
230
231 /* Add it to the register. */
232 fVariants.put(name, declaration);
233
234 /* It also defined a new type, so add it to the type declarations. */
235 String variantPrefix = "variant "; //$NON-NLS-1$
236 registerType(variantPrefix + name, declaration);
237 }
238
239 // ------------------------------------------------------------------------
240 // Lookup operations
241 // ------------------------------------------------------------------------
242
243 /**
244 * Lookup the children scopes of this scope
245 *
246 * @param name
247 * the child to lookup
248 * @return the scope or null
249 */
250 public @Nullable DeclarationScope lookupChild(String name) {
251 return fChildren.get(name);
252 }
253
254 /**
255 * Lookup the children scopes of this scope and this scope's parents
256 *
257 * @param name
258 * the child to lookup
259 * @return the scope or null
260 */
261 public @Nullable DeclarationScope lookupChildRecursive(String name) {
262 final DeclarationScope declarationScope = fChildren.get(name);
263 if (declarationScope == null && hasParent()) {
264 return fParentScope.lookupChildRecursive(name);
265 }
266 return declarationScope;
267 }
268
269 /**
270 * Looks up a type declaration in the current scope.
271 *
272 * @param name
273 * The name of the type to search for.
274 * @return The type declaration, or null if no type with that name has been
275 * defined.
276 */
277 public IDeclaration lookupType(String name) {
278 return fTypes.get(name);
279 }
280
281 /**
282 * Looks up a type declaration in the current scope and recursively in the
283 * parent scopes.
284 *
285 * @param name
286 * The name of the type to search for.
287 * @return The type declaration, or null if no type with that name has been
288 * defined.
289 */
290 public IDeclaration lookupTypeRecursive(String name) {
291 IDeclaration declaration = lookupType(name);
292 if (declaration != null) {
293 return declaration;
294 } else if (hasParent()) {
295 return fParentScope.lookupTypeRecursive(name);
296 } else {
297 return null;
298 }
299 }
300
301 /**
302 * Looks up a struct declaration.
303 *
304 * @param name
305 * The name of the struct to search for.
306 * @return The struct declaration, or null if no struct with that name has
307 * been defined.
308 */
309 public StructDeclaration lookupStruct(String name) {
310 return fStructs.get(name);
311 }
312
313 /**
314 * Looks up a struct declaration in the current scope and recursively in the
315 * parent scopes.
316 *
317 * @param name
318 * The name of the struct to search for.
319 * @return The struct declaration, or null if no struct with that name has
320 * been defined.
321 */
322 public StructDeclaration lookupStructRecursive(String name) {
323 StructDeclaration declaration = lookupStruct(name);
324 if (declaration != null) {
325 return declaration;
326 } else if (hasParent()) {
327 return fParentScope.lookupStructRecursive(name);
328 } else {
329 return null;
330 }
331 }
332
333 /**
334 * Looks up an enum declaration.
335 *
336 * @param name
337 * The name of the enum to search for.
338 * @return The enum declaration, or null if no enum with that name has been
339 * defined.
340 */
341 public EnumDeclaration lookupEnum(String name) {
342 return fEnums.get(name);
343 }
344
345 /**
346 * Looks up an enum declaration in the current scope and recursively in the
347 * parent scopes.
348 *
349 * @param name
350 * The name of the enum to search for.
351 * @return The enum declaration, or null if no enum with that name has been
352 * defined.
353 */
354 public EnumDeclaration lookupEnumRecursive(String name) {
355 EnumDeclaration declaration = lookupEnum(name);
356 if (declaration != null) {
357 return declaration;
358 } else if (hasParent()) {
359 return fParentScope.lookupEnumRecursive(name);
360 } else {
361 return null;
362 }
363 }
364
365 /**
366 * Looks up a variant declaration.
367 *
368 * @param name
369 * The name of the variant to search for.
370 * @return The variant declaration, or null if no variant with that name has
371 * been defined.
372 */
373 public VariantDeclaration lookupVariant(String name) {
374 return fVariants.get(name);
375 }
376
377 /**
378 * Looks up a variant declaration in the current scope and recursively in
379 * the parent scopes.
380 *
381 * @param name
382 * The name of the variant to search for.
383 * @return The variant declaration, or null if no variant with that name has
384 * been defined.
385 */
386 public VariantDeclaration lookupVariantRecursive(String name) {
387 VariantDeclaration declaration = lookupVariant(name);
388 if (declaration != null) {
389 return declaration;
390 } else if (hasParent()) {
391 return fParentScope.lookupVariantRecursive(name);
392 } else {
393 return null;
394 }
395 }
396
397 private boolean hasParent() {
398 return fParentScope != null;
399 }
400
401 /**
402 * Lookup query for an identifier in this scope.
403 *
404 * @param identifier
405 * the name of the identifier to search for. In the case of int
406 * x; it would be "x"
407 * @return the declaration of the type associated to that identifier
408 */
409 public IDeclaration lookupIdentifier(String identifier) {
410 return fIdentifiers.get(identifier);
411 }
412
413 /**
414 * Lookup query for an identifier through this scope and its ancestors. An
415 * ancestor scope is a scope in which this scope is nested.
416 *
417 * @param identifier
418 * the name of the identifier to search for. In the case of int
419 * x; it would be "x"
420 * @return the declaration of the type associated to that identifier
421 */
422 public IDeclaration lookupIdentifierRecursive(String identifier) {
423 if (identifier.contains(".")) { //$NON-NLS-1$
424 String[] scopes = identifier.split("\\."); //$NON-NLS-1$
425 return lookupIdentifierRecursive(scopes);
426 }
427 IDeclaration declaration = lookupIdentifier(identifier);
428 if (declaration != null) {
429 return declaration;
430 } else if (hasParent()) {
431 return fParentScope.lookupIdentifierRecursive(identifier);
432 }
433 return null;
434 }
435
436 private IDeclaration lookupIdentifierRecursive(String[] scopes) {
437 if (scopes.length < 1) {
438 return null;
439 }
440 // find first element
441 DeclarationScope scope = this;
442 scope = lookupRoot(scopes, scope);
443 if (scope == null) {
444 return null;
445 }
446 for (int i = 1; i < scopes.length; i++) {
447 final String scopeName = scopes[i];
448 if (scope == null) {
449 return null;
450 }
451 IDeclaration declaration = lookupIdentifierElement(scope, scopeName, Arrays.copyOfRange(scopes, i, scopes.length));
452 if (declaration != null) {
453 return declaration;
454 }
455 scope = scope.fChildren.get(scopeName);
456 }
457 return null;
458 }
459
460 private static DeclarationScope lookupRoot(String[] scopes, DeclarationScope originScope) {
461 DeclarationScope scope = originScope;
462 final String rootElement = scopes[0];
463 while (!rootElement.equals(scope.fName)) {
464 if (!scope.hasParent()) {
465 return scope.fChildren.get(rootElement);
466 }
467 scope = scope.getParentScope();
468 }
469 return scope;
470 }
471
472 private IDeclaration lookupIdentifierElement(DeclarationScope scope, String scopeName, String[] scopes) {
473 if (scope.fStructs.containsKey(scopeName)) {
474 return lookupStructScope(scope, scopeName, scopes);
475 } else if (scope.fTypes.containsKey(scopeName)) {
476 return scope.fTypes.get(scopeName);
477 } else if (scope.fEnums.containsKey(scopeName)) {
478 return scope.fEnums.get(scopeName);
479 } else if (scope.fIdentifiers.containsKey(scopeName)) {
480 return scope.fIdentifiers.get(scopeName);
481 }
482 return null;
483 }
484
485 private IDeclaration lookupStructScope(DeclarationScope scope, String scopeName, String[] scopes) {
486 final IDeclaration structDeclaration = scope.fStructs.get(scopeName);
487 if (scopes.length <= 1) {
488 return structDeclaration;
489 }
490 return lookupIdentifierStructElement((StructDeclaration) structDeclaration, scopes[1], Arrays.copyOfRange(scopes, 2, scopes.length));
491 }
492
493 private IDeclaration lookupIdentifierStructElement(StructDeclaration structDeclaration, String string, String[] children) {
494 IDeclaration field = structDeclaration.getField(string);
495 if (children == null || children.length <= 0) {
496 return field;
497 }
498 if (field instanceof StructDeclaration) {
499 StructDeclaration fieldStructDeclaration = (StructDeclaration) field;
500 return lookupIdentifierStructElement(fieldStructDeclaration, children[0], Arrays.copyOfRange(children, 1, children.length));
501 }
502 return null;
503 }
504
505 /**
506 * Get all the type names of this scope.
507 *
508 * @return The type names
509 */
510 public Set<String> getTypeNames() {
511 return fTypes.keySet();
512 }
513
514 /**
515 * Replace a type with a new one.
516 *
517 * @param name
518 * The name of the type
519 * @param newType
520 * The type
521 * @throws ParseException
522 * If the type does not exist.
523 */
524 public void replaceType(String name, IDeclaration newType) throws ParseException {
525 if (fTypes.containsKey(name)) {
526 fTypes.put(name, newType);
527 } else {
528 throw new ParseException("Trace does not contain type:" + name); //$NON-NLS-1$
529 }
530 }
531
532 /**
533 * Add a child scope
534 *
535 * @param scope
536 * the child
537 */
538 public void addChild(DeclarationScope scope) {
539 final DeclarationScope oldParent = scope.getParentScope();
540 if (oldParent != null) {
541 oldParent.fChildren.remove(scope.fName);
542 }
543 fChildren.put(scope.fName, scope);
544 scope.fParentScope = this;
545 }
546 }
This page took 0.0419929999999999 seconds and 4 git commands to generate.