Files
compiler-the-translators/src/grammar.y
2025-04-09 13:13:20 -04:00

858 lines
31 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);
int token_tracker;
TableNode * tn;
%}
%union {
int integ;
char* words;
void* tn;
}
%locations
%type <integ> idlist
%type <tn> assignable
%type <tn> expression
%type <tn> constant
%type <tn> id_or_types
%type <tn> types
%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));
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 {
TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) {
printdebug(" [TYPE CHECK] undefined nodedeclared at line %d, column %d", @1.first_line, @1.first_column);
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
printdebug("[TYPE CHECK] not a valid function declaration at line %d, column %d", @1.first_line, @1.first_column);
}
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(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1))));
printdebug("parameter type: %s", getType(parameter));
if (parameter == undefined) {
printdebug("[TYPE CHECK] function defined with as, but parameter is undefined at line %d, column %d", @1.first_line, @1.first_column);
}else if(getAdInfoType(parameter) != TYPE_RECORD){
int type_of_param_type = getAdInfoType(parameter);
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_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
printdebug("[TYPE CHECK] type of parameter being passed in to function definition is %s which is invalid", 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 {
CreateEntry(cur, getAdInfoType(parameter), parameter,NULL, getAdInfo(parameter));
}
} else {
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_DECLARATION
|| type_of_param_type == TYPE_ARRAY
|| type_of_param_type == TYPE_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
printdebug("[TYPE CHECK] type of parameter being passed in to AS function definition is %s which is invalid", getName(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", getName(entry));
}
if(type_of_param_type == TYPE_UNDEFINED){
CreateEntry(cur,type_of_param_type, undefined, NULL, NULL);
} else {
CreateEntry(cur,type_of_param_type, entry, NULL, getAdInfo(entry));
/*printdebug("creating entry of type %s for function", getType(entry));
CreateEntry(cur, getTypeEntry(entry), "undefined", NULL);*/
}
}
}
} idlist {
printdebug("Currently see a function definition taking one paramter (with as) of name %s and number of arguments %d", $1,$5);
} R_PAREN ASSIGN sblock //check sblock 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{
printdebug("[TYPE CHECK] function declaration of %s is not a valid function type at line %d, column %d", $2, @1.first_line, @1.first_column);
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{
printdebug("[TYPE CHECK] function declaration of %s is not a valid function type at line %d, column %d", $3, @1.first_line, @1.first_column);
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false));
}
}
;
idlist:
ID
{
TableNode *entry = getFirstEntry(cur);
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);
}
COMMA idlist
{
$$ = $4 + 1;
}
| ID
{
TableNode *entry = getFirstEntry(cur);
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, $<words>1);
$$ = 1;
}
;
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
{
printdebug("Moving up a scope after seeing sblock");
cur = getParent(cur);
}
R_BRACE
| 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);
}
R_BRACE
;
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) {
printdebug("undefined type at line %d and column %d", @2.first_line, @2.first_column);
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_TYPE;
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){
printdebug("primitive variable at line %d and column %d", @2.first_line, @2.first_column);
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}else {
printdebug("other invalid type passed at %d and column %d", @2.first_line, @2.first_column);
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
| compound_statement
| simple_statement SEMI_COLON statement_list
| simple_statement SEMI_COLON
;
compound_statement:
WHILE L_PAREN expression R_PAREN sblock
| IF L_PAREN expression R_PAREN THEN sblock ELSE sblock
| sblock
;
simple_statement:
assignable ASSIGN expression
{
bool passCheck = false;
TableNode * left = (TableNode*)$1;
TableNode * right = (TableNode*)$3;
printTableNode((TableNode*)$1);
printTableNode((TableNode*)$3);
if (strcmp(getType(right), "primitive") == 0) {
if (strcmp((getType(left)),(getName(right))) == 0) {
printdebug("%s[☺] Passed primitive type check; %s = %s", COLOR_GREEN, getName(left), getName(right));
passCheck = true;
}
}
if(strcmp(getName(left), getName(right)) == 0) {
printdebug("Passed standard type check; assignable = expression");
passCheck = true;
}
if((strcmp(getType(left), "array") == 0) && (strcmp(getName(right), "address") == 0)) {
printdebug("%s[☺] Passed array type check; %s = %s", COLOR_GREEN, getName(left), getName(right));
passCheck = true;
}
if((strcmp(getType(left), "record") == 0) && (strcmp(getName(right), "address") == 0)) {
printdebug("%s[☺] Passed address type check; %s = %s", COLOR_GREEN, getName(left), getName(right));
passCheck = true;
}
if((strcmp(getType(left), "function type primitive") == 0) && (strcmp(getName(right), "address") == 0)) {
printdebug("%s[☺] Passed function type primitive type check; %s = %s", COLOR_GREEN, getName(left), getName(right));
passCheck = true;
}
// Type check fails:
if (!passCheck) {
printdebug("%s[TYPE CHECK] %sMismatch at %sline %d and column %d%s", COLOR_ORANGE, COLOR_WHITE, COLOR_YELLOW, @2.first_line, @2.first_column, COLOR_WHITE);
printdebug(" - Invalid types %s$1: %s and $3: %s%s", COLOR_YELLOW, getType(left), getType(right), COLOR_WHITE);
printdebug(" - %sgetType for address: %s", COLOR_YELLOW, getType(left));
}
}
| RETURN expression
;
rec_op:
DOT
ablock:
L_PAREN argument_list R_PAREN
{
$$ = $2;
printdebug("ablock is %d", $$);
}
;
argument_list:
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((TableNode*)$2 != integ) {
printdebug("cant negate something not an integer at line %d and column %d",@2.first_line,@2.first_column);
$$=undefined;
} else {
$$=(TableNode*)$2;
}
}
| NOT expression
{
printdebug("not expression");
if((TableNode*)$2 == boo) {
$$=(TableNode*)$2;
} else {
$$=undefined;
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid type being negated is %s", @1.first_line,@1.first_column,getName((TableNode*)$2));
}
}
| expression ADD expression
{
printdebug("add expression");
if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) {
$$=(TableNode*)$1;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression SUB_OR_NEG expression
{
printdebug("sub or neg expression");
if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) {
$$=(TableNode*)$1;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression MUL expression
{
printdebug("multiply expression");
if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) {
$$=(TableNode*)$1;
} else{
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName($1),getName($3));
$$=undefined;
}
}
| expression DIV expression
{
printdebug("divide expression");
if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && ((TableNode*)$1 == integ)) {
$$=(TableNode*)$1;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression REM expression
{
printdebug("remainder expression");
if($1 == $3 && $1 == integ) {
$$=$1;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression AND expression
{
printdebug("AND expression");
if($1 == $3 && $1 == boo){
$$=$1;
} else{
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression OR expression
{
printdebug("OR");
if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && $1 == boo) {
$$=$1;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression LESS_THAN expression
{
printdebug("less than expression");
if($1 == $3 && $1==integ) {
$$=boo;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$=undefined;
}
}
| expression EQUAL_TO expression
{
printdebug("equals check expression");
if($1 == $3 && $1 != undefined) {
$$=boo;
} else {
printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3));
$$ = undefined;
}
}
| assignable
{
printdebug("assignable expression. current type is %s",getName((TableNode*)$1));
if(getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE||
getAdInfoType((TableNode*)$1) == TYPE_ARRAY ||
getAdInfoType((TableNode*)$1) == TYPE_RECORD){
printdebug("assignable passing up to expression is primitive, array instance, or record instance. Passing up its type");
$$= getTypeEntry((TableNode*)$1);
}
else if(getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE||
getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE||
getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_TYPE||
getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION){
printdebug("assignable passing up to expression is array type, record type, function type, or function declaration");
$$= ((TableNode*)$1);
}
else {
printdebug("[TYPE CHECK] assignable passing up an invalid type to expression");
$$= ((TableNode*)$1);
}
}
| L_PAREN expression R_PAREN
{
printdebug("paren expression. current type is %s",getName((TableNode*)$2));
$$=$2;
}
| memOp assignable
{
int d = getAdInfoType((TableNode*)$2);
if(d == TYPE_ARRAY_TYPE || d == TYPE_ARRAY || d == TYPE_RECORD_TYPE || d == TYPE_RECORD) {
//printdebug("[TYPE CHECK] valid memOp expression");
$$ = addr;
} else {
printdebug("[TYPE CHECK] invalid memOp expression at line %d and column %d.", @2.first_line,@2.first_column,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
{
$$ = look_up(cur,$1);
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getName((TableNode*)$$), $1);
}
| assignable
{
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
cur = CreateScope(cur, -1,-1);
}
ablock
{
int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1)));
printdebug("%stype is %d", COLOR_PURPLE, type);
printdebug("%s", getName((TableNode*)$1));
if (type == TYPE_FUNCTION_DECLARATION) {
printdebug("%sEntering function call", COLOR_LIGHTGREEN);
if (look_up(getParent(cur), getName((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 = table_lookup(getAncestor(cur), getType((TableNode*)$1));
TableNode *param = getParameter(typeNode);
printTableNode(param);
SymbolTable *recList = getRecList(param);
TableNode *lastCheckedRef = getFirstEntry(recList);
TableNode *lastCheckedAct = getFirstEntry(cur);
while (getNextEntry(lastCheckedRef) != NULL) {
lastCheckedRef = getNextEntry(lastCheckedRef);
}
//this isn't very efficient, but will hopefully work
while (lastCheckedAct != NULL && lastCheckedRef != NULL) {
if (strcmp(getName(lastCheckedAct), getName(lastCheckedRef)) != 0) {
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);
printdebug("%d", strcmp(getName(lastCheckedAct), getName(lastCheckedRef)));
}
lastCheckedAct = getNextEntry(lastCheckedAct);
TableNode *tn = getFirstEntry(recList);
if (tn != lastCheckedRef) {
while (getNextEntry(tn) != lastCheckedRef) {
tn = getNextEntry(tn);
}
lastCheckedRef = tn;
} else {break;}
}
} else {
char *expected = getName(getParameter(look_up(getParent(cur), getName((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);
}
}
$$ = getReturn((table_lookup(getAncestor(cur), getType((TableNode*)$1))));
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName((TableNode*)$$), getName((TableNode*)$1));
} else if (type == TYPE_ARRAY_TYPE) {
printdebug("%sEntering array call", COLOR_LIGHTGREEN);
if (getNumArrDim(look_up(getParent(cur), getName((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);
}
$$ = getArrType(look_up(getParent(cur), getName((TableNode*)$1)));
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName((TableNode*)$$), getName((TableNode*)$1));
}
cur = getParent(cur);
}
| assignable rec_op ID
{
if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName((TableNode*)$1))), $3)) {
$$ = table_lookup(getRecList(table_lookup(getAncestor(cur), getName((TableNode*)$1))), $3);
}
printdebug("[ASSIGNABLE - RULE 3] assignable = type: %s | ID = %s", getName((TableNode*)($$)), $1);
}
;
memOp:
RESERVE
{
printdebug("reserve expression");
}
| RELEASE
{
printdebug("release expression");
}
;
constant:
C_STRING
{
$$ = $1;
printdebug("string of C_STRING in constant is %s",getName((TableNode*)$1));
}
| C_INTEGER
{
$$ = integ;
printdebug("string of C_INTEGER in constant is integer");
}
| C_NULL
{
$$ = $1;
printdebug("string of C_NULL in constant is %s",getName((TableNode*)$1));
}
| C_CHARACTER
{
$$ = $1;
printdebug("string of C_CHARACTER in constant is %s",getName((TableNode*)$1));
}
| C_TRUE
{
$$ = $1;
printdebug("string of C_TRUE in constant is %s",getName((TableNode*)$1));
}
| C_FALSE
{
$$ = $1;
printdebug("string of C_FALSE in constant is %s",getName((TableNode*)$1));
}
;
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 yyerror(const char *err) {
fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d", err,yytext,yylloc.first_line,yylloc.first_column);
}