From d22d2718a039cd673e461d03721de532849d09d0 Mon Sep 17 00:00:00 2001 From: Victor Fernandes Date: Fri, 21 Apr 2017 23:26:25 -0400 Subject: [PATCH] AAAAAAAAAAAAAAA --- parser.c | 868 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.h | 71 +++++ 2 files changed, 939 insertions(+) create mode 100644 parser.c create mode 100644 parser.h diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..689b193 --- /dev/null +++ b/parser.c @@ -0,0 +1,868 @@ +/* File Name: parser.c + * The PLATYPUS parsing program for the final assignment of + How To Train Your Dragon (AKA Compilers) + * Author: Victor Fernandes, 040772243 + * Course: CST8152 - Compilers, Lab Section: 011 + * Date: April 21, 2017 + * Professor: Svillen Ravev + * Version: 0.1 + */ + +#include "parser.h" + +/* Global variables for the parser */ + Token lookahead; + extern int synerrno; /* Error counter */ + extern char* kw_table[]; /* Keyword table with matching enum */ + extern STD sym_table; /* The symbol table */ + extern Buffer* sc_buf; /* Scanner buffer */ + extern Buffer* str_LTBL; /* String literal table */ + extern int line /* Line position of the Scanner */ + + +/* Begins the source file parsing + * Author: Victor Fernandes, 040772243 + * Version: 0.0.1 + * Called functions: malar_next_token, program, match, gen_incode + * Parameters: pBuffer - The input buffer + * Return value: N/A + */ +void parser(pBuffer in_buf) +{ + sc_buf = in_buf; + lookahead = malar_next_token(sc_buf); + program(); + match(SEOF_T, NO_ATTR); + gen_incode("PLATY: Source file parsed"); +} + +/* Matches the given token code+attribute pair to the current lookahead token + * Author: Victor Fernandes, 040772243 + * Version: 0.0.1 + * Called functions: syn_eh, syn_printe, malar_next_token + * Parameters: pr_token_code, pr_token_attribute + * Return value: + * Algorithm: + */ +void match(int pr_token_code, int pr_token_attribute) +{ + if (pr_token_code != lookahead.code) + { + syn_eh(pr_token_code); + return; + } + + switch (pr_token_code) + { + case ART_OP_T: + case REL_OP_T: + case LOG_OP_T: + case KW_T: + if (pr_token_attribute != lookahead.attribute.get_int) + { + break; + } + default: + if (lookahead.code == SEOF_T) + return; + lookahead = malar_next_token(sc_buf); + if (lookahead.code == ERR_T) + { + synerrno++; + syn_printe(); + lookahead = malar_next_token(sc_buf); + } + return; + } + syn_eh(pr_token_code); +} + +/* Error "recovery" function for the parser + * Author: Victor Fernandes, 040772243 + * Version: 0.0.1 + * Called functions: syn_printe, malar_next_token, exit + * Parameters: int pr_token_code + * Return value: + * Algorithm: Outputs a standard syn_printe error, and steps through + the source file with the Scanner until it finds the next matching + code needed by pr_token_code. + */ +void syn_eh(int pr_token_code) +{ + syn_printe(); + synerrno++; + + while (lookahead.code != SEOF_T) + { + lookahead = malar_next_token(sc_buf); + if (lookahead.code == pr_token_code) + { + if (lookahead.code != SEOF_T) + { + lookahead = malar_next_token(sc_buf); + } + return; + } + } + + if (pr_token_code != SEOF_T) + exit(synerrno); +} + +/* Outputs an error message to stdout using the current lookahead token + * Author: Victor Fernandes, 040772243 + * Version: 0.0.1 + * Called functions: printf, b_setmark + * Parameters: N/A + */ +void syn_printe() +{ + printf("PLATY: Syntax error: Line:%3d\n" + "***** Token code: %3d Attribute: ", line, lookahead.code); + switch (lookahead.code) + { + case ERR_T: + printf("%s\n", lookahead.attribute.err_lex); + break; + case SEOF_T: + printf("NA\n"); + break; + case AVID_T: + case SVID_T: + printf("%s\n", sym_table.pstvr[lookahead.attribute.get_int].plex); + break; + case FPL_T: + printf("%5.1f\n", lookahead.attribute.flt_value); + break; + case INL_T: + printf("%d\n", lookahead.attribute.get_int); + break; + case STR_T: + printf("%s\n", b_setmark(str_LTBL, lookahead.attribute.str_offset)); + break; + case SCC_OP_T: + printf("NA\n"); + break; + case ASS_OP_T: + printf("NA\n"); + break; + case ART_OP_T: + printf("%d\n", lookahead.attribute.get_int); + break; + case REL_OP_T: + printf("%d\n", lookahead.attribute.get_int); + break; + case LOG_OP_T: + printf("%d\n", lookahead.attribute.get_int); + break; + case LPR_T: + printf("NA\n"); + break; + case RPR_T: + printf("NA\n"); + break; + case LBR_T: + printf("NA\n"); + break; + case RBR_T: + printf("NA\n"); + break; + case KW_T: + printf("%s\n", kw_table[lookahead.attribute.get_int]); + break; + case COM_T: + printf("NA\n"); + break; + case EOS_T: + printf("NA\n"); + break; + default: + printf("PLATY: Scanner error: invalid token code: %d\n", lookahead.code); + } +} + +/* Generates a message to stdout (can be later modified to generate C code) + * Author: Victor Fernandes, 040772243 + * Version: 0.0.1 + * Called functions: printf + * Parameters: char* code + * Return value: N/A + */ +void gen_incode(char *code) +{ + printf("%s\n", code); +} + +/* + * Grammar functions ahoy + */ + + +/* + * -> + + FIRST Set = {AVID_T, FPL_T, INL_T, (} + */ +void additive_arithmetic_expression() +{ + multiplicative_arithmetic_expression(); + additive_arithmetic_expression_prime(); +} + +/* + * -> + + FIRST Set = {AVID_T, FPL_T, INL_T, (} + */ +void additive_arithmetic_expression_prime() +{ + if (lookahead.code == ART_OP && + lookahead.attribute.arr_op != MULT && + lookahead.attribute.arr_op != DIV) + { + match(lookahead.code, lookahead.attribute.arr_op); + multiplicative_arithmetic_expression(); + additive_arithmetic_expression_prime(); + gen_incode("PLATY: Additive arithmetic expression parsed"); + } +} + +/* + * | + + FIRST Set = {-, +, AVID_T, FPL_T, INL_T, (} + */ +void arithmetic_expression() +{ + switch (lookahead.code) + { + case ART_OP_T: + switch (lookahead.attribute.arr_op) + { + case MULT: + case DIV: + syn_printe(); + return; + } + unary_arithmetic_expression(); + break; + case AVID_T: + case FPL_T: + case INL_T: + case LPR_T: + additive_arithmetic_expression(); + break; + case EOS_T: + return; + default: + syn_printe(); + return; + } + gen_incode("PLATY: Arithmetic expression parsed"); +} + +/* + * -> + AVID = | SVID = + FIRST Set = {AVID, SVID} + */ +void assignment_expression() +{ + switch (lookahead.code) + { + case AVID_T: + match(AVID_T, NO_ATTR); + match(ASS_OP_T, NO_ATTR); + arithmetic_expression(); + gen_incode("PLATY: Assignment expression (arithmetic) parsed"); + break; + case SVID_T: + match(SVID_T, NO_ATTR); + match(ASS_OP_T, NO_ATTR); + string_expression(); + gen_incode("PLATY: Assignment expression (string) parsed"); + break; + default: + syn_printe(); + } +} + +/* + * -> + ; + FIRST Set = {AVID, SVID} + */ +void assignment_statement() +{ + assignment_expression(); + match(EOS_T, NO_ATTR); + gen_incode("PLATY: Assignment statement parsed"); +} + +/* + * -> + + FIRST Set = {AVID_T, SVID_T, INL_T, SVID_T, STR_T} + */ +void conditional_expression() +{ + logical_or_expression(); + gen_incode("PLATY: Conditional expression parsed"); +} + +/* + * -> + INPUT ( ); + FIRST Set = {INPUT} + */ +void input_statement() +{ + match(KW_T, INPUT); + match(LPR_T, NO_ATTR); + variable_list(); + match(RPR_T, NO_ATTR); + match(EOS_T, NO_ATTR); + gen_incode("PLATY: Input statement parsed"); +} + +/* + * -> + USING ( , , ) REPEAT { } ; + FIRST Set = {USING} + */ +void iteration_statement() +{ + match(KW_T, USING); + match(LPR_T, NO_ATTR); + assignment_expression(); + match(COM_T, NO_ATTR); + assignment_expression(); + match(RPR_T, NO_ATTR); + match(KW_T, REPEAT); + match(LBR_T, NO_ATTR); + opt_statements(); + match(RBR_T, NO_ATTR); + match(EOS_T, NO_ATTR); + gen_incode("PLATY: USING statement parsed"); +} + +/* + * -> + + FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T} + */ +void logical_and_expression() +{ + relational_expression(); + logical_and_expression_prime(); +} + +/* + * -> + .AND. | E + FIRST Set = { .AND., E} + */ +void logical_and_expression_prime() +{ + if (lookahead.code == LOG_OP_T && + lookahead.attribute.log_op == AND) + { + match(LOG_OP_T, AND); + relational_expression(); + logical_and_expression_prime(); + gen_incode("PLATY: Logical AND expression parsed"); + } +} + +/* + * -> + + FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T} + */ +void logical_or_expression() +{ + logical_and_expression(); + logical_or_expression_prime(); +} + +/* + * -> + .OR. + FIRST Set = { .OR., E } + */ +voic logical_or_expression_prime() +{ + if (lookahead.code == LOG_OP_T && + lookahead.attribute.log_op == OR) + { + logical_and_expression(); + logical_or_expression_prime(); + gen_incode("PLATY: Logical OR expression parsed"); + } +} + +/* + * -> + + FIRST Set = {AVID_T, FPL_T, INL_T, (} + */ +void multiplicative_arithmetic_expression() +{ + primary_arithmetic_expression(); + multiplicative_arithmetic_expression_prime(); +} + +/* + * -> + + FIRST Set = {*, /, E} + */ +void multiplicative_arithmetic_expression_prime() +{ + if (lookahead.code == ART_OP_T && + lookahead.attribute.arr_op != PLUS && + lookahead.attribute.arr_op != MINUS) + { + match(lookahead.code, lookahead.attribute.arr_op); + primary_arithmetic_expression(); + multiplicative_arithmetic_expression_prime(); + gen_incode("PLATY: Multiplicative arithmetic expression parsed"); + } +} + +/* + * -> + | E + FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT, E} + */ +void opt_statements() +{ + switch (lookahead.code) + { + case KW_T: + switch (lookahead.attribute.kwt_idx) + { + case PLATYPUS: + case ELSE: + case THEN: + case REPEAT: + gen_incode("PLATY: Opt_statements parsed"); + return; + } + case AVID_T: + case SVID_T: + statements() : break; + default: + gen_incode("PLATY: Opt_statements parsed"); + } +} + +/* + * -> + OUTPUT ( ); + + -> + | + + FIRST() = {OUTPUT} + FIRST Set = {AVID_T, SVID_T, E} + + This can be done in one function + */ +void output_statement() +{ + match(KW_T, OUTPUT); + match(LPR_T, NO_ATTR); + + switch (lookahead.code) + { + case AVID_T: + case SVID_T: + variable_list(); + break; + case STR_T: + match(STR_T, NO_ATTR); + gen_incode("PLATY: Output list (string literal) parsed"); + break; + default: + gen_incode("PLATY: Output list (empty) parsed"); + } + match(RPR_T, NO_ATTR); + match(EOS_T, NO_ATTR); + gen_incode("PLATY: OUTPUT statement parsed"); +} + +/* + * -> + AVID_T | FPL_T | INL_T + FIRST Set = {AVID_T, FPL_T, INL_T} + */ +void primary_a_relational_expression() +{ + switch (lookahead.code) + { + case AVID_T: + case FPL_T: + case INL_T: + match(lookahead.code, NO_ATTR); + break; + case LOG_OP_T: + break; + default: + syn_printe(); + } + gen_incode("PLATY: Primary a_relational expression parsed"); +} + +/* + * -> + AVID_T | FPL_T | INL_T | ( ) + FIRST Set = {AVID_T, FPL_T, INL_T, (} + */ +void primary_arithmetic_expression() +{ + switch (lookahead.code) + { + case AVID_T: + case FPL_T: + case INL_T: + match(lookahead.code, lookahead.attribute.arr_op); + break; + case LPR_T: + match(lookahead.code, lookahead.attribute,arr_op); + arithmetic_expression(); + match(RPR_T, NO_ATTR); + default: + syn_printe(); + return; + } + gen_incode("PLATY: Primary arithmetic expression parsed"); +} + +/* + * -> + + FIRST Set = {SVID_T, STR_T} + */ +void primary_s_relational_expression() +{ + switch (lookahead.code) + { + case SVID_T: + case AVID_T: + primary_string_expression(); + break; + default: + syn_printe(); + } + gen_incode("PLATY: Primary s_relational expression parsed"); +} + +/* + * -> + SVID_T | STR_T + FIRST Set = {SVID_T, STR_T} + */ +void primary_string_expression() +{ + switch (lookahead.code) + { + case SVID_T: + case STR_T: + match(lookahead.code, NO_ATTR); + break; + default: + syn_printe(); + } + gen_incode("PLATY: Primary string expression parsed"); +} + +/* + * -> + PLATYPUS { } + FIRST Set = {PLATYPUS} + */ +void program() +{ + match(KW_T, PLATYPUS); + match(LBR_T, NO_ATTR); + opt_statements(); + match(RBR_T, NO_ATTR); + gen_incode("PLATY: Program parsed"); +} + +/* + * -> + + | + FIRST Set = {AVID_T, FPL_T, INL_T, SVID_T, STR_T} + */ +void relational_expression() +{ + switch (lookahead.code) + { + case AVID_T: + case FPL_T: + case INL_T: + primary_a_relational_expression(); + relational_expression_prime(); + break; + case SVID_T: + case STR_T: + primary_s_relational_expression(); + relational_expression_prime_string(); + break; + default: + syn_printe(); + } + gen_incode("PLATY: Relational expression parsed"); +} + +/* + * -> + == + | <> + | > + | < + FIRST Set = { ==, <>, >, <} + */ +void relational_expression_prime() +{ + if (lookahead.code == REL_OP_T) + { + switch (lookahead.attribute.rel_op) + { + case EQ: + case NE: + case GT: + case LT: + match(lookahead.code, lookahead.attribute.arr_op); + primary_a_relational_expression(); + return; + } + } + syn_printe(); +} + +/* + * -> + == + | <> + | > + | < + FIRST Set = {==, <>, >, <} + */ +void relational_expression_prime_string() +{ + if (lookahead.code == REL_OP_T) + { + switch (lookahead.attribute.rel_op) + { + case EQ: + case NE: + case GT: + case LT: + match(lookahead.codem, lookahead.attribute.arr_op); + primary_s_relational_expression(); + return; + } + } + syn_printe(); +} + +/* + * -> + IF ( ) THEN ELSE { } ; + FIRST Set = {IF} + */ +void selection_statement() +{ + match(KW_T, IF); + match(LPR_T, NO_ATTR); + conditional_expression(); + match(RPR_T, NO_ATTR); + match(KW_T, THEN); + opt_statements(); + match(KW_T, ELSE); + match(LBR_T, NO_ATTR); + opt_statements(); + match(RBR_T, NO_ATTR); + match(EOS_T, NO_ATTR); + gen_incode("PLATY: IF statement parsed"); +} + +/* + * -> + + | + | + | + | + FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT} + */ +void statement() +{ + switch (lookahead.code) + { + case AVID_T: + case SVID_T: + assignment_statement(); + break; + case KW_T: + switch (lookahead.attribute.kwt_idx) + { + case IF: + selection_statement(); + break; + case USING: + iteration_statement(); + break; + case INPUT: + input_statement(); + break; + case OUTPUT: + output_statement(); + break; + default: + syn_printe(); + } + break; + default: + syn_printe(); + } +} + +/* + * -> + + FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT} + */ +void statements() +{ + statement(); + statements_prime(); +} + +/* + * -> + | E + FIRST Set = {AVID_T, SVID_T, IF, USING, INPUT, OUTPUT} + */ +void statements_prime() +{ + switch (lookahead.code) + { + case KW_T: + switch (lookahead.attribute.kwt_idx) + { + case PLATYPUS: + case ELSE: + case THEN: + case REPEAT: + return; + } + case AVID_T: + case SVID_T: + statement(); + statements_prime(); + break; + } +} + +/* + * -> + + FIRST Set = {SVID_T, STR_T} + */ +void string_expression() +{ + primary_string_expression(); + string_expression_prime(); + gen_incode("PLATY: String expression parsed"); +} + +/* + * + << | E + FIRST Set = {<< , E} + */ +void string_expression_prime() +{ + if (lookahead.code == SCC_OP_T) + { + match(SCC_OP_T, NO_ATTR); + primary_string_expression(); + stirng_expression_prime(); + } +} + +/* + * -> + - + | + + FIRST Set = {-, +} + */ +void unary_arithmetic_expression() +{ + switch (lookahead.code) + { + case ART_OP_T: + switch (lookahead.attribute.arr_op) + { + case MULT: + case DIV: + syn_printe(); + return; + } + match(lookahead.code, lookahead.attribute.arr_op); + primary_arithmetic_expression(); + gen_incode("PLATY: Unary arithmetic expression parsed"); + break; + default: + syn_printe(); + return; + } +} + +/* + * -> + AVID_T | SVID_T + FIRST Set = {AVID_T, SVID_T} + */ +void variable_identifier() +{ + switch (lookahead.code) + { + case AVID_T: + case SVID_T: + match(lookahead.code, NO_ATTR); + break; + default: + syn_printe(); + } +} + +/* + * -> + + FIRST Set = {AVID_T, SVID_T} + */ +void variable_list() +{ + variable_identifier(); + variable_list_prime(); + gen_incode("PLATY: Variable list parsed"); +} + +/* + * -> + , | E + FIRST Set = {AVID_T, SVID_T, E} + */ +void variable_list_prime() +{ + if (lookahead.code != COM_T) + return; + match(COM_T, NO_ATTR); + variable_identifier(); + variable_list_prime(); +} diff --git a/parser.h b/parser.h new file mode 100644 index 0000000..3fdc711 --- /dev/null +++ b/parser.h @@ -0,0 +1,71 @@ +/* File Name: parser.h + * Parser function definitions for the PLATYPUS Compiler + * Author: Victor Fernandes, 040772243 + * Course: CST8152 - Compilers, Lab Section: 011 + * Date: April 17, 2017 + * Professor: Svillen Ravev + * Version: 0.1 + */ +#ifndef PARSER_H_ +#define PARSER_H_ + +#include "token.h" +#include "stable.h" +#include "buffer.h" + +/* Keyword enum to match kw_table in table.h */ +enum kw { + NO_ATTR = -1, + ELSE, + IF, + INPUT, + OUTPUT, + PLATYPUS, + REPEAT, + THEN, + USING +}; + +/* Main parser functions */ + void parser(Buffer* const); + void gen_incode(char*); + void match(int, int); + void syn_eh(int); + void syn_printe(void); + + /* Literally the entire grammar */ +void additive_arithmetic_expression(void); +void additive_arithmetic_expression_prime(void); +void arithmetic_expression(void); +void assignment_expression(void); +void assignment_statement(void); +void conditional_expression(void); +void input_statement(void); +void iteration_statement(void); +void logical_and_expression(void); +void logical_and_expression_prime(void); +void logical_or_expression(void); +void logical_or_expression_prime(void); +void multiplicative_arithmetic_expression(void); +void multiplicative_arithmetic_expression_prime(void); +void opt_statements(void); +void output_statement(void); +void primary_a_relational_expression(void); +void primary_arithmetic_expression(void); +void primary_s_relational_expression(void); +void primary_string_expression(void); +void program(void); +void relational_expression(void); +void relational_expression_prime(void); +void relational_expression_prime_string(void); +void selection_statement(void); +void statement(void); +void statements(void); +void statements_prime(void); +void string_expression(void); +void unary_arithmetic_expression(void); +void variable_identifier(void); +void variable_list(void); +void variable_list_prime(void); + +#endif