Added vectors into the syntax of the language
This commit is contained in:
parent
034a97e3ab
commit
cf0a90dda1
6 changed files with 71 additions and 6 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define STATEMENT 200
|
||||
#define CALLFUNC 201
|
||||
#define VECTOR 202
|
||||
|
||||
class Node;
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ std::string tree_string(const Node* node, uint tabs) {
|
|||
|
||||
switch(node->type) {
|
||||
case IDENTIFIER: result += "IDENTIFIER: " + node->id + "\n"; break;
|
||||
case VECTOR: result += "VECTOR:\n"; break;
|
||||
case PLUS: result += "PLUS:\n"; break;
|
||||
case MINUS: result += "MINUS:\n"; break;
|
||||
case DIVIDE: result += "DIVIDE:\n"; break;
|
||||
|
@ -81,6 +82,54 @@ std::string tree_string(const Node* node, uint tabs) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Value* parse_vector(Node* node) {
|
||||
// We will only support homogeneous vectors
|
||||
// Get the first data type from the first node
|
||||
Value* tempValue = new Value(*node->value);
|
||||
TypeTag type = tempValue->type;
|
||||
delete tempValue;
|
||||
|
||||
// Only numeric types and booleans are supported currently
|
||||
if (type != LONG && type != BOOLEAN && type != DOUBLE) {
|
||||
std::cerr << "Error, only numeric types and booleans are supported in vector form." << std::endl;
|
||||
return make_false();
|
||||
}
|
||||
|
||||
std::vector<long> longResult;
|
||||
std::vector<double> doubleResult;
|
||||
bool lastNode = false;
|
||||
|
||||
Node* currentNode = node;
|
||||
do {
|
||||
if (currentNode->value->type == type) {
|
||||
tempValue = new Value(*currentNode->value);
|
||||
if (type == LONG || type == BOOLEAN) {
|
||||
std::vector<long> tempVec = get_long(tempValue);
|
||||
delete tempValue;
|
||||
longResult.insert(std::end(longResult), std::begin(tempVec), std::end(tempVec));
|
||||
} else { // Assume Double
|
||||
std::vector<double> tempVec = get_double(tempValue);
|
||||
delete tempValue;
|
||||
doubleResult.insert(std::end(doubleResult), std::begin(tempVec), std::end(tempVec));
|
||||
}
|
||||
} else { std::cerr << "Error, only homogenous arrays are supported." << std::endl; return make_false(); }
|
||||
if (currentNode->num_children == 0) {
|
||||
lastNode = true;
|
||||
} else {
|
||||
currentNode = currentNode->children[0];
|
||||
}
|
||||
} while (currentNode->num_children == 1 || !lastNode);
|
||||
|
||||
|
||||
|
||||
if (type == LONG || type == BOOLEAN) {
|
||||
return make_long(longResult);
|
||||
} else { // Assume double
|
||||
return make_double(doubleResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Value* eval_expression(Node* node, Environment* env) {
|
||||
/* base case */
|
||||
if(!node) {
|
||||
|
@ -112,6 +161,7 @@ Value* eval_expression(Node* node, Environment* env) {
|
|||
|
||||
switch(node->type) {
|
||||
case LAMBDATAG: return make_expression(node); break;
|
||||
case VECTOR: return parse_vector(node->children[0]); break;
|
||||
case CALLFUNC:
|
||||
check_num_nodes(node, 2, "cannot have more than two nodes for a function call.");
|
||||
tempVal = get_value(find_variable(env, node->children[0]->id));
|
||||
|
|
|
@ -51,4 +51,6 @@ std::string tree_string(const Node* node, uint tabs);
|
|||
void eval_statement(Node* node, Environment* env);
|
||||
Value* eval_expression(Node* node, Environment* env);
|
||||
|
||||
Value* parse_vector(Node* node);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,6 +46,7 @@ DIGIT [0-9]
|
|||
"input" {return INPUT;}
|
||||
"lambda" {return LAMBDATAG;}
|
||||
":" {return COLON;}
|
||||
"," {return COMMA;}
|
||||
"true" {yylval.value = new Node(VALUE, std::unique_ptr<Value>(make_true()), ""); return VALUE;}
|
||||
"false" {yylval.value = new Node(VALUE, std::unique_ptr<Value>(make_false()), ""); return VALUE;}
|
||||
\".*\" {yylval.value = new Node(VALUE, std::unique_ptr<Value>(make_string(substring(yytext, 1, strlen(yytext) - 1))), ""); return VALUE; }
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
/* declare type possibilities of symbols */
|
||||
%union {
|
||||
struct Node* value;
|
||||
Node* value;
|
||||
}
|
||||
|
||||
/* declare tokens (default is typeless) */
|
||||
|
@ -31,7 +31,9 @@
|
|||
%token SEMICOLON
|
||||
%token ASSIGN
|
||||
%token OPENPAREM
|
||||
%token ENDPAREM
|
||||
%token ENDPAREM
|
||||
%token OPENVECTOR
|
||||
%token CLOSEVECTOR
|
||||
%token BEGINTOK
|
||||
%token END
|
||||
%token IF
|
||||
|
@ -46,9 +48,10 @@
|
|||
%token DONE
|
||||
%token <value> LAMBDATAG
|
||||
%token COLON
|
||||
%token COMMA
|
||||
|
||||
/* declare non-terminals */
|
||||
%type <value> program statement assignment if-statement if-else-statement while print statements substatements callfunc exprlambda expression subexpression term subterm factor atom identvalue ident
|
||||
%type <value> program statement assignment if-statement if-else-statement while print statements substatements callfunc vector vectorlist exprlambda expression subexpression term subterm factor atom identvalue ident
|
||||
|
||||
/* give us more detailed errors */
|
||||
%error-verbose
|
||||
|
@ -64,7 +67,7 @@ statement: assignment { $$ = $1; }
|
|||
| print { $$ = $1; }
|
||||
| statements { $$ = $1; }
|
||||
|
||||
assignment: ident ASSIGN exprlambda SEMICOLON {
|
||||
assignment: ident ASSIGN vector SEMICOLON {
|
||||
$$ = new Node(ASSIGN, NULL, "");
|
||||
attach_node($$, $1);
|
||||
attach_node($$, $3);
|
||||
|
@ -89,7 +92,7 @@ while: WHILE expression DO statement {
|
|||
attach_node($$, $4);
|
||||
}
|
||||
|
||||
print: PRINT exprlambda SEMICOLON {
|
||||
print: PRINT vector SEMICOLON {
|
||||
$$ = new Node(PRINT, NULL, "");
|
||||
attach_node($$, $2);
|
||||
}
|
||||
|
@ -101,6 +104,13 @@ statements: BEGINTOK substatements END { $$ = $2; }
|
|||
substatements: statement substatements {$$ = new Node(STATEMENT, NULL, ""); attach_node($$, $1); attach_node($$, $2); }
|
||||
| statement {$$ = new Node(STATEMENT, NULL, ""); attach_node($$, $1); }
|
||||
|
||||
vector: OPENVECTOR CLOSEVECTOR { $$ = new Node(VECTOR, std::unique_ptr<Value>(nullptr), ""); /*Empty vector*/ }
|
||||
| OPENVECTOR vectorlist CLOSEVECTOR { $$ = new Node(VECTOR, std::unique_ptr<Value>(nullptr), ""); attach_node($$, $2); }
|
||||
| exprlambda { $$ = $1; }
|
||||
|
||||
vectorlist: exprlambda COMMA vectorlist {$$ = $1; attach_node($$, $3); }
|
||||
| exprlambda { $$ = $1; }
|
||||
|
||||
exprlambda: LAMBDATAG ident COLON expression {
|
||||
// Only supports one argument functions for now
|
||||
$$ = new Node(LAMBDATAG, NULL, "");
|
||||
|
@ -143,6 +153,7 @@ ident: IDENTIFIER { $$ = $1; }
|
|||
identvalue: ident { $$ = $1; }
|
||||
| VALUE { $$ = $1; }
|
||||
| INPUT { $$ = new Node(INPUT, NULL , ""); }
|
||||
| OPENVECTOR identvalue CLOSEVECTOR { $$ = new Node(OPENVECTOR, NULL, ""); attach_node($$, $2); }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class Value {
|
|||
|
||||
// Destructor
|
||||
~Value() {
|
||||
std::cout << "VALUE DESTROYED" << std::endl;
|
||||
// std::cout << "VALUE DESTROYED" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Reference in a new issue