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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
|
/* $Id$
*
* NodeFactory: helper scripts for the Parser to create AST nodes, mainly
* useful to not keep lots of c++ code out of the parser.
*
* Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
* This program is free software. You can redistribute it and/or modify it
* under the terms of the GNU General Public License, either version 2 of
* the License, or (at your option) any later version. See COPYING.
*/
#ifndef __NODE_FACTORY_HPP_INCLUDED
#define __NODE_FACTORY_HPP_INCLUDED
#include <list>
#include <string>
#include "frontend/ast/Expression.hpp"
#include "frontend/ast/IfStat.hpp"
#include "frontend/ast/LoopStat.hpp"
#include "frontend/ast/ValDeclaration.hpp"
#include "frontend/ast/CondalSigAssign.hpp"
#include "frontend/ast/Location.hpp"
#include "frontend/ast/RecordType.hpp"
#include "frontend/reporting/SyntaxError.hpp"
#include "frontend/visitor/TopDownVisitor.hpp"
#include "frontend/ast/SignalDeclaration.hpp"
#include "frontend/ast/ConstantDeclaration.hpp"
#include "frontend/ast/Aggregate.hpp"
#include "frontend/ast/SubtypeIndication.hpp"
namespace ast {
class Symbol;
class SymbolTable;
class NameLookup;
/** The NodeFactory creates various AST nodes. It serves as a bridge between
* the parser and the Syntax Tree.
*/
class NodeFactory {
public:
/** entity class of an attribute specification */
enum entityClassE {
EC_ENTITY,
EC_ARCHITECTURE,
EC_CONFIGURATION,
EC_PROCEDURE,
EC_FUNCTION,
EC_PACKAGE,
EC_TYPE,
EC_SUBTYPE,
EC_CONSTANT,
EC_SIGNAL,
EC_VARIABLE,
EC_COMPONENT,
EC_LABEL,
EC_LITERAL,
EC_UNITS,
EC_GROUP,
EC_FILE
};
/** storage helper class to unify range and index constraints. */
class Constraint {
public:
/** range constraint (if any) */
DiscreteRange *rangeConstraint;
/** index constraint(s) (if any) */
std::list<DiscreteRange*> *indexConstraint;
};
/** glue class to forward information about one identifier */
class Identifier {
public:
//! c'tor
/** @param id string of the identifier
* @param sym corresponding symbol (if any)
*/
Identifier(
std::string *id,
std::list<Symbol*> cands
) : identifier(id), candidates(cands) {}
/** string of the identifier */
std::string *identifier;
/** list of candidate symbols */
std::list<Symbol*> candidates;
};
/** helper class for generating if_stats and condal signal
* assignments.
* */
struct IfHelperS {
/** dummy c'tor: initialize members with NULL */
IfHelperS() : topstat(NULL), bottomElse(NULL) {}
/** topmost if-statement of elsif part */
IfStat *topstat;
/** reference to bottom most else part of elsif */
std::list<SeqStat*> **bottomElse;
};
/** helper struct to flatten context items during parsing. */
struct ContextItemS {
/** dummy c'tor: initialize members with NULL */
ContextItemS() : libClauses(NULL), useClauses(NULL) {}
/** library clauses */
std::list<SimpleName*> *libClauses;
/** use clauses */
std::list<Name*> *useClauses;
};
/** helper struct for type definitions. */
struct TypeDeclHelper {
public:
/** c'tor for enumeration types
* @param et declared EnumerationType */
TypeDeclHelper(
EnumerationType *et
) : enumType(et),
typeDecl(NULL),
conArrayBase(NULL),
wasRecordType(false) {}
/** c'tor for record types.
* @param rt declared RecordType
*/
TypeDeclHelper(
RecordType *rt
) : enumType(NULL),
typeDecl(rt),
conArrayBase(NULL),
wasRecordType(true) {}
/** c'tor for constraint array types.
* The constraint array types declare an anonymous
* unconstraint array and a subtype with an index constraint.
* @param indexConstraint index constraint of the array.
* @param elementType SubtypeIndication of the elements.
* @param loc location of the array definition.
* @param s SymbolTable instance.
*/
TypeDeclHelper(
std::list<DiscreteRange*> *indexConstraint,
SubtypeIndication *elementType,
Location loc,
SymbolTable &s);
/** c'tor for other types.
* @param other any other type declaration.
*/
TypeDeclHelper(
TypeDeclaration *other
) : enumType(NULL),
typeDecl(other),
conArrayBase(NULL),
wasRecordType(false) {}
/** register type declaration to SymbolTable
* @param symTab SymbolTable instance.
* @param id identifier of the type declaration.
*/
void
registerType(
SymbolTable &symTab,
NodeFactory::Identifier *id
) const;
/** flatten to a list of SymbolDeclarations. */
std::list<SymbolDeclaration*>*
flatten(void) const;
/** enumeration type, in case one was declared. */
EnumerationType *enumType;
/** any other type declaration. */
TypeDeclaration *typeDecl;
/** corresponding anonymous base type of a constraint array */
TypeDeclaration *conArrayBase;
/** was this type declaration a record type? */
bool wasRecordType;
};
/** Helper function for parsing elsif statement lists
* Attach a new ifStat from condition, thenStats to remainder.
* If remainder doesn't exist, create a new IfHelperS.
*
* @param remainder the parent elsif remainder.
* @param condition condition of the current elsif part.
* @param thenStats then-statements of the current elsif part.
* @param loc location of the elseif token.
*
* @return adjusted remainder or a new one if remainder doesn't exist
* yet.
*/
static struct IfHelperS&
createNestedElseIfs(
struct IfHelperS *remainder,
Expression* condition,
std::list<SeqStat*> *thenStats,
Location loc
);
/** Helper function for parsing if_stats.
* In case of elseIfs present, attach elseStats to bottom most
* if-statement, and set elsIf part of current if statement to
* else-part.
* Otherwise build a "regular" if-then-else statement.
*
* @param condition condition of the current if-stat.
* @param thenStats then-statement of the current if-stat.
* @param elsIfs the elseIfs, which should already be nested. Struct
* will get deleted from this function.
* @param elseStats else statements of current if-stat.
* @param loc location of the if token.
*
* @return parsed IfStat.
*/
static struct IfStat&
createIfStat(
Expression *condition,
std::list<SeqStat*> *thenStats,
struct IfHelperS* elsIfs,
std::list<SeqStat*> *elseStats,
Location loc
);
/** Create a list of Signal declarations.
* The contents of the parameters are reused in the result, so
* the caller mustn't free them.
*
* @param ids list of Identifiers for each Signal. The list itself
* isn't reused anywhere, so caller can free it.
* @param mode access mode of signal (in, out, inout).
* @param isBus is the signal tagged as bus?
* @param varInit optional initializer of signal.
* @param subtypeIndic subtype indication of signal.
* @param loc location of the signal declaration.
* @return list of ValDecls, caller must free it.
*/
static std::list<SignalDeclaration*>&
makeSignalDecls(
std::list<std::string*> &ids,
enum ValDeclaration::Mode mode,
bool isBus,
Expression *varInit,
SubtypeIndication *subtypeIndic,
Location loc
);
/** Create a list of constant declarations.
* The contents of the parameters are reused in the result, so
* the caller mustn't free them.
*
* @param ids list of Identifiers for each Signal. The list itself
* isn't reused anywhere, so caller can free it.
* @param varInit optional initializer of constant.
* @param subtypeIndic subtype indication of the constant.
* @param loc Location of the constant declaration.
* @return list of ValDecls, caller must free it.
*/
static std::list<ConstantDeclaration*>&
makeConstantDecls(
std::list<std::string*> &ids,
Expression* varInit,
SubtypeIndication *subtypeIndic,
Location loc
);
/** Create a list of Variable declarations.
* The contents of the parameters are reused in the result, so
* the caller mustn't free them.
*
* @param ids list of Identifiers for each Variable. The list itself
* isn't reused anywhere, so caller can free it.
* @param varInit optional initializer of variable.
* @param subtypeIndic subtype indication of the variable.
* @param loc Location of the variable declaration.
* @return list of ValDecls, caller must free it.
*/
static std::list<SymbolDeclaration*>&
makeVarDecls(
std::list<std::string*> &ids,
Expression *varInit,
SubtypeIndication *subtypeIndic,
Location loc
);
/** Create a list of ValDeclaration declarations.
* The contents of the parameters are reused in the result, so
* the caller mustn't free them.
*
* This version is for function declarations.
*
* @param ids list of Identifiers for each Variable. The list itself
* isn't reused anywhere, so caller can free it.
* @param varInit optional initializer of variable.
* @param cls object class that will determine if it's a
* Signal, Variable or Constant.
* @param subtypeIndic subtype indication of the element.
* @param mode access mode of the ValDeclaration.
* @param loc location in the source file.
* @return list of ValDecls, caller must free it.
*/
static std::list<ValDeclaration*>&
makeFuncInterfaceDecls(
std::list<std::string*> &ids,
Expression *varInit,
enum ValDeclaration::Mode mode,
enum ValDeclaration::ObjClass cls,
SubtypeIndication *subtypeIndic,
Location loc
);
/** Create a list of ValDeclaration declarations.
* The contents of the parameters are reused in the result, so
* the caller mustn't free them.
*
* This version is for procedure declarations.
*
* @param ids list of Identifiers for each Variable. The list itself
* isn't reused anywhere, so caller can free it.
* @param varInit optional initializer of variable.
* @param mode access mode (in/out/inout)
* @param cls object class that will determine if it's a
* Signal, Variable or Constant.
* @param subtypeIndic subtype indication of the element.
* @param loc location in the source file.
* @return list of ValDecls, caller must free it.
*/
static std::list<ValDeclaration*>&
makeProcInterfaceDecls(
std::list<std::string*> &ids,
Expression *varInit,
enum ValDeclaration::Mode mode,
enum ValDeclaration::ObjClass cls,
SubtypeIndication *subtypeIndic,
Location loc
);
/** merge two context items.
* The order will be all items from first context item first, then
* items from second context item.
*
* @param first first context item. Parameter will be reused for
* result, caller must free it.
* @param second second context item. Parameter will get freed
* during call.
* @result merged context item.
*/
static struct ContextItemS&
mergeContextItems(
struct ContextItemS &first,
struct ContextItemS &second
);
/** correctly create a CondalSigAssign during parsing.
* @param trg target value. Reused in result.
* @param conds top IfStat or SigAssignStat. Reused in result.
* @param loc location of assignment token.
* @return created CondalSigAssign. Allocated node, caller should
* free it once done with it.
*/
static CondalSigAssign&
makeCondalSigAssign(Name &trg, SeqStat &conds, Location loc);
/** create a list of record type elements.
* @param idlist list of identifiers.
* @param subtype subtype indication of element.
* @param loc location of the first elements (FIXME)
* @return list of elements.
*/
static std::list<RecordTypeElement*>&
makeRecordTypeElements(
std::list<std::string*> &idlist,
SubtypeIndication &subtype,
Location loc);
/** create the corresponding Aggregate from the give String Literal.
* @param stringLit string literal.
* @param loc Location of the string literal.
* @param nl NameLookup instance.
* @return the corresponding Aggregate or NULL if the string is a
* null-string.
*/
static Aggregate*
makeAggregateFromString(
const std::string &stringLit,
Location loc,
const NameLookup &nl
);
//! register all enumeration elements from an enumeration type
/** @param etype EnumerationType for which all EnumerationElements
* should get registered in the SymbolTable
* @param symbolTable SymbolTable instance.
* @param typeSym Symbol of the EnumerationType.
*/
static void
registerEnumElems(
const EnumerationType *etype,
SymbolTable &symbolTable,
Symbol *typeSym
);
/** create an AttributeSpecification for the attribute denoted by
* designator with initializer init and attribute the named
* entities in entityList that fit the entity class classFilter
* with it.
* @param designator referred to attribute
* @param entityList list of named entities to attribute
* @param classFilter entity class
* @param init initializer for the specification.
* @param symTab SymbolTable instance.
*/
static AttributeSpecification *
handleAttributeSpecs(
SimpleName *designator,
std::list<SimpleName*> entityList,
enum entityClassE classFilter,
Expression *init,
const SymbolTable &symTab);
/** safe upward cast a list of derived class U to a list of parent
* class T.
* @param l pointer to list of derived class pointers. Memory will
* be reused as base class list.
* @return list of base class pointers, type T
*
* Hint: if this function won't compile anywhere, just copy the
* elements from the list, as this will always work (but is
* slower).
*/
template <typename T, typename U>
static std::list<T>*
listCast(std::list<U> *l);
/** combine two lists of same type.
* @param dest list where elements are getting push_back'ed.
* @param source list which contains elements to add.
*/
template <typename T>
static void
listCombine(std::list<T> *dest, std::list<T> *source);
private:
/** is the symbol sym of entityClass ec?
* @param sym Symbol to check.
* @param ec entity class
* @return true if sym is of class ec.
*/
static bool
isOfEntityClass(const Symbol &sym, enum entityClassE ec);
//! very small visitor for attributing CondalSigAssign stats.
/** This visitor will set the target for each SigAssignStat
* that's part of a CondalSigAssign.
*/
class CondalSigAssignSetter : public TopDownVisitor {
public:
//! c'tor
/** @param trg target that will get passed downwards.
*/
CondalSigAssignSetter(Name &trg) : target(trg) {}
/** set target to SigAssignStat nodes.
* @param node SigAssignStat that gets visited.
*/
virtual void visit(SigAssignStat &node);
private:
/** target that will be passed downwards. */
Name ⌖
};
};
}; /* namespace ast */
/* template definitions */
#include "frontend/ast/NodeFactory.tpp"
#endif /* __NODE_FACTORY_HPP_INCLUDED */
|