ast.c

Description du code

Arbre syntaxique abstrait Compilateur LSD010

Code source ou contenu du fichier

  1. /*
  2.  * ast.c : generation of an Abstract Syntaxic Tree,
  3.  * and LSD10 constraints checks (data types, etc.).
  4.  * Part of the compiler project for LSD10 language
  5.  * Gaudry Stéphane
  6.  * More information on http://www.gaudry.be/langages-analyse-syntaxique-ast.html
  7.  */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #if(VERBOSE_LEVEL<=DEB_E)
  12. #include <errno.h>
  13. #endif
  14.  
  15. #include "common.h"
  16.  
  17. /*
  18.  * **********************************************************
  19.  * Internal business implementations
  20.  * **********************************************************
  21.  */
  22.  
  23. extern int lexLinesCount;
  24. extern char* yytext;
  25. extern int *yylineno;
  26. extern AstNode *rootNode;
  27. /*
  28.  * counter for unique names
  29.  */
  30. int nameIncrementor=0;
  31. /**
  32.  * main function node
  33.  * allows to detect if the only one valid main function has been found before
  34.  * and allows to get the main node without a new search
  35.  */
  36. AstNode *mainNode=NULL;
  37. /**
  38.  * Never use this out of internal ast functions
  39.  */
  40. #define AST_TODO 21378
  41.  
  42. /**
  43.  * Generates a human readable string for a type error
  44.  */
  45. char* typeFailureToString(int found, int expected, AstNode *checkedNode, char *file, int line)
  46. {
  47. char errorStr[1024];//todo: minimize length
  48. char *str = errorStr;
  49. if(checkedNode->type==NODE_TYPE_REXP)
  50. {
  51. str,
  52. "Wrong type for %s operation : \"%s\"(%d) expected, but \"%s\"(%d) found (compiler %s,%d)",
  53. typeToString(checkedNode->subtype),
  54. typeToString(expected),
  55. expected,
  56. typeToString(found),
  57. found,
  58. file,
  59. line
  60. );
  61. }
  62. else
  63. {
  64. str,
  65. "Type check failure : \"%s\"(%d) expected, but \"%s\"(%d) found for %s (compiler %s,%d)",
  66. typeToString(expected),
  67. expected,
  68. typeToString(found),
  69. found,
  70. checkedNode->info->name,
  71. file,
  72. line
  73. );
  74. }
  75. return str;
  76. }
  77. /**
  78.  * Checks if the two given types are the same, and
  79.  * triggers a Yacc custom error if they are not equals
  80.  */
  81. void checkType(int found, int expected, AstNode *checkedNode, char *file, int line)
  82. {
  83. if(found!=NODE_TYPE_NOTHING && found!=expected)
  84. {
  85. if(
  86. (found==AST_INTEGER_ARRAY_VAR_TYPE && expected==AST_INTEGER_VAR_TYPE)
  87. ||(found==AST_INTEGER_VAR_TYPE && expected==AST_INTEGER_ARRAY_VAR_TYPE)
  88. ||(found==AST_BOOLEAN_ARRAY_VAR_TYPE && expected==AST_BOOLEAN_VAR_TYPE)
  89. ||(found==AST_BOOLEAN_VAR_TYPE && expected==AST_BOOLEAN_ARRAY_VAR_TYPE)
  90. )
  91. {
  92. return;
  93. }
  94. onError(typeFailureToString(found, expected, checkedNode, file, line), __FILE__, __LINE__, checkedNode);
  95. }
  96. }
  97. /**
  98.  * Calls methods on the table of symbols to get the type of a given node (checkedNode)
  99.  * Sets also the computed type to avoid further type checks
  100.  * Pre-condition : table may not be null
  101.  */
  102. int getTypeWrapper(AstNode *checkedNode)
  103. {
  104. if(!isSymbolsTableAvailable())
  105. {
  106. onError("Table of Symbols must not be NULL", __FILE__, __LINE__, checkedNode);
  107. //Failure of the compiler behavior, independent of the parsed code
  108. exit(EXIT_FAILURE);
  109. }
  110. int type = NODE_TYPE_NOTHING;
  111. if(checkedNode!=NULL){
  112. #if(VERBOSE_LEVEL<=DEB_AST)
  113. ";\n\tgetTypeWrapper check for %15s (line %d, col %d) = %15s (%d), computed type= %s(%d) (compiler %s,%d)",
  114. checkedNode->info->name,
  115. checkedNode->debug->line,
  116. checkedNode->debug->linePsn,
  117. typeToString(checkedNode->type),
  118. checkedNode->type,
  119. typeToString(checkedNode->info->computedType),
  120. checkedNode->info->computedType,
  121. __FILE__,
  122. __LINE__
  123. );
  124. #endif
  125. if(/*checkedNode->info!=NULL && */checkedNode->info->computedType!=AST_TODO)
  126. {
  127. //the node type is already computed, no need to ask for it
  128. return checkedNode->info->computedType;
  129. }
  130. switch(checkedNode->type)
  131. {
  132. case LEXICAL_TRUE_VAL:
  133. case LEXICAL_FALSE_VAL:
  134. case NUMBER:
  135. case LEXICAL_WRITE_OPS:
  136. case LEXICAL_READ_OPS:
  137. // if(checkedNode->info!=NULL)
  138. // {
  139. // Pre defined types, no need to check
  140. type=checkedNode->info->type;
  141. // }
  142. break;
  143. default:
  144. // if(checkedNode->info!=NULL)
  145. // {
  146. switch(checkedNode->subtype)
  147. {
  148. case LEXICAL_EQUALS:
  149. case LEXICAL_PLUS:
  150. case LEXICAL_MINUS:
  151. case LEXICAL_MULT:
  152. case LEXICAL_MOD:
  153. case LEXICAL_DIV:
  154. case LEXICAL_LESS_EQUALS:
  155. case LEXICAL_LESS:
  156. case LEXICAL_AND:
  157. case LEXICAL_OR:
  158. case LEXICAL_ANDLAZY:
  159. case LEXICAL_ORLAZY:
  160. case LEXICAL_NOT:
  161. case LEXICAL_ISEMPTY_OPS:
  162. case LEXICAL_GET_OPS:
  163. type=checkedNode->info->type;
  164. break;
  165. default:
  166. {
  167. AstNode *declarationNode = getDeclaration(checkedNode);
  168. type = declarationNode->info->type;
  169.  
  170. #if(VERBOSE_LEVEL<=DEB_AST)
  171. ";\n;\tgetType result for %s %s [%p], declaration : \"%s\"[%p] (%s type) (compiler %s,%d)\n",
  172. typeToString(type),
  173. checkedNode->info->name,
  174. checkedNode,
  175. declarationNode->info->name,
  176. declarationNode,
  177. typeToString(declarationNode->type),
  178. __FILE__,
  179. __LINE__
  180. );
  181. #endif
  182. }
  183. break;
  184. }
  185. // }
  186. break;
  187. }
  188. if(type==NODE_TYPE_NOTHING || type==NODE_TYPE_TODO)
  189. {
  190. #if(VERBOSE_LEVEL<=DEB_AST)
  191. printf(";\tSearch on left for \"%40s\" (%20s) type...\n", checkedNode->info->name, typeToString(checkedNode->type));
  192. #endif
  193. type=getTypeWrapper(checkedNode->left);
  194. }
  195. if(type==NODE_TYPE_NOTHING || type==NODE_TYPE_TODO)
  196. {
  197. #if(VERBOSE_LEVEL<=DEB_AST)
  198. printf(";\tSearch on right for \"%40s\" (%20s) type...\n", checkedNode->info->name, typeToString(checkedNode->type));
  199. #endif
  200. type=getTypeWrapper(checkedNode->right);
  201. }
  202. #if(VERBOSE_LEVEL<=DEB_AST)
  203. ";\n;\ttype of \"%s\" (%s) is %s... on %s line %d (compiler %s,%d)\n;\n",
  204. checkedNode->info->name,
  205. typeToString(checkedNode->type),
  206. typeToString(type),
  207. checkedNode->debug->file,
  208. checkedNode->debug->line,
  209. __FILE__,
  210. __LINE__
  211. );
  212. #endif
  213. // if(type == NODE_TYPE_NOTHING)
  214. // {
  215. // char errorStr[1024];//todo: minimize length
  216. // sprintf(
  217. // errorStr,
  218. // "Undeclared item \"%s\" (compiler %s,%d)",
  219. // checkedNode->info->name,
  220. // __FILE__,
  221. // __LINE__
  222. // );
  223. // onError(errorStr, __FILE__, __LINE__, checkedNode);
  224. // //failure for the parsed code, but success for the compiler (it must stop here)
  225. // exit(EXIT_SUCCESS);
  226. // }
  227. // else
  228. // {
  229. checkedNode->info->computedType = type;
  230. // }
  231. }
  232. return type;
  233. }
  234.  
  235. /**
  236.  * Checks if a node has the right type
  237.  */
  238. void checkOperationTypes(AstNode *operationNode)
  239. {
  240. //allowed type is the operand(s) type, not operator type
  241. int allowedType = NODE_TYPE_NOTHING;
  242. switch(operationNode->subtype)
  243. {
  244. case LEXICAL_PLUS:
  245. case LEXICAL_MULT:
  246. case LEXICAL_MOD:
  247. case LEXICAL_DIV:
  248. allowedType=AST_INTEGER_VAR_TYPE;//checkedNode->info->type;
  249. break;
  250. case LEXICAL_AND:
  251. case LEXICAL_OR:
  252. case LEXICAL_ANDLAZY:
  253. case LEXICAL_ORLAZY:
  254. allowedType=AST_BOOLEAN_VAR_TYPE;//checkedNode->info->type;
  255. break;
  256. case LEXICAL_NOT:
  257. allowedType=NODE_TYPE_NOTHING;
  258. checkType(getTypeWrapper(operationNode->right), AST_BOOLEAN_VAR_TYPE, operationNode, __FILE__, __LINE__);
  259. break;
  260. case LEXICAL_EQUALS:
  261. allowedType=NODE_TYPE_NOTHING;
  262. checkType(getTypeWrapper(operationNode->left), getTypeWrapper(operationNode->right), operationNode, __FILE__, __LINE__);
  263. break;
  264. case LEXICAL_LESS_EQUALS:
  265. case LEXICAL_LESS:
  266. allowedType=AST_INTEGER_VAR_TYPE;
  267. break;
  268. case LEXICAL_ISEMPTY_OPS:
  269. case LEXICAL_GET_OPS:
  270. allowedType=NODE_TYPE_NOTHING;
  271. checkType(getTypeWrapper(operationNode->right), AST_INSTACK_VAR_TYPE, operationNode, __FILE__, __LINE__);
  272. break;
  273. }
  274. if(allowedType!=NODE_TYPE_NOTHING)
  275. {
  276. checkType(getTypeWrapper(operationNode->right), allowedType, operationNode, __FILE__, __LINE__);
  277. checkType(getTypeWrapper(operationNode->left), allowedType, operationNode, __FILE__, __LINE__);
  278. }
  279. }
  280. /**
  281.  * Initialize the first return statement found into the function.
  282.  * todo : use a pointer to the next statement to manage a list of return statements found into a same function
  283.  * pre-conditions: node type is LEXICAL_RETURN_STMT constant
  284.  * node is not null
  285.  */
  286. void addReturnStatement(AstNode *returnNode)
  287. {
  288. //if(returnNode->type!=LEXICAL_RETURN_STMT)return;
  289. int type = getTypeWrapper(returnNode->right);
  290. AstNode *functionNode = (AstNode *)scopeHelperGetCurrentFunction();
  291. if(functionNode!=NULL)
  292. {
  293. // this is needed by the specification of LSD10
  294. checkType(
  295. type,
  296. functionNode->info->type,
  297. returnNode,
  298. __FILE__, __LINE__
  299. );
  300. returnNode->info->type=functionNode->info->type;
  301. returnNode->info->computedType=returnNode->info->type;
  302. // this is only for increase speed of further tests
  303. functionNode->info->returnStatement = returnNode;
  304. }
  305. }
  306. /**
  307.  * Checks (the list of ->not yet) return statement(s) of a given function node.
  308.  * todo : implement the list check
  309.  * pre-conditions: node type is NODE_TYPE_FUNCTION constant
  310.  * node is not null
  311.  * checkTreeTypes has been called on the children of
  312.  * this node before calling this, to set the return statements
  313.  */
  314. void checkReturnStatement(AstNode *functionNode)
  315. {
  316. //if(node->type!=NODE_TYPE_FUNCTION)return;
  317.  
  318. switch(functionNode->info->type)
  319. {
  320. case AST_VOID_VAR_TYPE:
  321. if(functionNode->info->returnStatement!=NULL)
  322. {
  323. char errorStr[1024];//todo: minimize length
  324. errorStr,
  325. "Illegal return statement line %d col %d found into void %s function line %d col %d (compiler %s,%d)",
  326. functionNode->info->returnStatement->debug->line,
  327. functionNode->info->returnStatement->debug->linePsn,
  328. functionNode->info->name,
  329. functionNode->debug->line,
  330. functionNode->debug->linePsn,
  331. __FILE__,
  332. __LINE__
  333. );
  334. onError(errorStr, __FILE__, __LINE__, functionNode);
  335. }
  336. break;
  337. case AST_INTEGER_VAR_TYPE:
  338. case AST_BOOLEAN_VAR_TYPE:
  339. #if AST_RETURN_CHECK_REQUESTED==1
  340. // this is not needed by the specification of LSD10
  341. // LSD10 doesn't require the static check of a return existence into a function
  342. if(functionNode->info->returnStatement==NULL)
  343. {
  344. char errorStr[1024];//todo: minimize length
  345. errorStr,
  346. "Return statement not found for %s function line %d col %d, expected %s type (compiler %s,%d)",
  347. functionNode->info->name,
  348. functionNode->debug->line,
  349. functionNode->debug->linePsn,
  350. typeToString(functionNode->info->type),
  351. __FILE__,
  352. __LINE__
  353. );
  354. onError(errorStr, __FILE__, __LINE__, functionNode);
  355. }
  356. #endif
  357. break;
  358. }
  359. }
  360. /**
  361.  * Sets the mainNode and returns an error if we detect another main function
  362.  */
  363. void checkMainFunction(AstNode *node)
  364. {
  365.  
  366. if(mainNode==NULL)
  367. {
  368. if(isMainSignature(node))
  369. {
  370. mainNode=node;
  371. }
  372. else
  373. {
  374. char errorStr[1024];//todo: minimize length
  375. errorStr,
  376. "Main function is not the last one (%s detected line %d col %d) (compiler %s,%d)",
  377. node->info->name,
  378. node->debug->line,
  379. node->debug->linePsn,
  380. __FILE__,
  381. __LINE__
  382. );
  383. onError(errorStr, __FILE__, __LINE__, node);
  384. }
  385. }
  386. // if(isMainSignature(node))
  387. // {
  388. // mainNode=node;
  389. // AstNode *nodeToCheck = node->parent;
  390. // if(nodeToCheck!=NULL)
  391. // {
  392. // nodeToCheck = nodeToCheck->left;
  393. // if(nodeToCheck!=node && nodeToCheck!=NULL && nodeToCheck->type==NODE_TYPE_FUNCTION)
  394. // {
  395. // char errorStr[1024];//todo: minimize length
  396. // sprintf(
  397. // errorStr,
  398. // "Main function is not the last one (%s detected line %d col %d) (compiler %s,%d)",
  399. // nodeToCheck->info->name,
  400. // nodeToCheck->debug->line,
  401. // nodeToCheck->debug->linePsn,
  402. // __FILE__,
  403. // __LINE__
  404. // );
  405. // onError(errorStr, __FILE__, __LINE__, node);
  406. // }
  407. // }
  408. // }
  409. }
  410. /**
  411.  * Checks if the main function is the last one, without parameters, and with a void type
  412.  */
  413. void testMainPresence()
  414. {
  415. if(mainNode==NULL)
  416. {
  417. char errorStr[1024];//todo: minimize length
  418. errorStr,
  419. "Missing main function (compiler %s,%d)",
  420. __FILE__,
  421. __LINE__
  422. );
  423. onError(errorStr, __FILE__, __LINE__, NULL);
  424. }
  425. }
  426. /**
  427.  * Fill the symbols table with the declarations
  428.  * @param node AST node from witch we want to start type check
  429.  */
  430. void fillSymbolsTable(AstNode *node)
  431. {
  432. if(!isSymbolsTableAvailable())
  433. {
  434. onError("Table of Symbols must not be NULL", __FILE__, __LINE__, node);
  435. //Failure of the compiler behavior, independent of the parsed code
  436. exit(EXIT_FAILURE);
  437. }
  438. if(node!=NULL)
  439. {
  440. if(node->info==NULL)
  441. {
  442. // Stop on error
  443. char errorStr[1024];//todo: minimize length
  444. sprintf(errorStr, "Missing Node Info for %20s, compiler can't perform the job (compiler %s,%d)", typeToString(node->type), __FILE__, __LINE__);
  445. onError(errorStr, __FILE__, __LINE__, node);
  446. //Failure of the compiler behavior, independent of the parsed code
  447. exit(EXIT_FAILURE);
  448. }
  449. node->info->scopeDepth=scopeHelperGetCurrentDepth();
  450. node->info->scopeId=scopeHelperGetCurrentScope();
  451. switch(node->type)
  452. {
  453. case NODE_TYPE_PARAM_DECL:
  454. if(node->subtype!=LEXICAL_VAR && node->info->type==AST_INSTACK_VAR_TYPE)
  455. {
  456. char errorStr[1024];//todo: minimize length
  457. errorStr,
  458. "%s passed by value, but %s must be passed by address, line %3d col %3d (compiler %s,%3d)",
  459. node->info->name,
  460. typeToString(AST_INSTACK_VAR_TYPE),
  461. node->debug->line,
  462. node->debug->linePsn,
  463. __FILE__,
  464. __LINE__
  465. );
  466. onError(errorStr, __FILE__, __LINE__, node);
  467. }
  468. addDeclaration(node);
  469. break;
  470. case NODE_TYPE_VAR_DECL:
  471. addDeclaration(node);
  472. break;
  473. case NODE_TYPE_FUNCTION:
  474. checkMainFunction(node);
  475. addDeclaration(node);
  476. enterFunctionScope(node);
  477. break;
  478. case LEXICAL_RETURN_STMT:
  479. node->info->type = ((AstNode*)scopeHelperGetCurrentFunction())->info->type;
  480. addReturnStatement(node);
  481. break;
  482. }
  483. fillSymbolsTable(node->left);
  484. fillSymbolsTable(node->right);
  485. switch(node->type)
  486. {
  487. case NODE_TYPE_FUNCTION:
  488. exitScope();
  489. break;
  490. }
  491. }
  492. }
  493. /**
  494.  * Returns true (1 in C) if the given node has the
  495.  * main signature (program enter point)
  496.  */
  497. int isMainSignature(AstNode *node)
  498. {
  499. return node->left==NULL //no parameters
  500. && node->info->type == AST_VOID_VAR_TYPE //return void
  501. && (strcmp(node->info->name,"main")==0) //function name
  502. && node->info->scopeDepth == (INITIAL_INT+1); //program scope
  503. }
  504. /**
  505.  * Checks into the table of symbols after a matching type for the given node (node)
  506.  * @param node AST node from witch we want to start type check
  507.  */
  508. void checkTreeTypes(AstNode *node)
  509. {
  510. if(!isSymbolsTableAvailable())
  511. {
  512. onError("Table of Symbols must not be NULL", __FILE__, __LINE__, node);
  513. //Failure of the compiler behavior, independent of the parsed code
  514. exit(EXIT_FAILURE);
  515. }
  516. if(node!=NULL)
  517. {
  518. if(node->info==NULL)
  519. {
  520. // Stop on error
  521. char errorStr[1024];//todo: minimize length
  522. sprintf(errorStr, "Missing Node Info for %20s, compiler can't perform the job (compiler %s,%d)", typeToString(node->type), __FILE__, __LINE__);
  523. onError(errorStr, __FILE__, __LINE__, node);
  524. //Failure of the compiler behavior, independent of the parsed code
  525. exit(EXIT_FAILURE);
  526. }
  527. #if(VERBOSE_LEVEL<=DEB_AST)
  528. if(node->type!=NODE_TYPE_VAR_DECL && node->type!=NODE_TYPE_FUNCTION)
  529. ";\n;\tCheck type for %20s %30s, line %3d col %3d (compiler %s,%3d)\n",
  530. typeToString(node->type),
  531. node->info->name,
  532. node->debug->line,
  533. node->debug->linePsn,
  534. __FILE__,
  535. __LINE__
  536. );
  537. #endif
  538. switch(node->type)
  539. {
  540. case NODE_TYPE_ID:
  541. node->info->computedType = getTypeWrapper(node);
  542. break;
  543. case NODE_TYPE_PARAM_DECL:
  544. //printf("\n;Check param type (%s, %d)\n", __FILE__, __LINE__);
  545. if(node->subtype!=LEXICAL_VAR && node->info->type==AST_INSTACK_VAR_TYPE)
  546. {
  547. char errorStr[1024];//todo: minimize length
  548. errorStr,
  549. "%s passed by value, but %s must be passed by address, line %3d col %3d (compiler %s,%3d)",
  550. node->info->name,
  551. typeToString(AST_INSTACK_VAR_TYPE),
  552. node->debug->line,
  553. node->debug->linePsn,
  554. __FILE__,
  555. __LINE__
  556. );
  557. onError(errorStr, __FILE__, __LINE__, node);
  558. }
  559. //addDeclaration(node);
  560. break;
  561. case NODE_TYPE_DECLARATION:
  562. //addDeclaration(node);
  563. break;
  564. case NODE_TYPE_REXP:
  565. checkOperationTypes(node);
  566. break;
  567. case NODE_TYPE_FUNCTION_CALL:
  568. getTypeWrapper(node);
  569. break;
  570. // case NODE_TYPE_PARAM_LIST:
  571. // getTypeWrapper(node);
  572. // break;
  573. case LEXICAL_WRITE_OPS:
  574. case LEXICAL_READ_OPS:
  575. checkType(getTypeWrapper(node->right), AST_INTEGER_VAR_TYPE, node, __FILE__, __LINE__);
  576. break;
  577. case LEXICAL_PUT_OPS:
  578. checkType(getTypeWrapper(node->left), AST_INSTACK_VAR_TYPE, node, __FILE__, __LINE__);
  579. checkType(getTypeWrapper(node->right), AST_INTEGER_VAR_TYPE, node, __FILE__, __LINE__);
  580. break;
  581. case NODE_TYPE_STATEMENT:
  582. {
  583. int rightType=INITIAL_INT;
  584. if(node->subtype==LEXICAL_AFFECTATION)
  585. {
  586. rightType=getTypeWrapper(node->right);
  587. switch(rightType)
  588. {
  589. case AST_INTEGER_ARRAY_VAR_TYPE:
  590. rightType=AST_INTEGER_VAR_TYPE;
  591. break;
  592. case AST_BOOLEAN_ARRAY_VAR_TYPE:
  593. rightType=AST_BOOLEAN_VAR_TYPE;
  594. break;
  595. }
  596. }
  597. if(node->info->type == NODE_TYPE_CHECK)
  598. {
  599. //check right and left types
  600. int leftType = getTypeWrapper(node->left);
  601. if(rightType==INITIAL_INT)
  602. {
  603. rightType=getTypeWrapper(node->right);
  604. }
  605. checkType(rightType, leftType, node, __FILE__, __LINE__);
  606. }
  607. }
  608. break;
  609. case NODE_TYPE_FUNCTION:
  610. #if(VERBOSE_LEVEL<=DEB_AST)
  611. printf(";\tname %40s [%p], type %s, mainDetected? %s (compiler %s,%d)\n",
  612. node->info->name,
  613. node,
  614. typeToString(node->info->type),
  615. (mainNode!=NULL)?"yes":"no",
  616. __FILE__,
  617. __LINE__
  618. );
  619. #endif
  620. enterFunctionScope(node);
  621. break;
  622. case NODE_TYPE_FUNCTIONS:
  623. break;
  624. default:
  625. switch(node->subtype)
  626. {
  627. case LEXICAL_IF_STMT:
  628. case AST_IF_ELSE_STMT:
  629. case LEXICAL_WHILE_STMT:
  630. checkType(getTypeWrapper(node->left), AST_BOOLEAN_VAR_TYPE, node, __FILE__, __LINE__);
  631. //scopeHelperEnterScope();
  632. break;
  633. case LEXICAL_FOR_STMT:
  634. if(node->left!=NULL)
  635. {
  636. checkType(getTypeWrapper(node->left), AST_BOOLEAN_VAR_TYPE, node, __FILE__, __LINE__);
  637. }
  638. //scopeHelperEnterScope();
  639. break;
  640. }
  641. }
  642. checkTreeTypes(node->left);
  643. checkTreeTypes(node->right);
  644. switch(node->type)
  645. {
  646. case NODE_TYPE_FUNCTION:
  647. checkReturnStatement(node);
  648. //case NODE_TYPE_LEXICAL_FOR_STMT:
  649. exitScope();
  650. break;
  651. }
  652. }
  653. }
  654.  
  655. /**
  656.  * Sets debug informations into an AST node. This allows keeping the location
  657.  * of the current item into the parsed code
  658.  * In this case, don't care about freeing it, it's delegate to the node finalization
  659.  */
  660. void setDebug(AstNode *node, debugYacc yaccPsn)
  661. {
  662. DebugInfo *debug=createDebug();
  663. debug->line=yaccPsn==NULL?ERROR_INT:yaccPsn->first_line;
  664. debug->linePsn=yaccPsn==NULL?ERROR_INT:yaccPsn->first_column;
  665. node->debug=debug;
  666. }
  667. /**
  668.  * Sets given node as parent for the children of the given node
  669.  */
  670. void setParent(AstNode *node)
  671. {
  672. if(node!=NULL)
  673. {
  674. if(node->right!=NULL)
  675. {
  676. node->right->parent=node;
  677. }
  678. if(node->left!=NULL)
  679. {
  680. node->left->parent=node;
  681. }
  682. }
  683. }
  684.  
  685. /**
  686.  * Cleans memory allocated for the AST
  687.  */
  688. void finalizeTree(AstNode *node)
  689. {
  690. if (node != NULL)
  691. {
  692. if (node->info != NULL)
  693. {
  694. free(node->info);
  695. }
  696. if (node->debug != NULL)
  697. {
  698. free(node->debug);
  699. }
  700. //Must not free parent!
  701. if (node->left != NULL) finalizeTree(node->left);
  702. if (node->right != NULL) finalizeTree(node->right);
  703. free(node);
  704. }
  705. }
  706. /**
  707.  * Sets a unique name to an unnamed node
  708.  */
  709. void setIncrementedName(AstNodeInfo *info)
  710. {
  711. char incremName[32];
  712. char *str = incremName;
  713. nameIncrementor++;
  714. sprintf(str, "AutoGeneratedName_%d",nameIncrementor);
  715. //printf("\n;\t--- %s",str);
  716. info->name=calloc(strlen(str)+1, sizeof(char));
  717. strcpy(info->name, str);
  718. }
  719.  
  720. /*
  721.  * **********************************************************
  722.  * Implementation of the header exposed items
  723.  * See ast.h for these functions comments
  724.  * **********************************************************
  725.  */
  726.  
  727. AstNodeInfo* createASTNodeInfo(char *name, int type, int value)
  728. {
  729. AstNodeInfo *pNodeInfo=(AstNodeInfo *)malloc(sizeof(AstNodeInfo));
  730. if(!pNodeInfo)
  731. {
  732. if(VERBOSE_LEVEL<=DEB_E)
  733. {
  734. printMsg(DEB_E,"Allocation Error(AST node info)", __FILE__, __LINE__);
  735. printMsg(DEB_E, (char *)strerror(errno), __FILE__, __LINE__);
  736. }
  737. //Failure of the compiler behavior, independent of the parsed code
  738. exit(EXIT_FAILURE);
  739. }
  740. //put a unique generated name if null, to allow checking into sym table
  741. if(name==NULL || strcmp(name,"")==0)
  742. {
  743. setIncrementedName(pNodeInfo);
  744. }
  745. else
  746. {
  747. pNodeInfo->name=name;
  748. }
  749. // //Must keep a copy
  750. // pNodeInfo->varName=calloc(strlen(pNodeInfo->name)+1, sizeof(char));
  751. // strcpy(pNodeInfo->varName, pNodeInfo->name);
  752.  
  753. pNodeInfo->type = type;
  754. pNodeInfo->computedType=AST_TODO;
  755. pNodeInfo->value=value;
  756. pNodeInfo->declarationNode=NULL;
  757. pNodeInfo->memoryLocation=INITIAL_INT;
  758. pNodeInfo->scopeId = scopeHelperGetCurrentScope();
  759. pNodeInfo->scopeDepth = scopeHelperGetCurrentDepth();//INITIAL_INT;
  760. pNodeInfo->returnStatement=NULL;
  761. if(VERBOSE_LEVEL<=DEB_AST)
  762. {
  763. ";\n\tCreation of Node Info %20s %40s On %s, Line %d\n",
  764. typeToString(pNodeInfo->type),
  765. pNodeInfo->name,
  766. __FILE__,
  767. __LINE__
  768. );
  769. }
  770. return pNodeInfo;
  771. }
  772.  
  773. void checkAST()
  774. {
  775. #if(VERBOSE_LEVEL<=DEB_EXEC)
  776. printMsg(DEB_EXEC,"1st AST walk: filling symbols table...", __FILE__, __LINE__);
  777. #endif
  778. scopeHelperEnterScope();
  779. fillSymbolsTable(rootNode);
  780. resetScopeHelper();
  781. scopeHelperEnterScope();
  782. #if(VERBOSE_LEVEL<=DEB_EXEC)
  783. printMsg(DEB_EXEC,"2nd AST walk: checking types and constraints...", __FILE__, __LINE__);
  784. #endif
  785. checkTreeTypes(rootNode);
  786. //testMainPresence();
  787. }
  788.  
  789. DebugInfo* createDebug()
  790. {
  791. DebugInfo *debug=(DebugInfo *)malloc(sizeof(DebugInfo));
  792. if(!debug)
  793. {
  794. if(VERBOSE_LEVEL<=DEB_E)
  795. {
  796. printMsg(DEB_E,"Allocation Error(Debug info)", __FILE__, __LINE__);
  797. printMsg(DEB_E, (char *)strerror(errno), __FILE__, __LINE__);
  798. }
  799. //Failure of the compiler behavior, independent of the parsed code
  800. exit(EXIT_FAILURE);
  801. }
  802. // todo : get name from parsed file (all ways are OS dependent)
  803. // if(yyin!=NULL)
  804. // {
  805. // debug->file=yyin->f_name;
  806. // }
  807. // else
  808. // {
  809. debug->file="parsed code";
  810. // }
  811. debug->line=0;
  812. debug->linePsn=0;
  813. return debug;
  814. }
  815.  
  816. void setNodeType(AstNode *node, int type)
  817. {
  818. node->type = type;
  819. }
  820. void setNodeSubType(AstNode *node, int subtype)
  821. {
  822. node->subtype = subtype;
  823. }
  824.  
  825. void setComputedType(AstNode *node, int varType)
  826. {
  827. node->info->type = varType;
  828. node->info->computedType=varType;
  829. }
  830.  
  831. AstNode* createASTNode(debugYacc yaccPsn, int type, AstNodeInfo *info, AstNode *left, AstNode *right)
  832. {
  833. AstNode *pNode=(AstNode *)malloc(sizeof(AstNode));
  834. if(!pNode)
  835. {
  836. if(VERBOSE_LEVEL<=DEB_E)
  837. {
  838. printMsg(DEB_E,"Allocation Error(AST node)", __FILE__, __LINE__);
  839. printMsg(DEB_E, (char *)strerror(errno), __FILE__, __LINE__);
  840. }
  841. //Failure of the compiler behavior, independent of the parsed code
  842. exit(EXIT_FAILURE);
  843. }
  844. pNode->type=type;
  845. pNode->info=info;
  846.  
  847. pNode->right=right;
  848. pNode->left=left;
  849.  
  850. pNode->subtype=NODE_TYPE_NOTHING;
  851.  
  852. setParent(pNode);
  853. setDebug(pNode, yaccPsn);
  854.  
  855. if(VERBOSE_LEVEL<=DEB_O)
  856. {
  857. printf(";\tMessage : Creation of Node %20s (type : %20s, name : %40s) (compiler %s,%d)\n",
  858. typeToString(pNode->type),
  859. typeToString(pNode->info->type),
  860. pNode->info->name,//(info!=NULL)?info->name:"?",
  861. __FILE__,
  862. __LINE__
  863. );
  864. }
  865. return pNode;
  866. }
  867.  
  868. int isBefore(AstNode *node1, AstNode *node2)
  869. {
  870. if(node1==NULL)return -2;
  871. if(node2==NULL)return -3;
  872. if(node1==node2) return AST_CMP_EQUALS;
  873. if(node1->debug->line < node2->debug->line)return AST_CMP_BEFORE;
  874. if((node1->debug->line == node2->debug->line) && (node1->debug->linePsn < node2->debug->linePsn))return AST_CMP_BEFORE;
  875. return AST_CMP_AFTER;
  876. }
  877.  
  878. AstNode *getMain()
  879. {
  880. return mainNode;
  881. }
  882.  
  883. void finalizeAST()
  884. {
  885. finalizeTree(rootNode);
  886. }
  887.  
  888. char* typeToString(int type)
  889. {
  890. char *str = NULL;
  891. switch(type)
  892. {
  893. case NODE_TYPE_TODO:
  894. str = "NODE_TYPE_TODO";
  895. break;
  896. case NODE_TYPE_CHECK:
  897. str = "NODE_TYPE_CHECK";
  898. break;
  899. case NODE_TYPE_NOTHING:
  900. str = "type not set";
  901. break;
  902. case NODE_TYPE_CONTAINER:
  903. str = "Structural node";
  904. break;
  905. case NODE_TYPE_FUNCTION_CALL:
  906. str = "function call";
  907. break;
  908. case AST_VOID_VAR_TYPE:
  909. str = "void";
  910. break;
  911. case AST_BOOLEAN_VAR_TYPE:
  912. str = "boolean";
  913. break;
  914. case AST_INTEGER_VAR_TYPE:
  915. str = "integer";
  916. break;
  917. case AST_INSTACK_VAR_TYPE:
  918. str = "intstack";
  919. break;
  920. case AST_INTEGER_ARRAY_VAR_TYPE:
  921. str = "array of integers";
  922. break;
  923. case AST_BOOLEAN_ARRAY_VAR_TYPE:
  924. str = "array of booleans";
  925. break;
  926. case NODE_TYPE_FUNCTIONS:
  927. str = "Functions";
  928. break;
  929. case NODE_TYPE_FUNCTION:
  930. str = "Function";
  931. break;
  932. case NODE_TYPE_DECLARATIONS:
  933. str = "Type declarations";
  934. break;
  935. case NODE_TYPE_DECLARATION:
  936. str = "Type declaration";
  937. break;
  938. case NODE_TYPE_FUNCTION_BODY:
  939. str = "function body";
  940. break;
  941. case NODE_TYPE_STATEMENT:
  942. str = "Statement";
  943. break;
  944. case NODE_TYPE_REXP:
  945. str = "Right expression";
  946. break;
  947. case NODE_TYPE_ID:
  948. str = "Id";
  949. break;
  950. case NODE_TYPE_VAR_DECL:
  951. str = "Variable declaration";
  952. break;
  953. case NODE_TYPE_PARAM_LIST:
  954. str = "Parameters list";
  955. break;
  956. case NODE_TYPE_PARAM:
  957. str = "Parameter";
  958. break;
  959. case NODE_DECL_PADR:
  960. str = "By address parameter";
  961. break;
  962. case NODE_DECL_PVAL:
  963. str = "By value parameter";
  964. break;
  965. case LEXICAL_AFFECTATION:
  966. str = "=";
  967. break;
  968. case LEXICAL_PLUS:
  969. str = "+";
  970. break;
  971. case LEXICAL_MINUS:
  972. str = "-";
  973. break;
  974. case LEXICAL_MULT:
  975. str = "*";
  976. break;
  977. case LEXICAL_AND:
  978. str = "&&";
  979. break;
  980. case LEXICAL_OR:
  981. str = "||";
  982. break;
  983. case LEXICAL_LESS:
  984. str = "<";
  985. break;
  986. case LEXICAL_LESS_EQUALS:
  987. str = "<=";
  988. break;
  989. case LEXICAL_DIV:
  990. str = "div";
  991. break;
  992. case LEXICAL_MOD:
  993. str = "mod";
  994. break;
  995. case LEXICAL_EQUALS:
  996. str = "==";
  997. break;
  998. case LEXICAL_NOT:
  999. str = "!";
  1000. break;
  1001. // yytokentype enum
  1002. case LEXICAL_TRUE_VAL:
  1003. str = "true";
  1004. break;
  1005. case LEXICAL_FALSE_VAL:
  1006. str = "false";
  1007. break;
  1008. case NUMBER:
  1009. str = "number";
  1010. break;
  1011. case LEXICAL_ISEMPTY_OPS:
  1012. str = "ISEMPTY";
  1013. break;
  1014. case LEXICAL_GET_OPS:
  1015. str = "GET";
  1016. break;
  1017. case LEXICAL_WRITE_OPS:
  1018. str = "WRITE";
  1019. break;
  1020. case LEXICAL_READ_OPS:
  1021. str = "READ";
  1022. break;
  1023. case LEXICAL_RETURN_STMT:
  1024. str="return";
  1025. break;
  1026. case NODE_TYPE_PARAM_DECL:
  1027. str="NODE_TYPE_PARAM_DECL";
  1028. break;
  1029. case ID :
  1030. str="ID";
  1031. break;
  1032. case LEXICAL_VAR :
  1033. str="LEXICAL_VAR";
  1034. break;
  1035. //Internal business
  1036. case AST_TODO:
  1037. str="Not yet defined";
  1038. break;
  1039. default:
  1040. str = "undefined";
  1041. #if(VERBOSE_LEVEL<=DEB_W)
  1042. char str[1024];//todo: minimize length
  1043. sprintf(str, "Undefined constant value '%d (compiler %s,%d)'", type, __FILE__, __LINE__);
  1044. printMsg(DEB_W, str, __FILE__, __LINE__);
  1045. #endif
  1046. break;
  1047. }
  1048. return str;
  1049. }

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/ast.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.