| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2011, 2014 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.linuxtools.internal.ctf.core.event.metadata; |
| 14 | |
| 15 | import java.util.HashMap; |
| 16 | import java.util.Map; |
| 17 | import java.util.Set; |
| 18 | |
| 19 | import org.eclipse.linuxtools.ctf.core.event.types.EnumDeclaration; |
| 20 | import org.eclipse.linuxtools.ctf.core.event.types.IDeclaration; |
| 21 | import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration; |
| 22 | import org.eclipse.linuxtools.ctf.core.event.types.VariantDeclaration; |
| 23 | import org.eclipse.linuxtools.internal.ctf.core.event.metadata.exceptions.ParseException; |
| 24 | |
| 25 | /** |
| 26 | * <b><u>DeclarationScope</u></b> |
| 27 | * <p> |
| 28 | * A DeclarationScope keeps track of the various CTF declarations for a given |
| 29 | * scope. |
| 30 | * |
| 31 | * TODO: The notion of "symbols" and the notion of "scope" are misused in this |
| 32 | * parser, which leads to inefficient tree management. It should be cleaned up. |
| 33 | * |
| 34 | * @author Matthew Khouzam |
| 35 | * @author Simon Marchi |
| 36 | * |
| 37 | */ |
| 38 | class DeclarationScope { |
| 39 | |
| 40 | // ------------------------------------------------------------------------ |
| 41 | // Attributes |
| 42 | // ------------------------------------------------------------------------ |
| 43 | |
| 44 | private DeclarationScope fParentScope = null; |
| 45 | |
| 46 | private final Map<String, StructDeclaration> fStructs = new HashMap<>(); |
| 47 | private final Map<String, EnumDeclaration> fEnums = new HashMap<>(); |
| 48 | private final Map<String, VariantDeclaration> fVariants = new HashMap<>(); |
| 49 | private final Map<String, IDeclaration> fTypes = new HashMap<>(); |
| 50 | private final Map<String, IDeclaration> fIdentifiers = new HashMap<>(); |
| 51 | |
| 52 | // ------------------------------------------------------------------------ |
| 53 | // Constructors |
| 54 | // ------------------------------------------------------------------------ |
| 55 | |
| 56 | /** |
| 57 | * Creates a declaration scope with no parent. |
| 58 | */ |
| 59 | public DeclarationScope() { |
| 60 | } |
| 61 | |
| 62 | /** |
| 63 | * Creates a declaration scope with the specified parent. |
| 64 | * |
| 65 | * @param parentScope |
| 66 | * The parent of the newly created scope. |
| 67 | */ |
| 68 | public DeclarationScope(DeclarationScope parentScope) { |
| 69 | fParentScope = parentScope; |
| 70 | } |
| 71 | |
| 72 | // ------------------------------------------------------------------------ |
| 73 | // Getters/Setters/Predicates |
| 74 | // ------------------------------------------------------------------------ |
| 75 | |
| 76 | /** |
| 77 | * Returns the parent of the current scope. |
| 78 | * |
| 79 | * @return The parent scope. |
| 80 | */ |
| 81 | public DeclarationScope getParentScope() { |
| 82 | return fParentScope; |
| 83 | } |
| 84 | |
| 85 | // ------------------------------------------------------------------------ |
| 86 | // Registration operations |
| 87 | // ------------------------------------------------------------------------ |
| 88 | |
| 89 | /** |
| 90 | * Registers a type declaration. |
| 91 | * |
| 92 | * @param name |
| 93 | * The name of the type. |
| 94 | * @param declaration |
| 95 | * The type declaration. |
| 96 | * @throws ParseException |
| 97 | * if a type with the same name has already been defined. |
| 98 | */ |
| 99 | public void registerType(String name, IDeclaration declaration) |
| 100 | throws ParseException { |
| 101 | /* Check if the type has been defined in the current scope */ |
| 102 | if (fTypes.containsKey(name)) { |
| 103 | throw new ParseException("Type has already been defined:" + name); //$NON-NLS-1$ |
| 104 | } |
| 105 | |
| 106 | /* Add it to the register. */ |
| 107 | fTypes.put(name, declaration); |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * Registers an identifier declaration. |
| 112 | * |
| 113 | * @param name |
| 114 | * name of the identifier |
| 115 | * @param declaration |
| 116 | * the identfier's declaration |
| 117 | * @throws ParseException |
| 118 | * if an identifier with the same name has already been defined. |
| 119 | */ |
| 120 | public void registerIdentifier(String name, IDeclaration declaration) throws ParseException { |
| 121 | /* Check if the type has been defined in the current scope */ |
| 122 | if (fIdentifiers.containsKey(name)) { |
| 123 | throw new ParseException("Identifier has already been defined:" + name); //$NON-NLS-1$ |
| 124 | } |
| 125 | |
| 126 | /* Add it to the register. */ |
| 127 | fIdentifiers.put(name, declaration); |
| 128 | } |
| 129 | |
| 130 | /** |
| 131 | * Registers a struct declaration. |
| 132 | * |
| 133 | * @param name |
| 134 | * The name of the struct. |
| 135 | * @param declaration |
| 136 | * The declaration of the struct. |
| 137 | * @throws ParseException |
| 138 | * if a struct with the same name has already been registered. |
| 139 | */ |
| 140 | public void registerStruct(String name, StructDeclaration declaration) |
| 141 | throws ParseException { |
| 142 | /* Check if the struct has been defined in the current scope. */ |
| 143 | if (fStructs.containsKey(name)) { |
| 144 | throw new ParseException("Struct has already been defined:" + name); //$NON-NLS-1$ |
| 145 | } |
| 146 | |
| 147 | /* Add it to the register. */ |
| 148 | fStructs.put(name, declaration); |
| 149 | |
| 150 | /* It also defined a new type, so add it to the type declarations. */ |
| 151 | String structPrefix = "struct "; //$NON-NLS-1$ |
| 152 | registerType(structPrefix + name, declaration); |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Registers an enum declaration. |
| 157 | * |
| 158 | * @param name |
| 159 | * The name of the enum. |
| 160 | * @param declaration |
| 161 | * The declaration of the enum. |
| 162 | * @throws ParseException |
| 163 | * if an enum with the same name has already been registered. |
| 164 | */ |
| 165 | public void registerEnum(String name, EnumDeclaration declaration) |
| 166 | throws ParseException { |
| 167 | /* Check if the enum has been defined in the current scope. */ |
| 168 | if (lookupEnum(name) != null) { |
| 169 | throw new ParseException("Enum has already been defined:" + name); //$NON-NLS-1$ |
| 170 | } |
| 171 | |
| 172 | /* Add it to the register. */ |
| 173 | fEnums.put(name, declaration); |
| 174 | |
| 175 | /* It also defined a new type, so add it to the type declarations. */ |
| 176 | String enumPrefix = "enum "; //$NON-NLS-1$ |
| 177 | registerType(enumPrefix + name, declaration); |
| 178 | } |
| 179 | |
| 180 | /** |
| 181 | * Registers a variant declaration. |
| 182 | * |
| 183 | * @param name |
| 184 | * The name of the variant. |
| 185 | * @param declaration |
| 186 | * The declaration of the variant. |
| 187 | * @throws ParseException |
| 188 | * if a variant with the same name has already been registered. |
| 189 | */ |
| 190 | public void registerVariant(String name, VariantDeclaration declaration) |
| 191 | throws ParseException { |
| 192 | /* Check if the variant has been defined in the current scope. */ |
| 193 | if (lookupVariant(name) != null) { |
| 194 | throw new ParseException("Variant has already been defined:" + name); //$NON-NLS-1$ |
| 195 | } |
| 196 | |
| 197 | /* Add it to the register. */ |
| 198 | fVariants.put(name, declaration); |
| 199 | |
| 200 | /* It also defined a new type, so add it to the type declarations. */ |
| 201 | String variantPrefix = "variant "; //$NON-NLS-1$ |
| 202 | registerType(variantPrefix + name, declaration); |
| 203 | } |
| 204 | |
| 205 | // ------------------------------------------------------------------------ |
| 206 | // Lookup operations |
| 207 | // ------------------------------------------------------------------------ |
| 208 | |
| 209 | /** |
| 210 | * Looks up a type declaration in the current scope. |
| 211 | * |
| 212 | * @param name |
| 213 | * The name of the type to search for. |
| 214 | * @return The type declaration, or null if no type with that name has been |
| 215 | * defined. |
| 216 | */ |
| 217 | public IDeclaration lookupType(String name) { |
| 218 | return fTypes.get(name); |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * Looks up a type declaration in the current scope and recursively in the |
| 223 | * parent scopes. |
| 224 | * |
| 225 | * @param name |
| 226 | * The name of the type to search for. |
| 227 | * @return The type declaration, or null if no type with that name has been |
| 228 | * defined. |
| 229 | */ |
| 230 | public IDeclaration lookupTypeRecursive(String name) { |
| 231 | IDeclaration declaration = lookupType(name); |
| 232 | if (declaration != null) { |
| 233 | return declaration; |
| 234 | } else if (fParentScope != null) { |
| 235 | return fParentScope.lookupTypeRecursive(name); |
| 236 | } else { |
| 237 | return null; |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | /** |
| 242 | * Looks up a struct declaration. |
| 243 | * |
| 244 | * @param name |
| 245 | * The name of the struct to search for. |
| 246 | * @return The struct declaration, or null if no struct with that name has |
| 247 | * been defined. |
| 248 | */ |
| 249 | public StructDeclaration lookupStruct(String name) { |
| 250 | return fStructs.get(name); |
| 251 | } |
| 252 | |
| 253 | /** |
| 254 | * Looks up a struct declaration in the current scope and recursively in the |
| 255 | * parent scopes. |
| 256 | * |
| 257 | * @param name |
| 258 | * The name of the struct to search for. |
| 259 | * @return The struct declaration, or null if no struct with that name has |
| 260 | * been defined. |
| 261 | */ |
| 262 | public StructDeclaration lookupStructRecursive(String name) { |
| 263 | StructDeclaration declaration = lookupStruct(name); |
| 264 | if (declaration != null) { |
| 265 | return declaration; |
| 266 | } else if (fParentScope != null) { |
| 267 | return fParentScope.lookupStructRecursive(name); |
| 268 | } else { |
| 269 | return null; |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | /** |
| 274 | * Looks up an enum declaration. |
| 275 | * |
| 276 | * @param name |
| 277 | * The name of the enum to search for. |
| 278 | * @return The enum declaration, or null if no enum with that name has been |
| 279 | * defined. |
| 280 | */ |
| 281 | public EnumDeclaration lookupEnum(String name) { |
| 282 | return fEnums.get(name); |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Looks up an enum declaration in the current scope and recursively in the |
| 287 | * parent scopes. |
| 288 | * |
| 289 | * @param name |
| 290 | * The name of the enum to search for. |
| 291 | * @return The enum declaration, or null if no enum with that name has been |
| 292 | * defined. |
| 293 | */ |
| 294 | public EnumDeclaration lookupEnumRecursive(String name) { |
| 295 | EnumDeclaration declaration = lookupEnum(name); |
| 296 | if (declaration != null) { |
| 297 | return declaration; |
| 298 | } else if (fParentScope != null) { |
| 299 | return fParentScope.lookupEnumRecursive(name); |
| 300 | } else { |
| 301 | return null; |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | /** |
| 306 | * Looks up a variant declaration. |
| 307 | * |
| 308 | * @param name |
| 309 | * The name of the variant to search for. |
| 310 | * @return The variant declaration, or null if no variant with that name has |
| 311 | * been defined. |
| 312 | */ |
| 313 | public VariantDeclaration lookupVariant(String name) { |
| 314 | return fVariants.get(name); |
| 315 | } |
| 316 | |
| 317 | /** |
| 318 | * Looks up a variant declaration in the current scope and recursively in |
| 319 | * the parent scopes. |
| 320 | * |
| 321 | * @param name |
| 322 | * The name of the variant to search for. |
| 323 | * @return The variant declaration, or null if no variant with that name has |
| 324 | * been defined. |
| 325 | */ |
| 326 | public VariantDeclaration lookupVariantRecursive(String name) { |
| 327 | VariantDeclaration declaration = lookupVariant(name); |
| 328 | if (declaration != null) { |
| 329 | return declaration; |
| 330 | } else if (fParentScope != null) { |
| 331 | return fParentScope.lookupVariantRecursive(name); |
| 332 | } else { |
| 333 | return null; |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | /** |
| 338 | * Lookup query for an identifier in this scope. |
| 339 | * |
| 340 | * @param identifier |
| 341 | * the name of the identifier to search for. In the case of int |
| 342 | * x; it would be "x" |
| 343 | * @return the declaration of the type associated to that identifier |
| 344 | */ |
| 345 | public IDeclaration lookupIdentifier(String identifier) { |
| 346 | return fIdentifiers.get(identifier); |
| 347 | } |
| 348 | |
| 349 | /** |
| 350 | * Lookup query for an identifier through this scope and its ancestors. |
| 351 | * An ancestor scope is a scope in which this scope is nested. |
| 352 | * |
| 353 | * @param identifier |
| 354 | * the name of the identifier to search for. In the case of int |
| 355 | * x; it would be "x" |
| 356 | * @return the declaration of the type associated to that identifier |
| 357 | */ |
| 358 | public IDeclaration lookupIdentifierRecursive(String identifier) { |
| 359 | IDeclaration declaration = lookupIdentifier(identifier); |
| 360 | if (declaration != null) { |
| 361 | return declaration; |
| 362 | } else if (fParentScope != null) { |
| 363 | return fParentScope.lookupIdentifierRecursive(identifier); |
| 364 | } |
| 365 | return null; |
| 366 | } |
| 367 | |
| 368 | /** |
| 369 | * Get all the type names of this scope. |
| 370 | * |
| 371 | * @return The type names |
| 372 | */ |
| 373 | public Set<String> getTypeNames() { |
| 374 | return fTypes.keySet(); |
| 375 | } |
| 376 | |
| 377 | /** |
| 378 | * Replace a type with a new one. |
| 379 | * |
| 380 | * @param name |
| 381 | * The name of the type |
| 382 | * @param newType |
| 383 | * The type |
| 384 | * @throws ParseException |
| 385 | * If the type does not exist. |
| 386 | */ |
| 387 | public void replaceType(String name, IDeclaration newType) throws ParseException { |
| 388 | if (fTypes.containsKey(name)) { |
| 389 | fTypes.put(name, newType); |
| 390 | } else { |
| 391 | throw new ParseException("Trace does not contain type:" + name); //$NON-NLS-1$ |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | } |