symbolsTable.c

Description du code

Fonctions de gestion de la table des symboles Compilateur LSD010

Code source ou contenu du fichier

  1. /*
  2.  * symbolsTable.c : Implementation to manage the symbols table
  3.  * Part of the compiler project for LSD10 language
  4.  * Gaudry Stéphane
  5.  * More information on http://www.gaudry.be/langages-table-des-symboles.html
  6.  * **********************************************************
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #if(VERBOSE_LEVEL<=DEB_E)
  13. #include <errno.h>
  14. #endif
  15. #include "symbolsTableDataRepresentation.h"
  16. #include "scopeStack.h"
  17. #include "scopeHelper.h"
  18. #include "common.h"
  19. #include "hashCode.h"
  20.  
  21. /*
  22.  * **********************************************************
  23.  * Internal business implementations
  24.  * **********************************************************
  25.  */
  26.  
  27. int symbolsTableAvailable=0;
  28. /**
  29.  * Memory location of the last declaration
  30.  */
  31. int memoryUpperBound=INITIAL_INT;
  32.  
  33. /**
  34.  * Creates a new SymTableEntry instance.
  35.  */
  36. SymTableEntry* createSymTableEntry(AstNode *declarationNode)
  37. {
  38. SymTableEntry *entry=(SymTableEntry*)malloc(sizeof(SymTableEntry));
  39. if(!(entry))
  40. {
  41. if(VERBOSE_LEVEL<=DEB_E)
  42. {
  43. printMsg(DEB_E,"Allocation Error(SymTableEntry)", __FILE__, __LINE__);
  44. printMsg(DEB_E, (char *)strerror(errno), __FILE__, __LINE__);
  45. }
  46. //Failure of the compiler behavior, independent of the parsed code
  47. exit(EXIT_FAILURE);
  48. }
  49. entry->next = NULL;
  50.  
  51. ScopeStack *scopeStack = createScopeStack();
  52. scopeStack->declarationNode = declarationNode;
  53. scopeStack->parentPtr = NULL;
  54. declarationNode->info->memoryLocation=memoryUpperBound;
  55. scopeStack->functionNode = (AstNode *)scopeHelperGetCurrentFunction();
  56. if(declarationNode==getMain())
  57. {
  58. scopeStack->usage=VAR_USAGE_ALWAYS;
  59. }
  60. entry->scopeStack = scopeStack;
  61. #if(VERBOSE_LEVEL<=DEB_SYM)
  62. "\n;\tCreation of an entry for %s on scope %d (compiler %s, %d)....main=%s\n",
  63. declarationNode->info->name,
  64. getScopeDepth(scopeStack),
  65. __FILE__,
  66. __LINE__,
  67. getMain()==NULL?"null":"ok"
  68. );
  69. #endif
  70. return entry;
  71. }
  72. void finalizeSymTableEntry(SymTableEntry *entry)
  73. {
  74. if(entry!=NULL)
  75. {
  76. finalizeSymTableEntry(entry->next);
  77. free(entry);
  78. }
  79. }
  80. /**
  81.  * Search only on a given scope stack for a declaration
  82.  * Pre-condition: the scope stack matches the identifier
  83.  * @param astNode, pointer to the node for witch we search the declaration
  84.  * @param scopeId
  85.  * @param scopeStack, pointer to the stack where to search
  86.  */
  87. ScopeStack* searchDeclarationOnStack(AstNode *astNode, int scopeId, ScopeStack *scopeStack)
  88. {
  89. if(scopeStack==NULL)
  90. {
  91. return NULL;
  92. }
  93. int foundScopeId=getScopeDepth(scopeStack);
  94. #if(VERBOSE_LEVEL<=DEB_SYM)
  95. "\n;------Search for %s [%p, scope %d] on scope %d (compiler %s,%d)\n",
  96. astNode->info->name,
  97. astNode,
  98. foundScopeId,
  99. scopeId,
  100. __FILE__,
  101. __LINE__
  102. );
  103. #endif
  104. // there is a scopeStackPtr for this identifier
  105. if(foundScopeId!=ERROR_INT && foundScopeId<=scopeId)
  106. {
  107. return scopeStack;
  108. }
  109. #if(VERBOSE_LEVEL<=DEB_SYM)
  110. "\n; Nothing found for %s (%p) on scope %d (compiler %s,%d)\n",
  111. astNode->info->name,
  112. astNode,
  113. scopeId,
  114. __FILE__,
  115. __LINE__
  116. );
  117. #endif
  118. // search into the wrapper scope
  119. ScopeStack *parentScope = scopeStack->parentPtr;
  120. if(parentScope!=NULL)
  121. {
  122. #if(VERBOSE_LEVEL<=DEB_SYM)
  123. "\n;------Try to search on parent scope [%p] for %s [%p] (compiler %s,%d)\n",
  124. parentScope,
  125. astNode->info->name,
  126. astNode,
  127. __FILE__,
  128. __LINE__
  129. );
  130. #endif
  131. return searchDeclarationOnStack(astNode, scopeId, parentScope);
  132. }
  133. else
  134. {
  135. #if(VERBOSE_LEVEL<=DEB_SYM)
  136. "\n;------Scope %d, No parent scope where to search for %s (compiler %s,%d)\n",
  137. foundScopeId,
  138. astNode->info->name,
  139. __FILE__,
  140. __LINE__
  141. );
  142. #endif
  143. }
  144. return NULL;
  145. }
  146. /**
  147.  * Search on all of the linked list of given scope stack for a declaration
  148.  * @param currentNode, pointer to the node for witch we search the declaration
  149.  * @param scopeId, scope where to search
  150.  * @param scopeStack, pointer to the stack where to start search
  151.  */
  152. ScopeStack* searchDeclaration(AstNode *currentNode, int scopeId, SymTableEntry *entry)
  153. {
  154. if(entry==NULL || entry->scopeStack==NULL)
  155. {
  156. return NULL;
  157. }
  158. // if(currentNode==NULL)
  159. // {
  160. // return NULL;
  161. // }
  162. // if(currentNode->info==NULL)
  163. // {
  164. // return NULL;
  165. // }
  166. // test name to detect hashcode collisions
  167. if(strcmp(getEntryName(entry), currentNode->info->name)!=0)
  168. {
  169. // printf(
  170. // "\n; collision: %s searched, %s found, %s next\n",
  171. // currentNode->info->name,
  172. // entry->scopeStack->declarationNode->info->name,
  173. // entry->next==NULL?"null":entry->next->scopeStack->declarationNode->info->name
  174. // );
  175. // if there is collision of hashcodes, search into the next identifier stack
  176. return searchDeclaration(currentNode, scopeId, entry->next) ;
  177. }
  178. // printf(
  179. // "\nOK : %s searched, %s found\n",
  180. // currentNode->info->name,
  181. // entry->scopeStack->declarationNode->info->name
  182. // );
  183. // the scope stack matches the identifier
  184. return searchDeclarationOnStack(currentNode, scopeId, entry->scopeStack);
  185. }
  186. /**
  187.  * Search into the symbols table for a declaration of a given AST node for the current scope.
  188.  * If no backward declaration exists, the program exits with an error message
  189.  * pre-condition: astNode not NULL
  190.  */
  191. ScopeStack* getScopeDeclaration(AstNode* astNode)
  192. {
  193. int hash = getASTHashCode(astNode);
  194.  
  195. ScopeStack* foundStack = NULL;
  196. #if(VERBOSE_LEVEL<=DEB_SYM)
  197. "\n;------Search for %s; current scope=%d, Table[%d] %s (compiler %s,%d)",
  198. astNode->info->name,
  199. astNode->info->scopeId,
  200. hash,
  201. declarations[hash]==NULL?"empty":"not empty",
  202. __FILE__,
  203. __LINE__
  204. );
  205. #endif
  206. if(declarations[hash]!=NULL)
  207. {
  208. foundStack = searchDeclaration(astNode, scopeHelperGetCurrentScope(), declarations[hash]);
  209. // printf(
  210. // "\n;\tnode=%s; founstack=%s\n",
  211. // astNode->info->name,
  212. // foundStack==NULL?"null":foundStack->declarationNode->info->name
  213. // );
  214. if(foundStack!=NULL && isBefore(astNode, foundStack->declarationNode)==AST_CMP_BEFORE)
  215. {
  216. #if(VERBOSE_LEVEL<=DEB_E)
  217. ";\n;\tForward declaration detected for %s line %d col %d, declaration line %d col%d",
  218. astNode->info->name,
  219. astNode->debug->line,
  220. astNode->debug->linePsn,
  221. foundStack->declarationNode->debug->line,
  222. foundStack->declarationNode->debug->linePsn
  223. );
  224. #endif
  225. foundStack=NULL;
  226. }
  227. }
  228. //else printf("\nentry null (%s,%d)",__FILE__, __LINE__);
  229. if(foundStack==NULL)
  230. {
  231. char errorStr[1024];//todo: minimize length
  232. errorStr,
  233. "No previous declaration found for %s line %d col %d (compiler %s,%d)",
  234. astNode->info->name,
  235. astNode->debug->line,
  236. astNode->debug->linePsn,
  237. __FILE__,
  238. __LINE__
  239. );
  240. onError(errorStr, __FILE__, __LINE__, astNode);
  241. }
  242. #if(VERBOSE_LEVEL<=DEB_SYM)
  243. printf("\n;------Found %s (%p)",astNode->info->name, astNode);
  244. #endif
  245. return foundStack;
  246. }
  247. /**
  248.  * Adds a declaration into the symbols table
  249.  * @param entry pointer to an existing item of linked list (to solve hash collisions)
  250.  * @param declarationNode declaration to add into the symbols table
  251.  * @param hash index of the item on the symbols table
  252.  * pre-condition: entry not null
  253.  */
  254. void addSafeDeclaration(SymTableEntry *entry, AstNode* declarationNode, int hash)
  255. {
  256. if(strcmp( getEntryName(entry), declarationNode->info->name )!=0)
  257. {
  258. // hash collision detected;
  259. #if(VERBOSE_LEVEL<=DEB_SYM)
  260. "\n;------Collision detected for %s hash=%d [%s found on %p] (compiler %s,%d)",
  261. declarationNode->info->name,
  262. hash,
  263. getEntryName(entry),
  264. entry,
  265. __FILE__,
  266. __LINE__
  267. );
  268. #endif
  269. SymTableEntry *nextEntry = entry->next;
  270. if(nextEntry==NULL)
  271. {
  272. SymTableEntry *tempEntry = createSymTableEntry(declarationNode);
  273. tempEntry->next=entry;
  274. // we add the new entry as first item of the linked list(proximity possible usage)
  275. declarations[hash]=tempEntry;
  276. }
  277. else
  278. {
  279. addSafeDeclaration(nextEntry, declarationNode, hash);
  280. }
  281. }
  282. else
  283. {
  284. #if(VERBOSE_LEVEL<=DEB_SYM)
  285. "\n;------A scope exists for %s [%s] (compiler %s,%d)",
  286. declarationNode->info->name,
  287. getEntryName(entry),
  288. __FILE__,
  289. __LINE__
  290. );
  291. #endif
  292. int curScope = scopeHelperGetCurrentScope();
  293. int foundScope = getScopeDepth(entry->scopeStack);
  294. if(foundScope==curScope)
  295. {
  296. AstNode* foundNode = entry->scopeStack->declarationNode;
  297. char errorStr[1024];//todo: minimize length
  298. errorStr,
  299. "A previous declaration for %s (scope %d line %d col %d) has been detected (scope %d line %d col %d) by compiler %s,%d",
  300. declarationNode->info->name,
  301. curScope,
  302. declarationNode->debug->line,
  303. declarationNode->debug->linePsn,
  304. foundScope,
  305. foundNode->debug->line,
  306. foundNode->debug->linePsn,
  307. __FILE__,
  308. __LINE__
  309. );
  310. onError(errorStr, __FILE__, __LINE__, declarationNode);
  311. }
  312. pushScopesStack(&(entry->scopeStack), scopeHelperGetCurrentScope(), declarationNode);
  313. entry->scopeStack->declarationNode->info->memoryLocation=memoryUpperBound;
  314. }
  315. }
  316. /**
  317.  * Parses nodes from variable usage node to root to detect if we are on a conditional bloc
  318.  */
  319. void checkUsage(ScopeStack* scopeStack, AstNode *node)
  320. {
  321. if(scopeStack==NULL)
  322. {
  323. scopeStack = getScopeDeclaration(node);
  324. }
  325. if(scopeStack!=NULL && scopeStack->usage!=VAR_USAGE_ALWAYS)
  326. {
  327. while(node->parent!=NULL)
  328. {
  329. // printf(
  330. // "\n; Check usage for %s line %d col %d, parent=%s (compiler(%s, %d)",
  331. // node->info->name,
  332. // node->debug->line,
  333. // node->debug->linePsn,
  334. // node->parent==NULL?"NULL":node->parent->info->name,
  335. // __FILE__,
  336. // __LINE__
  337. // );
  338. switch(node->parent->subtype)
  339. {
  340. case LEXICAL_IF_STMT:
  341. case AST_IF_ELSE_STMT:
  342. scopeStack->usage = VAR_USAGE_SOMETIMES;
  343. return;
  344. }
  345. node=node->parent;
  346. }
  347. scopeStack->usage=VAR_USAGE_ALWAYS;
  348. }
  349. }
  350. /*
  351.  * **********************************************************
  352.  * Implementation of the header exposed items
  353.  * See symbolsTable.h for these functions comments
  354.  * **********************************************************
  355.  */
  356.  
  357. int setUsage(AstNode *currentVarNode, VariableUsage usage)
  358. {
  359. switch(currentVarNode->type)
  360. {
  361. case NODE_TYPE_ID:
  362. case NODE_TYPE_FUNCTION_CALL:
  363. break;
  364. default:return EXIT_FAILURE;
  365. }
  366. ScopeStack* foundStack = getScopeDeclaration(currentVarNode);
  367. if(foundStack==NULL)
  368. {
  369. return EXIT_FAILURE;
  370. }
  371. foundStack->usage = usage;
  372. }
  373.  
  374. char *getEntryName(SymTableEntry *entry)
  375. {
  376. if(entry==NULL)return "NULL entry";
  377. // if(entry->scopeStack==NULL)return "NULL entry stack";
  378. // if(entry->scopeStack->declarationNode==NULL)return "NULL entry declaration node";
  379. // if(entry->scopeStack->declarationNode->info==NULL)return "NULL entry declaration node info";
  380. return entry->scopeStack->declarationNode->info->name;
  381. }
  382.  
  383. int isSymbolsTableAvailable()
  384. {
  385. return symbolsTableAvailable;
  386. }
  387.  
  388. void initializeSymbolsTable()
  389. {
  390. setHashUpperBoundary(TABLES_SIZE);
  391. initializeScopeHelper();
  392. //declare i before ‘for’ statement because ‘for’ loop initial declarations are only allowed in C99 mode
  393. int i;
  394. for(i=0;i<TABLES_SIZE;i++)
  395. {
  396. declarations[i]=NULL;//createSymTableEntry(NULL);
  397. }
  398. symbolsTableAvailable=1;
  399. }
  400. void finalizeSymbolsTable()
  401. {
  402. //printScopeUsage();
  403. int i;
  404. for(i=0;i<TABLES_SIZE;i++)
  405. {
  406. finalizeSymTableEntry(declarations[i]);
  407. }
  408. symbolsTableAvailable=0;
  409. finalizeScopeHelper();
  410. }
  411. void enterScope()
  412. {
  413. scopeHelperEnterScope();
  414. }
  415. void exitScope()
  416. {
  417. scopeHelperExitScope();
  418. }
  419. int enterFunctionScope(AstNode* functionNode)
  420. {
  421. scopeHelperEnterScope();
  422. scopeHelperSetCurrentFunction(functionNode);
  423. }
  424. void addDeclaration(AstNode* declarationNode)
  425. {
  426. switch(declarationNode->type)
  427. {
  428. case NODE_TYPE_VAR_DECL:
  429. ++memoryUpperBound;
  430. case NODE_TYPE_PARAM_DECL:
  431. case NODE_TYPE_FUNCTION:
  432. {
  433. int hash = getASTHashCode(declarationNode);
  434. if(declarations[hash]==NULL)
  435. {
  436. #if(VERBOSE_LEVEL<=DEB_SYM)
  437. printf(";\n; Adding %s declaration into symbols table[new entry], scope=%d (compiler %s, line %d)",
  438. declarationNode->info->name,
  439. scopeHelperGetCurrentScope(),
  440. __FILE__,
  441. __LINE__
  442. );
  443. #endif
  444. declarations[hash]=createSymTableEntry(declarationNode);
  445. }
  446. else
  447. {
  448. #if(VERBOSE_LEVEL<=DEB_SYM)
  449. printf(";\n; Adding %s declaration into symbols table[existing entry], scope=%d (compiler %s, line %d)",
  450. declarationNode->info->name,
  451. scopeHelperGetCurrentScope(),
  452. __FILE__,
  453. __LINE__
  454. );
  455. #endif
  456. addSafeDeclaration(declarations[hash], declarationNode, hash);
  457. }
  458. #if(VERBOSE_LEVEL<=DEB_SYM)
  459. printSymbolsTableDebug(__FILE__, __LINE__);
  460. #endif
  461. }
  462. break;
  463. }
  464. // A declaration node is his own declaration
  465. declarationNode->info->declarationNode=declarationNode;
  466. }
  467.  
  468. AstNode* getDeclaration(AstNode *node)
  469. {
  470. if(node==NULL)
  471. {
  472. #if(VERBOSE_LEVEL<=DEB_E)
  473. {
  474. printMsg(DEB_E,"Illegal argument (NULL)", __FILE__, __LINE__);
  475. }
  476. #endif
  477. //Failure of the compiler behavior, independent of the parsed code
  478. exit(EXIT_FAILURE);
  479. }
  480. #if(VERBOSE_LEVEL<=DEB_SYM)
  481. printf(";\n; Get %s declaration from symbols table[bypass=%s] (compiler %s, line %d)",
  482. node->info->name,
  483. node->info->declarationNode==NULL?"no":"yes",
  484. __FILE__,
  485. __LINE__
  486. );
  487. #endif
  488. if(node->info->declarationNode!=NULL)
  489. {
  490. return node->info->declarationNode;
  491. }
  492. //node->info->scopeDepth=scopeHelperGetCurrentDepth();
  493. ScopeStack* foundStack = NULL;
  494. switch(node->type)
  495. {
  496. case NODE_TYPE_VAR_DECL:
  497. return node;
  498. case NODE_TYPE_FUNCTION:
  499. case NODE_TYPE_PARAM:
  500. #if(VAR_USAGE_REPORT_REQUESTED)
  501. checkUsage(foundStack, node);
  502. #endif
  503. return node;
  504. case NODE_TYPE_ID:
  505. case NODE_TYPE_FUNCTION_CALL:
  506. // if(node->info->declarationNode==NULL)
  507. // {
  508. #if(VERBOSE_LEVEL<=DEB_SYM)
  509. ";\n; Declaration not yet found for %s line %d col %d, must search into table (compiler %s, line %d)",
  510. node->info->name,
  511. node->debug->line,
  512. node->debug->linePsn,
  513. __FILE__,
  514. __LINE__
  515. );
  516. #endif
  517. foundStack = getScopeDeclaration(node);
  518. node->info->declarationNode = foundStack==NULL?NULL:foundStack->declarationNode;
  519. // }
  520. #if(VAR_USAGE_REPORT_REQUESTED)
  521. checkUsage(foundStack, node);
  522. #endif
  523. return node->info->declarationNode;
  524. }
  525. #if(VERBOSE_LEVEL<=DEB_E)
  526. {
  527. ";\n; Error : Illegal argument (%s is not an id or a function call) On %s, Line%d",
  528. node->info->name,
  529. __FILE__,
  530. __LINE__
  531. );
  532. }
  533. #endif
  534. //Failure of the compiler behavior, independent of the parsed code
  535. exit(EXIT_FAILURE);
  536. }
  537. int getDeclarationsMemoryUpperBound()
  538. {
  539. return memoryUpperBound;
  540. }
  541. int getDeclarationMemoryLocation(AstNode *node)
  542. {
  543. AstNode *declarationNode = getDeclaration(node);
  544. return declarationNode==NULL?INITIAL_INT:declarationNode->info->memoryLocation;
  545. }

Autres extraits de codes en c

  • DisquetteDispo Vérifier la disponibilité du lecteur de disquette
  • Suite de Fibonacci Exemple d'itération en C
  • Suite de Fibonacci Exemple de récursion en C
  • astDataRepresentation.h Représentation de données de l'arbre syntaxique abstrait Compilateur LSD010
  • ast.h Arbre syntaxique abstrait Compilateur LSD010
  • ast.c Arbre syntaxique abstrait Compilateur LSD010
  • symbolsTableDataRepresentation.h Représentation de données de la table des symboles Compilateur LSD010
  • symbolsTable.h Fonctions de gestion de la table des symboles Compilateur LSD010
  • symbolsTable.c Fonctions de gestion de la table des symboles Compilateur LSD010
  • hashCode.h Fonctions de hachage Compilateur LSD010
  • hashCode.c Fonctions de hachage Compilateur LSD010
  • scopeStack.h Fonctions de gestion d'une pile de portées Compilateur LSD010
  • scopeStack.c Fonctions de gestion d'une pile de portées Compilateur LSD010
  • scopeHelper.h Fonctions de gestion de la portée courante Compilateur LSD010
  • console.h Fonctions d'affichage Compilateur LSD010
  • console.c Fonctions d'affichage Compilateur LSD010
  • graphVizHelper.h Génération d'une image d'un arbre syntaxique abstrait.
    Classe d'intégration de l'outil GraphViz. Compilateur LSD010
  • graphVizHelper.c Génération d'une image d'un arbre syntaxique abstrait.
    Classe d'intégration de l'outil GraphViz. Compilateur LSD010
  • common.h Définition des constantes et variables communes Compilateur LSD010
  • pcode.c Génération de p-code Compilateur LSD010
  • pcode.h Génération de p-code Compilateur LSD010
  • Tous les extraits

Document créé le 05/10/2009, dernière modification le 28/10/2018
Source du document imprimé : https://www.gaudry.be/sniplet-rf-lsd010/project/source/symbolsTable.c.html

L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.