Advertisement
Guest User

comp.c

a guest
Jun 15th, 2019
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.95 KB | None | 0 0
  1. /* fichier: "petit-comp-print.c" */
  2.  
  3. /* Un petit compilateur et machine virtuelle pour un sous-ensemble de C. */
  4.  
  5. /*TP1 -- IFT2035
  6. * Simon Besozzi
  7. * Ryan Godin
  8. * */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <setjmp.h>
  14.  
  15. /*---------------------------------------------------------------------------*/
  16.  
  17. /* Analyseur lexical. */
  18.  
  19. enum {
  20. DO_SYM, ELSE_SYM, IF_SYM, WHILE_SYM, PRINT_SYM, BREAK_SYM, CONTINUE_SYM, GOTO_SYM, LBRA, RBRA, LPAR,
  21. RPAR, PLUS, MINUS, LESS, SEMI, COL, EQUAL, INT, ID, LTOE, GTOE, GREATER, EQUIV, NEQUAL, MULT, DIV, MOD, EOI
  22. };
  23.  
  24. char *words[] = {"do", "else", "if", "while", "print", "break", "continue", "goto", NULL};
  25.  
  26. int ch = ' ';
  27. int sym;
  28. int int_val;
  29. char id_name[100];
  30. char tag_name[1000];
  31.  
  32. int tag_iter = 0;
  33. jmp_buf env;
  34. int fileRead = 0; //1 if the compiler has to run a file specified in the command line arguments
  35. int isId = 0; //Checks if : can be used instead of ;
  36. FILE *source;
  37.  
  38. void syntax_error(char *errorReport);
  39.  
  40. void next_ch() {
  41.  
  42. //This reads the next char from an outside file, rather than user input
  43.  
  44. if (fileRead == 1 && ch != '\0' && source != NULL) {
  45. ch = fgetc(source);
  46. } else {
  47. ch = getchar();
  48. }
  49.  
  50. }
  51.  
  52. void next_sym() {
  53. while (ch == ' ' || ch == '\n') next_ch();
  54. switch (ch) {
  55. case '{':
  56. sym = LBRA;
  57. next_ch();
  58. break;
  59. case '}':
  60. sym = RBRA;
  61. next_ch();
  62. break;
  63. case '(':
  64. sym = LPAR;
  65. next_ch();
  66. break;
  67. case ')':
  68. sym = RPAR;
  69. next_ch();
  70. break;
  71. case '+':
  72. sym = PLUS;
  73. next_ch();
  74. break;
  75. case '-':
  76. sym = MINUS;
  77. next_ch();
  78. break;
  79. case '/':
  80. sym = DIV;
  81. next_ch();
  82. break; // new
  83. case '*':
  84. sym = MULT;
  85. next_ch();
  86. break; // new
  87. case '%':
  88. sym = MOD;
  89. next_ch();
  90. break; // new
  91.  
  92. case '<': //Checks to see if the next character completes <= operation or simply <
  93. next_ch();
  94. if (ch == '=') {
  95. sym = LTOE;
  96. next_ch();
  97. } else sym = LESS;
  98. break;
  99. case '>': //Checks to see if the next character completes >= operation or simply >
  100. next_ch();
  101. if (ch == '=') {
  102. sym = GTOE;
  103. next_ch();
  104. } else sym = GREATER;
  105. break;
  106. case ';':
  107. sym = SEMI;
  108. next_ch();
  109. break;
  110. case '=': //Checks to see if the next character completes == operation or simply =
  111. next_ch();
  112. if (ch == '=') {
  113. sym = EQUIV;
  114. next_ch();
  115. } else sym = EQUAL;
  116. break;
  117. case ':': //Checks for the last label declared
  118. sym = COL;
  119. tag_name[tag_iter - 1] = id_name[0]; //Adds the label for the goto
  120. next_ch();
  121. break;
  122. case '!' : //Checks to see if the next character completes != operation
  123. next_ch();
  124. if (ch == '=') {
  125. sym = NEQUAL;
  126. next_ch();
  127. }
  128. break;
  129.  
  130. case EOF:
  131. sym = EOI;
  132. next_ch();
  133. break;
  134. default:
  135. if (ch >= '0' && ch <= '9') {
  136. int_val = 0; /* overflow? */
  137.  
  138. while (ch >= '0' && ch <= '9') {
  139. int_val = int_val * 10 + (ch - '0');
  140. next_ch();
  141. }
  142.  
  143. sym = INT;
  144. } else if (ch >= 'a' && ch <= 'z') {
  145. int i = 0; /* overflow? */
  146.  
  147. while ((ch >= 'a' && ch <= 'z') || ch == '_') {
  148. id_name[i++] = ch;
  149. next_ch();
  150. }
  151.  
  152. id_name[i] = '\0';
  153. sym = 0;
  154.  
  155. while (words[sym] != NULL && strcmp(words[sym], id_name) != 0)
  156. sym++;
  157.  
  158. if (words[sym] == NULL) {
  159. if (id_name[1] == '\0') sym = ID;
  160. else
  161. syntax_error("--> words[sym] == NULL | line 107 | function next_sym");
  162. }
  163. } else syntax_error("--> default | line 110 | function next_sym");
  164. }
  165.  
  166. tag_iter++; //This was the first attemps to implement label addresses
  167. //Did not work, but compatible with current implementation
  168.  
  169. }
  170.  
  171. /*---------------------------------------------------------------------------*/
  172.  
  173.  
  174. /* Analyseur syntaxique. */
  175.  
  176. enum {
  177. VAR, CST, ADD, SUB, LT, GT, LTE, GTE, MLT, DIVI, MODU, EQ, NEQ, ASSIGN,
  178. IF1, IF2, WHILE, DO, PRINT, EMPTY, SEQ, EXPR, GOTO_K, BREAK, CONTINUE, PROG
  179. };
  180.  
  181. struct node {
  182. int kind;
  183. struct node *o1;
  184. struct node *o2;
  185. struct node *o3;
  186. int val;
  187. };
  188.  
  189. typedef struct node node;
  190.  
  191. //This is the first node of the ASA, typically a PROGRAM type node
  192. node *start;
  193.  
  194. /**
  195. * This method is called every time the program has to terminate to prevent memory leaks
  196. * parameter node *x is the inital node of the ASA
  197. */
  198.  
  199. void freeMem(node *x) {
  200.  
  201. while (x->kind != EMPTY && x->o1 != NULL) {
  202. freeMem(x->o1);
  203. x->o1 = NULL;
  204. break;
  205. }
  206.  
  207. while (x->kind != EMPTY && x->o2 != NULL) {
  208. freeMem(x->o2);
  209. x->o2 = NULL;
  210. break;
  211. }
  212.  
  213. while (x->kind != EMPTY && x->o3 != NULL) {
  214. freeMem(x->o3);
  215. x->o3 = NULL;
  216. break;
  217. }
  218.  
  219. if (x->kind != EMPTY) {
  220. free(x);
  221. }
  222. return;
  223. }
  224.  
  225. node *new_node(int k) {
  226. node *x = malloc(sizeof(node));
  227.  
  228. /*
  229. This statement deals with memory exhaustion issues
  230. */
  231. if (x != NULL) {
  232. x->kind = k;
  233. return x;
  234. } else {
  235. fprintf(stderr, "Memory exhausted");
  236. freeMem(start); //Prevents memory leaks
  237. exit(1);
  238. }
  239. }
  240.  
  241. node *paren_expr(); /* forward declaration */
  242.  
  243. node *tag() {
  244. node *x;
  245. x = new_node(CST);
  246. x->val = id_name[0];
  247. next_sym();
  248. return x;
  249. }
  250.  
  251. node *term() /* <term> ::= <id> | <int> | <paren_expr> */
  252. {
  253. node *x;
  254.  
  255. if (sym == ID) /* <term> ::= <id> */
  256. {
  257.  
  258. isId = 1; //Boolean to determine if a ':' char can be used instead of ';'
  259.  
  260. x = new_node(VAR);
  261. x->val = id_name[0] - 'a';
  262. next_sym();
  263. } else if (sym == INT) /* <term> ::= <int> */
  264. {
  265. x = new_node(CST);
  266. x->val = int_val;
  267. next_sym();
  268. } else /* <term> ::= <paren_expr> */
  269. x = paren_expr();
  270.  
  271. return x;
  272. }
  273.  
  274. node *mult() /*<mult> ::= <term>|<mult>"*"<term>|<mult>"/"<term>|<mult>"%"<term> */
  275. {
  276. node *x = term();
  277.  
  278. if (sym == MULT) {
  279. node *t = x;
  280. x = new_node(MLT);
  281. next_sym();
  282. x->o1 = t;
  283. x->o2 = term();
  284. } else if (sym == DIV) {
  285. node *t = x;
  286. x = new_node(DIVI);
  287. next_sym();
  288. x->o1 = t;
  289. x->o2 = term();
  290. } else if (sym == MOD) {
  291. node *t = x;
  292. x = new_node(MODU);
  293. next_sym();
  294. x->o1 = t;
  295. x->o2 = term();
  296. }
  297. return x;
  298. }
  299.  
  300. node *sum() /* <sum> ::= <term>|<sum>"+"<term>|<sum>"-"<term> */
  301. {
  302. node *x = term();
  303.  
  304. while (sym == PLUS || sym == MINUS) {
  305. node *t = x;
  306. x = new_node(sym == PLUS ? ADD : SUB);
  307. next_sym();
  308. x->o1 = t;
  309. x->o2 = term();
  310. }
  311. /*<sum> ::= <term>|<sum>"*"<term>|<sum>"/"<term>|<sum>"%"<term> */
  312. while (sym == MULT || sym == DIV || sym == MOD) {
  313. if (sym == MULT) {
  314. node *t = x;
  315. x = new_node(MLT);
  316. next_sym();
  317. x->o1 = t;
  318. x->o2 = mult();
  319. } else if (sym == DIV) {
  320. node *t = x;
  321. x = new_node(DIVI);
  322. next_sym();
  323. x->o1 = t;
  324. x->o2 = mult();
  325. } else if (sym == MOD) {
  326. node *t = x;
  327. x = new_node(MODU);
  328. next_sym();
  329. x->o1 = t;
  330. x->o2 = mult();
  331. }
  332.  
  333. }
  334.  
  335. return x;
  336. }
  337.  
  338. node *test()
  339. {
  340. node *x = sum();
  341. /* <test> ::= <sum> | <sum> "<" <sum> */
  342. if (sym == LESS) {
  343. node *t = x;
  344. x = new_node(LT);
  345. next_sym();
  346. x->o1 = t;
  347. x->o2 = sum();
  348.  
  349. }
  350. /* <test> ::= <sum> | <sum> ">" <sum> */
  351. else if (sym == GREATER) {
  352. node *t = x;
  353. x = new_node(GT);
  354. next_sym();
  355. x->o1 = t;
  356. x->o2 = sum();
  357. }
  358. /* <test> ::= <sum> | <sum> "<=" <sum> */
  359. else if (sym == LTOE) {
  360. node *t = x;
  361. x = new_node(LTE);
  362. next_sym();
  363. x->o1 = t;
  364. x->o2 = sum();
  365.  
  366. }
  367. /* <test> ::= <sum> | <sum> ">=" <sum> */
  368. else if (sym == GTOE) {
  369. node *t = x;
  370. x = new_node(GTE);
  371. next_sym();
  372. x->o1 = t;
  373. x->o2 = sum();
  374.  
  375. }
  376. /* <test> ::= <sum> | <sum> "==" <sum> */
  377. else if (sym == EQUIV) {
  378. node *t = x;
  379. x = new_node(EQ);
  380. next_sym();
  381. x->o1 = t;
  382. x->o2 = sum();
  383.  
  384. }
  385. /* <test> ::= <sum> | <sum> "!=" <sum> */
  386. else if (sym == NEQUAL) {
  387. node *t = x;
  388. x = new_node(NEQ);
  389. next_sym();
  390. x->o1 = t;
  391. x->o2 = sum();
  392. }
  393.  
  394. return x;
  395. }
  396.  
  397. node *expr() /* <expr> ::= <test> | <id> "=" <expr> */
  398. {
  399. node *x;
  400.  
  401. if (sym != ID) return test();
  402.  
  403. x = test();
  404.  
  405. if (sym == EQUAL) {
  406. node *t = x;
  407. x = new_node(ASSIGN);
  408. next_sym();
  409. x->o1 = t;
  410. x->o2 = expr();
  411. }
  412.  
  413. return x;
  414. }
  415.  
  416. node *paren_expr() /* <paren_expr> ::= "(" <expr> ")" */
  417. {
  418. node *x;
  419.  
  420. if (sym == LPAR) next_sym(); else syntax_error("--> sym != LPAR | line 318 | function *paren_expr");
  421.  
  422. x = expr();
  423.  
  424. if (sym == RPAR) next_sym(); else syntax_error("--> sym != RPAR | line 322 | function *paren_expr");
  425.  
  426. return x;
  427. }
  428.  
  429. node *statement() {
  430. node *x;
  431.  
  432. if (sym == IF_SYM) /* "if" <paren_expr> <stat> */
  433. {
  434. x = new_node(IF1);
  435. next_sym();
  436. x->o1 = paren_expr();
  437. x->o2 = statement();
  438. if (sym == ELSE_SYM) /* ... "else" <stat> */
  439. {
  440. x->kind = IF2;
  441. next_sym();
  442. x->o3 = statement();
  443. }
  444. } else if (sym == WHILE_SYM) /* "while" <paren_expr> <stat> */
  445. {
  446. x = new_node(WHILE);
  447. next_sym();
  448. x->o1 = paren_expr();
  449. x->o2 = statement();
  450. } else if (sym == DO_SYM) /* "do" <stat> "while" <paren_expr> ";" */
  451. {
  452. x = new_node(DO);
  453. next_sym();
  454. x->o1 = statement();
  455. if (sym == WHILE_SYM) next_sym(); else syntax_error("--> sym != WHILE_SYM | line 355 | function *statement");
  456. x->o2 = paren_expr();
  457. if (sym == SEMI) next_sym(); else syntax_error("--> sym != SEMI | line 357 | function *statement");
  458. } else if (sym == PRINT_SYM) /* "print" <paren_expr> ";" */
  459. {
  460. x = new_node(PRINT);
  461. next_sym();
  462. x->o1 = paren_expr();
  463. if (sym == SEMI) next_sym(); else syntax_error("--> sym != SEMI | line 364 | function *statement");
  464. }
  465. // Creates new goto node, checks if the goto has a id and semi colon.
  466. else if (sym == GOTO_SYM) {
  467. x = new_node(GOTO_K);
  468. next_sym();
  469. if(sym == ID) x->o1=tag(); else syntax_error("--> sym != ID | line 450 | function *statement");
  470. x->o2 = NULL;
  471. x->o3 = NULL;
  472. if (sym == SEMI) next_sym(); else syntax_error("--> sym != SEMI | line 364 | function *statement");
  473. }
  474. // Creates new break node, checks if the break has a id and semi colon.
  475. else if (sym == BREAK_SYM) {
  476. /*
  477. x = new_node(BREAK);
  478. next_sym();
  479. if (sym == ID){ x->o1 = term(); next_sym(); }
  480. if (sym == SEMI)next_sym(); else syntax_error("Missing semi colon after break statement");
  481. */
  482.  
  483. }
  484. // Creates new continue node, checks if the continue has a id and semi colon.
  485. else if (sym == CONTINUE_SYM) {
  486. /* x = new_node(CONTINUE);
  487. next_sym();
  488. if (sym == ID){ x->o1 = term(); next_sym(); }
  489. if (sym == SEMI)next_sym(); else syntax_error("Missing semi colon after continue statement");
  490. */
  491. }
  492.  
  493. else if (sym == SEMI) /* ";" */
  494. {
  495. x = new_node(EMPTY);
  496. next_sym();
  497. } else if (sym == COL) {
  498. x = new_node(EMPTY);
  499. next_sym();
  500. } else if (sym == LBRA) /* "{" { <stat> } "}" */
  501. {
  502. x = new_node(EMPTY);
  503. next_sym();
  504. while (sym != RBRA) {
  505. node *t = x;
  506. x = new_node(SEQ);
  507. x->o1 = t;
  508. x->o2 = statement();
  509. }
  510. next_sym();
  511. } else /* <expr> ";" */
  512. {
  513. x = new_node(EXPR);
  514. x->o1 = expr();
  515. if (sym == SEMI || (sym == COL && isId == 1)) next_sym();
  516. else
  517. syntax_error("--> sym != SEMI | line 400 | function *statement");
  518. isId = 0;
  519. }
  520.  
  521. return x;
  522. }
  523.  
  524. node *program() /* <program> ::= <stat> */
  525. {
  526. node *x = new_node(PROG);
  527. start = x;
  528. next_sym();
  529. x->o1 = statement();
  530. if (sym != EOI) syntax_error("--> sym != EOI | line 412 | function *program");
  531. return x;
  532. }
  533.  
  534. /**
  535. * This method has been modified to call freeMem when a syntax error occurs the program ends abruptly
  536. * - Simon
  537. */
  538. void syntax_error(char *errorReport) {
  539. {
  540. fprintf(stderr, "syntax error\n");
  541. printf("%s", errorReport);
  542. freeMem(start);
  543. exit(1);
  544. }
  545. }
  546.  
  547. void wip(char type[]) {
  548. fprintf(stderr, "%s partly implemented, but crashes or doesn't work properly", type);
  549. freeMem(start);
  550. exit(1);
  551. }
  552. /*---------------------------------------------------------------------------*/
  553.  
  554. /* Generateur de code. */
  555.  
  556. enum {
  557. ILOAD, ISTORE, BIPUSH, DUP, POP, IADD, ISUB, IPRINT,
  558. GOTO, IFEQ, IFNE, IFLT, IFGT, IMULT, IDIV, IMOD, IEQ, INEQ, ILOE, IGOE, RETURN
  559. };
  560.  
  561. typedef signed char code;
  562.  
  563. int tags[256][0];
  564.  
  565. code object[1000], *here = object;
  566. int idName;
  567. int ad = 0;
  568.  
  569. void gen(code c) {
  570.  
  571. ad++;
  572. *here++ = c;
  573.  
  574. } /* overflow? */
  575.  
  576. #ifdef SHOW_CODE
  577. #define g(c) do { printf(" %d",c); gen(c); } while (0)
  578. #define gi(c) do { printf("\n%s", #c); gen(c); } while (0)
  579. #else
  580. #define g(c) gen(c)
  581. #define gi(c) gen(c)
  582. #endif
  583.  
  584. void fix(code *src, code *dst) { *src = dst - src; } /* overflow? */
  585.  
  586. void c(node *x) {
  587.  
  588.  
  589. tags[x->val][0] = ad; //This array holds the addresses for the labels. Not working, so can't implement goto
  590.  
  591.  
  592. switch (x->kind) {
  593. case VAR :
  594. gi(ILOAD);
  595. g(x->val);
  596. break;
  597.  
  598. case CST :
  599. gi(BIPUSH);
  600. g(x->val);
  601. break;
  602.  
  603. case ADD :
  604. c(x->o1);
  605. c(x->o2);
  606. gi(IADD);
  607. break;
  608.  
  609. case SUB :
  610. c(x->o1);
  611. c(x->o2);
  612. gi(ISUB);
  613. break;
  614.  
  615. case MLT :
  616. c(x->o1);
  617. c(x->o2);
  618. gi(IMULT);
  619. break;
  620.  
  621. case DIVI :
  622. c(x->o1);
  623. c(x->o2);
  624. gi(IDIV);
  625. break;
  626.  
  627. case MODU :
  628. c(x->o1);
  629. c(x->o2);
  630. gi(IMOD);
  631. break;
  632.  
  633. case EQ :
  634. c(x->o1);
  635. c(x->o2);
  636. gi(IEQ);
  637. break;
  638.  
  639. case NEQ :
  640. c(x->o1);
  641. c(x->o2);
  642. gi(INEQ);
  643. break;
  644.  
  645. case LTE :
  646. c(x->o1);
  647. c(x->o2);
  648. gi(ILOE);
  649. break;
  650.  
  651. case GTE :
  652. c(x->o1);
  653. c(x->o2);
  654. gi(IGOE);
  655. break;
  656.  
  657. case LT :
  658. gi(BIPUSH);
  659. g(1);
  660. c(x->o1);
  661. c(x->o2);
  662. gi(ISUB);
  663. gi(IFLT);
  664. g(4);
  665. gi(POP);
  666. gi(BIPUSH);
  667. g(0);
  668. break;
  669.  
  670. case GT :
  671. gi(BIPUSH);
  672. g(0);
  673. c(x->o2);
  674. c(x->o1);
  675. gi(ISUB);
  676. gi(IFGT);
  677. g(4);
  678. gi(POP);
  679. gi(BIPUSH);
  680. g(1);
  681. break;
  682.  
  683. case ASSIGN:
  684. c(x->o2);
  685. gi(DUP);
  686. gi(ISTORE);
  687. g(x->o1->val);
  688. break;
  689.  
  690. case IF1 : {
  691. code *p1;
  692. c(x->o1);
  693. gi(IFEQ);
  694. p1 = here++;
  695. c(x->o2);
  696. fix(p1, here);
  697. break;
  698. }
  699.  
  700. case IF2 : {
  701. code *p1, *p2;
  702. c(x->o1);
  703. gi(IFEQ);
  704. p1 = here++;
  705. c(x->o2);
  706. gi(GOTO);
  707. p2 = here++;
  708. fix(p1, here);
  709. c(x->o3);
  710. fix(p2, here);
  711. break;
  712. }
  713.  
  714. case WHILE : {
  715. code *p1 = here, *p2;
  716. c(x->o1);
  717. gi(IFEQ);
  718. p2 = here++;
  719. c(x->o2);
  720. gi(GOTO);
  721. fix(here++, p1);
  722. fix(p2, here);
  723. break;
  724. }
  725.  
  726. case DO : {
  727. code *p1 = here;
  728. c(x->o1);
  729. c(x->o2);
  730. gi(IFNE);
  731. fix(here++, p1);
  732. break;
  733. }
  734.  
  735. case PRINT : {
  736. c(x->o1);
  737. gi(IPRINT);
  738. break;
  739. }
  740.  
  741. case EMPTY :
  742. break;
  743.  
  744. case SEQ :
  745. c(x->o1);
  746. c(x->o2);
  747. break;
  748.  
  749. case EXPR :
  750. c(x->o1);
  751. gi(POP);
  752. break;
  753.  
  754. case PROG :
  755. c(x->o1);
  756. gi(RETURN);
  757. break;
  758.  
  759. case GOTO_K :
  760.  
  761. idName = x->o1->val;
  762. int hasTag;
  763. int tag = tags[idName - 'a'][0];
  764.  
  765. /**
  766. * Checks if a label is declared
  767. */
  768. for (int i = 0; i < 1000; i++) {
  769. if (idName == tag_name[i]) {
  770.  
  771. if (hasTag) {
  772. fprintf(stderr, "forbidden double declaration of a label");
  773. freeMem(start);
  774. exit(1);
  775. }
  776.  
  777. hasTag = 1;
  778.  
  779. }
  780. }
  781.  
  782. if (hasTag != 1) {
  783. fprintf(stderr, "undeclared goto destination");
  784. freeMem(start);
  785. exit(1);
  786. }
  787.  
  788. wip("goto");
  789.  
  790. gi(GOTO);
  791. g(tag - ad);
  792.  
  793. //(tag-ad % 2 == 0) ? g(tag-ad) : g((tag-ad)+1);
  794.  
  795. break;
  796.  
  797. case BREAK :
  798. wip("break");
  799. break;
  800.  
  801.  
  802.  
  803. case CONTINUE :
  804. wip("continue");
  805. break;
  806.  
  807.  
  808. }
  809. }
  810.  
  811.  
  812. /*---------------------------------------------------------------------------*/
  813.  
  814. /* Machine virtuelle. */
  815.  
  816. int globals[26];
  817.  
  818. void run() {
  819. int stack[1000], *sp = stack; /* overflow? */
  820. code *pc = object;
  821.  
  822. for (;;)
  823. switch (*pc++) {
  824. case ILOAD :
  825. *sp++ = globals[*pc++];
  826. break;
  827. case ISTORE:
  828. globals[*pc++] = *--sp;
  829. break;
  830. case BIPUSH:
  831. *sp++ = *pc++;
  832. break;
  833. case DUP :
  834. sp++;
  835. sp[-1] = sp[-2];
  836. break;
  837. case POP :
  838. --sp;
  839. break;
  840. case IADD :
  841. sp[-2] = sp[-2] + sp[-1];
  842. --sp;
  843. break;
  844. case ISUB :
  845. sp[-2] = sp[-2] - sp[-1];
  846. --sp;
  847. break;
  848. case IMULT :
  849. sp[-2] = sp[-2] * sp[-1];
  850. --sp;
  851. break;
  852. case IMOD :
  853. sp[-2] = sp[-2] % sp[-1];
  854. --sp;
  855. break;
  856. case IDIV :
  857. sp[-2] = sp[-2] / sp[-1];
  858. --sp;
  859. break;
  860. case IEQ :
  861. sp[-2] = sp[-2] == sp[-1];
  862. --sp;
  863. break;
  864. case INEQ :
  865. sp[-2] = sp[-2] != sp[-1];
  866. --sp;
  867. break;
  868. case ILOE :
  869. sp[-2] = sp[-2] <= sp[-1];
  870. --sp;
  871. break;
  872. case IGOE :
  873. sp[-2] = sp[-2] >= sp[-1];
  874. --sp;
  875. break;
  876. case IPRINT:
  877. printf("%d\n", *--sp);
  878. break;
  879. case GOTO :
  880. pc += *pc;
  881. break;
  882. case IFEQ :
  883. if (*--sp == 0) pc += *pc;
  884. else pc++;
  885. break;
  886. case IFNE :
  887. if (*--sp != 0) pc += *pc;
  888. else pc++;
  889. break;
  890. case IFLT :
  891. if (*--sp < 0) pc += *pc;
  892. else pc++;
  893. break;
  894. case IFGT :
  895. if (*--sp > 0) pc += *pc;
  896. else pc++;
  897. break;
  898. case RETURN:
  899. return;
  900. }
  901. }
  902.  
  903. //Reads a file
  904. void runFromFile(char in[]) {
  905.  
  906. source = fopen(in, "r");
  907.  
  908. if (source == NULL) {
  909. printf("File not found. Enter source code here: \n");
  910. longjmp(env, 1);
  911. }
  912.  
  913. }
  914.  
  915. /*---------------------------------------------------------------------------*/
  916.  
  917. /* Programme principal. */
  918.  
  919. int main(int argc, char *argv[]) {
  920.  
  921. //In case of an I/O error while reading the source code from a file
  922. int code = setjmp(env);
  923.  
  924. int i;
  925.  
  926. //Ask for user input if the file was incorrect
  927. if (code != 0) {
  928. goto nofile;
  929. }
  930.  
  931. //If a file path has been specified in the command line read source code from file
  932. if (argc > 1) {
  933. runFromFile(argv[1]);
  934. }
  935.  
  936. //This will affect how next_ch will behave
  937. fileRead = 1;
  938.  
  939. nofile:
  940.  
  941. c(program());
  942.  
  943. #ifdef SHOW_CODE
  944. printf("\n");
  945. #endif
  946.  
  947. for (i = 0; i < 26; i++)
  948. globals[i] = 0;
  949.  
  950. run();
  951.  
  952. return 0;
  953. }
  954.  
  955.  
  956. /*---------------------------------------------------------------------------*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement