/* * Production: Arithmetic Expression * FIRST set: { -, +, AVID_T, FPL_T, INL_T, ( } */ void arithmetic_expression(void) { switch (lookahead.code) { case ART_OP_T: /* The attribute must be MINUS or PLUS. */ switch (lookahead.attribute.arr_op) { case MINUS: case PLUS: unary_arithmetic_expression(); break; default: syn_printe(); return; } break; case AVID_T: case FPL_T: case INL_T: case LPR_T: additive_arithmetic_expression(); break; /* If nothing matches, print an error. */ default: syn_printe(); return; } gen_incode("PLATY: Arithmetic expression parsed"); }
/* FIRST(arithmetic expression)={-,+,AVID_T,FPL_T,INL_T,(} <arithmetic expression> - > <unary arithmetic expression> | <additive arithmetic expression> Author: Kwok Hong Kelvin Chan */ void arithmetic_expression(void){ switch(lookahead_token.code){ case AVID_T: case FPL_T: case INL_T: case LPR_T: additive_arithmetic_expression(); gen_incode("Arithmetic expression parsed"); break; case ART_OP_T: switch(lookahead_token.attribute.arr_op){ case MINUS: case PLUS: unary_arithmetic_expression(); gen_incode("Arithmetic expression parsed"); break; default: syn_printe(); break; } break; default: syn_printe(); break; } }
/* FIRST(statement)={AVID,SVID,IF,USING,INPUT,OUTPUT} <statement> -> <assignment statement> | <selection statement> | <iteration statement> | <input statement> | <output statement> Author: Kwok Hong Kelvin Chan */ void statement(void){ switch(lookahead_token.code){ case AVID_T: case SVID_T: assignment_statement(); break; case KW_T: switch(lookahead_token.attribute.get_int) { case IF: selection_statement(); break; case USING: iteration_statement(); break; case INPUT: input_statement(); break; case OUTPUT: output_statement(); break; default: syn_printe(); break; } break; default: syn_printe(); break; } }
/* FIRST(relational expression)={AVID_T, FPL_T,INL_T,SVID_T, STR_T} <relational expression> -> <primary a_relational expression> <p_operator> <primary a_relational expression> | <primary s_relational expression> <p_operator> <primary s_relational expression> Author: Kyle Hinskens */ void relational_expression(void){ switch(lookahead_token.code){ case AVID_T: case FPL_T: case INL_T: primary_a_relational_expression(); switch (lookahead_token.code){ case REL_OP_T: p_operator(); primary_a_relational_expression(); break; default : syn_printe(); } break; case SVID_T: case STR_T: primary_s_relational_expression(); switch (lookahead_token.code){ case REL_OP_T: p_operator(); primary_s_relational_expression(); break; default : syn_printe(); } break; default: syn_printe(); break; } gen_incode("Relational expression parsed"); }
/* * Purpose: Implement the panic recovery mode. * Author: Jason Macfarlane * History/Versions: 1.0 * Called functions: syn_printe(), mlwpar_next_token(), exit() * Parameters: int sync_token_code * Return value: STD * Algorithm: Print an error message and increment the number of errors. * If the token code is not SEOF, advance it to the next token. If the * new token matches the required token (sync_token_code), attempt to * advance the current token once more and return. Otherwise, exit the * program. */ void syn_eh(int sync_token_code) { /* Print an error and increment the error counter. */ syn_printe(); ++synerrno; /* * While the current token code is not equal to SEOF_T, advance * the current token and validate it. Repeat until the current * token code is equal to the required token code. */ while (lookahead.code != SEOF_T) { lookahead = mlwpar_next_token(sc_buf); if (lookahead.code == sync_token_code) { /* If the current token code is not SEOF_T, advance it to the next token. */ if (lookahead.code != SEOF_T) lookahead = mlwpar_next_token(sc_buf); return; } } /* * If the loop exists without returning, check if the * required token code is SEOF_T. If not, no match was * found. Exit with the number of errors. */ if (sync_token_code != SEOF_T) exit(synerrno); }
/* Purpose: Error handling function implementing simple panic mode. Author: Kyle Hinskens, Kwok Hong Kelvin Chan Version: 13.12.6 Called functions: syn_printe, mlwpar_next_token Parameters: int sync_token_code The token code Return value: None */ void syn_eh(int sync_token_code) { /* First, the function calls syn_printe() and increments the error counter. Then the function implements a panic mode error recovery: the function advances the input token (lookahead_token) until it finds a token code matching the one required by the parser (pr_token_code passed to the function as sync_token_code). */ syn_printe(); ++synerrno; /* It is possible, when advancing, that the function can reach the end of the source file without finding the matching token. To prevent from overrunning the input buffer, before every move the function checks if the end of the file is reached. If the function looks for sync_token_code different from SEOF_T and reaches the end of the source file, the function calls exit(synerrno). */ while (sync_token_code != lookahead_token.code) { if (sync_token_code != SEOF_T && lookahead_token.code == SEOF_T) { exit(synerrno); } lookahead_token = mlwpar_next_token(sc_buf); } /* If a matching token is found and the matching token is not SEOF_T, the function advances the input token one more time and returns. If a matching token is found and the matching token is SEOF_T, the function returns. */ if (sync_token_code != SEOF_T) { lookahead_token = mlwpar_next_token(sc_buf); } }
/* * Production: Relational Expression - String - (P) * FIRST set: { ==, <>, >, < } */ void relational_expression_s_p(void) { /* If the current code is not REL_OP_T (relational operator), print an error and return. */ if (lookahead.code != REL_OP_T) { syn_printe(); return; } match(lookahead.code, lookahead.attribute.arr_op); primary_s_relational_expression(); }
/* FIRST(variable identifier)={AVID_T, SVID_T} <variable identifier> -> AVID_T | SVID_T Author: Kwok Hong Kelvin Chan */ void variable_identifier(void) { switch(lookahead_token.code) { case AVID_T: match(AVID_T, NO_ATTR); break; case SVID_T: match(SVID_T, NO_ATTR); break; default: syn_printe(); break; } }
/* * Production: Variable Identifier * FIRST set: { AVID_T, SVID_T } */ void variable_identifier(void) { switch (lookahead.code) { case AVID_T: /* Arithmetic variable identifier token */ case SVID_T: /* String variable identifier token */ match(lookahead.code, NO_ATTR); return; /* If the token code is not AVID_T or SVID_T, print an error. */ default: syn_printe(); return; } }
/* * Production: Statement * FIRST set: { AVID_T, SVID_T, KW_T (only IF, USING, INPUT, OUTPUT) } */ void statement(void) { switch (lookahead.code) { case AVID_T: case SVID_T: assignment_statement(); return; case KW_T: /* The token attribute must be IF, INPut, OUTPUT or USING */ switch (lookahead.attribute.kwt_idx) { case IF: selection_statement(); return; case INPUT: input_statement(); return; case OUTPUT: output_statement(); return; case USING: iteration_statement(); return; /* If the keyword token does not match the above, print an error and return. */ default: syn_printe(); return; } /* If nothing matches, print an error. */ default: syn_printe(); return; } }
/* * Production: Unary Arithmetic Expression * FIRST set: { -, + } */ void unary_arithmetic_expression(void) { switch (lookahead.code) { case ART_OP_T: /* Arithmetic operator token */ /* The current token attribute must be MINUS or PLUS. */ switch (lookahead.attribute.arr_op) { case MINUS: case PLUS: match(lookahead.code, lookahead.attribute.arr_op); primary_arithmetic_expression(); gen_incode("PLATY: Unary arithmetic expression parsed"); return; /* If the token attribute is not MINUS or PLUS, print an error. */ default: syn_printe(); return; } /* If the token code is not ART_OP_T, print an error. */ default: syn_printe(); return; } }
/* FIRST(primary string expression={SVID_T, STR_T} <primary string expression> -> SVID_T | STR_T Author: Kyle Hinskens */ void primary_string_expression(void){ switch(lookahead_token.code){ case SVID_T: match(SVID_T, NO_ATTR); gen_incode("Primary string expression parsed"); break; case STR_T: match(STR_T, NO_ATTR); gen_incode("Primary string expression parsed"); break; default: syn_printe(); break; } }
/* * Production: Primary String Expression * FIRST set: { SVID_T, STR_T } */ void primary_string_expression(void) { switch (lookahead.code) { case STR_T: case SVID_T: match(lookahead.code, NO_ATTR); break; /* If the current token code is not STR_T or SVID_T, print an error. */ default: syn_printe(); break; } gen_incode("PLATY: Primary string expression parsed"); }
/* * Production: Primary Arithmetic Relational Expression * FIRST set: { AVID_T, FPL_T, INL_T } */ void primary_a_relational_expression(void) { switch (lookahead.code) { case AVID_T: case FPL_T: case INL_T: match(lookahead.code, lookahead.attribute.rel_op); break; /* If the current token code is not AVID_T, FPL_T or INL_T, print an error. */ default: syn_printe(); break; } gen_incode("PLATY: Primary a_relational expression parsed"); }
/* FIRST(unary arithmetic expression)={-,+} <unary arithmetic expression> -> - <primary arithmetic expression> | + <primary arithmetic expression> Author: Kyle Hinskens */ void unary_arithmetic_expression(void){ switch(lookahead_token.attribute.arr_op){ case MINUS: match(ART_OP_T,MINUS); primary_arithmetic_expression(); gen_incode("Unary arithmetic expression parsed"); break; case PLUS: match(ART_OP_T,PLUS); primary_arithmetic_expression(); gen_incode("Unary arithmetic expression parsed"); break; default: syn_printe(); break; } }
/* FIRST(primary a_relational expression)={AVID_T, FPL_T,INL_T} <primary a_relational expression> -> AVID_T | FPL_T | INL_T Author: Kyle Hinskens */ void primary_a_relational_expression(void){ switch(lookahead_token.code){ case AVID_T: match(AVID_T, NO_ATTR); break; case FPL_T: match(FPL_T, NO_ATTR); break; case INL_T: match(INL_T, NO_ATTR); break; default: syn_printe(); break; } gen_incode("Primary a_relational expression parsed"); }
/* * Purpose: Match two tokens: the current input token and the required token. * Author: Jason Macfarlane * History/Versions: 1.0 * Called functions: syn_printe(), mlwpar_next_token(), syn_eh() * Parameters: int pr_token_code, int pr_token_attribute * Algorithm: If the required token code matches the current code, check the types. * If the required token code is ART_OP_T, KW_T, LOG_OP_T or REL_OP_T, check if * the attributes from both token codes match. If not, break. Otherwise, advance * the input token (lookahead). Check for errors and invalid codes. */ void match(int pr_token_code, int pr_token_attribute) { /* If the required token code matches the current code, enter panic mode and return. */ if (pr_token_code != lookahead.code) { syn_eh(pr_token_code); return; } /* Verify the token code. */ switch (pr_token_code) { case ART_OP_T: /* Arithmetic operator token */ case KW_T: /* Keyword token */ case LOG_OP_T: /* Logical operator token */ case REL_OP_T: /* Relational operator token */ /* * If the required token attribute doesn't match the * current attribute, enter panic more and return. */ if (pr_token_attribute != lookahead.attribute.get_int) { syn_eh(pr_token_code); return; } default: /* If the current token code matches SEOF, return. */ if (lookahead.code == SEOF_T) return; /* Advance to the next token. */ lookahead = mlwpar_next_token(sc_buf); /* * If the current token code matches ERR_T, print an error, advance * the token and increment the error counter. */ if (lookahead.code == ERR_T) { syn_printe(); lookahead = mlwpar_next_token(sc_buf); ++synerrno; } return; } }
/* FIRST(assignment expression)={AVID ,SVID} <assignment expression> -> AVID = <arithmetic expression> | SVID = <string expression> Author: Kwok Hong Kelvin Chan */ void assignment_expression(void){ switch(lookahead_token.code){ case AVID_T: match(AVID_T, NO_ATTR); match(ASS_OP_T, NO_ATTR); arithmetic_expression(); gen_incode("Assignment expression (arithmetic) parsed"); break; case SVID_T: match(SVID_T, NO_ATTR); match(ASS_OP_T, NO_ATTR); string_expression(); gen_incode("Assignment expression (string) parsed"); break; default: syn_printe(); break; } }
/* Purpose: Matches two tokens: the current input token (lookahead_token) and the token required by the parser. Author: Kyle Hinskens, Kwok Hong Kelvin Chan Version: 13.12.6 Called functions: syn_eh, mlwpar_next_token Parameters: int pr_token_code The token code int pr_token_attribute The token attribute Return value: None */ void match(int pr_token_code, int pr_token_attribute) { int matched = 0; /* The attribute code is used only when the token code is one of the following codes: KW_T, LOG_OP_T, ART_OP_T, REL_OP_T. In all other cases the token code is matched only. */ if (lookahead_token.code == pr_token_code) { switch(pr_token_code) { case KW_T: case LOG_OP_T: case ART_OP_T: case REL_OP_T: if (lookahead_token.attribute.get_int == pr_token_attribute) matched = 1; break; default: matched = 1; break; } } /* If the match is successful and the lookahead_token is SEOF_T, the function returns. */ if (matched) { if (lookahead_token.code == SEOF_T) return; /* If the match is successful and the lookahead_token is not SEOF_T, the function advances to the next input token */ lookahead_token = mlwpar_next_token(sc_buf); /* If the new lookahead token is ERR_T, the function calls the error printing function */ if (lookahead_token.code == ERR_T) { syn_printe(); lookahead_token = mlwpar_next_token(sc_buf); /* Advance to the next input token */ ++synerrno; return; } } else { /* If the match is unsuccessful, the function calls the error handler and returns. */ syn_eh(pr_token_code); return; } }
/* FIRST(statements)={AVID,SVID,IF,USING,INPUT,OUTPUT} <statements> -> <statement><statements'> Author: Kwok Hong Kelvin Chan */ void statements(void){ switch(lookahead_token.code){ case AVID_T: case SVID_T: statement(); statements_p(); break; case KW_T: if (lookahead_token.attribute.get_int == IF || lookahead_token.attribute.get_int == USING || lookahead_token.attribute.get_int == INPUT || lookahead_token.attribute.get_int == OUTPUT) { statement(); statements_p(); } break; default: syn_printe(); break; } }
/* * Production: Primary Arithmetic Expression * FIRST set: { AVID_T, FPL_T, INL_T, ( } */ void primary_arithmetic_expression(void) { switch (lookahead.code) { case AVID_T: case FPL_T: case INL_T: match(lookahead.code, lookahead.attribute.rel_op); break; case LPR_T: match(LPR_T, lookahead.attribute.arr_op); arithmetic_expression(); match(RPR_T, NO_ATTR); break; /* If nothing matches, print an error. */ default: syn_printe(); break; } gen_incode("PLATY: Primary arithmetic expression parsed"); }
/* FIRST(p_operator)={==,!=,>,<} <operator> -> == | != | > | < Author: Kwok Hong Kelvin Chan */ void p_operator(void){ switch(lookahead_token.code){ case REL_OP_T: switch (lookahead_token.attribute.rel_op){ case EQ: match(REL_OP_T, EQ); break; case NE: match(REL_OP_T, NE); break; case GT: match(REL_OP_T, GT); break; case LT: match(REL_OP_T, LT); break; default: syn_printe(); break; } } }
/* * Production: Relational Expression * FIRST set: { AVID_T, FPL_T, INL_T, SVID_T, STR_T } */ void relational_expression(void) { switch (lookahead.code) { case AVID_T: case FPL_T: case INL_T: primary_a_relational_expression(); relational_expression_a_p(); break; case STR_T: case SVID_T: primary_s_relational_expression(); relational_expression_s_p(); break; /* If nothing matches, print an error. */ default: syn_printe(); break; } gen_incode("PLATY: Relational expression parsed"); }
/* * Production: Assignment Expression * FIRST set: { AVID, SVID } */ void assignment_expression(void) { 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"); return; case SVID_T: match(SVID_T, NO_ATTR); match(ASS_OP_T, NO_ATTR); string_expression(); gen_incode("PLATY: Assignment expression (string) parsed"); return; /* If the current token code is not AVID or SVID, print an error. */ default: syn_printe(); return; } }
/* FIRST(primary arithmetic expression)={AVID_T, FPL_T ,INL_T ,(} <primary arithmetic expression> -> AVID_T | FPL_T | INL_T | (<arithmetic expression>) Author: Kwok Hong Kelvin Chan */ void primary_arithmetic_expression(void){ switch(lookahead_token.code){ case LPR_T: match(LPR_T, NO_ATTR); arithmetic_expression(); match(RPR_T, NO_ATTR); break; case AVID_T: match(AVID_T, NO_ATTR); break; case FPL_T: match(FPL_T, NO_ATTR); break; case INL_T: match(INL_T, NO_ATTR); break; default: syn_printe(); break; } gen_incode("Primary arithmetic expression parsed"); }