This server is intended for use for Academic Classwork related Git repositories only. Projects/repositories will generally be removed after 6 months following close of the semester. Inactive repositories from previous semester are now being archived when no activity for 365 days. They are renamed and marked as 'archived'. After 90 days in that state they will be removed from the system completely.

Commit ded446bf authored by jdev52's avatar jdev52

finished assignment (all but one test case works)

parent ac157dd0
......@@ -18,6 +18,10 @@ using namespace std;
#define INT_OR_STR_OR_BOOL 7
#define NOT_APPLICABLE -1
#define ARITHMETIC 10
#define LOGICAL 11
#define RELATIONAL 12
class SYMBOL_TABLE
{
private:
......@@ -54,7 +58,7 @@ public:
SYMBOL_TABLE_ENTRY getEntry(string theName)
{
return hashTable.find(theName)->first;
return hashTable.find(theName)->second;
}
int count()
......
......@@ -8,11 +8,15 @@ using namespace std;
typedef struct
{
int type;
// one of the above type codes
int numParams;
int type;
// numParams and returnType only applicable if type == FUNCTION
int returnType;
int numParams;
int returnType;
// operatorType is only applicable if production is an operator
int operatorType;
} TYPE_INFO;
class SYMBOL_TABLE_ENTRY
......@@ -38,9 +42,17 @@ public:
typeInfo.numParams = theType.numParams;
}
SYMBOL_TABLE_ENTRY(const string theName, const int type = UNDEFINED,
const int numParams = UNDEFINED, const int returnType = UNDEFINED){
name = theName;
typeInfo.type = type;
typeInfo.returnType = numParams;
typeInfo.numParams = returnType;
}
// Accessors
string getName() const { return name; }
TYPE_INFO getTypeCode() const { return typeInfo; }
TYPE_INFO getTypeInfo() const { return typeInfo; }
};
#endif // SYMBOL_TABLE_ENTRY_H
......@@ -23,7 +23,7 @@ test_files=`ls ./sample_input`
diff_files=0
for file in $test_files; do
mfpl < ./sample_input/$file > ./my_output/$file.out
./mfpl < ./sample_input/$file > ./my_output/$file.out
diff_lines=`diff ./my_output/$file.out \
./expected_output/$file.out \
......
......@@ -29,151 +29,124 @@ COMMENT ";".*
{COMMENT} {}
"let*" {
printToken("LETSTAR", yytext);
beginScope();
return T_LETSTAR;
}
"lambda" {
printToken("LAMBDA", yytext);
beginScope();
return T_LAMBDA;
}
"input" {
printToken("INPUT", yytext);
return T_INPUT;
}
"print" {
printToken("PRINT", yytext);
return T_PRINT;
}
"if" {
printToken("IF", yytext);
return T_IF;
}
"exit" {
printToken("EXIT", yytext);
return T_EXIT;
}
"progn" {
printToken("PROGN", yytext);
return T_PROGN;
}
"(" {
printToken("LPAREN", yytext);
return T_LPAREN;
}
")" {
printToken("RPAREN", yytext);
return T_RPAREN;
}
"+" {
printToken("ADD", yytext);
return T_ADD;
}
"*" {
printToken("MULT", yytext);
return T_MULT;
}
"/" {
printToken("DIV", yytext);
return T_DIV;
}
"-" {
printToken("SUB", yytext);
return T_SUB;
}
"and" {
printToken("AND", yytext);
return T_AND;
}
"or" {
printToken("OR", yytext);
return T_OR;
}
"not" {
printToken("NOT", yytext);
return T_NOT;
}
"<" {
printToken("LT", yytext);
return T_LT;
}
">" {
printToken("GT", yytext);
return T_GT;
}
"<=" {
printToken("LE", yytext);
return T_LE;
}
">=" {
printToken("GE", yytext);
return T_GE;
}
"=" {
printToken("EQ", yytext);
return T_EQ;
}
"/=" {
printToken("NE", yytext);
return T_NE;
}
"t" {
printToken("T", yytext);
return T_T;
}
"nil" {
printToken("NIL", yytext);
return T_NIL;
}
{IDENT} {
yylval.text = strdup(yytext);
printToken("IDENT", yytext);
return T_IDENT;
}
{INTCONST} {
printToken("INTCONST", yytext);
return T_INTCONST;
}
{STRCONST} {
printToken("STRCONST", yytext);
return T_STRCONST;
}
......@@ -184,7 +157,6 @@ COMMENT ";".*
{WSPACE} { }
. {
printToken("UNKNOWN", yytext);
return T_UNKNOWN;
}
%%
\ No newline at end of file
......@@ -8,8 +8,6 @@
#include "SymbolTable.h"
using namespace std;
int lineNum = 1; // line # being processed
stack<SYMBOL_TABLE> scopeStack; // stack of scope hashtables
void beginScope();
......@@ -19,17 +17,14 @@ void prepareToTerminate();
void bail();
bool findEntryInAnyScope(const string theName);
SYMBOL_TABLE_ENTRY getEntryInAnyScope(const string theName);
void printToken(const char* tokenType, char* lexeme);
void printRule(const char*, const char*);
int yyerror(const char* s)
{
printf("Line %d: %s\n", lineNum, s);
bail();
return 0;
}
int yyerror(const char* s);
extern "C"
{
......@@ -76,6 +71,7 @@ N_START : // epsilon
}
| N_START N_EXPR
{
cout << "EXPR type is: ";
switch ($2.type){
case 1:
cout<<"INT"<<"\n";
......@@ -99,9 +95,11 @@ N_START : // epsilon
cout<<"STR_OR_BOOL"<<"\n";
break;
case 7:
cout<<"INT_STR_OR_BOOL"<<"\n";
cout<<"INT_OR_STR_OR_BOOL"<<"\n";
break;
}
cout << "---- Completed parsing ----\n" << endl;
}
;
N_EXPR : N_CONST
......@@ -113,18 +111,19 @@ N_EXPR : N_CONST
}
| T_IDENT
{
if (!findEntryInAnyScope(string($1)))
string lexeme = string($1);
if (!findEntryInAnyScope(lexeme))
yyerror("Undefined identifier");
//resulting type is the type of the identifier
//look up in the symbol table
$$.type = getEntryInAnyScope(lexeme).getTypeInfo().type;
}
| T_LPAREN N_PARENTHESIZED_EXPR T_RPAREN
{
//resulting type is the resulting type of the parenthesized expr
$$.type=$2.type;
$$.numParams=$2.numParams;
$$.returnType=$2.returnType;
$$.type=$2.type;
$$.numParams=$2.numParams;
$$.returnType=$2.returnType;
}
;
N_CONST : T_INTCONST
......@@ -156,7 +155,8 @@ N_CONST : T_INTCONST
$$.returnType=NOT_APPLICABLE;
}
;
N_PARENTHESIZED_EXPR : N_ARITHLOGIC_EXPR //resulting type of whatever rule is applied
N_PARENTHESIZED_EXPR : N_ARITHLOGIC_EXPR
//resulting type of whatever rule is applied
{
$$.type=$1.type;
$$.numParams=$1.numParams;
......@@ -201,40 +201,84 @@ N_PARENTHESIZED_EXPR : N_ARITHLOGIC_EXPR //resulting type of whatever rule is
}
| T_EXIT
{
bail();
bail();
}
;
N_PROGN_OR_USERFUNCTCALL : N_FUNCT_NAME N_ACTUAL_PARAMS
{
if($1.type == UNDEFINED){
if($2.type == NOT_APPLICABLE){
$$.type = BOOL;
} else {
$$.type = $2.type;
}
} else {
if($1.numParams < $2.numParams){
yyerror("Too many parameters in function call");
} else if ($1.numParams < $2.numParams){
yyerror("Too few parameters in function call");
}
$$.type = $1.type;
}
$$.numParams = $2.numParams;
$$.returnType = UNDEFINED;
}
| T_LPAREN N_LAMBDA_EXPR T_RPAREN N_ACTUAL_PARAMS
{
if($2.numParams < $4.numParams){
yyerror("Too many parameters in function call");
} else if ($4.numParams < $2.numParams){
yyerror("Too few parameters in function call");
}
$$.type = $2.returnType;
$$.numParams = $4.numParams;
$$.returnType = $2.returnType;
}
;
N_ACTUAL_PARAMS : N_EXPR_LIST
{
$$.type = $1.type;
$$.numParams = $1.numParams;
$$.returnType = $1.type;
}
| /*epsilon*/
{
$$.type = NOT_APPLICABLE;
$$.numParams = 0;
$$.returnType = NOT_APPLICABLE;
}
N_FUNCT_NAME : T_PROGN
{
}
| T_IDENT
{
{
$$.type = UNDEFINED;
$$.numParams = 0;
$$.returnType = UNDEFINED;
}
| T_IDENT
{
string lexeme = string($1);
if (!findEntryInAnyScope(lexeme))
yyerror("Undefined identifier");
if (!findEntryInAnyScope(string($1)))
yyerror("Undefined identifier");
}
;
TYPE_INFO typeInfo = getEntryInAnyScope(lexeme).getTypeInfo();
if(typeInfo.type != FUNCTION){
yyerror("Arg n must be a function");
}
$$.type = typeInfo.returnType;
$$.numParams = typeInfo.numParams;
$$.returnType = typeInfo.returnType;
}
;
N_ARITHLOGIC_EXPR : N_UN_OP N_EXPR
{
printRule("ARITHLOGIC_EXPR", "UN_OP EXPR");
if ($2.type == FUNCTION)
yyerror("Arg 1 cannot be function");
yyerror("Arg 1 cannot be a function");
$$.type = BOOL;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
......@@ -242,122 +286,212 @@ N_ARITHLOGIC_EXPR : N_UN_OP N_EXPR
| N_BIN_OP N_EXPR N_EXPR
{
//check if operation can be preformed
switch($1.operatorType){
case RELATIONAL:
if(($2.type != INT) && ($2.type != STR)){
yyerror("Arg 1 must be integer or string");
}
if(($3.type != INT) && ($3.type != STR)){
yyerror("Arg 2 must be integer or string");
}
if(($2.type == INT) && (($3.type != INT) && ($3.type != INT_OR_STR))){
yyerror("Arg 2 must be integer");
}
if(($2.type == STR) && (($3.type != STR) && ($3.type != INT_OR_STR))){
yyerror("Arg 2 must be string");
}
break;
case LOGICAL:
if($2.type == FUNCTION) {
yyerror("Arg 1 cannot be a function");
}
if($3.type == FUNCTION) {
yyerror("Arg 2 cannot be a function");
}
break;
case ARITHMETIC:
switch($2.type){
case INT:
case INT_OR_STR:
case INT_OR_BOOL:
case INT_OR_STR_OR_BOOL:
break;
default:
yyerror("Arg 1 must be integer");
break;
}
switch($3.type){
case INT:
case INT_OR_STR:
case INT_OR_BOOL:
case INT_OR_STR_OR_BOOL:
break;
default:
yyerror("Arg 2 must be integer");
break;
}
break;
}
$$.type = $1.type;
$$.numParams = $1.numParams;
$$.returnType = $1.returnType;
}
;
N_IF_EXPR : T_IF N_EXPR N_EXPR N_EXPR
{
//type of expr1 + type of expr2+ type of expr3= type of if statement
if($2.type == FUNCTION)
yyerror("Arg 1 cannot be function");
yyerror("Arg 1 cannot be a function");
else if($3.type == FUNCTION)
yyerror("Arg 2 cannot be function");
yyerror("Arg 2 cannot be a function");
else if($4.type == FUNCTION)
yyerror("Arg 3 cannot be function");
$$.type=$2.type + $3.type + $4.type;
yyerror("Arg 3 cannot be a function");
$$.type = $3.type | $4.type;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
}
;
N_LET_EXPR
: T_LETSTAR T_LPAREN N_ID_EXPR_LIST T_RPAREN N_EXPR
{
endScope();
if($5.type==FUNCTION)
yyerror("Arg 1 cannot be function");
yyerror("Arg 2 cannot be a function");
$$.type=$5.type;
endScope();
$$.numParams = $5.numParams;
$$.returnType = $5.returnType;
}
;
N_ID_EXPR_LIST : /* epsilon */
{
}
| N_ID_EXPR_LIST T_LPAREN T_IDENT N_EXPR T_RPAREN
{
string lexeme = string($3);
printf("___Adding %s to symbol table\n", $3);
bool found = scopeStack.top().findEntry(lexeme);
if (found)
yyerror("Multiply defined identifier");
string lexeme = string($3);
printf("___Adding %s to symbol table\n", $3);
bool success = scopeStack.top().addEntry
(SYMBOL_TABLE_ENTRY(lexeme,
UNDEFINED));
if (! success)
yyerror("Multiply defined identifier");
$3.type=$4.type;
scopeStack.top().addEntry(SYMBOL_TABLE_ENTRY(lexeme, $4));
}
;
N_LAMBDA_EXPR : T_LAMBDA T_LPAREN N_ID_LIST T_RPAREN N_EXPR
{
endScope();
if($5.type==FUNCTION)
yyerror("Arg 1 cannot be function");
yyerror("Arg 1 cannot be a function");
$$.type=FUNCTION;
$$.numParams=//length of id list
$$.numParams=$3.numParams;
$$.returnType=$5.type;
endScope();
}
;
N_ID_LIST : /* epsilon */
{
$$.numParams = 0;
}
| N_ID_LIST T_IDENT
{
string lexeme = string($2);
printf("___Adding %s to symbol table\n", $2);
bool found = scopeStack.top().findEntry(lexeme);
if (found)
yyerror("Multiply defined identifier");
scopeStack.top().addEntry(SYMBOL_TABLE_ENTRY(lexeme, INT_OR_STR_OR_BOOL));
string lexeme = string($2);
printf("___Adding %s to symbol table\n", $2);
bool success = scopeStack.top().addEntry(SYMBOL_TABLE_ENTRY(lexeme,UNDEFINED));
if (! success)
yyerror("Multiply defined identifier");
$2.type=INT_OR_STR_OR_BOOL;
$$.type = INT;
$$.numParams = $1.numParams+1;
$$.returnType = NOT_APPLICABLE;
}
;
N_PRINT_EXPR : T_PRINT N_EXPR
{
if($2.type==FUNCTION)
yyerror("Arg 1 cannot be function");
yyerror("Arg 1 cannot be a function");
$$.type=$2.type;
$$.numParams = $2.numParams;
$$.returnType = $2.returnType;
}
;
N_INPUT_EXPR : T_INPUT
{
$$.type=INT_OR_STR;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
}
;
N_EXPR_LIST : N_EXPR N_EXPR_LIST
{
$$.type=$2.type;
// if($1.type == FUNCTION){
// if($1.numParams < $2.numParams){
// yyerror("Too many parameters in function call");
// } else if ($2.numParams < $1.numParams){
// yyerror("Too few parameters in function call");
// }
// }
$$.type = $2.type;
$$.numParams = $2.numParams+1;
$$.returnType = NOT_APPLICABLE;
}
| N_EXPR
{
$$.type=$1.type;
if($1.type == FUNCTION) {
$$.type = $1.returnType;
}
$$.numParams = 1;
$$.returnType = NOT_APPLICABLE;
}
;
N_BIN_OP : N_ARITH_OP
N_BIN_OP : N_ARITH_OP
{
$$.type = INT;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
$$.operatorType = ARITHMETIC;
}
|
N_LOG_OP
{
$$.type = BOOL;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
$$.operatorType = LOGICAL;
}
|
N_REL_OP
{
$$.type = BOOL;
$$.numParams = NOT_APPLICABLE;
$$.returnType = NOT_APPLICABLE;
$$.operatorType = RELATIONAL;
}
;
N_ARITH_OP : T_ADD
N_ARITH_OP : T_ADD
{
}
| T_SUB
| T_SUB
{
}
| T_MULT
{
}
| T_DIV
{
}
;
N_REL_OP : T_LT
N_REL_OP : T_LT
{
}
| T_GT
......@@ -376,7 +510,7 @@ N_REL_OP : T_LT
{
}
;
N_LOG_OP : T_AND
N_LOG_OP : T_AND
{
}
| T_OR
......@@ -398,6 +532,13 @@ void printRule(const char* lhs, const char* rhs)
return;
}
int yyerror(const char* s)
{
printf("Line %d: %s\n", numLines, s);
bail();
return 0;
}
void printToken(const char* tokenType, char* lexeme){
printf("TOKEN: %-8s LEXEME: %s\n", tokenType, lexeme);