Files
compiler-the-translators/src/grammar.y
2025-04-25 13:01:31 -04:00

1143 lines
43 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Syntax Analyzer with Bison (3.8.2) */
/* The Translators - Spring 2025 */
// ----- THIS FILE MUST BE FORMATTED CORRECTLY FOR READABILITY ----- //
// ✏️ FORMATTING RULES:
// 1⃣ Use 4 spaces for indentation.
// 2⃣ Grammar rules (terminals and nonterminals) should always be on their own line.
// 3⃣ Grammar rules and C-blocks should always begin 8 spaces in.
// 4⃣ Rule end-markers (;, |) should always be 4 spaces in.
// 5⃣ C-blocks should always be clearly defined and follow clang formatting rules.
// 6⃣ 1-line if/for/while statements must be wrapped in curly braces.
// 7⃣ Comments should always be above rules
// 8⃣ DO NOT USE TABS. EVER.
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
%{
#include "../src/symbol_table.c"
void yyerror(const char *err);
extern FILE *asc_flag;
extern bool tc_flag;
int token_tracker;
TableNode * tn;
void error_type(TableNode * left, TableNode * right, const char *format, ...);
%}
%union {
int integ;
char* words;
char letter;
void* tn;
}
%locations
%type <integ> idlist
%type <tn> assignable
%type <tn> expression
%type <tn> constant
%type <tn> id_or_types
%type <tn> types
%type <tn> sblock
%type <tn> compound_statement
%type <tn> simple_statement
%type <tn> statement_list
%type <integ> argument_list
%type <integ> ablock
%token <words> ID 101
%token <tn> T_INTEGER 201
%token <tn> T_ADDRESS 202
%token <tn> T_BOOLEAN 203
%token <tn> T_CHARACTER 204
%token <tn> T_STRING 205
%token <integ> C_INTEGER 301
%token <tn> C_NULL 302
%token <tn> C_CHARACTER 303
%token <tn> C_STRING 304
%token <tn> C_TRUE 305
%token <tn> C_FALSE 306
%token WHILE 401
%token IF 402
%token THEN 403
%token ELSE 404
%token TYPE 405
%token FUNCTION 406
%token RETURN 407
%token EXTERNAL 408
%token AS 409
%token L_PAREN 501
%token R_PAREN 502
%token L_BRACKET 503
%token R_BRACKET 504
%token L_BRACE 505
%token R_BRACE 506
%token SEMI_COLON 507
%token COLON 508
%token COMMA 509
%token ARROW 510
%token MUL 603
%token DIV 604
%token REM 605
%token ADD 601
%token LESS_THAN 606
%token EQUAL_TO 607
%token AND 610
%token OR 611
%token ASSIGN 608
%token SUB_OR_NEG 602
%token NOT 609
%token DOT 612
%token RESERVE 613
%token RELEASE 614
%token COMMENT 700
//precedence order
%left ASSIGN
%left OR
%left AND
%left EQUAL_TO
%left LESS_THAN
%left ADD SUB_OR_NEG
%left MUL DIV REM
%precedence NOT
%precedence UMINUS
%precedence DOT
%precedence RESERVE RELEASE
%%
program:
prototype_or_definition_list
;
prototype_or_definition_list:
prototype prototype_or_definition_list
| definition prototype_or_definition_list
| prototype
| definition
;
prototype:
L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID;
definition:
TYPE ID COLON
{
printdebug("Currently see a record definition for %s", $2);
tn = CreateEntry(getAncestor(cur),TYPE_RECORD_TYPE, recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0)));
printdebug("Created a new scope");
//if (look_up(cur, $2) == undefined) {
// printdebug("rec not found");
//}
}
dblock
{
//We are scanning through the dblock scope to get the length of the dblock (num of elements) from getRecSize
//and then putting it in the entry that we created above.
setRecSize(look_up(getParent(cur), $2), getRecSize(cur));
//putting in all the offsets
setRecOffsetInfo(cur, look_up(getParent(cur),$2));
printdebug("Moving up a scope after seeing a record definition");
cur = getParent(cur);
}
| TYPE ID COLON C_INTEGER ARROW id_or_types
{
printdebug("Currently see a array definition of name %s,storing type %s, of dimensions %d", $2, getName((TableNode*)$6), $4);
CreateEntry(cur,TYPE_ARRAY_TYPE, arrayprim, $2, CreateArrayInfo($4, (TableNode*)$6));
printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, getName((TableNode*)$6));
}
| function_declaration
| TYPE ID COLON id_or_types ARROW id_or_types
{
printdebug("Currently see a function type definition of name %s,parameter type %s, of return type %s", $2, getName((TableNode*)$4), getName((TableNode*)$6));
CreateEntry(cur,TYPE_FUNCTION_TYPE,funtypeprime,$2,CreateFunctionTypeInfo((TableNode*)$4 ,(TableNode*)$6));
}
| ID {
printdebug("see function def rule 1\n");
TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) {
error_type(undefined, undefined, "Undefined node declared.");
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
error_type(undefined, undefined, "Not a valid function declaration.");
}
else {
printdebug("setting as keyword to true");
setStartLine(node, @1.first_line);
setAsKeyword(node, true);
}
cur = CreateScope(cur, 0, 0);
printdebug("Created a new scope");
} L_PAREN {
TableNode * parameter = getParameter(getTypeEntry(table_lookup(getAncestor(cur), $1)));
//TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1))));
printdebug("type of parameter: %s", getName(parameter));
if (parameter == undefined) {
error_type(undefined, undefined, "Undefined parameter in function definition.");
}else if(getAdInfoType(parameter) != TYPE_RECORD_TYPE){
int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h
if( type_of_param_type == TYPE_UNDEFINED
|| type_of_param_type == TYPE_FUNCTION_DECLARATION
|| type_of_param_type == TYPE_ARRAY
|| type_of_param_type == TYPE_PRIMITIVE
|| type_of_param_type == TYPE_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
error_type(parameter, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter));
type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
}
if(type_of_param_type == TYPE_UNDEFINED){
CreateEntry(cur,type_of_param_type, undefined, NULL, NULL);
} else {
if(type_of_param_type == TYPE_FUNCTION_TYPE){
CreateEntry(cur, TYPE_FUNCTION_DECLARATION, parameter,NULL, getAdInfo(parameter));
}
if(type_of_param_type == TYPE_ARRAY_TYPE){
CreateEntry(cur, TYPE_ARRAY, parameter,NULL, getAdInfo(parameter));
}
if(type_of_param_type == TYPE_PRIMITIVE_TYPE){
CreateEntry(cur, TYPE_PRIMITIVE, parameter,NULL, getAdInfo(parameter));
}
}
} else {
printdebug("record found");
for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){
int type_of_param_type = getAdInfoType(entry);
if( type_of_param_type == TYPE_UNDEFINED
|| type_of_param_type == TYPE_FUNCTION_TYPE
|| type_of_param_type == TYPE_ARRAY_TYPE
|| type_of_param_type == TYPE_PRIMITIVE_TYPE
|| type_of_param_type == TYPE_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD_TYPE
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
error_type(entry, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry));
type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
}else{
printdebug("type of parameter correctly being passed in to AS function definition is %s which is valid", getType(entry));
}
if(type_of_param_type == TYPE_UNDEFINED){
printdebug("undefined type of parameter inside record");
CreateEntry(cur,type_of_param_type, undefined, NULL, NULL);
} else {
if(type_of_param_type == TYPE_FUNCTION_DECLARATION){
printdebug("function declaration of parameter inside record");
CreateEntry(cur, TYPE_FUNCTION_DECLARATION, getTypeEntry(entry),NULL, getAdInfo(entry));
}
if(type_of_param_type == TYPE_ARRAY){
printdebug("array type of parameter inside record");
CreateEntry(cur, TYPE_ARRAY, getTypeEntry(entry),NULL, getAdInfo(entry));
}
if(type_of_param_type == TYPE_PRIMITIVE){
printdebug("primitive type of parameter inside record");
CreateEntry(cur, TYPE_PRIMITIVE, getTypeEntry(entry),NULL, getAdInfo(entry));
}
/*printdebug("creating entry of type %s for function", getType(entry));
CreateEntry(cur, getTypeEntry(entry), "undefined", NULL);*/
}
}
}
//counter = 0;
printdebug("Created a new scope after seeing a function definition");
} idlist R_PAREN ASSIGN sblock {
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
if ($8 == undefined) {
error_type(undefined, undefined, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected));
} else if ($8 != expected) {
error_type(undefined, undefined, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8));
} else {
printdebug("CORRECT RETURN TYPE!!!");
}
}
;
function_declaration:
FUNCTION ID COLON ID
{
if(getAdInfoType(look_up(cur, $4))==TYPE_FUNCTION_TYPE){
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
}
else{
error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $2);
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
}
}
| EXTERNAL FUNCTION ID COLON ID
{
if(getAdInfoType(look_up(cur, $5))==TYPE_FUNCTION_TYPE){
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false));
}
else{
error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $3);
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false));
}
}
;
idlist:
ID
{
printdebug("idlist rule 1 ID: %s", $1);
TableNode *entry = getFirstEntry(cur);
while((getName(entry) != getName(undefined))){
entry = getNextEntry(entry);
}
if (entry == NULL){
printdebug("mismatch in number of parameters passed to function");
}
else if(entry->theName == NULL){
addName(entry, $1);
printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1);
} else {
printdebug("undefined types passed in to function scope. Improper.");
addName(entry, $1);
}
printTableNode(entry);
//while (strcmp(getName(entry),"undefined") != 0) {
// entry = getNextEntry(entry);
//}
//if (getNextEntry(entry) == NULL) {
// printdebug("too many parameters at line %d column %d", @1.first_line, @1.first_column);
//}
//addName(entry, $1);
//printdebug("name added to entry is %s", $1);
//printTableNode(entry);
}
COMMA idlist
{
$$ = $4 + 1;
}
| ID
{ printdebug("idlist rule 2 ID: %s", $1);
TableNode *entry = getFirstEntry(cur);
while((getName(entry) != getName(undefined))){
entry = getNextEntry(entry);
}
if (entry == NULL){
printdebug("mismatch in number of parameters passed to function");
}
else if(entry->theName == NULL){
addName(entry, $1);
printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1);
} else {
printdebug("undefined types passed in to function scope. Improper.");
addName(entry, $1);
}
printTableNode(entry);
printdebug("Name of entry is now %s", getName(entry));
printdebug("Type of entry is %s", getType(entry));
printdebug("tag is %d", getAdInfoType(entry));
}
;
sblock:
L_BRACE
{
if (getLine(cur) != 0) {
cur = CreateScope(cur,@1.first_line,@1.first_column);
printdebug("Created a new scope");
} else {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
}
}
statement_list
{
//$<tn>$ = $3;
printdebug("Moving up a scope after seeing sblock");
cur = getParent(cur);
}
R_BRACE
{$$ = $3;}
| L_BRACE
{
if (getLine(cur) != 0) {
cur = CreateScope(cur,@1.first_line,@1.first_column);
printdebug("Created a new scope when seeing an L brace");
} else {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
printdebug("Did not create a new scope when saw L Brace, set line number to %d", @1.first_line);
}
}
dblock
{
printdebug("seen sblock with dblock");
}
statement_list
{
printdebug("Moving up a scope after seeing sblock with dblock");
cur = getParent(cur);
//$<tn>$ = $5;
}
R_BRACE
{$$ = $5;}
;
dblock:
L_BRACKET
{
if (getLine(cur) == 0) {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
printdebug("Did not create a new scope when saw dblock, set line number to %d instead", @1.first_line);
} else{
//cur = CreateScope(cur,@1.first_line,@1.first_column); // <----- What is this?
printdebug("Created a new scope when seeing a dblock");
}
}
declaration_list R_BRACKET;
declaration_list:
declaration SEMI_COLON declaration_list
| declaration
;
declaration:
id_or_types COLON ID
{
printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ;
int d = getAdInfoType((TableNode*)$1);
if(d == TYPE_UNDEFINED) {
error_type(undefined, undefined, "Undefined type passed in declaration list");
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
else if(d == TYPE_FUNCTION_TYPE) {
printdebug("invalid (function) type passed in declaration list in dblock", @2.first_line, @2.first_column);
d = TYPE_FUNCTION_DECLARATION;
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
else if(d == TYPE_ARRAY_TYPE){
printdebug("array variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_ARRAY;
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
else if(d == TYPE_RECORD_TYPE){
printdebug("record variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_RECORD;
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
else if(d == TYPE_PRIMITIVE_TYPE){
printdebug("primitive variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_PRIMITIVE;
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}else {
error_type(undefined, undefined, "Invalid type passed in declaration list.");
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
}
;
id_or_types:
ID
{
printdebug("string of id is %s in ID pattern of id_or_type rule.", $1);
$$ = table_lookup(getAncestor(cur), $1);
}
| types
{
printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1));
$$ = (TableNode*)$1;
}
;
statement_list:
compound_statement statement_list {
if ($1 == undefined && $2 != undefined) {
$$ = $2;
} else if ($1 != undefined && $2 == undefined) {
$$ = $1;
} else if ($1 == $2) {
$$ = $1;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| compound_statement {
$$ = $1;
}
| simple_statement SEMI_COLON statement_list{
if ($1 == undefined && $3 != undefined) {
$$ = $3;
} else if ($1 != undefined && $3 == undefined) {
$$ = $1;
} else if ($1 == $3) {
$$ = $1;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| simple_statement SEMI_COLON {
$$ = $1;
}
;
compound_statement:
WHILE L_PAREN expression R_PAREN sblock {
$$ = $5;
}
| IF L_PAREN expression R_PAREN THEN sblock ELSE sblock {
if ($6 == undefined && $8 != undefined) {
$$ = $8;
} else if ($6 != undefined && $8 == undefined) {
$$ = $6;
} else if ($6 == $8) {
$$ = $6;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| sblock {
$$ = $1;
}
;
simple_statement:
assignable ASSIGN expression
{ printdebug("simple statement");
TableNode* node;
if((getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION)||
(getAdInfoType((TableNode*)$1) == TYPE_ARRAY)||
(getAdInfoType((TableNode*)$1) == TYPE_RECORD)||
(getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE)){
node = ((TableNode*)$1);
} else{
error_type(undefined, undefined, "Invalid type passed to assignable.");
node = undefined;
}
if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){
//EMIT ASSIGN INSTRUCTION HERE
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3));
} else {
error_type(node, (TableNode*)$3, "");
}
$$ = undefined;
}
| RETURN expression {$$ = getTypeEntry((TableNode*)$2);}
;
rec_op:
DOT
ablock:
L_PAREN argument_list R_PAREN
{
$$ = $2;
printdebug("ablock is %d", $$);
}
;
argument_list:
//NEED TO EMIT PARAMETERS HERE. MAYBE USE STACK STRUCTURE
expression COMMA argument_list
{
CreateEntry(cur,getAdInfoType((TableNode*)$1), (TableNode*)$1, getName((TableNode*)$1), NULL);
$$ = $3 + 1;
printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
| expression
{
CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL);
$$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
;
// will ALWAYS be a TYPE
expression:
constant
{
printdebug("constant expression");
$$ = (TableNode*)$1;
}
| SUB_OR_NEG expression %prec UMINUS
{
printdebug("negative expression");
if(getTypeEntry((TableNode*)$2) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of unary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$2), integ, "");
}
}
| NOT expression
{
printdebug("not expression");
if(getTypeEntry((TableNode*)$2) == boo) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of unary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$2), boo, "");
}
}
| expression ADD expression
{
printdebug("add expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of binary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression SUB_OR_NEG expression
{
printdebug("sub or neg expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of binary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression MUL expression
{
printdebug("multiply expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of binary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression DIV expression
{
printdebug("divide expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of binary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression REM expression
{
printdebug("remainder expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of binary operation
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression AND expression
{
printdebug("AND");
if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of comparison
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression OR expression
{
printdebug("OR");
if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of comparison
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression LESS_THAN expression
{
printdebug("less than expression");
if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of comparison
$$ = node;
} else {
$$=undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| expression EQUAL_TO expression
{
printdebug("equals check expression");
if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1) != undefined) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of compariosn
$$ = node;
} else {
$$ = undefined;
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
}
}
| assignable
{
$$ = $1;
}
| L_PAREN expression R_PAREN
{
printdebug("paren expression. current type is %s",getType((TableNode*)$2));
$$=$2;
}
| memOp assignable
{
int d = getAdInfoType((TableNode*)$2);
if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
$$ = node;
} else {
error_type(undefined, undefined, "Invalid memOp expression (%s).", getName((TableNode*)$2));
$$=undefined;
}
}
;
//UPDATED $$ for tablenodes to this point
// prolly right, check back with me later
// add array case
// include type check for ablock in arrays - ablock is always the int of the elements in array/rec
assignable:
ID
{
TableNode* pass = look_up(cur,$1);
$$ = pass;
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass));
}
| assignable
{
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
cur = CreateScope(cur, -1,-1);
}
//we have to consider emmissions in ablocks
ablock
{
//int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1)));
int type = getAdInfoType(getTypeEntry((TableNode*)$1));
printdebug("%stype is %d", COLOR_PURPLE, type);
printdebug("%s", getName((TableNode*)$1));
if (type == TYPE_FUNCTION_TYPE) {
printdebug("%sEntering function call", COLOR_LIGHTGREEN);
if (look_up(getParent(cur), getType((TableNode*)$1))->additionalinfo->FunDecAdInfo->regularoras) {
printdebug("as function");
//char *funtype = getType(look_up(cur, $1));
//printdebug("%s", getType(look_up(cur, getName((TableNode*)$1))));
TableNode * typeNode = getTypeEntry((TableNode*)$1);
TableNode *param = getParameter(typeNode);
printTableNode(param);
if (getAdInfoType(param) == TYPE_RECORD_TYPE) {
SymbolTable *recList = getRecList(param);
TableNode *lastCheckedRef = getFirstEntry(recList);
TableNode *lastCheckedAct = getFirstEntry(cur);
while (getNextEntry(lastCheckedRef) != NULL) {
lastCheckedRef = getNextEntry(lastCheckedRef);
}
if ($3 != getRecLength(param)) {
printdebug("expected %d arguments but got %d", getRecLength(param), $3);
}
//this isn't very efficient, but will hopefully work
while (lastCheckedAct != NULL && lastCheckedRef != NULL) {
if (getTypeEntry(lastCheckedRef) != getTypeEntry(lastCheckedAct)) {
printdebug("expected %s. expression in function call got %s. at line %d and column %d",getType(lastCheckedRef), getName(lastCheckedAct), @3.first_line, @3.first_column);
}
lastCheckedAct = getNextEntry(lastCheckedAct);
TableNode *tn = getFirstEntry(recList);
if (tn != lastCheckedRef) {
while (getNextEntry(tn) != lastCheckedRef) {
tn = getNextEntry(tn);
}
lastCheckedRef = tn;
} else {break;}
}
} else {
if (strcmp(getName(param), getName(getFirstEntry(cur))) != 0) {
printdebug("expected %s expression in function call but got %s", getName(param), getName(getFirstEntry(cur)));
}
if (getNextEntry(getFirstEntry(cur)) != NULL) {
printdebug("expected 1 parameter, but got multiple in function call");
}
}
} else {
char *expected = getName(getParameter(look_up(getParent(cur), getType((TableNode*)$1))));
char *actual = getType(getFirstEntry(cur));
if (strcmp(expected, actual) != 0) {
printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column);
}
if ($3 != 1) {
printdebug("expected 1 argument but got %d", $3);
}
}
printTableNode(getReturn(getTypeEntry((TableNode*)$1)));
//
char* temp = temp_var_gen();
TableNode* typeNode2 = getReturn(getTypeEntry($1));
int t = -1;
if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
$$ = node;
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK for function call)
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1));
} else if (type == TYPE_ARRAY_TYPE) {
printdebug("%sEntering array call", COLOR_LIGHTGREEN);
if (getNumArrDim(look_up(getParent(cur), getType((TableNode*)$1))) != $<integ>2) {
printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, getName((TableNode*)$1))), $<integ>2, @2.first_line, @2.first_column);
}
char* temp = temp_var_gen();
TableNode* typeNode2 = getArrType(look_up(getAncestor(cur), getType((TableNode*)$1)));
int t = -1;
if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
//emit assign here
//emit_array_access(char* node, char* array, ...)
$$ = node;
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getType((TableNode*)$1), getName((TableNode*)$1));
}
cur = getParent(cur);
}
| assignable rec_op ID
{
if(getAdInfoType((TableNode*)$1) != TYPE_RECORD_TYPE){
printdebug("CHANGE ME [TYPE CHECK]Invalid type passed to record access");
}
else if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)) {
TableNode* type = table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3);
char* temp = temp_var_gen();
int t = -1;
if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(type) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(type) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
else if(getAdInfoType(type) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
}
TableNode* node = CreateEntry(cur,t, type, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//emit_field_access(char* node, char* record, $3)
$$=node;
}else{
printdebug("CHANGE ME [TYPE CHECK] undefined type (Field Access Lookup failed)");
$$=undefined;
}
printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3));
}
;
memOp:
RESERVE
{
printdebug("reserve expression");
}
| RELEASE
{
printdebug("release expression");
}
;
constant:
C_STRING
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL);
emit_assignment(node, tn_or_const(STRING,$1));
printdebug("string of C_STRING in constant is %s", $1);
$$ = node;
}
| C_INTEGER
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_assignment(node, tn_or_const(INTEGER,&$1));
printdebug("number of C_INTEGER in constant is %d", $1);
$$ = node;
}
| C_NULL
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
emit_assignment(node, tn_or_const(ADDRESS,$1));
printdebug("string of C_NULL in constant is NULL");
$$ = node;
}
| C_CHARACTER
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL);
emit_assignment(node, tn_or_const(CHARACTER,&$1));
printdebug("string of C_CHARACTER in constant is %s",$1);
$$ = node;
}
| C_TRUE
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
uint_least8_t b = 1;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
printdebug("string of C_TRUE in constant is true");
$$ = node;
}
| C_FALSE
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
uint_least8_t b = 0;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
printdebug("string of C_FALSE in constant is false");
$$ = node;
}
;
types:
T_INTEGER
{
$$ = $1;
printdebug("string of T_INTEGER in types is %s",getName((TableNode*)$1));
}
| T_ADDRESS
{
$$ = $1;
printdebug("string of T_ADDRESS in types is %s",getName((TableNode*)$1));
}
| T_CHARACTER
{
$$ = $1;
printdebug("string of T_CHARACTER in types is %s",getName((TableNode*)$1));
}
| T_BOOLEAN
{
$$ = $1;
printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1));
}
;
%%
void error_type(TableNode * left, TableNode * right, const char *format, ...) {
int line = yylloc.first_line;
int column = yylloc.first_column;
if (tc_flag) {
yyerror("");
if (strcmp(format, "") == 0) {
if (asc_flag != NULL) {
fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: %s != %s\n", line, column, getName(left), getName(right));
} else {
fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s%s %s!= %s%s\n",
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, getName(left), COLOR_WHITE, COLOR_YELLOW, getName(right), COLOR_WHITE);
}
} else {
if (asc_flag != NULL) {
fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: ", line, column);
va_list args;
va_start(args, format);
vfprintf(asc_flag, format, args);
va_end(args);
fprintf(asc_flag, "\n");
} else {
fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s", COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW);
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, "%s\n", COLOR_WHITE);
}
}
}
}
void yyerror(const char *err) {
int line = yylloc.first_line;
int column = yylloc.first_column;
// Grammar Fallback Case
if (strcmp(err, "syntax error") == 0) {
if (asc_flag != NULL) {
fprintf(asc_flag, "(%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext);
}
else {
fprintf(stderr, "%s(%d:%d) ** SYNTAX ERROR%s: Incorrect syntax at token '%s%s%s'\n",
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, yytext, COLOR_WHITE);
}
}
}