ast.c

Description du code

ast.c est un fichier du projet Compilateur LSD010.
Ce fichier est situé dans /var/www/bin/sniplets/lsd010/.

Projet Compilateur LSD010 :

Compilateur LSD010 développé dans le cadre du cours de syntaxe et sémantiqueref 1

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. }

Structure et Fichiers du projet

Afficher/masquer...


Répertoires contenus dans /var/www/bin/sniplets/lsd010/project/source/ 
IcôneNomTailleModification
Pas de sous-répertoires.
IcôneNomTailleModification
| _ Répertoire parent0 octets1734899182 22/12/2024 21:26:22
Fichiers contenus dans /var/www/bin/sniplets/lsd010/project/source/ 
IcôneNomTailleModificationAction
IcôneNomTailleModificationAction
Afficher le fichier .o|.ographVizHelper.o4.72 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .c|.cast.c27.73 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hconst.h4.01 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .c|.cy.tab.c84.53 Ko31/10/2018 18:32:39-refusé-
Afficher le fichier .y|.ylsd10.y22.88 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .o|.olex.yy.o18.88 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .c|.cscopeStack.c3.69 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hgraphVizHelper.h573 octets31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hsymbolsTableDataRepresentation.h1.31 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .o|.osymbolsTable.o5.2 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hcommon.h1.08 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .c|.cscopeHelper.c4.09 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .o|.ohashCode.o1.45 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hconsole.h2.21 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .o|.oconsole.o12.23 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .|lsd10lsd1075.26 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hhashCode.h1020 octets31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hsymbolsTable.h2.65 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hpcode.h417 octets31/10/2018 18:32:38-refusé-
Afficher le fichier .o|.oast.o11.45 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hscopeStack.h2.2 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .c|.cgraphVizHelper.c6.11 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .l|.llsd10.l6.46 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hy.tab.h4.69 Ko31/10/2018 18:32:39-refusé-
Afficher le fichier .output|.outputy.output81.69 Ko31/10/2018 18:32:39-refusé-
Afficher le fichier .o|.oy.tab.o24.45 Ko31/10/2018 18:32:39-refusé-
Afficher le fichier .c|.clex.yy.c57.93 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hast.h2.39 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .o|.oscopeStack.o1.34 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .o|.oscopeHelper.o2.59 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .h|.hastDataRepresentation.h1.87 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .c|.csymbolsTable.c14.91 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .c|.cpcode.c23.45 Ko31/10/2018 18:32:38-refusé-
Afficher le fichier .c|.chashCode.c3.94 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .c|.cconsole.c18.01 Ko31/10/2018 18:32:37-refusé-
Afficher le fichier .h|.hscopeHelper.h719 octets31/10/2018 18:32:38-refusé-

Warning

Ce code présente une manière possible d'implémenter un compilateur, et certains choix peuvent être discutés.
Cependant, il peut donner des pistes pour démarrer, ou approcher certains concepts, et je tenterais par la suite de mettre à jour le code.

Utilisation de l'explorateur de code

  • Navigation :
    • Un clic sur une icône de répertoire ouvre ce répertoire pour en afficher les fichiers.
    • Lorsque le répertoire en cours ne contient pas de sous-répertoires il est possible de remonter vers le répertoire parent.
    • La structure de répertoires en treetable (tableau en forme d'arborescence) n'est plus possibledans cette version.
    • Un clic sur une icône de fichier ouvre ce fichier pour en afficher le code avec la coloration syntaxique adaptée en fonction du langage principal utilisé dans le fichier.
  • Affichage :
    • Il est possible de trier les répertoires ou les fichiers selon certains critères (nom, taille, date).
  • Actions :
    • Les actions possible sur les fichiers dépendent de vos droits d'utilisateur sur le site. Veuillez activer le mode utilisateur pour activer les actions.

English translation

You have asked to visit this site in English. For now, only the interface is translated, but not all the content yet.

If you want to help me in translations, your contribution is welcome. All you need to do is register on the site, and send me a message asking me to add you to the group of translators, which will give you the opportunity to translate the pages you want. A link at the bottom of each translated page indicates that you are the translator, and has a link to your profile.

Thank you in advance.

Document created the 07/03/2010, last modified the 28/10/2018
Source of the printed document:https://www.gaudry.be/en/langages-lsd10-source-rf-project/source/ast.c.html

The infobrol is a personal site whose content is my sole responsibility. The text is available under CreativeCommons license (BY-NC-SA). More info on the terms of use and the author.

Notes
  1. a,b LSD010 : Langage Simple et Didactique Il existe une un certain nombre d'interprétations de l'acronyme LSD (Langage Symbolique Didactique, Langage Sans Difficulté, Langage Simple et Didactique). LSD010 est la version 2010 de la suite LSD80, LSD_02, LSD03, LSD04, LSD05, LSD06, LSD07, LSD08, et LSD09.

Contents Haut

References

  1. book Language of the document:fr IHDCB332 - Théorie des langages : Syntaxe et sémantique : PY Schobbens, Syntaxe et sémantique (January 2010)

These references and links indicate documents consulted during the writing of this page, or which may provide additional information, but the authors of these sources can not be held responsible for the content of this page.
The author This site is solely responsible for the way in which the various concepts, and the freedoms that are taken with the reference works, are presented here. Remember that you must cross multiple source information to reduce the risk of errors.

Contents Haut