Advertisement
Guest User

Untitled

a guest
Nov 18th, 2017
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.13 KB | None | 0 0
  1. %{ /* pars1.y Pascal Parser Gordon S. Novak Jr. ; 30 Jul 13 */
  2.  
  3. /* Copyright (c) 2013 Gordon S. Novak Jr. and
  4. The University of Texas at Austin. */
  5.  
  6. /* 14 Feb 01; 01 Oct 04; 02 Mar 07; 27 Feb 08; 24 Jul 09; 02 Aug 12 */
  7.  
  8. //William Han
  9. //wh7244
  10. //Nov. 17, 2017
  11.  
  12. /*
  13. ; This program is free software; you can redistribute it and/or modify
  14. ; it under the terms of the GNU General Public License as published by
  15. ; the Free Software Foundation; either version 2 of the License, or
  16. ; (at your option) any later version.
  17.  
  18. ; This program is distributed in the hope that it will be useful,
  19. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. ; GNU General Public License for more details.
  22.  
  23. ; You should have received a copy of the GNU General Public License
  24. ; along with this program; if not, see <http://www.gnu.org/licenses/>.
  25. */
  26.  
  27.  
  28. /* NOTE: Copy your lexan.l lexical analyzer to this directory. */
  29.  
  30. /* To use:
  31. make pars1y has 1 shift/reduce conflict
  32. pars1y execute the parser
  33. i:=j .
  34. ^D control-D to end input
  35.  
  36. pars1y execute the parser
  37. begin i:=j; if i+j then x:=a+b*c else x:=a*b+c; k:=i end.
  38. ^D
  39.  
  40. pars1y execute the parser
  41. if x+y then if y+z then i:=j else k:=2.
  42. ^D
  43.  
  44. You may copy pars1.y to be parse.y and extend it for your
  45. assignment. Then use make parser as above.
  46. */
  47.  
  48. /* Yacc reports 1 shift/reduce conflict, due to the ELSE part of
  49. the IF statement, but Yacc's default resolves it in the right way.*/
  50.  
  51. #include <stdio.h>
  52. #include <string.h>
  53. #include <ctype.h>
  54. #include "token.h"
  55. #include "lexan.h"
  56. #include "symtab.h"
  57. #include "parse.h"
  58. #include "instvars.c"
  59.  
  60. /* define the type of the Yacc stack element to be TOKEN */
  61.  
  62. #define YYSTYPE TOKEN
  63.  
  64. TOKEN parseresult;
  65.  
  66. %}
  67.  
  68. /* Order of tokens corresponds to tokendefs.c; do not change */
  69.  
  70. %token IDENTIFIER STRING NUMBER /* token types */
  71.  
  72. %token PLUS MINUS TIMES DIVIDE /* Operators */
  73. %token ASSIGN EQ NE LT LE GE GT POINT DOT AND OR NOT DIV MOD IN
  74.  
  75. %token COMMA /* Delimiters */
  76. %token SEMICOLON COLON LPAREN RPAREN LBRACKET RBRACKET DOTDOT
  77.  
  78. %token ARRAY BEGINBEGIN /* Lex uses BEGIN */
  79. %token CASE CONST DO DOWNTO ELSE END FILEFILE FOR FUNCTION GOTO IF LABEL NIL
  80. %token OF PACKED PROCEDURE PROGRAM RECORD REPEAT SET THEN TO TYPE UNTIL
  81. %token VAR WHILE WITH
  82.  
  83.  
  84. %%
  85.  
  86. program : header DOT { parseresult = $1; }
  87. ;
  88.  
  89. header : PROGRAM IDENTIFIER LPAREN argument RPAREN SEMICOLON lblock
  90. { $$ = makeprogram($1, $2, $4, $7); }
  91. ;
  92.  
  93. block : BEGINBEGIN statement endpart
  94. { $$ = makeprogn($1,cons($2, $3)); }
  95. ;
  96.  
  97. lblock : LABEL labelspecs block { $$ = $3; }
  98. | LABEL labelspecs vblock { $$ = $3; }
  99. | LABEL labelspecs tblock { $$ = $3; }
  100. | LABEL labelspecs cblock { $$ = $3; }
  101. | cblock
  102. ;
  103.  
  104. labelspecs : labelgroup SEMICOLON
  105. ;
  106.  
  107. labelgroup : NUMBER COMMA labelgroup { instlabel($1); }
  108. | NUMBER { instlabel($1); }
  109. ;
  110.  
  111. cblock : CONST constspecs block { $$ = $3; }
  112. | CONST constspecs lblock { $$ = $3; }
  113. | CONST constspecs vblock { $$ = $3; }
  114. | tblock
  115. ;
  116.  
  117. constspecs : constgroup SEMICOLON constspecs
  118. | constgroup SEMICOLON
  119. ;
  120.  
  121. constgroup : IDENTIFIER EQ factor { instconst($1, $3); }
  122. ;
  123.  
  124.  
  125. tblock : TYPE typespecs block { $$ = $3; }
  126. | TYPE typespecs vblock { $$ = $3; }
  127. | vblock
  128. ;
  129.  
  130. typespecs : typegroup SEMICOLON typespecs
  131. | typegroup SEMICOLON
  132. ;
  133.  
  134. typegroup : IDENTIFIER EQ type { insttype($1, $2, $3); }
  135. ;
  136.  
  137.  
  138. vblock : VAR varspecs block { $$ = $3; }
  139. | block
  140. ;
  141.  
  142. varspecs : vargroup SEMICOLON varspecs
  143. | vargroup SEMICOLON
  144. ;
  145.  
  146. vargroup : idlist COLON type { instvars($1, $3); }
  147. ;
  148.  
  149. type : simpletype
  150. | POINT simpletype { $$ = instpoint($1, $2); }
  151. | ARRAY LBRACKET index RBRACKET OF type { $$ = instarray($3, $6); }
  152. // | FILE
  153. // | SET
  154. | RECORD fieldlist END { $$ = instrec($1, $2); }
  155. ;
  156.  
  157. index : simpletype COMMA index { $$ = cons($1, $3); }
  158. | simpletype
  159.  
  160. simpletype : IDENTIFIER { $$ = findtype($1); }
  161. | LPAREN idlist RPAREN { $$ = instenum($1, $2, $3); }
  162. | factor DOTDOT factor { $$ = instdotdot($1, $2, $3); }
  163. ;
  164.  
  165. fieldlist : idlist COLON type SEMICOLON fieldlist { $$ = cons(instfields($1, $3), $5); }
  166. | idlist COLON type { $$ = instfields($1, $3); }
  167.  
  168. idlist : IDENTIFIER COMMA idlist { $$ = cons($1, $3); }
  169. | IDENTIFIER { $$ = cons($1, NULL); }
  170. ;
  171.  
  172. argument : expr COMMA argument { $$ = makeprogn((TOKEN) talloc(), cons($1, $3)); }
  173. | expr { $$ = makeprogn((TOKEN) talloc(), $1); }
  174. ;
  175.  
  176.  
  177. statement : BEGINBEGIN statement endpart { $$ = makeprogn($1,cons($2, $3)); }
  178. | IF expr THEN statement endif { $$ = makeif($1, $2, $4, $5); }
  179. | FOR assignment TO expr DO statement { $$ = makefor(1, $1, $2, $3, $4, $5, $6); }
  180. | FOR assignment DOWNTO expr DO statement { $$ = makefor(-1, $1, $2, $3, $4, $5, $6); }
  181. | REPEAT statements UNTIL expr { $$ = makerepeat($1, makeprogn((TOKEN)talloc(), $2), $3, $4); }
  182. | WHILE expr DO statement { $$ = makewhile($1, $2, $3, $4); }
  183. | funcall
  184. | assignment
  185. | NUMBER COLON statement { $$ = dolabel($1, $2, $3); }
  186. | GOTO NUMBER { $$ = dogoto($1, $2); }
  187. ;
  188.  
  189. statements : statement endstates { $$ = cons($1, $2); }
  190. | statement
  191. ;
  192.  
  193. endstates : SEMICOLON statements { $$ = $2; }
  194. ;
  195.  
  196.  
  197. funcall : IDENTIFIER LPAREN funargs RPAREN { $$ = makefuncall($2, $1, $3); }
  198. ;
  199.  
  200. funargs : expr COMMA argument { $$ = cons($1, $3); }
  201. | expr { $$ = $1; }
  202. ;
  203.  
  204. endpart : SEMICOLON statement endpart { $$ = cons($2, $3); }
  205. | END { $$ = NULL; }
  206. ;
  207.  
  208. endif : ELSE statement { $$ = $2; }
  209. | /* empty */ { $$ = NULL; }
  210. ;
  211.  
  212. assignment : variable ASSIGN expr { $$ = binop($2, $1, $3); }
  213. ;
  214.  
  215. expr : simexpr EQ simexpr { $$ = binop($2, $1, $3); }
  216. | simexpr LT simexpr { $$ = binop($2, $1, $3); }
  217. | simexpr GT simexpr { $$ = binop($2, $1, $3); }
  218. | simexpr NE simexpr { $$ = binop($2, $1, $3); }
  219. | simexpr LE simexpr { $$ = binop($2, $1, $3); }
  220. | simexpr GE simexpr { $$ = binop($2, $1, $3); }
  221. | simexpr IN simexpr { $$ = binop($2, $1, $3); }
  222. | simexpr
  223. ;
  224.  
  225. simexpr : expr PLUS term { $$ = binop($2, $1, $3); }
  226. | expr MINUS term { $$ = binop($2, $1, $3); }
  227. | term
  228.  
  229. term : term TIMES factor { $$ = binop($2, $1, $3); }
  230. | factor
  231. ;
  232.  
  233. factor : LPAREN expr RPAREN { $$ = $2; }
  234. | variable
  235. | NUMBER
  236. | MINUS variable { $$ = unaryop($1, $2); }
  237. | STRING
  238. | funcall
  239. | NIL { $$ = donil($1); }
  240. ;
  241.  
  242. variable : IDENTIFIER { $$ = findid($1); }
  243. | variable DOT IDENTIFIER { $$ = arrayref($1, $2, $3, (TOKEN)talloc());}
  244. | variable POINT { $$ = dopoint($1,$2); }
  245. | variable LBRACKET exprlist RBRACKET { $$ = arrayref($1, $2, $3, $4);}
  246. ;
  247.  
  248. exprlist : expr COMMA exprlist
  249. | expr
  250.  
  251.  
  252. %%
  253.  
  254. /* You should add your own debugging flags below, and add debugging
  255. printouts to your programs.
  256.  
  257. You will want to change DEBUG to turn off printouts once things
  258. are working.
  259. */
  260.  
  261. #define DEBUG 0 /* set bits here for debugging, 0 = off */
  262. #define DB_CONS 1 /* bit to trace cons */
  263. #define DB_BINOP 2 /* bit to trace binop */
  264. #define DB_MAKEIF 4 /* bit to trace makeif */
  265. #define DB_MAKEPROGN 8 /* bit to trace makeprogn */
  266. #define DB_PARSERES 16 /* bit to trace parseresult */
  267. #define DB_MAKEPROGRAM 32 /* bit to trace makeprogram */
  268. #define DB_MAKEFOR 64 /* bit to trace makefor */
  269. #define DB_MAKEFUNCALL 128
  270. #define DB_INSTALLCONST 256
  271. #define DB_UNARYOP 512
  272.  
  273. int labelnumber = 0; /* sequential counter for internal label numbers */
  274. int labels[5] = {0,0,0,0,0};
  275.  
  276. /* Note: you should add to the above values and insert debugging
  277. printouts in your routines similar to those that are shown here. */
  278.  
  279.  
  280. /* cons links a new item onto the front of a list. Equivalent to a push.
  281. (cons 'a '(b c)) = (a b c) */
  282. TOKEN cons(TOKEN item, TOKEN list) /* add item to front of list */
  283. { item->link = list;
  284. if (DEBUG & DB_CONS)
  285. { printf("cons\n");
  286. dbugprinttok(item);
  287. dbugprinttok(list);
  288. };
  289. return item;
  290. }
  291.  
  292. //Handle NULL values
  293. TOKEN donil(TOKEN niltok)
  294. {
  295. niltok->tokentype = NUMBERTOK;
  296. niltok->datatype = POINTER;
  297. niltok->intval = 0;
  298. return niltok;
  299. }
  300.  
  301. /* findid finds an identifier in the symbol table, sets up symbol table
  302. pointers, changes a constant to its number equivalent */
  303. TOKEN findid(TOKEN tok)
  304. {
  305. SYMBOL toksym = searchst(tok->stringval);
  306. if(toksym != NULL)
  307. {
  308. //If its a constant, smash it into its number
  309. if(toksym->kind == CONSTSYM)
  310. {
  311. tok->tokentype = NUMBERTOK;
  312. tok->datatype = toksym->basicdt;
  313.  
  314. switch(toksym->basicdt)
  315. {
  316. case REAL:
  317. tok->realval = toksym->constval.realnum;
  318. break;
  319. case INTEGER:
  320. tok->intval = toksym->constval.intnum;
  321. break;
  322. }/* findid finds an identifier in the symbol table, sets up symbol table
  323. pointers, changes a constant to its number equivalent */
  324. }
  325. else
  326. {
  327. SYMBOL typ = toksym->datatype;
  328. tok->symentry = toksym;
  329. tok->symtype = typ;
  330. tok->datatype = typ->basicdt;
  331. }
  332. }
  333.  
  334. return tok;
  335. }
  336.  
  337. /* makefloat forces the item tok to be floating, by floating a constant
  338. or by inserting a FLOATOP operator */
  339. TOKEN makefloat(TOKEN tok)
  340. {
  341.  
  342. TOKEN floattok = (TOKEN) talloc();
  343. floattok->tokentype = OPERATOR;
  344. floattok->whichval = FLOATOP;
  345. floattok->datatype = REAL;
  346.  
  347. return unaryop(floattok, tok);
  348. }
  349.  
  350. /* makefix forces the item tok to be integer, by truncating a constant
  351. or by inserting a FIXOP operator */
  352. TOKEN makefix(TOKEN tok)
  353. {
  354.  
  355. TOKEN inttok = (TOKEN) talloc();
  356. inttok->tokentype = OPERATOR;
  357. inttok->whichval = FIXOP;
  358. inttok->datatype = INTEGER;
  359. return unaryop(inttok, tok);
  360. }
  361.  
  362. /* unaryop links a unary operator op to one operand, lhs */
  363. TOKEN unaryop(TOKEN op, TOKEN lhs)
  364. {
  365. op->operands = lhs; /* link operands to operator */
  366. lhs->link = NULL; /* terminate op list */
  367. if (DEBUG & DB_UNARYOP)
  368. {
  369. printf("unaryop\n");
  370. dbugprinttok(op);
  371. dbugprinttok(lhs);
  372. };
  373. return op;
  374. }
  375.  
  376. /* binop links a binary operator op to two operands, lhs and rhs. */
  377. TOKEN binop(TOKEN op, TOKEN lhs, TOKEN rhs){
  378. if (DEBUG) printf("called binop()\n");
  379. op->operands = lhs;
  380. if(lhs->datatype == 1 && rhs->datatype == 0)
  381. {
  382. rhs = makefloat(rhs);
  383. }
  384. else if(rhs->datatype == 1 && lhs->datatype == 0)
  385. {
  386. lhs = makefloat(lhs);
  387. }
  388. lhs = cons(lhs, cons(rhs, NULL));
  389. return op;
  390. }
  391.  
  392. /* makeif makes an IF operator and links it to its arguments.
  393. tok is a (now) unused token that is recycled to become an IFOP operator */
  394. TOKEN makeif(TOKEN tok, TOKEN exp, TOKEN thenpart, TOKEN elsepart)
  395. {
  396. tok->tokentype = OPERATOR; /* Make it look like an operator */
  397. tok->whichval = IFOP;
  398. if (elsepart != NULL) elsepart->link = NULL;
  399. thenpart->link = elsepart;
  400. exp->link = thenpart;
  401. tok->operands = exp;
  402. return tok;
  403. }
  404.  
  405. /* makeprogn makes a PROGN operator and links it to the list of statements.
  406. tok is a (now) unused token that is recycled. */
  407. TOKEN makeprogn(TOKEN tok, TOKEN statements)
  408. { tok->tokentype = OPERATOR;
  409. tok->whichval = PROGNOP;
  410. tok->operands = statements;
  411. if (DEBUG & DB_MAKEPROGN)
  412. { printf("makeprogn\n");
  413. dbugprinttok(tok);
  414. dbugprinttok(statements);
  415. };
  416. return tok;
  417. }
  418.  
  419. /* makeprogram makes the tree structures for the top-level program */
  420. TOKEN makeprogram(TOKEN tok, TOKEN name, TOKEN arguments, TOKEN statements)
  421. { tok->tokentype = OPERATOR;
  422. tok->whichval = PROGRAMOP;
  423. tok->operands = name;
  424. name->link = arguments;
  425. arguments->link = statements;
  426. if (DEBUG & DB_MAKEPROGRAM)
  427. { printf("makeprogram\n");
  428. dbugprinttok(tok);
  429. dbugprinttok(name);
  430. dbugprinttok(arguments);
  431. dbugprinttok(statements);
  432. };
  433. return tok;
  434. }
  435.  
  436. /* makefor makes structures for a for statement.
  437. sign is 1 for normal loop, -1 for downto.
  438. asg is an assignment statement, e.g. (:= i 1)
  439. endexpr is the end expression
  440. tok, tokb and tokc are (now) unused tokens that are recycled. */
  441. TOKEN makefor(int sign, TOKEN tok, TOKEN asg, TOKEN tokb, TOKEN endexpr,
  442. TOKEN tokc, TOKEN statement)
  443. {
  444. int labelnum = labelnumber;
  445. TOKEN i1 = (TOKEN) talloc();
  446. i1->tokentype = IDENTIFIERTOK;
  447. i1->symentry = asg->operands->symentry;
  448. strcpy(i1->stringval, asg->operands->stringval);
  449. TOKEN i2 = (TOKEN) talloc();
  450. i2->tokentype = IDENTIFIERTOK;
  451. i2->symentry = asg->operands->symentry;
  452. strcpy(i2->stringval, asg->operands->stringval);
  453. TOKEN i3 = (TOKEN) talloc();
  454. i3->tokentype = IDENTIFIERTOK;
  455. i3->symentry = asg->operands->symentry;
  456. strcpy(i3->stringval, asg->operands->stringval);
  457. TOKEN lessthan = (TOKEN) talloc();
  458. lessthan->tokentype = OPERATOR;
  459. lessthan->whichval = LE - OPERATOR_BIAS;
  460. TOKEN assign = (TOKEN) talloc();
  461. assign->tokentype = OPERATOR;
  462. assign->whichval = ASSIGN - OPERATOR_BIAS;
  463. TOKEN plus = (TOKEN) talloc();
  464. plus->tokentype = OPERATOR;
  465. plus->whichval = PLUSOP;
  466. TOKEN one = (TOKEN) talloc();
  467. one->tokentype = NUMBERTOK;
  468. one->datatype = INTEGER;
  469. one->intval = 1;
  470. TOKEN temp = (TOKEN) talloc();
  471. temp = binop(plus, i1, one);
  472. tok = binop(assign, i2, temp);
  473. TOKEN label = makelabel();
  474. TOKEN forstatements = NULL;
  475. forstatements = cons(makegoto(labelnum), forstatements);
  476. forstatements = cons(tok , forstatements);
  477. forstatements = cons(statement, forstatements);
  478. forstatements = makeprogn((TOKEN) talloc(), forstatements);
  479. TOKEN iftok = makeif(tokb, binop(lessthan, i3, endexpr), forstatements, NULL);
  480. iftok = cons(label, iftok);
  481. iftok = cons(asg, iftok);
  482. return makeprogn(tokc, iftok);
  483. }
  484.  
  485. /* makerepeat makes structures for a repeat statement.
  486. tok and tokb are (now) unused tokens that are recycled. */
  487. TOKEN makerepeat(TOKEN tok, TOKEN statements, TOKEN tokb, TOKEN expr) {
  488. int labelnum = labelnumber;
  489. TOKEN tempLabel = makelabel();
  490. TOKEN tokProg = makeprogn(tokb, statements);
  491. TOKEN tokGOTO = makegoto(labelnum);
  492. TOKEN tokEmpty = makeprogn((TOKEN) talloc(), NULL);
  493. TOKEN tokIF = talloc();
  494. tok = makeprogn(tok, tempLabel);
  495. tokIF = makeif(tokIF, expr, tokEmpty, tokGOTO);
  496. tempLabel->link = tokProg;
  497. tokEmpty->link = tokGOTO;
  498. tokProg->link = tokIF;
  499. return tok;
  500. }
  501.  
  502. /* makegoto makes a GOTO operator to go to the specified label.
  503. The label number is put into a number token. */
  504. TOKEN makegoto(int label) {
  505. //Or label, that also works.
  506. int val = labelnumber - 1;
  507. TOKEN tok_goto = talloc();
  508. tok_goto->tokentype = OPERATOR;
  509. tok_goto->operands = makeintc(val);
  510. tok_goto->whichval = GOTOOP;
  511. return tok_goto;
  512. }
  513.  
  514. /* makeintc makes a new token with num as its value */
  515. TOKEN makeintc(int num) {
  516. TOKEN newint = talloc();
  517. newint->tokentype = NUMBERTOK;
  518. newint->intval = num;
  519. newint->datatype = INTEGER;
  520. return newint;
  521. }
  522.  
  523. /* makelabel makes a new label, using labelnumber++ */
  524. TOKEN makelabel() {
  525. TOKEN label = talloc();
  526. label->tokentype = OPERATOR;
  527. label->operands = makeintc(labelnumber);
  528. label->whichval = LABELOP;
  529. labelnumber++;
  530. return label;
  531. }
  532.  
  533. /* makefuncall makes a FUNCALL operator and links it to the fn and args.
  534. tok is a (now) unused token that is recycled. */
  535. TOKEN makefuncall(TOKEN tok, TOKEN fn, TOKEN args)
  536. {
  537. SYMBOL funsym = searchst(fn->stringval);
  538.  
  539. if(funsym != NULL)
  540. {
  541. fn->datatype = (funsym->datatype)->basicdt;
  542. }
  543.  
  544. if(strcmp(funsym->namestring, "new") != 0)
  545. {
  546. tok->tokentype = OPERATOR;
  547. tok->whichval = FUNCALLOP;
  548. tok->datatype = fn->datatype;
  549. tok->operands= fn;
  550. fn->link = args;
  551. }
  552. else
  553. {
  554. tok->tokentype = OPERATOR;
  555. tok->whichval = FUNCALLOP;
  556. tok->datatype = fn->datatype;
  557. tok->operands = fn;
  558. TOKEN sizetok = (TOKEN)talloc();
  559. sizetok->tokentype = NUMBERTOK;
  560. sizetok->intval = searchst((((searchst(args->stringval)->datatype)->datatype)->datatype)->namestring)->size;
  561. fn->link = sizetok;
  562. TOKEN assignop = (TOKEN)talloc();
  563. assignop->tokentype = OPERATOR;
  564. assignop->whichval = ASSIGNOP;
  565. args->datatype = POINTER;
  566. tok = binop(assignop, args, tok);
  567. }
  568.  
  569. if(strcmp(funsym->namestring, "writeln") == 0)
  570. {
  571. if(args->tokentype == NUMBERTOK)
  572. {
  573. switch(args->datatype)
  574. {
  575. case INTEGER:
  576. strcpy(fn->stringval, "writelni");
  577. break;
  578. case REAL:
  579. strcpy(fn->stringval, "writelnf");
  580. break;
  581. }
  582. }
  583. else if(args->tokentype == IDENTIFIERTOK)
  584. {
  585. switch(args->symentry->basicdt)
  586. {
  587. case INTEGER:
  588. strcpy(fn->stringval, "writelni");
  589. break;
  590. case REAL:
  591. strcpy(fn->stringval, "writelnf");
  592. break;
  593. }
  594. }
  595. }
  596.  
  597. else if(strcmp(funsym->namestring, "write") == 0)
  598. {
  599. if(args->tokentype == NUMBERTOK)
  600. {
  601. switch(args->datatype)
  602. {
  603. case INTEGER:
  604. strcpy(fn->stringval, "writei");
  605. break;
  606. case REAL:
  607. strcpy(fn->stringval, "writef");
  608. break;
  609. }
  610. }
  611. else if(args->tokentype == IDENTIFIERTOK)
  612. {
  613. switch(searchst(args->stringval)->basicdt)
  614. {
  615. case INTEGER:
  616. strcpy(fn->stringval, "writei");
  617. break;
  618. case REAL:
  619. strcpy(fn->stringval, "writef");
  620. break;
  621. }
  622. }
  623. }
  624. return tok;
  625. }
  626.  
  627. /* install variables in symbol table */
  628. void instconst(TOKEN idtok, TOKEN consttok)
  629. {
  630. SYMBOL sym;
  631. sym = symalloc();
  632. sym = insertsym(idtok->stringval);
  633. sym->kind = CONSTSYM;
  634. sym->basicdt = consttok->datatype;
  635. switch(consttok->datatype)
  636. {
  637. case REAL:
  638. sym->constval.realnum = consttok->realval;
  639. break;
  640. case INTEGER:
  641. sym->constval.intnum = consttok->intval;
  642. break;
  643. case STRINGTYPE:
  644. strcpy(sym->constval.stringconst, consttok->stringval);
  645. break;
  646. }
  647. }
  648.  
  649. /* instlabel installs a user label into the label table */
  650. void instlabel (TOKEN num)
  651. {
  652. if(labelnumber < 5)
  653. labels[labelnumber++] = num->intval;
  654. }
  655.  
  656. /* insttype will install a type name in symbol table.
  657. typetok is a token containing symbol table pointers. */
  658. void insttype(TOKEN typename, TOKEN eqtok, TOKEN typetok)
  659. {
  660. SYMBOL typesym;
  661. typesym = searchins(typename->stringval);
  662.  
  663. typesym->kind = TYPESYM;
  664. typesym->datatype = typetok->symentry;
  665. typesym->size = (typetok->symentry)->size;
  666.  
  667. }
  668.  
  669. /* instenum installs an enumerated subrange in the symbol table,
  670. e.g., type color = (red, white, blue)
  671. by calling makesubrange and returning the token it returns. */
  672. TOKEN instenum(TOKEN rparen, TOKEN idlist, TOKEN lparen)
  673. {
  674. //Smash r paren into a const token
  675. rparen->tokentype = NUMBERTOK;
  676. rparen->datatype = INTEGER;
  677. rparen->intval = 0;
  678.  
  679. while(idlist != NULL)
  680. {
  681. instconst(idlist, rparen);
  682. (rparen->intval)++;
  683. idlist = idlist->link;
  684. }
  685.  
  686. return makesubrange(lparen, 0, (rparen->intval) - 1);
  687. }
  688.  
  689. /* makesubrange makes a SUBRANGE symbol table entry, puts the pointer to it
  690. into tok, and returns tok. */
  691. TOKEN makesubrange(TOKEN tok, int low, int high)
  692. {
  693. SYMBOL subrange = (SYMBOL)symalloc();
  694.  
  695. subrange->kind = SUBRANGE;
  696. subrange->basicdt = INTEGER;
  697. subrange->lowbound = low;
  698. subrange->highbound = high;
  699. subrange->size = basicsizes[INTEGER];
  700. tok->symentry = subrange;
  701. return tok;
  702. }
  703.  
  704. /* instfields will install type in a list idlist of field name tokens:
  705. re, im: real put the pointer to REAL in the RE, IM tokens.
  706. typetok is a token whose symtype is a symbol table pointer.
  707. Note that nconc() can be used to combine these lists after instrec() */
  708. TOKEN instfields(TOKEN idlist, TOKEN typetok)
  709. {
  710. SYMBOL typesym = searchins(typetok->stringval);
  711. SYMBOL sym;
  712. TOKEN tempTok = idlist;
  713. int align = alignsize(typesym);
  714. if(typesym->size == 0)
  715. typesym->size = 8;
  716.  
  717. while(tempTok != NULL)
  718. {
  719. sym = (SYMBOL)symalloc();
  720. strcpy(sym->namestring, tempTok->stringval);
  721. sym->size = typesym->size;
  722. sym->datatype = typesym;
  723. sym->basicdt = typesym->basicdt;
  724. tempTok->symentry = sym;
  725. tempTok = tempTok->link;
  726. }
  727. return idlist;
  728. }
  729.  
  730. /* instrec will install a record definition. Each token in the linked list
  731. argstok has a pointer its type. rectok is just a trash token to be
  732. used to return the result in its symtype */
  733. TOKEN instrec(TOKEN rectok, TOKEN argstok)
  734. {
  735. SYMBOL recsym = (SYMBOL)symalloc();
  736. TOKEN tempTok = argstok;
  737. int size = 0;
  738. while(tempTok->link != NULL)
  739. {
  740. (tempTok->symentry)->link = (tempTok->link)->symentry;
  741. while( size % (tempTok->symentry)->size != 0)
  742. size += 4;
  743. size += (tempTok->symentry)->size;
  744. tempTok = tempTok->link;
  745. }
  746. while( size % (tempTok->symentry)->size != 0)
  747. size += 4;
  748. size += (tempTok->symentry)->size;
  749. recsym->kind = RECORDSYM;
  750. recsym->datatype = argstok->symentry;
  751. recsym->size = size;
  752. rectok->symentry = recsym;
  753. return rectok;
  754. }
  755.  
  756. /* instpoint will install a pointer type in symbol table */
  757. TOKEN instpoint(TOKEN tok, TOKEN typename)
  758. {
  759. SYMBOL pointsym = (SYMBOL)symalloc();
  760. SYMBOL typenamesym = (SYMBOL)symalloc();
  761. strcpy(typenamesym->namestring, typename->stringval);
  762. pointsym->kind = POINTERSYM;
  763. pointsym->datatype = typenamesym;
  764. pointsym->basicdt = POINTER;
  765. pointsym->size = basicsizes[POINTER];
  766. tok->symentry = pointsym;
  767. return tok;
  768. }
  769.  
  770. /* instdotdot installs a .. subrange in the symbol table.
  771. dottok is a (now) unused token that is recycled. */
  772. TOKEN instdotdot(TOKEN lowtok, TOKEN dottok, TOKEN hightok)
  773. {
  774. SYMBOL dotsym = (SYMBOL)symalloc();
  775.  
  776. dotsym->kind = SUBRANGE;
  777. dotsym->basicdt = INTEGER;
  778. dotsym->lowbound = lowtok->intval;
  779. dotsym->highbound = hightok->intval;
  780. dotsym->size = basicsizes[INTEGER];
  781. dottok->symentry = dotsym;
  782. return dottok;
  783. }
  784.  
  785. /* instarray installs an array declaration into the symbol table.
  786. bounds points to a SUBRANGE symbol table entry.
  787. The symbol table pointer is returned in token typetok. */
  788. TOKEN instarray(TOKEN bounds, TOKEN typetok)
  789. {
  790. SYMBOL arrsym = (SYMBOL)symalloc();
  791. SYMBOL typesym = searchst(typetok->stringval);
  792. if(bounds->link != NULL)
  793. {
  794. TOKEN bound1 = bounds;
  795. TOKEN bound2 = bounds->link;
  796. bounds->link = NULL;
  797. TOKEN newType = instarray(bound2, typetok);
  798. typesym = newType->symtype;
  799. }
  800. arrsym->kind = ARRAYSYM;
  801. arrsym->datatype = typesym;
  802. if(bounds->tokentype != IDENTIFIERTOK)
  803. {
  804. arrsym->lowbound = (bounds->symentry)->lowbound;
  805. arrsym->highbound = (bounds->symentry)->highbound;
  806. }
  807. else
  808. {
  809. arrsym->lowbound = 0;
  810. arrsym->highbound = 2;
  811. }
  812.  
  813. arrsym->size = (arrsym->highbound - arrsym->lowbound + 1) * typesym->size;
  814.  
  815. typetok->symtype = arrsym;
  816.  
  817. return typetok;
  818. }
  819.  
  820. /* dopoint handles a ^ operator.
  821. tok is a (now) unused token that is recycled. */
  822. TOKEN dopoint(TOKEN var, TOKEN tok)
  823. {
  824.  
  825. tok->tokentype = OPERATOR;
  826. tok->whichval = POINTEROP;
  827. tok->symentry = searchst(var->stringval);
  828.  
  829. //coming from a nested point - var is an aref
  830. if(tok->symentry == NULL)
  831. {
  832. tok->symtype = searchst(var->symtype->datatype->namestring)->datatype;
  833. }
  834. else
  835. {
  836. tok->symtype = searchst((tok->symentry)->datatype->datatype->datatype->namestring)->datatype;//->datatype;
  837. }
  838. tok = unaryop(tok, var);
  839.  
  840.  
  841. return tok;
  842. }
  843.  
  844. /* makearef makes an array reference operation.
  845. off is be an integer constant token
  846. tok (if not NULL) is a (now) unused token that is recycled. */
  847. TOKEN makearef(TOKEN var, TOKEN off, TOKEN tok)
  848. {
  849. tok->tokentype = OPERATOR;
  850. tok->whichval = AREFOP;
  851.  
  852. return binop(tok, var, off);
  853. }
  854.  
  855. /* arrayref processes an array reference a[i]
  856. subs is a list of subscript expressions.
  857. tok and tokb are (now) unused tokens that are recycled. */
  858. TOKEN arrayref(TOKEN arr, TOKEN tok, TOKEN subs, TOKEN tokb)
  859. {
  860. TOKEN ofs = tokb;
  861. ofs->tokentype = NUMBERTOK;
  862. ofs->datatype = INTEGER;
  863. SYMBOL sym = arr->symtype;
  864.  
  865. if(arr->whichval == AREFOP)
  866. {
  867. sym = sym->datatype;
  868. while( strcmp(sym->namestring, subs->stringval) != 0)
  869. {
  870. while( ofs->intval % sym->size != 0)
  871. ofs->intval += 4;
  872. ofs->intval +=sym->size;
  873.  
  874. sym = sym->link;
  875. }
  876. while( ofs->intval % sym->size != 0)
  877. ofs->intval += 4;
  878. arr->operands->link->intval+= ofs->intval;
  879. arr->symtype = sym->datatype->datatype;
  880. return arr;
  881. }
  882. else
  883. {
  884. if(sym->kind == RECORDSYM)
  885. {
  886. sym = sym->datatype;
  887. while( strcmp(sym->namestring, subs->stringval) != 0)
  888. {
  889. while( ofs->intval % sym->size != 0)
  890. ofs->intval += 4;
  891. ofs->intval +=sym->size;
  892.  
  893. sym = sym->link;
  894. }
  895. while( ofs->intval % sym->size != 0)
  896. ofs->intval += 4;
  897. tok = makearef(arr, ofs, tok);
  898. tok->symtype = sym->datatype->datatype;
  899.  
  900. return tok;
  901. }
  902. else if(sym->kind == ARRAYSYM)
  903. {
  904. if(subs->tokentype == NUMBERTOK)
  905. {
  906. ofs->intval = (subs->intval - sym->lowbound) * (sym->datatype->size);
  907. tok = makearef(arr, ofs, tok);
  908. }
  909. else
  910. {
  911. TOKEN plustok = (TOKEN)talloc();
  912. plustok->tokentype = OPERATOR;
  913. plustok->whichval = PLUSOP;
  914. TOKEN timestok = (TOKEN)talloc();
  915. timestok->tokentype = OPERATOR;
  916. timestok->whichval = TIMESOP;
  917. TOKEN term1 = (TOKEN)talloc();
  918. term1->tokentype = NUMBERTOK;
  919. term1->intval = -(sym->lowbound) * (sym->datatype->size);
  920. TOKEN elesize = (TOKEN)talloc();
  921. elesize->tokentype = NUMBERTOK;
  922. elesize->intval = (sym->datatype->size);
  923. ofs = binop(plustok, term1, binop(timestok, elesize, subs));
  924. ofs->tokentype = OPERATOR;
  925. tok = makearef(arr, ofs, tok);
  926. }
  927. tok->symtype = sym->datatype->datatype;
  928.  
  929. return tok;
  930. }
  931.  
  932. return tok;
  933. }
  934.  
  935. }
  936.  
  937. /* dolabel is the action for a label of the form <number>: <statement>
  938. tok is a (now) unused token that is recycled. */
  939. TOKEN dolabel(TOKEN labeltok, TOKEN tok, TOKEN statement)
  940. {
  941. TOKEN label = makelabel();
  942. labelnumber--;
  943. int i;
  944. for(i = 0; i < 50; i++)
  945. if(labels[i] == labeltok->intval)
  946. break;
  947. label->operands->intval = i;
  948. cons(label, statement);
  949. return makeprogn(tok, label);
  950. }
  951.  
  952. /* makewhile makes structures for a while statement.
  953. tok and tokb are (now) unused tokens that are recycled. */
  954. TOKEN makewhile(TOKEN tok, TOKEN expr, TOKEN tokb, TOKEN statement)
  955. {
  956. TOKEN labeltok = makelabel();
  957. TOKEN whiletok = NULL;
  958. TOKEN iftok = makeif(tok, expr, makeprogn(tokb, cons(statement, makegoto(labelnumber - 1))), NULL);
  959. whiletok = cons(iftok, whiletok);
  960. whiletok = cons(labeltok, whiletok);
  961. return makeprogn((TOKEN)talloc(), whiletok);
  962. }
  963.  
  964. /* findtype looks up a type name in the symbol table, puts the pointer
  965. to its type into tok->symtype, returns tok. */
  966. TOKEN findtype(TOKEN tok)
  967. {
  968. tok->symtype = searchst(tok->stringval);
  969. return tok;
  970. }
  971.  
  972. /* dogoto is the action for a goto statement.
  973. tok is a (now) unused token that is recycled. */
  974. TOKEN dogoto(TOKEN tok, TOKEN labeltok)
  975. {
  976. int i = 0;
  977. for(i = 0; i < 50; i++)
  978. if(labels[i] = labeltok->intval)
  979. break;
  980. return makegoto(i);
  981. }
  982.  
  983. yyerror(s)
  984. char * s;
  985. {
  986. fputs(s,stderr); putc('\n',stderr);
  987. }
  988.  
  989. main()
  990. { int res;
  991. initsyms();
  992. res = yyparse();
  993. printst();
  994. printf("yyparse result = %8d\n", res);
  995. if (DEBUG & DB_PARSERES) dbugprinttok(parseresult);
  996. ppexpr(parseresult); /* Pretty-print the result tree */
  997. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement