diff --git a/src/constants.hpp b/src/constants.hpp index 4f54aba..d7882c0 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -3,6 +3,7 @@ #define STATEMENT 200 #define CALLFUNC 201 +#define VECTOR 202 class Node; diff --git a/src/operations/node.cpp b/src/operations/node.cpp index 4d751c2..3a9feb0 100644 --- a/src/operations/node.cpp +++ b/src/operations/node.cpp @@ -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 longResult; + std::vector 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 tempVec = get_long(tempValue); + delete tempValue; + longResult.insert(std::end(longResult), std::begin(tempVec), std::end(tempVec)); + } else { // Assume Double + std::vector 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)); diff --git a/src/operations/node.hpp b/src/operations/node.hpp index 6da0660..7ac5a41 100644 --- a/src/operations/node.hpp +++ b/src/operations/node.hpp @@ -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 diff --git a/src/parser/lexer.l b/src/parser/lexer.l index ef87709..d31d458 100644 --- a/src/parser/lexer.l +++ b/src/parser/lexer.l @@ -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(make_true()), ""); return VALUE;} "false" {yylval.value = new Node(VALUE, std::unique_ptr(make_false()), ""); return VALUE;} \".*\" {yylval.value = new Node(VALUE, std::unique_ptr(make_string(substring(yytext, 1, strlen(yytext) - 1))), ""); return VALUE; } diff --git a/src/parser/parser.y b/src/parser/parser.y index a8d5e15..11d0b39 100644 --- a/src/parser/parser.y +++ b/src/parser/parser.y @@ -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 LAMBDATAG %token COLON +%token COMMA /* declare non-terminals */ -%type program statement assignment if-statement if-else-statement while print statements substatements callfunc exprlambda expression subexpression term subterm factor atom identvalue ident +%type 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(nullptr), ""); /*Empty vector*/ } + | OPENVECTOR vectorlist CLOSEVECTOR { $$ = new Node(VECTOR, std::unique_ptr(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); } diff --git a/src/variables/value.hpp b/src/variables/value.hpp index 790cf6e..f1870c7 100644 --- a/src/variables/value.hpp +++ b/src/variables/value.hpp @@ -52,7 +52,7 @@ class Value { // Destructor ~Value() { - std::cout << "VALUE DESTROYED" << std::endl; + // std::cout << "VALUE DESTROYED" << std::endl; } };