Expression functions enhanced.
[Jack-Compiler.git] / parse.c
blob6f2c0096ae0fa1fe5f49b664740be40342a433aa
1 #include <ctype.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
7 #include "error.h"
8 #include "jack.h"
9 #include "parse.h"
10 #include "token.h"
12 #define OP "+-*//&|<>="
13 #define UNARY_OP "-~"
15 void parse_class()
17 if(settings.tokens) { printf("<class>\n"); }
19 if(has_more_tokens(pC) == true)
21 pC = advance(pC, pT);
22 tk = token_type(pT);
23 } else {
24 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
27 if(strcmp(pT, "class") == 0 ) {
28 if(settings.tokens) { printf("\t<keyword>%s</keyword>\n", pT); }
29 } else {
30 compiler_error(40, "Incorrect Token Found: Must be 'class'", pS, pC, pT);
33 /* look for class name */
34 if(has_more_tokens(pC) == true)
36 pC = advance(pC, pT);
37 tk = token_type(pT);
38 } else {
39 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
42 if (tk == IDENTIFIER){
43 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
44 } else {
45 compiler_error(44, "Could Not Find Class Name or Subroutine Name at This Location", pS, pC, pT);
48 /* look for '{' symbol */
49 if(has_more_tokens(pC) == true)
51 pC = advance(pC, pT);
52 tk = token_type(pT);
53 } else {
54 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
57 if (tk == SYMBOL){
58 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
59 } else {
60 compiler_error(44, "Could Not Find Class Name or Subroutine Name at This Location", pS, pC, pT);
63 if(has_more_tokens(pC) == true)
65 pC = advance(pC, pT);
66 tk = token_type(pT);
67 } else {
68 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
71 while(strcmp(pT, "static") == 0 || strcmp(pT, "field") == 0)
73 parse_class_var_dec();
74 if(has_more_tokens(pC) == true)
76 pC = advance(pC, pT);
77 tk = token_type(pT);
78 } else {
79 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
83 parse_subroutine();
85 if(settings.tokens) { printf("</class>\n"); }
88 void parse_class_var_dec()
90 if(settings.tokens) { printf("<classVarDec>\n"); }
92 /* look for 'static' or 'field' */
93 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
94 if(has_more_tokens(pC) == true)
96 pC = advance(pC, pT);
97 tk = token_type(pT);
98 } else {
99 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
102 /* look for type */
103 if(tk == IDENTIFIER) {
104 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
105 } else if (tk == KEYWORD) {
106 if(strcmp(pT, "int") == 0 || strcmp(pT, "char") == 0 || strcmp(pT, "boolean") == 0) {
107 if(settings.tokens) { printf("\t<keyword>%s</keyword>\n", pT); }
108 } else {
109 compiler_error(41, "Token Must be Data Type.", pS, pC, pT);
111 } else {
112 compiler_error(41, "Token Must be Data Type", pS, pC, pT);
115 /* look or variable name */
116 if(has_more_tokens(pC) == true)
118 pC = advance(pC, pT);
119 tk = token_type(pT);
120 } else {
121 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
123 if(tk == IDENTIFIER) {
124 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
125 } else {
126 compiler_error(42, "Token Must be Variable Name", pS, pC, pT);
129 /* look for ',' */
130 if(has_more_tokens(pC) == true)
132 pC = advance(pC, pT);
133 tk = token_type(pT);
134 } else {
135 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
138 if(*pT == ',') {
139 do {
140 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
141 if(has_more_tokens(pC) == true)
143 pC = advance(pC, pT);
144 tk = token_type(pT);
145 } else {
146 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
148 if(tk == IDENTIFIER) {
149 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
150 } else {
151 compiler_error(42, "Token Must be Variable Name", pS, pC, pT);
153 if(has_more_tokens(pC) == true)
155 pC = advance(pC, pT);
156 tk = token_type(pT);
157 } else {
158 compiler_error(40, "Incomplete Class Declaration", pS, pC, pT);
160 } while (*pT == ',');
163 if(*pT == ';') {
164 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
165 } else {
166 compiler_error(33, "Could Not Find ';' Symbol At This Location", pS, pC, pT);
169 if(settings.tokens) { printf("</classVarDec>\n"); }
172 void parse_subroutine()
174 if(settings.tokens) { printf("<subroutineDec>\n"); }
176 if(tk == KEYWORD) {
177 if(strcmp(pT, "constructor") == 0 || strcmp(pT, "function") == 0 || strcmp(pT, "method") == 0)
179 if(settings.tokens) { printf("\t<keyword>%s</keyword>\n", pT); }
180 } else {
181 compiler_error(8, "Incorrect Token Found: Must be 'constructor', 'function', or 'method'", pS, pC, pT);
185 /* look for return type of function */
186 if(has_more_tokens(pC) == true)
188 pC = advance(pC, pT);
189 tk = token_type(pT);
190 if(tk == KEYWORD || tk == IDENTIFIER)
192 if(strcmp(pT, "void") == 0)
194 if(settings.tokens) { printf("\t<keyword>%s</keyword>\n", pT); }
195 } else {
196 if(settings.tokens) { printf("\t<type>%s</type>\n", pT); }
198 } else {
199 compiler_error(9, "Could Not Complete Parse Tree of Subroutine. Incomplete Program", pS, pC, pT);
201 } else {
202 compiler_error(29, "Incorrect Token Type", pS, pC, pT);
205 /* look for subroutine name */
206 if(has_more_tokens(pC) == true)
208 pC = advance(pC, pT);
209 tk = token_type(pT);
210 if(tk == IDENTIFIER)
212 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
213 } else {
214 compiler_error(9, "Could Not Complete Parse Tree of Subroutine. Incomplete Program", pS, pC, pT);
216 } else {
217 compiler_error(10, "Incorrect Token Type. Looking for Keyword or Identifier.", pS, pC, pT);
220 /* look for symbol '(' that specifies beginning of parameter list */
221 if(has_more_tokens(pC) == true)
223 pC = advance(pC, pT);
224 tk = token_type(pT);
225 if(*pT == '(')
227 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
228 parse_params();
229 } else {
230 compiler_error(12, "Parameter List for Function Missing", pS, pC, pT);
232 } else {
233 compiler_error(11, "Name of Function Must be an Identifier", pS, pC, pT);
236 /* look for end of parameter list */
237 if(*pT == ')')
239 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
240 } else {
241 compiler_error(13, "Could Not Complete Parameter List for Function", pS, pC, pT);
244 /* look for opening brace for block */
245 if(has_more_tokens(pC) == true)
247 pC = advance(pC, pT);
248 tk = token_type(pT);
249 if(*pT == '{')
251 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
252 if(has_more_tokens(pC) == true)
254 pC = advance(pC, pT);
255 tk = token_type(pT);
256 } else {
257 compiler_error(17, "Could Not Complete Variable List of Subroutine. Incomplete Program", pS, pC, pT);
259 parse_var_dec();
261 } else {
262 compiler_error(9, "Could Not Complete Parse Tree of Subroutine. Incomplete Program", pS, pC, pT);
265 while(strcmp(pT, "let") == 0 || strcmp(pT, "if") == 0 || strcmp(pT, "while") == 0 || strcmp(pT, "do") == 0 || strcmp(pT, "return") == 0)
267 parse_statements();
268 if(has_more_tokens(pC) == true)
270 pC = advance(pC, pT);
271 tk = token_type(pT);
272 } else {
273 compiler_error(9, "Could Not Complete Parse Tree of Subroutine. Incomplete Program", pS, pC, pT);
277 if(settings.tokens) { printf("</subroutineDec>\n"); }
280 void parse_params()
282 if(*pT == '(') { if(settings.tokens) { printf("<parameterList>\n"); } }
284 /* look for datatype in parameter list */
285 if(has_more_tokens(pC) == true)
287 pC = advance(pC, pT);
288 tk = token_type(pT);
289 if(tk == KEYWORD) {
290 if(strcmp(pT, "int") == 0 || strcmp(pT, "char") == 0 || strcmp(pT, "boolean") == 0)
292 if(settings.tokens) { printf("\t<keyword>%s</keyword>\n", pT); }
293 } else {
294 compiler_error(14, "Incorrect Token Type in Parameter List. Looking for Datatype name.", pS, pC, pT);
296 } else if(tk == SYMBOL && *pT == ')') { if(settings.tokens) { printf("</parameterList>\n"); } return; }
297 } else {
298 compiler_error(13, "Could Not Complete Parameter List for Function", pS, pC, pT);
301 /* look for identifier for this parameter */
302 if(has_more_tokens(pC) == true)
304 pC = advance(pC, pT);
305 tk = token_type(pT);
306 if(tk == IDENTIFIER) {
307 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
309 } else {
310 compiler_error(15, "Incorrect Token Type in Parameter List. Looking for Variable Identifier.", pS, pC, pT);
312 } else {
313 compiler_error(13, "Could Not Complete Parameter List for Function", pS, pC, pT);
316 /* are there more parameters? */
317 if(has_more_tokens(pC) == true)
319 pC = advance(pC, pT);
320 tk = token_type(pT);
321 if(*pT == ',') {
322 parse_params();
323 } else if (*pT == ')') { /* exit parse_params */
324 if(settings.tokens) { printf("</parameterList>\n"); }
325 return;
326 } else {
327 compiler_error(16, "Incorrect Token Type in Parameter List. Looking for ',' or ')'", pS, pC, pT);
329 } else {
330 compiler_error(13, "Could Not Complete Parameter List for Function", pS, pC, pT);
334 void parse_var_dec()
336 /* look for token named 'var' */
337 if(strcmp(pT, "var") == 0)
339 if(settings.tokens) { printf("<varDec>\n\t<symbol>%s</symbol>\n", pT); }
340 } else { return; }
342 /* look for variable data type */
343 if(has_more_tokens(pC) == true)
345 pC = advance(pC, pT);
346 tk = token_type(pT);
347 if(strcmp(pT, "int") == 0 || strcmp(pT, "char") == 0 || strcmp(pT, "boolean") == 0 || strcmp(pT, "Array") == 0)
349 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
351 } else if (tk == IDENTIFIER) { /* could also be a custom class name */
352 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
353 } else {
354 compiler_error(17, "Could Not Complete Variable List of Subroutine. Incomplete Program", pS, pC, pT);
358 /* look for identifier(s) for variable(s) */
359 do {
360 if(has_more_tokens(pC) == true)
362 pC = advance(pC, pT);
363 tk = token_type(pT);
364 } else {
365 compiler_error(17, "Could Not Complete Variable List of Subroutine. Incomplete Program", pS, pC, pT);
367 if(tk == IDENTIFIER)
369 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
372 if(has_more_tokens(pC) == true)
374 pC = advance(pC, pT);
375 tk = token_type(pT);
376 } else {
377 compiler_error(17, "Could Not Complete Variable List of Subroutine. Incomplete Program", pS, pC, pT);
379 if(tk == SYMBOL)
381 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
383 } while (*pT == ',');
385 if(has_more_tokens(pC) == true)
387 pC = advance(pC, pT);
388 tk = token_type(pT);
389 } else {
390 compiler_error(17, "Could Not Complete Variable List of Subroutine. Incomplete Program", pS, pC, pT);
392 parse_var_dec();
395 void parse_statements()
397 if(strcmp(pT, "let") == 0)
399 parse_let();
400 } else if(strcmp(pT, "if") == 0)
402 parse_if();
403 } else if(strcmp(pT, "while") == 0)
405 parse_while();
406 } else if(strcmp(pT, "do") == 0)
408 parse_do();
409 } else if(strcmp(pT, "return") == 0)
411 parse_return();
415 void parse_do()
417 if(settings.tokens) { printf("<doStatement>\n\t<keyword>do</keyword>\n"); }
418 if(has_more_tokens(pC) == true)
420 pC = advance(pC, pT);
421 tk = token_type(pT);
422 } else {
423 compiler_error(20, "Could Not Complete Do Statement. Incomplete Program", pS, pC, pT);
426 /* must be an identifier */
427 if(tk == IDENTIFIER) {
428 parse_subroutine_call();
429 } else {
430 compiler_error(30, "Subroutine Name Must Be Listed Here", pS, pC, pT);
433 if(settings.tokens) { printf("</doStatement>\n"); }
436 void parse_let()
438 if(settings.tokens) { printf("<letStatement>\n\t<keyword>let</keyword>\n"); }
439 if(has_more_tokens(pC) == true)
441 pC = advance(pC, pT);
442 tk = token_type(pT);
443 } else {
444 compiler_error(20, "Could Not Complete Let Statement. Incomplete Program", pS, pC, pT);
447 /* look for an identifier - must be a variable name */
448 if(tk == IDENTIFIER)
450 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
451 } else {
452 compiler_error(31, "Could Not Find Identifier At This Location", pS, pC, pT);
455 /* optional '[' for an array offset value */
456 if(has_more_tokens(pC) == true)
458 pC = advance(pC, pT);
459 tk = token_type(pT);
460 } else {
461 compiler_error(20, "Could Not Complete Let Statement. Incomplete Program", pS, pC, pT);
464 if(*pT == '[')
466 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
467 parse_expression();
470 if(*pT == ']')
472 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
475 /* look for '=' */
476 if(*pT == '=')
478 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
479 } else {
480 compiler_error(32, "Could Not Find '=' Symbol At This Location", pS, pC, pT);
483 /* parse_expression(); */
485 /* look for identifier */
486 if(has_more_tokens(pC) == true)
488 pC = advance(pC, pT);
489 tk = token_type(pT);
490 } else {
491 compiler_error(20, "Could Not Complete Let Statement. Incomplete Program", pS, pC, pT);
494 if(tk == IDENTIFIER)
496 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
497 } else {
498 compiler_error(20, "Could Not Find ';' Symbol At This Location", pS, pC, pT);
501 /* look for ';' */
502 if(has_more_tokens(pC) == true)
504 pC = advance(pC, pT);
505 tk = token_type(pT);
506 } else {
507 compiler_error(20, "Could Not Complete Let Statement. Incomplete Program", pS, pC, pT);
510 if(*pT == ';')
512 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
513 } else {
514 compiler_error(33, "Could Not Find ';' Symbol At This Location", pS, pC, pT);
517 if(settings.tokens) { printf("</letStatement>\n"); }
520 void parse_while()
523 exit_error(0, "Parsing While");
526 void parse_return()
528 if(settings.tokens) { printf("<returnStatement>\n\t<identifier>%s</identifier>\n", pT); }
530 /* look for ';' */
531 if(has_more_tokens(pC) == true)
533 pC = advance(pC, pT);
534 tk = token_type(pT);
535 } else {
536 compiler_error(20, "Could Not Complete Let Statement. Incomplete Program", pS, pC, pT);
539 if (*pT != ';') { parse_expression(); }
541 if(*pT == ';')
543 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
544 } else {
545 compiler_error(33, "Could Not Find ';' Symbol At This Location", pS, pC, pT);
547 if(settings.tokens) { printf("</returnStatement>\n"); }
550 void parse_if()
552 exit_error(0, "Parsing If");
555 void parse_expression()
557 parse_term();
559 if(has_more_tokens(pC) == true)
561 pC = advance(pC, pT);
562 tk = token_type(pT);
563 } else {
564 compiler_error(34, "Could Not Parse Expression. Incomplete Program", pS, pC, pT);
567 if(strchr(OP, *pT) != NULL)
569 if(settings.tokens) { printf("<operator>%s</operator>\n", pT); }
570 if(has_more_tokens(pC) == true)
572 pC = advance(pC, pT);
573 tk = token_type(pT);
574 } else {
575 compiler_error(34, "Could Not Parse Expression. Incomplete Program", pS, pC, pT);
577 parse_expression();
581 void parse_term()
583 if(tk == INT_CONST)
585 if(settings.tokens) { printf("<integerConst>%s</intConst>\n", pT); }
586 return;
589 if(strchr(UNARY_OP, *pT) != NULL)
591 if(settings.tokens) { printf("<unaryOperator>%s</unaryOperator>\n", pT); }
592 if(has_more_tokens(pC) == true)
594 pC = advance(pC, pT);
595 tk = token_type(pT);
596 parse_term();
597 } else {
598 compiler_error(25, "Could Not Complete Term. Incomplete Program", pS, pC, pT);
602 switch(*pT)
604 case '[':
605 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
606 parse_term();
607 if(has_more_tokens(pC) == true)
609 pC = advance(pC, pT);
610 tk = token_type(pT);
611 if(*pT == ']')
613 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
614 } else {
615 compiler_error(26, "Improperly Terminated Array Expression. Symbol ']' Required at this Location.", pS, pC, pT);
617 } else {
618 compiler_error(25, "Could Not Complete Term. Incomplete Program", pS, pC, pT);
620 break;
621 case '(':
622 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
623 if(has_more_tokens(pC) == true)
625 pC = advance(pC, pT);
626 tk = token_type(pT);
627 } else {
628 compiler_error(25, "Could Not Complete Term. Incomplete Program", pS, pC, pT);
630 parse_expression();
632 if (*pT == ')') {
633 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
634 } else {
635 compiler_error(38, "Could Not Find Symbol ')' At This Location", pS, pC, pT);
637 break;
638 case '.':
639 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
640 break;
641 default:
642 return;
646 void parse_subroutine_call()
648 if(settings.tokens) { printf("<subroutineCall>\n"); }
649 if(tk == IDENTIFIER)
651 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
652 } else {
653 compiler_error(35, "Could Not Find Class Name or Subroutine Name at This Location", pS, pC, pT);
656 if(has_more_tokens(pC) == true)
658 pC = advance(pC, pT);
659 tk = token_type(pT);
660 } else {
661 compiler_error(36, "Could Not Complete Subroutine Call. Incomplete Program", pS, pC, pT);
664 if (*pT == '.') {
665 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
666 if(has_more_tokens(pC) == true)
668 pC = advance(pC, pT);
669 tk = token_type(pT);
670 } else {
671 compiler_error(36, "Could Not Complete Subroutine Call. Incomplete Program", pS, pC, pT);
673 if(tk == IDENTIFIER)
675 if(settings.tokens) { printf("\t<identifier>%s</identifier>\n", pT); }
676 } else {
677 compiler_error(37, "Could Not Find Method Name or Subroutine Name at This Location", pS, pC, pT);
681 if(*pT != '(') /* this for calls with no class name at beginning */
683 if(has_more_tokens(pC) == true)
685 pC = advance(pC, pT);
686 tk = token_type(pT);
687 } else {
688 compiler_error(36, "Could Not Complete Subroutine Call. Incomplete Program", pS, pC, pT);
692 if(*pT == '(')
694 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
695 if(has_more_tokens(pC) == true)
697 pC = advance(pC, pT);
698 tk = token_type(pT);
699 } else {
700 compiler_error(36, "Could Not Complete Subroutine Call. Incomplete Program", pS, pC, pT);
702 parse_expr_lst();
704 if(*pT == ')')
706 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
707 if(has_more_tokens(pC) == true)
709 pC = advance(pC, pT);
710 tk = token_type(pT);
711 } else {
712 compiler_error(38, "Could Not Find Symbol ')' At This Location", pS, pC, pT);
715 } else {
716 compiler_error(39, "Could Not Find Symbol '(' At This Location", pS, pC, pT);
719 if(*pT == ';')
721 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
724 if(settings.tokens) { printf("<subroutineCall>\n"); }
727 void parse_expr_lst()
729 while(*pT != ')')
731 if(*pT == ',')
733 if(settings.tokens) { printf("\t<symbol>%s</symbol>\n", pT); }
734 if(has_more_tokens(pC) == true)
736 pC = advance(pC, pT);
737 tk = token_type(pT);
738 } else {
739 compiler_error(24, "Could Not Complete Expression List. Incomplete Program", pS, pC, pT);
741 } else {
742 parse_term();