New grammar formatting rules applied.
This commit is contained in:
497
src/grammar.y
497
src/grammar.y
@ -2,6 +2,19 @@
|
|||||||
/* Syntax Analyzer with Bison (3.8.2) */
|
/* Syntax Analyzer with Bison (3.8.2) */
|
||||||
/* The Translators - Spring 2025 */
|
/* 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️⃣ DO NOT USE TABS. EVER.
|
||||||
|
|
||||||
|
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "../src/symbol_table.c"
|
#include "../src/symbol_table.c"
|
||||||
@ -29,8 +42,9 @@
|
|||||||
extern TableNode* boo;
|
extern TableNode* boo;
|
||||||
TableNode * tn;
|
TableNode * tn;
|
||||||
%}
|
%}
|
||||||
//%define api.location.type {location_t}
|
|
||||||
%locations
|
%locations
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
int integ;
|
int integ;
|
||||||
char * words;
|
char * words;
|
||||||
@ -102,14 +116,14 @@
|
|||||||
%precedence DOT
|
%precedence DOT
|
||||||
%precedence RESERVE RELEASE
|
%precedence RESERVE RELEASE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
program:
|
program:
|
||||||
prototype_or_definition_list
|
prototype_or_definition_list
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
prototype_or_definition_list:
|
prototype_or_definition_list:
|
||||||
prototype prototype_or_definition_list
|
prototype prototype_or_definition_list
|
||||||
| definition prototype_or_definition_list
|
| definition prototype_or_definition_list
|
||||||
@ -117,89 +131,120 @@ prototype_or_definition_list:
|
|||||||
| definition
|
| definition
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
prototype:
|
prototype:
|
||||||
L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID;
|
L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
definition:
|
definition:
|
||||||
TYPE ID COLON {
|
TYPE ID COLON
|
||||||
|
{
|
||||||
printdebug("Currently see a record definition for %s", $<words>2);
|
printdebug("Currently see a record definition for %s", $<words>2);
|
||||||
tn = CreateEntry(getAncestor(cur), recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0)));
|
tn = CreateEntry(getAncestor(cur), recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0)));
|
||||||
if (table_lookup(getAncestor(cur), $2) == undefined) {
|
if (table_lookup(getAncestor(cur), $2) == undefined) {
|
||||||
printdebug("rec not found ");
|
printdebug("rec not found ");
|
||||||
}
|
}
|
||||||
}dblock { setRecSize(table_lookup(getParent(cur), $2), getRecSize(cur));
|
}
|
||||||
cur = getParent(cur);}
|
dblock
|
||||||
|
{
|
||||||
|
setRecSize(table_lookup(getParent(cur), $2), getRecSize(cur));
|
||||||
|
cur = getParent(cur);
|
||||||
|
}
|
||||||
|
|
||||||
| TYPE ID COLON C_INTEGER ARROW id_or_types
|
| 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, $6, $4);
|
printdebug("Currently see a array definition of name %s,storing type %s, of dimensions %d", $2, $6, $4);
|
||||||
CreateEntry(cur, arrayprim, $2, CreateArrayInfo($4, look_up(cur, $6)));
|
CreateEntry(cur, arrayprim, $2, CreateArrayInfo($4, look_up(cur, $6)));
|
||||||
printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, $6);
|
printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, $6);
|
||||||
}
|
}
|
||||||
|
|
||||||
| function_declaration
|
| 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",
|
| TYPE ID COLON id_or_types ARROW id_or_types
|
||||||
$2, $4, $6);
|
{
|
||||||
|
printdebug("Currently see a function type definition of name %s,parameter type %s, of return type %s", $2, $4, $6);
|
||||||
CreateEntry(cur,funtypeprime,$2,CreateFunctionTypeInfo(table_lookup(cur,$4),table_lookup(cur,$6)));
|
CreateEntry(cur,funtypeprime,$2,CreateFunctionTypeInfo(table_lookup(cur,$4),table_lookup(cur,$6)));
|
||||||
}
|
}
|
||||||
| ID {
|
|
||||||
|
| ID
|
||||||
|
{
|
||||||
TableNode *node = table_lookup(getAncestor(cur), $<words>1);
|
TableNode *node = table_lookup(getAncestor(cur), $<words>1);
|
||||||
if (node == undefined) {
|
if (node == undefined) {
|
||||||
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
||||||
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
|
} else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) {
|
||||||
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setStartLine(node, @1.first_line);
|
setStartLine(node, @1.first_line);
|
||||||
setAsKeyword(node, false);
|
setAsKeyword(node, false);
|
||||||
}
|
}
|
||||||
cur = CreateScope(cur, 0, 0);
|
cur = CreateScope(cur, 0, 0);
|
||||||
} L_PAREN ID {
|
}
|
||||||
printdebug("Currently see a function definition taking only one parameter (no as) of name %s and argument name %s",
|
L_PAREN ID
|
||||||
$1,$4);
|
{
|
||||||
|
printdebug("Currently see a function definition taking only one parameter (no as) of name %s and argument name %s", $1,$4);
|
||||||
CreateEntry(cur, getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $<words>1)))), $<words>4, NULL);
|
CreateEntry(cur, getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $<words>1)))), $<words>4, NULL);
|
||||||
}R_PAREN ASSIGN sblock
|
}
|
||||||
| ID {
|
R_PAREN ASSIGN sblock
|
||||||
|
|
||||||
|
| ID
|
||||||
|
{
|
||||||
TableNode *node = table_lookup(getAncestor(cur), $<words>1);
|
TableNode *node = table_lookup(getAncestor(cur), $<words>1);
|
||||||
if (node == undefined) {
|
if (node == undefined) {
|
||||||
printdebug("null check");
|
printdebug("null check");
|
||||||
}
|
}
|
||||||
if (node == undefined) {
|
if (node == undefined) {
|
||||||
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
||||||
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
|
} else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION) {
|
||||||
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
printdebug("function not declared at line %d, column %d", @1.first_line, @1.first_column);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setStartLine(node, @1.first_line);
|
setStartLine(node, @1.first_line);
|
||||||
setAsKeyword(node, true);
|
setAsKeyword(node, true);
|
||||||
}
|
}
|
||||||
cur = CreateScope(cur, 0, 0);
|
cur = CreateScope(cur, 0, 0);
|
||||||
}AS L_PAREN {
|
}
|
||||||
|
AS L_PAREN
|
||||||
|
{
|
||||||
TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $<words>1))));
|
TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $<words>1))));
|
||||||
printdebug("%s", getType(parameter));
|
printdebug("%s", getType(parameter));
|
||||||
if (parameter == undefined) {
|
if (parameter == undefined) {
|
||||||
printdebug("function defined with as, but parameter is undefined at line %d, column %d", @1.first_line, @1.first_column);
|
printdebug("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){
|
} else if(getAdInfoType(parameter) != TYPE_RECORD) {
|
||||||
printdebug("record: %s., primitive: %s.", getType(parameter), getName(recprime));
|
printdebug("record: %s., primitive: %s.", getType(parameter), getName(recprime));
|
||||||
printdebug("function defined with as, but parameter is type %s at line %d, column %d", getType(parameter),@1.first_line, @1.first_column);
|
printdebug("function defined with as, but parameter is type %s at line %d, column %d", getType(parameter),@1.first_line, @1.first_column);
|
||||||
}else {
|
} else {
|
||||||
for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){
|
for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)) {
|
||||||
CreateEntry(cur, entry, NULL, NULL);
|
CreateEntry(cur, entry, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} idlist {printdebug("Currently see a function definition taking one paramter (with as) of name %s and number of arguments %d",
|
}
|
||||||
$1,$6);} R_PAREN ASSIGN sblock
|
idlist
|
||||||
|
{
|
||||||
|
printdebug("Currently see a function definition taking one paramter (with as) of name %s and number of arguments %d", $1,$6);
|
||||||
|
}
|
||||||
|
R_PAREN ASSIGN sblock
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function_declaration:
|
function_declaration:
|
||||||
FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));}
|
FUNCTION ID COLON ID
|
||||||
| EXTERNAL FUNCTION ID COLON ID {CreateEntry(cur, look_up(cur, $5), $3, NULL);}
|
{
|
||||||
|
CreateEntry(cur, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
| EXTERNAL FUNCTION ID COLON ID
|
||||||
|
{
|
||||||
|
CreateEntry(cur, look_up(cur, $5), $3, NULL);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
idlist:
|
idlist:
|
||||||
ID {
|
ID
|
||||||
|
{
|
||||||
TableNode *entry = getFirstEntry(cur);
|
TableNode *entry = getFirstEntry(cur);
|
||||||
while (strcmp(getName(entry),"undefined") != 0) {
|
while (strcmp(getName(entry),"undefined") != 0) {
|
||||||
entry = getNextEntry(entry);
|
entry = getNextEntry(entry);
|
||||||
@ -208,9 +253,14 @@ idlist:
|
|||||||
printdebug("too many parameters at line %d column %d", @1.first_line, @1.first_column);
|
printdebug("too many parameters at line %d column %d", @1.first_line, @1.first_column);
|
||||||
}
|
}
|
||||||
addName(entry, $<words>1);
|
addName(entry, $<words>1);
|
||||||
} COMMA idlist {$$ = $<integ>4 + 1;}
|
}
|
||||||
| ID {
|
COMMA idlist
|
||||||
|
{
|
||||||
|
$$ = $<integ>4 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| ID
|
||||||
|
{
|
||||||
TableNode *entry = getFirstEntry(cur);
|
TableNode *entry = getFirstEntry(cur);
|
||||||
while (strcmp(getName(entry),"undefined") != 0) {
|
while (strcmp(getName(entry),"undefined") != 0) {
|
||||||
entry = getNextEntry(entry);
|
entry = getNextEntry(entry);
|
||||||
@ -225,19 +275,49 @@ idlist:
|
|||||||
|
|
||||||
|
|
||||||
sblock:
|
sblock:
|
||||||
L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} statement_list {cur = getParent(cur);} R_BRACE
|
L_BRACE
|
||||||
| L_BRACE {if (getLine(cur) != 0 && getColumn(cur))cur = CreateScope(cur,@1.first_line,@1.first_column);} dblock
|
{
|
||||||
{printdebug("seen sblock with dblock");} statement_list {cur = getParent(cur);} R_BRACE
|
if (getLine(cur) != 0 && getColumn(cur)) {
|
||||||
|
cur = CreateScope(cur,@1.first_line,@1.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statement_list
|
||||||
|
{
|
||||||
|
cur = getParent(cur);
|
||||||
|
}
|
||||||
|
R_BRACE
|
||||||
|
|
||||||
|
| L_BRACE
|
||||||
|
{
|
||||||
|
if (getLine(cur) != 0 && getColumn(cur)) {
|
||||||
|
cur = CreateScope(cur,@1.first_line,@1.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dblock
|
||||||
|
{
|
||||||
|
printdebug("seen sblock with dblock");
|
||||||
|
}
|
||||||
|
statement_list
|
||||||
|
{
|
||||||
|
cur = getParent(cur);
|
||||||
|
}
|
||||||
|
R_BRACE
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dblock:
|
dblock:
|
||||||
L_BRACKET declaration_list R_BRACKET;
|
L_BRACKET declaration_list R_BRACKET;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
declaration_list:
|
declaration_list:
|
||||||
declaration SEMI_COLON declaration_list
|
declaration SEMI_COLON declaration_list
|
||||||
| declaration
|
| declaration
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
declaration:
|
declaration:
|
||||||
id_or_types COLON ID
|
id_or_types COLON ID
|
||||||
{
|
{
|
||||||
@ -246,14 +326,23 @@ declaration:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
id_or_types:
|
id_or_types:
|
||||||
ID {printdebug("string of id is %s in ID pattern of id_or_type rule.", $1); $$ = $1;}
|
ID
|
||||||
//{printdebug("string of id is %s in ID pattern of id_or_type rule. Type passed up the tree is %s.",$1,getType(look_up(cur,$1))); $$ = getType(look_up(cur,$1));}
|
{
|
||||||
| types {printdebug("string of type is %s in types pattern of id_or_type rule.",$1);} {$$ = $1;}
|
printdebug("string of id is %s in ID pattern of id_or_type rule.", $1); $$ = $1;
|
||||||
//{printdebug("string of type is %s in types pattern of id_or_type rule. That is passed up the tree.",$<words>1);} {$$ = $<words>1;}
|
}
|
||||||
;
|
|
||||||
|
| types
|
||||||
|
{
|
||||||
|
printdebug("string of type is %s in types pattern of id_or_type rule.",$1);
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
statement_list:
|
statement_list:
|
||||||
compound_statement statement_list
|
compound_statement statement_list
|
||||||
| compound_statement
|
| compound_statement
|
||||||
@ -261,12 +350,16 @@ statement_list:
|
|||||||
| simple_statement SEMI_COLON
|
| simple_statement SEMI_COLON
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
compound_statement:
|
compound_statement:
|
||||||
WHILE L_PAREN expression R_PAREN sblock
|
WHILE L_PAREN expression R_PAREN sblock
|
||||||
| IF L_PAREN expression R_PAREN THEN sblock ELSE sblock
|
| IF L_PAREN expression R_PAREN THEN sblock ELSE sblock
|
||||||
| sblock //{printdebug("seen a compound statement rule");}
|
| sblock
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
simple_statement:
|
simple_statement:
|
||||||
assignable ASSIGN expression
|
assignable ASSIGN expression
|
||||||
{
|
{
|
||||||
@ -291,111 +384,191 @@ simple_statement:
|
|||||||
|
|
||||||
| RETURN expression
|
| RETURN expression
|
||||||
;
|
;
|
||||||
rec_op :
|
|
||||||
|
|
||||||
|
|
||||||
|
rec_op:
|
||||||
DOT
|
DOT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////// VERIFIED UP UNTIL THIS POINT
|
|
||||||
|
|
||||||
// assignable needs more code- specifically for arrays, records and ablock checks
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ablock:
|
ablock:
|
||||||
L_PAREN argument_list R_PAREN {$<integ>$ = $<integ>2; printdebug("ablock is %d", $<integ>$);}
|
L_PAREN argument_list R_PAREN
|
||||||
|
{
|
||||||
|
$<integ>$ = $<integ>2;
|
||||||
|
printdebug("ablock is %d", $<integ>$);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
argument_list:
|
argument_list:
|
||||||
expression COMMA argument_list {
|
expression COMMA argument_list
|
||||||
|
{
|
||||||
CreateEntry(cur, look_up(cur, $1), "", NULL);
|
CreateEntry(cur, look_up(cur, $1), "", NULL);
|
||||||
$<integ>$ = $<integ>3 + 1;
|
$<integ>$ = $<integ>3 + 1;
|
||||||
printdebug("[ARGUMENT_LIST] argument list is %d", $<integ>$);}
|
printdebug("[ARGUMENT_LIST] argument list is %d", $<integ>$);
|
||||||
| expression {
|
}
|
||||||
|
|
||||||
|
| expression
|
||||||
|
{
|
||||||
CreateEntry(cur, look_up(cur, $1), "", NULL);
|
CreateEntry(cur, look_up(cur, $1), "", NULL);
|
||||||
$<integ>$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $<integ>$);}
|
$<integ>$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $<integ>$);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// will ALWAYS be a TYPE
|
// will ALWAYS be a TYPE
|
||||||
expression:
|
expression:
|
||||||
constant {printdebug("constant expression");} {$$ = $<words>1;}
|
constant
|
||||||
|
{
|
||||||
|
printdebug("constant expression");
|
||||||
|
$$ = $<words>1;
|
||||||
|
}
|
||||||
|
|
||||||
| SUB_OR_NEG expression %prec UMINUS {printdebug("negative expression");if(strcmp($2,"integer") != 0)
|
| SUB_OR_NEG expression %prec UMINUS
|
||||||
{printdebug("cant negate something not an integer at line %d and column %d",@2.first_line,@2.first_column);
|
{
|
||||||
$$=strdup("undefined");}else{$$=$2;}}
|
printdebug("negative expression");
|
||||||
|
if(strcmp($2,"integer") != 0) {
|
||||||
|
printdebug("cant negate something not an integer at line %d and column %d",@2.first_line,@2.first_column);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
} else {
|
||||||
|
$$=$2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| NOT expression {printdebug("not expression"); if(strcmp($2,"Boolean")==0){$$=$2;}else{$$=strdup("undefined");
|
| NOT expression
|
||||||
printdebug("mismatch at line %d and column %d. Invalid type being negated is %s",
|
{
|
||||||
@1.first_line,@1.first_column,$2);}}
|
printdebug("not expression");
|
||||||
|
if(strcmp($2,"Boolean")==0) {
|
||||||
|
$$=$2;
|
||||||
|
} else {
|
||||||
|
$$=strdup("undefined");
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid type being negated is %s", @1.first_line,@1.first_column,$2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression ADD expression
|
| expression ADD expression
|
||||||
{printdebug("add expression");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");}
|
{
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
printdebug("add expression");
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
if(strcmp($1,$3)==0 && strcmp($1,"integer")==0) {
|
||||||
$$=strdup("undefined");}}
|
$$=strdup("integer");
|
||||||
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression SUB_OR_NEG expression
|
| expression SUB_OR_NEG expression
|
||||||
{printdebug("sub or neg expression");if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");}
|
{
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
printdebug("sub or neg expression");
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0) {
|
||||||
$$=strdup("undefined");}}
|
$$=strdup("integer");
|
||||||
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression MUL expression
|
| expression MUL expression
|
||||||
{printdebug("multiply expression");
|
{
|
||||||
if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0){$$=strdup("integer");}
|
printdebug("multiply expression");
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
if(strcmp($1,$3)==0 &&strcmp($1,"integer")==0) {
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
$$=strdup("integer");
|
||||||
$$=strdup("undefined");}}
|
} else{
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression DIV expression
|
| expression DIV expression
|
||||||
{printdebug("divide expression");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");}
|
{
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
printdebug("divide expression");
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
if(strcmp($1,$3)==0 && strcmp($1,"integer")==0) {
|
||||||
$$=strdup("undefined");}}
|
$$=strdup("integer");
|
||||||
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression REM expression
|
| expression REM expression
|
||||||
{printdebug("remainder expression");if(strcmp($1,$3)==0 && strcmp($1,"integer")==0){$$=strdup("integer");}
|
{
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
printdebug("remainder expression");
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
if(strcmp($1,$3)==0 && strcmp($1,"integer")==0) {
|
||||||
$$=strdup("undefined");}}
|
$$=strdup("integer");
|
||||||
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression AND expression
|
| expression AND expression
|
||||||
{printdebug("AND expression");if(strcmp($1,$3)==0 && strcmp($1,"Boolean")==0){$$=strdup("Boolean");}
|
{
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
printdebug("AND expression");
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
if(strcmp($1,$3)==0 && strcmp($1,"Boolean")==0) {
|
||||||
$$=strdup("undefined");}}
|
$$=strdup("Boolean");
|
||||||
|
} else{
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression OR expression
|
| expression OR expression
|
||||||
{printdebug("OR");if(strcmp($1,$3)==0 &&
|
{
|
||||||
strcmp($1,"Boolean")==0){$$=strdup("Boolean");}
|
printdebug("OR");
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
if(strcmp($1,$3)==0 && strcmp($1,"Boolean")==0) {
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
$$=strdup("Boolean");
|
||||||
$$=strdup("undefined");}}
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression LESS_THAN expression
|
| expression LESS_THAN expression
|
||||||
{printdebug("less than expression");if(strcmp($1,$3)==0 &&
|
{
|
||||||
strcmp($1,"integer")==0){$$=strdup("Boolean");}
|
printdebug("less than expression");
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s.",
|
if(strcmp($1,$3)==0 && strcmp($1,"integer")==0) {
|
||||||
@2.first_line,@2.first_column,$1,$3);
|
$$=strdup("Boolean");
|
||||||
$$=strdup("undefined");}}
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| expression EQUAL_TO expression {printdebug("equals check expression");
|
| expression EQUAL_TO expression
|
||||||
if(strcmp($1,$3)==0){$$=strdup("Boolean");}
|
{
|
||||||
//else if((strcmp($1,"array")==0||strcmp($1,"record")==0||
|
printdebug("equals check expression");
|
||||||
// strcmp($1,"function type primitive")==0) && (strcmp($3,"address")==0)){$$=strdup("Boolean");}
|
if(strcmp($1,$3)==0) {
|
||||||
else{printdebug("mismatch at line %d and column %d. Invalid types %s and %s",
|
$$=strdup("Boolean");
|
||||||
@2.first_line,@2.first_column,$1,$3);$$=strdup("undefined");}}
|
} else {
|
||||||
|
printdebug("mismatch at line %d and column %d. Invalid types %s and %s", @2.first_line,@2.first_column,$1,$3);
|
||||||
|
$$=strdup("undefined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
| assignable {printdebug("assignable expression. current type is %s",$1);$$=$1;}
|
| assignable
|
||||||
|
{
|
||||||
|
printdebug("assignable expression. current type is %s",$1);
|
||||||
|
$$=$1;
|
||||||
|
}
|
||||||
|
|
||||||
| L_PAREN expression R_PAREN {printdebug("paren expression. current type is %s",$2);$$=$2;}
|
| L_PAREN expression R_PAREN
|
||||||
|
{
|
||||||
|
printdebug("paren expression. current type is %s",$2);
|
||||||
|
$$=$2;
|
||||||
|
}
|
||||||
|
|
||||||
|
| memOp assignable
|
||||||
|
{
|
||||||
|
$$ = strdup("address");
|
||||||
|
}
|
||||||
|
|
||||||
| memOp assignable {$$ = strdup("address");}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// prolly right, check back with me later
|
// prolly right, check back with me later
|
||||||
// add array case
|
// add array case
|
||||||
// include type check for ablock in arrays - ablock is always the int of the elements in array/rec
|
// include type check for ablock in arrays - ablock is always the int of the elements in array/rec
|
||||||
@ -403,13 +576,16 @@ assignable:
|
|||||||
ID
|
ID
|
||||||
{
|
{
|
||||||
$$ = getType(look_up(cur,$1));
|
$$ = getType(look_up(cur,$1));
|
||||||
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", $$, $1);}
|
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", $$, $1);
|
||||||
|
}
|
||||||
|
|
||||||
| assignable
|
| assignable
|
||||||
{
|
{
|
||||||
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
|
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
|
||||||
cur = CreateScope(cur, -1,-1);
|
cur = CreateScope(cur, -1,-1);
|
||||||
}
|
}
|
||||||
ablock {
|
ablock
|
||||||
|
{
|
||||||
int type = getAdInfoType(look_up(getParent(cur), $1));
|
int type = getAdInfoType(look_up(getParent(cur), $1));
|
||||||
printdebug("%stype is %d", COLOR_PURPLE, type);
|
printdebug("%stype is %d", COLOR_PURPLE, type);
|
||||||
|
|
||||||
@ -435,7 +611,6 @@ assignable:
|
|||||||
}
|
}
|
||||||
lastCheckedRef = tn;
|
lastCheckedRef = tn;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char *expected = getName(getParameter(look_up(getParent(cur), $1)));
|
char *expected = getName(getParameter(look_up(getParent(cur), $1)));
|
||||||
char *actual = getType(getFirstEntry(cur));
|
char *actual = getType(getFirstEntry(cur));
|
||||||
@ -443,6 +618,7 @@ assignable:
|
|||||||
printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column);
|
printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$$ = getName(getReturn(table_lookup(getAncestor(cur), $1)));
|
$$ = getName(getReturn(table_lookup(getAncestor(cur), $1)));
|
||||||
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", $$, $1);
|
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", $$, $1);
|
||||||
|
|
||||||
@ -451,16 +627,12 @@ assignable:
|
|||||||
if (getNumArrDim(look_up(getParent(cur), $1)) != $<integ>2) {
|
if (getNumArrDim(look_up(getParent(cur), $1)) != $<integ>2) {
|
||||||
printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, $1)), $<integ>2, @2.first_line, @2.first_column);
|
printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, $1)), $<integ>2, @2.first_line, @2.first_column);
|
||||||
}
|
}
|
||||||
// for (TableNode *tn = getFirstEntry(cur); tn != NULL; tn = getNextEntry(tn)) {
|
|
||||||
// if (strcmp(getName(tn), "integer") != 0) {
|
|
||||||
// printdebug("expected only integer expressions in array ablock at line %d column %d", @3.first_line, @3.first_column);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
$$ = getName(getArrType(look_up(getParent(cur), $1)));
|
$$ = getName(getArrType(look_up(getParent(cur), $1)));
|
||||||
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", $$, $1);
|
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", $$, $1);
|
||||||
}
|
}
|
||||||
cur = getParent(cur);
|
cur = getParent(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
| assignable rec_op ID
|
| assignable rec_op ID
|
||||||
{
|
{
|
||||||
if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), $1)), $3)) {
|
if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), $1)), $3)) {
|
||||||
@ -468,34 +640,97 @@ assignable:
|
|||||||
}
|
}
|
||||||
printdebug("[ASSIGNABLE - RULE 3] assignable = type: %s | ID = %s", $$, $1);
|
printdebug("[ASSIGNABLE - RULE 3] assignable = type: %s | ID = %s", $$, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
memOp:
|
memOp:
|
||||||
RESERVE {printdebug("reserve expression");}
|
RESERVE
|
||||||
| RELEASE {printdebug("release expression");}
|
{
|
||||||
|
printdebug("reserve expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
| RELEASE
|
||||||
|
{
|
||||||
|
printdebug("release expression");
|
||||||
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
constant:
|
constant:
|
||||||
C_STRING {$$ = $<words>1; printdebug("string of C_STRING in constant is %s",$<words>1);}
|
C_STRING
|
||||||
| C_INTEGER {$$ = "integer"; printdebug("string of C_INTEGER in constant is integer");}
|
{
|
||||||
| C_NULL {$$ = $<words>1; printdebug("string of C_NULL in constant is %s",$<words>1);}
|
$$ = $<words>1;
|
||||||
| C_CHARACTER {$$ = $<words>1; printdebug("string of C_CHARACTER in constant is %s",$<words>1);}
|
printdebug("string of C_STRING in constant is %s",$<words>1);
|
||||||
| C_TRUE {$$ = $<words>1; printdebug("string of C_TRUE in constant is %s",$<words>1);}
|
}
|
||||||
| C_FALSE {$$ = $<words>1; printdebug("string of C_FALSE in constant is %s",$<words>1);}
|
|
||||||
|
| C_INTEGER
|
||||||
|
{
|
||||||
|
$$ = "integer";
|
||||||
|
printdebug("string of C_INTEGER in constant is integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
| C_NULL
|
||||||
|
{
|
||||||
|
$$ = $<words>1;
|
||||||
|
printdebug("string of C_NULL in constant is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
| C_CHARACTER
|
||||||
|
{
|
||||||
|
$$ = $<words>1;
|
||||||
|
printdebug("string of C_CHARACTER in constant is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
| C_TRUE
|
||||||
|
{
|
||||||
|
$$ = $<words>1;
|
||||||
|
printdebug("string of C_TRUE in constant is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
| C_FALSE
|
||||||
|
{
|
||||||
|
$$ = $<words>1;
|
||||||
|
printdebug("string of C_FALSE in constant is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
types:
|
types:
|
||||||
// Commented out T_String below
|
T_INTEGER
|
||||||
// T_STRING {printdebug("string of T_STRING in types is %s",$<words>1);} {$$ = $<words>1;}
|
{
|
||||||
T_INTEGER {printdebug("string of T_INTEGER in types is %s",$<words>1);} {$$ = $1;}
|
$$ = $1;
|
||||||
| T_ADDRESS {printdebug("string of T_ADDRESS in types is %s",$<words>1);} {$$ = $1;}
|
printdebug("string of T_INTEGER in types is %s",$<words>1);
|
||||||
| T_CHARACTER {printdebug("string of T_CHARACTER in types is %s",$<words>1);} {$$ = $1;}
|
}
|
||||||
| T_BOOLEAN {printdebug("string of T_BOOLEAN in types is %s",$<words>1);} {$$ = $1;}
|
|
||||||
|
| T_ADDRESS
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
printdebug("string of T_ADDRESS in types is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
| T_CHARACTER
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
printdebug("string of T_CHARACTER in types is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
|
| T_BOOLEAN
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
printdebug("string of T_BOOLEAN in types is %s",$<words>1);
|
||||||
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void yyerror(const char *err) {
|
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);
|
fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d", err,yytext,yylloc.first_line,yylloc.first_column);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,8 @@ typedef enum {
|
|||||||
// TYPE_ADDRESS,
|
// TYPE_ADDRESS,
|
||||||
// Type String is an array of char enclosed in double quotes per lexer
|
// Type String is an array of char enclosed in double quotes per lexer
|
||||||
TYPE_STRING = 1,
|
TYPE_STRING = 1,
|
||||||
// Array can be multidimensional. Information should be stored here. This is the type of the array
|
// Array can be multidimensional. Information should be stored here.
|
||||||
|
// This is the type of the array
|
||||||
TYPE_ARRAY_TYPE = 2,
|
TYPE_ARRAY_TYPE = 2,
|
||||||
// Record is user defined types
|
// Record is user defined types
|
||||||
TYPE_RECORD_TYPE = 3,
|
TYPE_RECORD_TYPE = 3,
|
||||||
@ -513,8 +514,9 @@ SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column) {
|
|||||||
// types
|
// types
|
||||||
SymbolTable *init(SymbolTable *start) {
|
SymbolTable *init(SymbolTable *start) {
|
||||||
if (start->Parent_Scope != NULL) {
|
if (start->Parent_Scope != NULL) {
|
||||||
printdebug(
|
printdebug("%s[FATAL] Cannot initialize a scope that is not "
|
||||||
"%s[FATAL] Cannot initialize a scope that is not the parent scope", COLOR_RED);
|
"the parent scope",
|
||||||
|
COLOR_RED);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
integ = (TableNode *)calloc(1, sizeof(TableNode));
|
integ = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
@ -707,15 +709,15 @@ int getAdInfoType(TableNode *tn) {
|
|||||||
if (strcmp(getName(tn), getName(undefined)) == 0) {
|
if (strcmp(getName(tn), getName(undefined)) == 0) {
|
||||||
return TYPE_UNDEFINED;
|
return TYPE_UNDEFINED;
|
||||||
} else {
|
} else {
|
||||||
if(strcmp(getType(tn), getName(funtypeprime))==0){
|
if (strcmp(getType(tn), getName(funtypeprime)) == 0) {
|
||||||
printdebug("passed in a function to getAdInfoType");
|
printdebug("passed in a function to getAdInfoType");
|
||||||
return TYPE_FUNCTION_DECLARATION;
|
return TYPE_FUNCTION_DECLARATION;
|
||||||
}
|
}
|
||||||
if(strcmp(getType(tn), getName(arrayprim))==0){
|
if (strcmp(getType(tn), getName(arrayprim)) == 0) {
|
||||||
printdebug("passed in an array to getAdInfoType");
|
printdebug("passed in an array to getAdInfoType");
|
||||||
return TYPE_ARRAY_TYPE;
|
return TYPE_ARRAY_TYPE;
|
||||||
}
|
}
|
||||||
if(strcmp(getType(tn), getName(recprime))==0){
|
if (strcmp(getType(tn), getName(recprime)) == 0) {
|
||||||
printdebug("passed in a record to getAdInfoType");
|
printdebug("passed in a record to getAdInfoType");
|
||||||
return TYPE_RECORD;
|
return TYPE_RECORD;
|
||||||
}
|
}
|
||||||
@ -1139,13 +1141,14 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
|
|||||||
if (getChildren(table) != NULL) {
|
if (getChildren(table) != NULL) {
|
||||||
ListOfTable *node = getChildren(table);
|
ListOfTable *node = getChildren(table);
|
||||||
for (; node != NULL; node = node->next) {
|
for (; node != NULL; node = node->next) {
|
||||||
if((node->table) == NULL){
|
if ((node->table) == NULL) {
|
||||||
print_symbol_table(node->table, file_ptr);
|
print_symbol_table(node->table, file_ptr);
|
||||||
}else{
|
} else {
|
||||||
if ((node->table)->Line_Number == -1){
|
if ((node->table)->Line_Number == -1) {
|
||||||
continue;
|
continue;
|
||||||
}else{
|
} else {
|
||||||
print_symbol_table(node->table, file_ptr);
|
print_symbol_table(node->table,
|
||||||
|
file_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user