Files
RCBASIC4/rcbasic_build/parser.h

7011 lines
277 KiB
C++
Executable File

#ifndef PARSER_H_INCLUDED
#define PARSER_H_INCLUDED
#include "tokenizer.h"
#include "identifier.h"
#include "rc_global.h"
#include "constants.h"
#include <inttypes.h>
using namespace std;
int max_for_count = 0;
//vm registers
int max_n_reg = 0;
int max_s_reg = 0;
int max_u_reg = 0;
int n_reg = 0;
int s_reg = 0;
int u_reg = 0;
//expression result
string expr_result = "";
bool type_delete_flag = false;
string type_delete_arg = "";
int type_delete_arg_type = 0;
bool type_delete_arg_whole = false;
bool type_redim_flag = false;
string type_redim_arg = "";
int type_redim_arg_type = 0;
string type_redim_arg_utype = "";
string type_redim_dim[3];
int type_redim_dim_count = 0;
bool type_no_arg_exception_raised = false;
struct type_error_exception
{
string error_log;
string tk_reg;
string resolve_reg;
int num_args;
bool exception_used;
};
vector<type_error_exception> byref_type_exception; //This will store the error that might be generated if a user type var is in an expression without its dimensions expressed
bool pre_parse(int start_token, int end_token, int pp_flags = 0, bool eval_udt = false); //puts number and string values and variables inside number and string registers
//void getBlock(int& start_block, int& end_block); //gets the start and end index of the next block to evaluate (first and last token if there isnt a block left to evaluate
bool eval_pow(int start_block, int end_block);
bool eval_muldiv(int start_block, int end_block); //MOD operator is also evaluated in this function
bool eval_addsub(int start_block, int end_block);
bool eval_tokens(); //evaluates the tokens and generates vm_asm opcodes
vector<string> n_tmp;
vector<string> s_tmp;
vector<string> u_tmp;
void inc_n(int x)
{
n_reg += x;
if( (n_reg+1) > max_n_reg)
max_n_reg = n_reg + 1;
}
void inc_s(int x)
{
s_reg += x;
if( (s_reg+1) > max_s_reg)
max_s_reg = s_reg + 1;
}
void inc_u(int x)
{
u_reg += x;
if( (u_reg+1) > max_u_reg)
max_u_reg = u_reg + 1;
}
void debug_output_VMASM()
{
for(int i = 0; i < vm_asm.vm_code.size(); i++)
cout << vm_asm.vm_code[i] << endl;
}
void clear_asm()
{
vm_asm.clear();
}
//end block will be set to -1 if a block was opened but wasn't closed
void getBlock(int start_token, int end_token, int& start_block, int& end_block)
{
start_block = start_token; //start_block is set to 0, if there is no block started it will automatically start at the first token
//end_block = token.size()-1; //end_block is set to the last token, if there is no block started or ended then it will be the last token
if(end_token > 0)
end_block = end_token;
else
end_block = token.size()-1;
//this loop will go through every token until it finds a start_block and end_block
for(int i = start_token; i <= end_token; i++)
{
//sets the start_block to the last open block token it discovers
if(token[i].compare("<par>")==0 || token[i].compare("<square>")==0 || token[i].compare("<curly>")==0)
start_block = i;
//if an ending block was encountered and it matches the current start block then the current end_block will be set to the current token
if( (token[i].compare("</par>")==0 && token[start_block].compare("<par>")==0) ||
(token[i].compare("</square>")==0 && token[start_block].compare("<square>")==0) ||
(token[i].compare("</curly>")==0 && token[start_block].compare("<curly>")==0))
{
end_block = i;
//put a ! at the beginning of the start and end block tokens so that they won't be evaluated the next time this function is called
token[start_block] = "!" + token[start_block];
token[end_block] = "!" + token[end_block];
return;
}
//if there is a ending block discovered that did not have a matching start block then we set end_block to -1 and set an error message
else if(token[i].compare("</par>")==0 || token[i].compare("</square>")==0 || token[i].compare("</curly>")==0)
{
if(token[i].compare("</par>")==0)
rc_setError("Found \")\" without \"(\"");
else if(token[i].compare("</square>")==0)
rc_setError("Found \"]\" without \"[\"");
else if(token[i].compare("</curly>")==0)
rc_setError("Found \"}\" without \"{\"");
end_block = -1;
return;
}
}
//if start_block is a bracket and the closing bracket was not found before the end of the loop then end_block is set to -1 and we set an error message
if(token[start_block].compare("<par>")==0)
{
rc_setError("Found \"(\" without \")\"");
end_block = -1;
}
else if(token[start_block].compare("<square>")==0)
{
rc_setError("Found \"[\" without \"]\"");
end_block = -1;
}
else if(token[start_block].compare("<curly>")==0)
{
rc_setError("Found \"{\" without \"}\"");
end_block = -1;
}
}
//This function checks to see if a token can be exempt from the token check that eval functions do
bool token_exemption(int i)
{
if(token[i].compare("!<par>")==0 || token[i].compare("!</par>")==0 ||
token[i].compare("!<square>")==0 || token[i].compare("!</square>")==0 ||
token[i].compare("!<curly>")==0 || token[i].compare("!</curly>")==0)
return true;
return false;
}
//This function will clear every token from the first operand to the second operand and set the start operand token to solution
void set_op_solution(int start_op, int end_op, string solution)
{
for(int i = start_op; i <= end_op; i++)
{
if(!token_exemption(i))
token[i] = "";
}
token[start_op] = solution;
}
void getRegInfo(string r_reg, int &arg_type, int &arg_utype)
{
for(int i = 0; i < resolveID_id_reg.size(); i++)
{
if(resolveID_id_reg[i].compare(r_reg)==0)
{
arg_type = resolveID_id_type[i];
arg_utype = resolveID_id_ut_index[i];
return;
}
}
if(r_reg.substr(0,1).compare("s")==0)
{
arg_type = ID_TYPE_STR;
arg_utype = 0;
}
else
{
arg_type = ID_TYPE_NUM;
arg_utype = 0;
}
return;
}
bool eval_pow(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
//cout << "debug_POW " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 && token[i].compare("<pow>")!=0 && (op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
//cout << "op2 = " << operand2 << endl;
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<pow>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for exponent operation");
return false;
}
op_flag = 2;
}
else if(token[i].compare("")!=0)
{
//cout << "reset -- " << token[i] << endl;
op_flag = 0;
}
if(op_flag==3)
{
if(operand1.substr(0,1).compare("n")!=0 || operand2.substr(0,1).compare("n")!=0)
{
rc_setError("Expected number operand for exponent operation");
return false;
}
vm_asm.push_back("pow " + operand1 + " " + operand2);
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for exponent operation");
return false;
}
return true;
}
bool eval_muldiv(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - mul, 1 - div, 2 - mod
//cout << "debug_MDM " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<mul>")!=0 &&
token[i].compare("<div>")!=0 &&
token[i].compare("<mod>")!=0 &&
(op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<mul>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for mul/div operation");
return false;
}
op_flag = 2;
operation = 0;
}
else if(token[i].compare("<div>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for mul/div operation");
return false;
}
op_flag = 2;
operation = 1;
}
else if(token[i].compare("<mod>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for mul/div operation");
return false;
}
op_flag = 2;
operation = 2;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==3)
{
if(operand1.substr(0,1).compare("n")!=0 || operand2.substr(0,1).compare("n")!=0)
{
rc_setError("Expected number operand for mul/div operation");
return false;
}
switch(operation)
{
case 0:
vm_asm.push_back("mul " + operand1 + " " + operand2);
break;
case 1:
vm_asm.push_back("div " + operand1 + " " + operand2);
break;
case 2:
vm_asm.push_back("mod " + operand1 + " " + operand2);
break;
}
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for mul/div operation");
return false;
}
return true;
}
bool eval_addsub(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - add, 1 - sub
//cout << "\ndebug_AS " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
//output_tokens();
//cout << endl << "^^^^^^^^^^^^^^" << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//cout << "hello: " << token[i] << endl;
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<add>")!=0 &&
token[i].compare("<sub>")!=0 &&
(op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "!!op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
//cout << "!!op2 = " << operand1 << endl;
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<add>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for add/sub operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 0;
}
else if(token[i].compare("<sub>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for add/sub operation");
return false;
}
op_flag = 2;
operation = 1;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==3)
{
switch(operation)
{
case 0:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("add " + operand1 + " " + operand2);
else if(operand1.substr(0,1).compare("s")==0 && operand2.substr(0,1).compare("s")==0)
vm_asm.push_back("add$ " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for add operation: " + operand1 + ", " + operand2);
return false;
}
break;
case 1:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("sub " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for add operation");
return false;
}
break;
}
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for add/sub operation");
return false;
}
return true;
}
bool eval_bitshift(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - add, 1 - sub
//cout << "\ndebug_BS " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
//output_tokens();
//cout << endl << "^^^^^^^^^^^^^^" << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//cout << "hello: " << token[i] << endl;
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<shl>")!=0 &&
token[i].compare("<shr>")!=0 &&
(op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "!!op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
//cout << "!!op2 = " << operand1 << endl;
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<shl>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for add/sub operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 0;
}
else if(token[i].compare("<shr>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for add/sub operation");
return false;
}
op_flag = 2;
operation = 1;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==3)
{
switch(operation)
{
case 0:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("shl " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for shl operation");
return false;
}
break;
case 1:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("shr " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for shr operation");
return false;
}
break;
}
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for add/sub operation");
return false;
}
return true;
}
bool eval_cmp(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - add, 1 - sub
//cout << "\ndebug_AS " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
//output_tokens();
//cout << endl << "^^^^^^^^^^^^^^" << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//cout << "hello: " << token[i] << endl;
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<less>")!=0 &&
token[i].compare("<less_equal>")!=0 &&
token[i].compare("<greater>")!=0 &&
token[i].compare("<greater_equal>")!=0 &&
token[i].compare("<equal>")!=0 &&
token[i].compare("<not_equal>")!=0 &&
(op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "!!op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
//cout << "!!op2 = " << operand1 << endl;
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<less>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for less operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 0;
}
else if(token[i].compare("<less_equal>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for less/equal operation");
return false;
}
op_flag = 2;
operation = 1;
}
else if(token[i].compare("<greater>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for greater operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 2;
}
else if(token[i].compare("<greater_equal>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for greater/equal operation");
return false;
}
op_flag = 2;
operation = 3;
}
else if(token[i].compare("<equal>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for equal operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 4;
}
else if(token[i].compare("<not_equal>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for not equal operation");
return false;
}
op_flag = 2;
operation = 5;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==3)
{
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("cmp " + operand1 + " " + operand2);
else if(operand1.substr(0,1).compare("s")==0 && operand2.substr(0,1).compare("s")==0)
vm_asm.push_back("cmp$ " + operand1 + " " + operand2);
else
{
rc_setError("Mismatch types in comparison operation");
return false;
}
string solution = "n" + rc_intToString(n_reg);
inc_n(1);
switch(operation)
{
case 0:
vm_asm.push_back("mov " + solution + " %LESS_FLAG");
break;
case 1:
vm_asm.push_back("mov " + solution + " %LESS_EQUAL_FLAG");
break;
case 2:
vm_asm.push_back("mov " + solution + " %GREATER_FLAG");
break;
case 3:
vm_asm.push_back("mov " + solution + " %GREATER_EQUAL_FLAG");
break;
case 4:
vm_asm.push_back("mov " + solution + " %EQUAL_FLAG");
break;
case 5:
vm_asm.push_back("mov " + solution + " %NOT_EQUAL_FLAG");
break;
}
set_op_solution(op1_index, op2_index, solution);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for add/sub operation");
return false;
}
return true;
}
bool eval_andor(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - add, 1 - sub
//cout << "\ndebug_AND " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
//output_tokens();
//cout << endl << "^^^^^^^^^^^^^^" << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//cout << "hello: " << token[i] << endl;
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<and>")!=0 &&
token[i].compare("<or>")!=0 &&
token[i].compare("<xor>")!=0 &&
(op_flag == 0 || op_flag == 2))
{
switch(op_flag)
{
case 0:
operand1 = token[i];
//cout << "!!op1 = " << operand1 << endl;
op1_index = i;
op_flag = 1;
break;
case 2:
operand2 = token[i];
//cout << "!!op2 = " << operand1 << endl;
op2_index = i;
op_flag = 3;
break;
}
}
else if(token[i].compare("<and>")==0)
{
//cout << "AND OPERATION" << endl;
if(op_flag != 1)
{
rc_setError("Missing operand for and operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 0;
}
else if(token[i].compare("<or>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for or operation");
return false;
}
op_flag = 2;
operation = 1;
}
else if(token[i].compare("<xor>")==0)
{
if(op_flag != 1)
{
rc_setError("Missing operand for xor operation : " + rc_intToString(op_flag) );
return false;
}
op_flag = 2;
operation = 2;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==3)
{
switch(operation)
{
case 0:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("and " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for and operation");
return false;
}
break;
case 1:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("or " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for or operation");
return false;
}
break;
case 2:
if(operand1.substr(0,1).compare("n")==0 && operand2.substr(0,1).compare("n")==0)
vm_asm.push_back("xor " + operand1 + " " + operand2);
else
{
rc_setError("Incompatible operands for xor operation");
return false;
}
break;
}
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for add/sub operation");
return false;
}
return true;
}
bool eval_not(int start_block, int end_block)
{
int op_flag = 0;
string operand1 = "";
string operand2 = "";
int op1_index = 0;
int op2_index = 0;
int operation = 0; //0 - add, 1 - sub
//cout << "\ndebug_AS " << start_block << " " << end_block << endl;
//cout << "t_size" << token.size() << endl;
//output_tokens();
//cout << endl << "^^^^^^^^^^^^^^" << endl;
for(int i = start_block; i <= end_block; i++)
{
if(token_exemption(i))
{
//cout << "hello: " << token[i] << endl;
//op_flag = 0;
continue;
}
if(token[i].compare("")!=0 &&
token[i].compare("<not>")!=0 &&
op_flag == 1)
{
operand1 = token[i];
//cout << "!!op1 = " << operand1 << endl;
op2_index = i;
op_flag = 2;
}
else if(token[i].compare("<not>")==0)
{
op1_index = i;
op_flag = 1;
}
else if(token[i].compare("")!=0)
{
op_flag = 0;
}
if(op_flag==2)
{
if(operand1.substr(0,1).compare("n")==0)
vm_asm.push_back("not " + operand1);
else
{
rc_setError("Incompatible operands for and operation");
return false;
}
set_op_solution(op1_index, op2_index, operand1);
op_flag = 0;
i = start_block-1;
}
}
if(op_flag == 2)
{
rc_setError("Expected operand for add/sub operation");
return false;
}
return true;
}
//still need to store negative numbers properly
#define PP_FLAG_NONE 0
#define PP_FLAG_ARRAY 1
int getArrayObjStart(int arg_id)
{
string start_arg = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("mov " + start_arg + " 0");
if(id[arg_id].type == ID_TYPE_ARR_NUM)
{
switch(id[arg_id].num_args)
{
case 1:
vm_asm.push_back("obj_num1 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg);
break;
case 2:
vm_asm.push_back("obj_num2 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg + " " + start_arg);
break;
case 3:
vm_asm.push_back("obj_num3 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg + " " + start_arg + " " + start_arg);
break;
}
int obj_n = n_reg;
inc_n(1);
vm_asm.push_back("obj_get n" + rc_intToString(obj_n));
return obj_n;
}
else if(id[arg_id].type == ID_TYPE_ARR_STR)
{
switch(id[arg_id].num_args)
{
case 1:
vm_asm.push_back("obj_str1 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg);
break;
case 2:
vm_asm.push_back("obj_str2 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg + " " + start_arg);
break;
case 3:
vm_asm.push_back("obj_str3 !" + rc_intToString(id[arg_id].vec_pos) + " " + start_arg + " " + start_arg + " " + start_arg);
break;
}
int obj_s = s_reg;
inc_s(1);
vm_asm.push_back("obj_get$ s" + rc_intToString(obj_s));
return obj_s;
}
return 0;
}
bool byref_type_generic(string utype_name)
{
if(utype_name.compare("empty")==0)
return true;
return false;
}
bool pre_parse(int start_token = 0, int end_token = -1, int pp_flags, bool eval_udt)
{
if(end_token == -1)
{
end_token = token.size();
}
int n_flag = 0; // id num ] ) } ,
string n = "";
string s = "";
string u = "";
int expr_id = -1;
string sdata = "";
bool byref_type_flag = false;
for(int i = start_token; i <= end_token; i++)
{
if(token[i].substr(0,5).compare("<num>")==0)
{
//cout << "WISHING FOR A MIRACLE" << endl;
n = "n" + rc_intToString(n_reg);
vm_asm.push_back("mov " + n + " " + token[i].substr(5));
token[i] = n;
inc_n(1);
}
else if(token[i].substr(0,8).compare("<string>")==0)
{
//store strings in data
sdata = token[i].substr(8);
int sdata_addr = data_segment.size();
for(int n = 0; n < sdata.length(); n++)
{
data_segment.push_back(sdata[n]);
}
data_segment.push_back('\0');
string token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("mov$ " + token_replace + " @" + rc_intToString(sdata_addr));
token[i] = token_replace;
}
else if(token[i].substr(0,4).compare("<id>")==0)
{
//cout << "ID: " << token[i].substr(4) << endl;
//more needs to be done here
n = "n" + rc_intToString(n_reg);
s = "s" + rc_intToString(s_reg);
u = "u" + rc_intToString(u_reg);
expr_id = getIDInScope_ByIndex(token[i].substr(4));
//cout << "expr = " << expr_id << endl;
//cout << "TYPE: " << id[expr_id].type << endl << endl;
bool is_udt_member = false;
if(i > 0)
if(token[i-1].compare("<child>")==0)
is_udt_member = true;
if(is_udt_member)
continue;
if(expr_id < 0)
{
//rc_setError(token[i].substr(4) + " was not found in this scope+: " + current_scope);
rc_setError(token[i].substr(4) + " was not found in this scope");
//output_vars();
return false;
}
// else if(id[expr_id].type == ID_TYPE_BYREF_NUM)
// {
// vm_asm.push_back("mov " + n + " !" + rc_intToString(id[expr_id].vec_pos));
// resolveID_id_reg.push_back(n);
// resolveID_id_type.push_back(id[expr_id].type);
// resolveID_id_ut_index.push_back(id[expr_id].type_index);
// token[i] = n;
// inc_n(1);
// }
else if(id[expr_id].type == ID_TYPE_NUM)
{
//cout << endl << "COME ON: " << id[expr_id].name << endl;
vm_asm.push_back("mov " + n + " !" + rc_intToString(id[expr_id].vec_pos));
resolveID_id_reg.push_back(n);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
token[i] = n;
inc_n(1);
}
else if(id[expr_id].type == ID_TYPE_STR)
{
vm_asm.push_back("mov$ " + s + " !" + rc_intToString(id[expr_id].vec_pos));
resolveID_id_reg.push_back(s);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
token[i] = s;
inc_s(1);
}
else if( (id[expr_id].type == ID_TYPE_BYREF_NUM || id[expr_id].type == ID_TYPE_BYREF_STR) && pp_flags == PP_FLAG_ARRAY)
{
//cout << "found array: " << id[expr_id].name << endl << endl;
int s_scope = 0;
int arr_token_start = i;
int arr_token_end = i;
string args[512];
int num_args = 0;
int p_scope = 0;
if( (i+1) <= end_token)
{
if(token[i+1].compare("!<square>")==0)
{
s_scope = 1;
for(i += 2; (i <= end_token) && (s_scope != 0); i++)
{
if(token[i].compare("!</square>")==0)
{
s_scope--;
if(s_scope == 0)
{
num_args++;
arr_token_end = i;
}
}
else if(token[i].compare("!<square>")==0)
s_scope++;
else if(token[i].compare("!<comma>")==0)
num_args++;
else if(token[i].substr(0,1).compare("n")==0)
args[num_args] = token[i];
else if(token[i].compare("!<par>")==0)
p_scope++;
else if(token[i].compare("!</par>")==0)
p_scope--;
else if(token[i].compare("")!=0)
{
rc_setError("Expected number");
return false;
}
}
if(p_scope > 0)
{
rc_setError("Parenthesis Block was not closed");
return false;
}
else if(p_scope < 0)
{
rc_setError("Parenthesis Block was not opened");
return false;
}
if(s_scope != 0)
{
rc_setError("Expected closing ]");
return false;
}
}
}
if(num_args > 1)
{
rc_setError("In " + id[expr_id].name + " Expected 0 to 1 dimensions and found " + rc_intToString(num_args));
return false;
}
if(id[expr_id].type == ID_TYPE_BYREF_NUM && num_args == 0)
{
vm_asm.push_back("mov " + n + " !" + rc_intToString(id[expr_id].vec_pos));
resolveID_id_reg.push_back(n);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
token[i] = n;
inc_n(1);
continue;
}
else if(id[expr_id].type == ID_TYPE_BYREF_STR && num_args == 0)
{
vm_asm.push_back("mov$ " + s + " !" + rc_intToString(id[expr_id].vec_pos));
resolveID_id_reg.push_back(s);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
token[i] = s;
inc_s(1);
continue;
}
if(args[0].substr(0,1).compare("n")!=0)
{
rc_setError("Invalid number of args in array");
return false;
}
string token_replace = "";
if(id[expr_id].type == ID_TYPE_BYREF_NUM)
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_num1 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0]);
token_replace = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("obj_get " + token_replace);
}
else
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_str1 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0]);
token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("obj_get$ " + token_replace);
}
resolveID_id_reg.push_back(token_replace);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
for(int p = arr_token_start; p <= arr_token_end; p++)
token[p] = "";
if(token_replace.compare("")==0)
{
rc_setError("%%could not resolve array " + id[expr_id].name);
return false;
}
token[arr_token_start] = token_replace;
//cout << "the end of array" << endl;
}
else if( ID_TYPE_USER_ALL(expr_id) && eval_udt )
{
//cout << "-Parsing User Variable: " << id[expr_id].name << endl;
//cout << "----------------------------------------------- : " << eval_udt << endl;
bool udt_id_init = true;
string tmp_scope = id[expr_id].scope;
/*for(int t = i; t < token.size(); t++)
{
try
{
cout << t << ":" << token.at(t) << endl;
}
catch(out_of_range& e)
{
cout << "Token Out of Range Error: " << e.what() << endl;
}
}*/
int tmp_id = 0;
bool has_child = false;
int num_id_parents = 0;
int num_id_children = 0;
byref_type_flag = false;
for(int t = i; t <= end_token; t++)
{
if(token[t].substr(0,4).compare("<id>")==0)
{
if(num_id_parents != num_id_children)
{
rc_setError("Expected member separator or member ID");
return false;
}
num_id_parents++;
//cout << "FIGURE IT OUT: " << t << endl;
string args[3];
int arg_count = 0;
string full_id = token[t].substr(4);
token[t] = "";
tmp_id = getIDInScope_ByIndex_TypeMatch(full_id, tmp_scope);
//cout << "\ntmp_id = " << tmp_id << endl;
if(tmp_id < 0)
{
rc_setError(tmp_scope.substr(5) + " does not have member [" + full_id + "]");
return false;
}
//cout << "Scope = " << tmp_scope << " ID = " << full_id << " -- " << tmp_id << endl << endl;
tmp_scope += "." + full_id;
//get arguments (ie. the dimensions of an array
int t2 = t+1;
if(t2 < end_token)
{
int arr_scope = 0;
if(token[t2].compare("!<square>")==0)
{
token[t2] = "";
args[0] = "";
args[1] = "";
args[2] = "";
arg_count = 0;
arr_scope = 1;
t2++;
//cout << "T2 = " << t2 << endl << endl;
for(; t2 <= end_token; t2++)
{
//cout << "DBG ARR: " << t2 << ", " << end_token << " : " << token[t2] << endl;
if(token[t2].compare("!</square>")==0)
arr_scope--;
else if(token[t2].compare("!<square>")==0)
arr_scope++;
else if(token[t2].compare("!<comma>")==0)
arg_count++;
else if(token[t2].substr(0,1).compare("n")==0)
{
if(args[arg_count].compare("")==0)
args[arg_count] = token[t2];
else
{
rc_setError("Error parsing array dimension: " + args[arg_count] + " :: " + token[t2] + " -- " + rc_intToString(t2) + ", " + rc_intToString(arg_count));
return false;
}
}
token[t2] = "";
if(arg_count >= 3)
{
rc_setError("Too many dimensions in array");
return false;
}
if(arr_scope == 0)
break;
}
if(arr_scope > 0)
{
rc_setError("Expected ]] in expression: " + rc_intToString(arr_scope));
return false;
}
arg_count++;
}
else if(type_delete_flag || type_redim_flag)
t2--;
}
has_child = false;
if((t2+1) < token.size())
{
if(token[t2+1].compare("<child>")==0)
{
has_child = true;
}
//cout << "Has Child = " << has_child << ", " << t << ", " << t2 << endl;
}
if(type_delete_flag && (!has_child) && arg_count != 0)
{
rc_setError("Expected identifier without index");
return false;
}
bool byref_isArray = (id[tmp_id].type == ID_TYPE_BYREF_USER && arg_count == 1);
if(arg_count != id[tmp_id].num_args && (!byref_isArray))
{
if(type_redim_flag)
{
if(has_child)
{
rc_setError("[1]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name);
return false;
}
}
else if(!type_delete_flag)
{
if(arg_count != 0)
{
rc_setError("[0]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name);
return false;
}
//cout << "ID_TYPE = " << id[tmp_id].type << ", " << arg_count << ", " << (has_child ? "true" : "false") << endl;
args[0] = "";
args[1] = "";
args[2] = "";
string tmp_instruction = "obj_usr_";
//trying stuff out
if(id[tmp_id].type == ID_TYPE_USER_NUM)
{
vm_asm.push_back("mov " + n + " 0");
tmp_instruction += "n" + ( id[tmp_id].num_args <= 0 ? "" : rc_intToString(id[tmp_id].num_args) );
for(int tmp_arg_i = 0; tmp_arg_i < id[tmp_id].num_args; tmp_arg_i++)
args[tmp_arg_i] = n;
vm_asm.push_back(tmp_instruction + " !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
byref_type_flag = true;
break;
}
else if(id[tmp_id].type == ID_TYPE_USER_STR)
{
vm_asm.push_back("mov " + n + " 0");
tmp_instruction += "s" + ( id[tmp_id].num_args <= 0 ? "" : rc_intToString(id[tmp_id].num_args) );
for(int tmp_arg_i = 0; tmp_arg_i < id[tmp_id].num_args; tmp_arg_i++)
args[tmp_arg_i] = n;
vm_asm.push_back(tmp_instruction + " !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
byref_type_flag = true;
break;
}
else if(id[tmp_id].type == ID_TYPE_USER)
{
if(udt_id_init)
tmp_instruction = "obj_usr_init";
else
tmp_instruction = "obj_usr";
vm_asm.push_back("mov " + n + " 0");
tmp_instruction += ( id[tmp_id].num_args <= 0 ? "" : rc_intToString(id[tmp_id].num_args) );
for(int tmp_arg_i = 0; tmp_arg_i < id[tmp_id].num_args; tmp_arg_i++)
args[tmp_arg_i] = n;
vm_asm.push_back(tmp_instruction + " !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
byref_type_flag = true;
break;
}
//-------------------------------
return false;
}
else
{
if(has_child)
{
rc_setError("[1]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name);
return false;
}
arg_count = id[tmp_id].num_args;
//vm_asm.push_back("mov n" + rc_intToString(n_reg) + " 0");
//args[0] = "n" + rc_intToString(n_reg);
//args[1] = args[0];
//args[2] = args[0];
//inc_n(1);
}
}
if(type_redim_flag && (!has_child))
{
//cout << "NO CHILD: " << id[tmp_id].name << " -- arg_count = " << arg_count << " -- arg[0] = " << args[0] << endl;
type_redim_dim_count = arg_count;
type_redim_dim[0] = args[0];
type_redim_dim[1] = args[1];
type_redim_dim[2] = args[2];
if(arg_count != id[tmp_id].num_args)
{
rc_setError("Expected " + rc_intToString(id[tmp_id].num_args) + " dimensions but found " + rc_intToString(arg_count));
return false;
}
}
else if(type_delete_flag && (!has_child))
{
//DO NOTHING
//cout << "NO CHILD: " << id[tmp_id].name << endl;
}
else
{
//if(type_delete_flag)
//cout << "TESTING STUFF" << endl;
switch(arg_count)
{
case 0:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init !" + rc_intToString(id[tmp_id].vec_pos));
else
vm_asm.push_back("obj_usr !" + rc_intToString(id[tmp_id].vec_pos));
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n !" + rc_intToString(id[tmp_id].vec_pos));
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s !" + rc_intToString(id[tmp_id].vec_pos));
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 1:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else
vm_asm.push_back("obj_usr1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 2:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else
vm_asm.push_back("obj_usr2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 3:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else
vm_asm.push_back("obj_usr3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
}
udt_id_init = false;
}
}
else if(token[t].compare("<child>")==0)
{
num_id_children++;
type_delete_arg_whole = false;
token[t] = "";
continue;
}
else if(token[t].compare("")!=0)
{
break;
}
}
//START HERE
if(type_redim_flag && (!has_child))
{
type_redim_arg = "!" + rc_intToString(id[tmp_id].vec_pos);
type_redim_arg_type = id[tmp_id].type;
type_redim_arg_utype = "!" + rc_intToString(id[tmp_id].type_index);
}
else if(type_delete_flag && (!has_child))
{
//cout << "DELETE_VAR = " << id[tmp_id].name << endl;
type_delete_arg = "!" + rc_intToString(id[tmp_id].vec_pos);
type_delete_arg_type = id[tmp_id].type;
}
else
switch(id[tmp_id].type)
{
case ID_TYPE_USER:
case ID_TYPE_BYREF_USER:
//cout << "test --> " << u << ", " << id[tmp_id].name << endl;
vm_asm.push_back("obj_usr_get " + u);
token[i] = u;
resolveID_id_reg.push_back(token[i]);
resolveID_id_type.push_back(id[tmp_id].type);
resolveID_id_ut_index.push_back(id[tmp_id].type_index);
resolveID_id_vec_pos.push_back(tmp_id);
inc_u(1);
break;
case ID_TYPE_USER_NUM:
vm_asm.push_back("obj_usr_get " + n);
token[i] = n;
//cout << "GET N: " << n << ", " << id[tmp_id].scope << " :: " << id[tmp_id].name << endl;
resolveID_id_reg.push_back(token[i]);
resolveID_id_type.push_back(id[tmp_id].type);
resolveID_id_ut_index.push_back(id[tmp_id].type_index);
resolveID_id_vec_pos.push_back(tmp_id);
inc_n(1);
break;
case ID_TYPE_USER_STR:
vm_asm.push_back("obj_usr_get " + s);
token[i] = s;
resolveID_id_reg.push_back(token[i]);
resolveID_id_type.push_back(id[tmp_id].type);
resolveID_id_ut_index.push_back(id[tmp_id].type_index);
resolveID_id_vec_pos.push_back(tmp_id);
inc_s(1);
break;
default:
break;
}
if(byref_type_flag)
{
type_error_exception tx;
tx.error_log = "[0]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name;
tx.tk_reg = token[i];
tx.num_args = id[tmp_id].num_args;
tx.exception_used = false;
//cout << "!!!! type_no_arg_exception_raised = false;" << endl;
//cout << "store = " << id[tmp_id].name << " = " << tx.tk_reg << " arg_count = " << arg_count << ", expected = " << id[tmp_id].num_args << endl;
byref_type_exception.push_back(tx);
byref_type_flag = false;
type_no_arg_exception_raised = true;
}
/*
cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
for(int t = 0; t < token.size(); t++)
{
try
{
cout << t << ":" << token.at(t) << endl;
}
catch(out_of_range& e)
{
cout << "Token Out of Range Error: " << e.what() << endl;
}
}
cout << "-----------------------------------------------" << endl;
*/
//for(int t = 0; t < id.size(); t++)
// if(id[t].type == ID_TYPE_USER) cout << "ID[" << id[t].name << "] SCOPE=" << id[t].scope << " -- " << id[t].vec_pos << endl;
}
else if( (id[expr_id].type == ID_TYPE_ARR_NUM || id[expr_id].type == ID_TYPE_ARR_STR) && pp_flags == PP_FLAG_ARRAY)
{
//cout << "found array: " << id[expr_id].name << endl << endl;
int s_scope = 0;
int arr_token_start = i;
int arr_token_end = i;
string args[3];
int num_args = 0;
int p_scope = 0;
if( (i+1) <= end_token)
{
if(token[i+1].compare("!<square>")==0)
{
s_scope = 1;
for(i += 2; (i <= end_token) && (s_scope != 0); i++)
{
if(token[i].compare("!</square>")==0)
{
s_scope--;
if(s_scope == 0)
{
num_args++;
arr_token_end = i;
}
}
else if(token[i].compare("!<square>")==0)
s_scope++;
else if(token[i].compare("!<comma>")==0)
num_args++;
else if(token[i].substr(0,1).compare("n")==0)
args[num_args] = token[i];
else if(token[i].compare("!<par>")==0)
p_scope++;
else if(token[i].compare("!</par>")==0)
p_scope--;
else if(token[i].compare("")!=0)
{
rc_setError("Expected number");
return false;
}
}
if(p_scope > 0)
{
rc_setError("Parenthesis Block was not closed");
return false;
}
else if(p_scope < 0)
{
rc_setError("Parenthesis Block was not opened");
return false;
}
}
}
//cout << endl << "ID_ARRAY: " << id[expr_id].name << endl;
//cout << "NUM_ARGS_EXPECTED: " << id[expr_id].num_args << endl;
//cout << "NUM_ARGS_FOUND: " << num_args << endl;
if(id[expr_id].isArrayArg)
{
//cout << "array arg found" << endl;
id[expr_id].isArrayArg = false;
string token_replace = "";
if(id[expr_id].type == ID_TYPE_ARR_NUM)
{
token_replace = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("mov_arr " + token_replace + " !" + rc_intToString(id[expr_id].vec_pos));
}
else
{
token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("mov_arr$ " + token_replace + " !" + rc_intToString(id[expr_id].vec_pos));
}
resolveID_id_reg.push_back(token_replace);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
for(int p = arr_token_start; p <= arr_token_end; p++)
token[p] = "";
token[arr_token_start] = token_replace;
continue;
}
if(id[expr_id].num_args != num_args)
{
if(num_args == 0)
continue;
rc_setError("In " + id[expr_id].name + " Expected " + rc_intToString(id[expr_id].num_args) + " dimensions and found " + rc_intToString(num_args));
return false;
}
for(int n = 0; n < id[expr_id].num_args; n++)
{
//cout << "arg " << n << ": " << args[n] << endl;
if(args[n].substr(0,1).compare("n")!=0)
{
rc_setError("Invalid number of args in array");
return false;
}
}
string token_replace = "";
switch(num_args)
{
case 1:
if(id[expr_id].type == ID_TYPE_ARR_NUM)
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_num1 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0]);
token_replace = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("obj_get " + token_replace);
}
else
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_str1 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0]);
token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("obj_get$ " + token_replace);
}
break;
case 2:
if(id[expr_id].type == ID_TYPE_ARR_NUM)
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_num2 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0] + " " + args[1]);
token_replace = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("obj_get " + token_replace);
}
else
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_str2 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0] + " " + args[1]);
token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("obj_get$ " + token_replace);
}
break;
case 3:
if(id[expr_id].type == ID_TYPE_ARR_NUM)
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_num3 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
token_replace = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("obj_get " + token_replace);
}
else
{
//vm_asm.push_back("clear_obj");
vm_asm.push_back("obj_str3 !" + rc_intToString(id[expr_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
token_replace = "s" + rc_intToString(s_reg);
inc_s(1);
vm_asm.push_back("obj_get$ " + token_replace);
}
break;
default:
rc_setError("Invalid number of dimensions in array");
return false;
}
resolveID_id_reg.push_back(token_replace);
resolveID_id_type.push_back(id[expr_id].type);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
for(int p = arr_token_start; p <= arr_token_end; p++)
token[p] = "";
if(token_replace.compare("")==0)
{
rc_setError("Could not resolve array " + id[expr_id].name);
return false;
}
token[arr_token_start] = token_replace;
//cout << "the end of array" << endl;
}
else if( (id[expr_id].type == ID_TYPE_FN_NUM || id[expr_id].type == ID_TYPE_FN_STR || id[expr_id].type == ID_TYPE_FN_USER || id[expr_id].type == ID_TYPE_SUB) && pp_flags == PP_FLAG_ARRAY)
{
//cout << "FUNCTION: " << id[expr_id].name << endl;
//output_tokens();
//cout << "found function: " << id[expr_id].name << " " << current_block_state << endl << endl;
//cout << "fn ids = " << id[expr_id].fn_var.size() << endl;
//push all current function ids onto stack before setting them with the expression function values
// if(isInFunctionScope)
// {
// for(int n = 0; n < id[expr_id].fn_var.size(); n++)
// {
// cout << "fid[" << n << "] = " << id[expr_id].fn_var[n].vec_str << endl;
// if(id[expr_id].fn_var[n].type == ID_TYPE_NUM || id[expr_id].fn_var[n].type == ID_TYPE_BYREF_NUM || id[expr_id].fn_var[n].type == ID_TYPE_ARR_NUM)
// {
// vm_asm.push_back("push " + id[expr_id].fn_var[n].vec_str);
// }
// else
// {
// vm_asm.push_back("push$ " + id[expr_id].fn_var[n].vec_str);
// }
// }
//
// }
//cout << "debug 1" << endl;
int s_scope = 0;
int arr_token_start = i;
int arr_token_end = i;
string args[1024];
args[0] = "";
int num_args = 0;
int arg_size = 0; //this variable counts the number of tokens in a argument; used to fix multiple tokens in 1 argument (ie. abs(5 7) should not compile)
if( (i+1) <= end_token)
{
//cout << "DBG #1: " << id[expr_id].name << endl;
if(token[i+1].compare("!<par>")==0)
{
//cout << "DBG #2" <<endl;
s_scope = 1;
for(i += 2; (i <= end_token) && (s_scope != 0); i++)
{
//cout << "DBG Token[" << i << "] = " << token[i] << endl;
//cout << "loop " << i << endl;
if(token[i].compare("!</par>")==0)
{
//cout << "DBG #4: " << s_scope << endl;
s_scope--;
if(s_scope == 0)
{
//num_args++;
if(num_args > 0 || args[0].compare("") != 0)
num_args++;
arr_token_end = i;
}
}
else if(token[i].compare("!<par>")==0)
s_scope++;
else if(token[i].compare("!<comma>")==0)
{
num_args++;
arg_size = 0;
}
else if(token[i].substr(0,1).compare("n")==0 || token[i].substr(0,1).compare("s")==0 || token[i].substr(0,1).compare("u")==0 || token[i].substr(0,4).compare("<id>")==0)
{
//cout << id[expr_id].name << "->DBG #3:" << num_args << " " << token[i] << endl;
args[num_args] = token[i];
arg_size++;
if(arg_size > 1)
{
rc_setError("Expected Operator in expression");
return false;
}
}
else if(token[i].compare("")!=0)
{
rc_setError("Invalid argument in function: "+token[i]);
return false;
}
}
}
}
//cout << endl << "ID_ARRAY: " << id[expr_id].name << endl;
//cout << "NUM_ARGS_EXPECTED: " << id[expr_id].num_args << endl;
//cout << "NUM_ARGS_FOUND: " << num_args << endl;
if(id[expr_id].num_args != num_args)
{
rc_setError("In " + id[expr_id].name + " Expected " + rc_intToString(id[expr_id].num_args) + " arguments and found " + rc_intToString(num_args));
//rc_setError("arg[0]=" + args[0]);
//cout <<"TOEK" << endl;
output_tokens();
return false;
}
int resolve_index = -1;
int resolve_index2 = -1;
int resolve_id = -1;
int resolve_id2 = -1;
int arg_index = -1;
bool local_state_is_pushed = false; //this variable checks will be set to true if the following function call is recursive
if(block_state.size() > 0)
{
if(current_scope.substr(0, ("main."+id[expr_id].name).length()).compare("main."+id[expr_id].name)==0)
{
local_state_is_pushed = true;
//cout << "DEBUG: local_state_is_pushed=" << (local_state_is_pushed ? "TRUE":"FALSE") << endl;
//push all variables that were made in current function
string tmp_type_scope = "_";
for(uint32_t fn_var_id = current_fn_index+1; fn_var_id < id.size(); fn_var_id++)
{
switch(id[fn_var_id].type)
{
case ID_TYPE_NUM:
vm_asm.push_back("push !" + rc_intToString(id[fn_var_id].vec_pos));
n_tmp.push_back("!" + rc_intToString(id[fn_var_id].vec_pos) );
//cout << "push -- " << id[fn_var_id].name << endl;
break;
case ID_TYPE_STR:
vm_asm.push_back("push$ !" + rc_intToString(id[fn_var_id].vec_pos));
s_tmp.push_back("!" + rc_intToString(id[fn_var_id].vec_pos) );
break;
//TODO: NEED TO ADD CASE TO PUSH USER TYPES HERE
case ID_TYPE_USER:
if(id[fn_var_id].scope.substr(0, tmp_type_scope.length()).compare(tmp_type_scope)==0)
break;
tmp_type_scope = id[fn_var_id].scope + "." + id[fn_var_id].name;
//cout << "TYPE Push: " << id[fn_var_id].name << " : SCOPE=" << tmp_type_scope << endl;
vm_asm.push_back("push_t !" + rc_intToString(id[fn_var_id].vec_pos));
u_tmp.push_back("!" + rc_intToString(id[fn_var_id].vec_pos) );
break;
}
}
}
}
for(int n = 0; n < id[expr_id].num_args; n++)
{
//cout << "args: " << args[n] << endl;
if(args[n].substr(0,1).compare("n")!=0 && args[n].substr(0,1).compare("s")!=0 && args[n].substr(0,1).compare("u")!=0 && args[n].substr(0,4).compare("<id>")!=0)
{
rc_setError("--Invalid number of args in function: " + args[n]);
return false;
}
if(id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_NUM || id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_STR)
{
resolve_index = getResolveReg(args[n]);
if(args[n].substr(0,4).compare("<id>")==0)
{
//cout << "found id: " << args[n] << " in " << id[expr_id].name << endl;
string t_replace = "";
int arg_id = getIDInScope_ByIndex(args[n].substr(4));
if(arg_id < 0)
{
rc_setError("Identifier was not declared in ByRef argument");
return false;
}
if(id[arg_id].type == ID_TYPE_ARR_NUM)
{
t_replace = "n" + rc_intToString( getArrayObjStart(arg_id));
//t_replace = "n" + rc_intToString(n_reg);
//inc_n(1);
//vm_asm.push_back("mov " + t_replace + " !" + rc_intToString(id[arg_id].vec_pos));
resolveID_id_reg.push_back(t_replace);
resolveID_id_type.push_back(id[arg_id].type);
resolveID_id_ut_index.push_back(id[arg_id].type_index);
resolveID_id_vec_pos.push_back(arg_id);
resolve_index = resolveID_id_reg.size()-1;
}
else if(id[arg_id].type == ID_TYPE_ARR_STR)
{
t_replace = "s" + rc_intToString( getArrayObjStart(arg_id));
//t_replace = "s" + rc_intToString(s_reg);
//inc_s(1);
//vm_asm.push_back("mov$ " + t_replace + " !" + rc_intToString(id[arg_id].vec_pos));
resolveID_id_reg.push_back(t_replace);
resolveID_id_type.push_back(id[arg_id].type);
resolveID_id_ut_index.push_back(id[arg_id].type_index);
resolveID_id_vec_pos.push_back(arg_id);
resolve_index = resolveID_id_reg.size()-1;
}
else
{
rc_setError("Could not resolve Identifier in ByRef argument");
return false;
}
}
else if( (args[n].substr(0,1).compare("n")==0 || args[n].substr(0,1).compare("s")==0) && resolve_index >= 0 )
{
//string t_replace = args[n];
}
//check if byref_type_exception
bool type_exception_found = false;
int type_exception_index = -1;
//cout << "CHECK EXCEPTION: " << args[n] << endl;
for(int bt_i = 0; bt_i < byref_type_exception.size(); bt_i++)
{
if(args[n].compare(byref_type_exception[bt_i].tk_reg)==0)
{
//cout << "FOUND EXCEPTION: " << args[n] << endl;
byref_type_exception[bt_i].tk_reg = "";
type_exception_found = true;
type_exception_index = bt_i;
}
//else
//cout << "NO MATCH (" << args[n] << ", " << byref_type_exception[bt_i].tk_reg << ")" << endl;
}
//----------------
if(resolve_index < 0 && (!type_exception_found))
{
rc_setError("[4]Expected identifier for ByRef argument");
return false;
}
/*arg_index = getIDInScope_ByIndex(resolveID_id_reg[resolve_index]);
if(arg_index < 0)
{
rc_setError("Identifier " + resolveID_id_reg[resolve_index] + " was not defined in this scope");
return false;
}*/
//Array Functions
string tmp_fn_name = StringToLower(id[expr_id].name);
if(tmp_fn_name.compare("arraydim")==0)
{
//cout << "found array dim" << endl;
int tmp_id_type = -1;
if(args[n].substr(0,4).compare("<id>")==0)
{
int tmp_id = getIDInScope_ByIndex(args[n].substr(4));
if(tmp_id >= 0)
tmp_id_type = id[tmp_id].type;
}
if(args[n].substr(0,1).compare("n")==0 || tmp_id_type == ID_TYPE_NUM || tmp_id_type == ID_TYPE_ARR_NUM || tmp_id_type == ID_TYPE_BYREF_NUM)
expr_id = getIDInScope_ByIndex("numberarraydim");
else if(args[n].substr(0,1).compare("s")==0 || tmp_id_type == ID_TYPE_STR || tmp_id_type == ID_TYPE_ARR_STR || tmp_id_type == ID_TYPE_BYREF_STR)
expr_id = getIDInScope_ByIndex("stringarraydim");
else if(args[n].substr(0,1).compare("u")==0 || tmp_id_type == ID_TYPE_USER || tmp_id_type == ID_TYPE_BYREF_USER)
expr_id = getIDInScope_ByIndex("typearraydim");
else
{
rc_setError("Expected valid array identifier: " + args[n]);
expr_id = -1;
}
if(expr_id < 0)
{
rc_setError("ArrayDim macro function does not exists for variable type");
return false;
}
}
else if(tmp_fn_name.compare("arraysize")==0)
{
//cout << "found array size: " << args[0] << endl;
int tmp_id_type = -1;
if(args[0].substr(0,4).compare("<id>")==0) // arg[0] is what determines the macro function used
{
int tmp_id = getIDInScope_ByIndex(args[n].substr(4));
if(tmp_id >= 0)
tmp_id_type = id[tmp_id].type;
}
if(args[0].substr(0,1).compare("n")==0 || tmp_id_type == ID_TYPE_NUM || tmp_id_type == ID_TYPE_ARR_NUM || tmp_id_type == ID_TYPE_BYREF_NUM)
expr_id = getIDInScope_ByIndex("numberarraysize");
else if(args[0].substr(0,1).compare("s")==0 || tmp_id_type == ID_TYPE_STR || tmp_id_type == ID_TYPE_ARR_STR || tmp_id_type == ID_TYPE_BYREF_STR)
expr_id = getIDInScope_ByIndex("stringarraysize");
else if(args[0].substr(0,1).compare("u")==0 || tmp_id_type == ID_TYPE_USER || tmp_id_type == ID_TYPE_BYREF_USER)
expr_id = getIDInScope_ByIndex("typearraysize");
else
{
rc_setError("Expected valid array identifier: " + args[0]);
expr_id = -1;
}
if(expr_id < 0)
{
rc_setError("ArraySize macro function does not exists for variable type");
return false;
}
}
else if(tmp_fn_name.compare("arraycopy")==0)
{
//cout << "found array copy: " << args[0] << endl;
int tmp_id_type = -1;
if(args[0].substr(0,4).compare("<id>")==0) // arg[0] is what determines the macro function used
{
int tmp_id = getIDInScope_ByIndex(args[n].substr(4));
if(tmp_id >= 0)
tmp_id_type = id[tmp_id].type;
}
if(args[0].substr(0,1).compare("n")==0 || tmp_id_type == ID_TYPE_NUM || tmp_id_type == ID_TYPE_ARR_NUM || tmp_id_type == ID_TYPE_BYREF_NUM)
expr_id = getIDInScope_ByIndex("numberarraycopy");
else if(args[0].substr(0,1).compare("s")==0 || tmp_id_type == ID_TYPE_STR || tmp_id_type == ID_TYPE_ARR_STR || tmp_id_type == ID_TYPE_BYREF_STR)
expr_id = getIDInScope_ByIndex("stringarraycopy");
else if(args[0].substr(0,1).compare("u")==0 || tmp_id_type == ID_TYPE_USER || tmp_id_type == ID_TYPE_BYREF_USER)
expr_id = getIDInScope_ByIndex("typearraycopy");
else
{
rc_setError("Expected valid array identifier: " + args[0]);
expr_id = -1;
}
if(expr_id < 0)
{
rc_setError("ArrayCopy macro function does not exists for variable type");
return false;
}
}
else if(tmp_fn_name.compare("arrayfill")==0)
{
//cout << "found array fill: " << args[0] << endl;
int tmp_id_type = -1;
if(args[0].substr(0,4).compare("<id>")==0) // arg[0] is what determines the macro function used
{
int tmp_id = getIDInScope_ByIndex(args[n].substr(4));
if(tmp_id >= 0)
tmp_id_type = id[tmp_id].type;
}
if(args[0].substr(0,1).compare("n")==0 || tmp_id_type == ID_TYPE_NUM || tmp_id_type == ID_TYPE_ARR_NUM || tmp_id_type == ID_TYPE_BYREF_NUM)
expr_id = getIDInScope_ByIndex("numberarrayfill");
else if(args[0].substr(0,1).compare("s")==0 || tmp_id_type == ID_TYPE_STR || tmp_id_type == ID_TYPE_ARR_STR || tmp_id_type == ID_TYPE_BYREF_STR)
expr_id = getIDInScope_ByIndex("stringarrayfill");
else if(args[0].substr(0,1).compare("u")==0 || tmp_id_type == ID_TYPE_USER || tmp_id_type == ID_TYPE_BYREF_USER)
expr_id = getIDInScope_ByIndex("typearrayfill");
else
{
rc_setError("Expected valid array identifier: " + args[0]);
expr_id = -1;
}
//cout << "dbg data: " << expr_id << " arg = " << args[0] << " type = " << tmp_id_type << " name = " << id[expr_id].name << endl;
if(expr_id < 0)
{
rc_setError("ArrayFill macro function does not exists for variable type");
return false;
}
}
//--------------------------------
if(type_exception_found)
switch(id[expr_id].fn_arg_type[n])
{
case ID_TYPE_BYREF_NUM:
if(args[n].substr(0,1).compare("n")!=0)
{
rc_setError("Expected number identifier for argument in " + id[expr_id].name);
return false;
}
byref_type_exception[type_exception_index].exception_used = true;
vm_asm.push_back("ptr !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
break;
case ID_TYPE_BYREF_STR:
if(args[n].substr(0,1).compare("s")!=0)
{
rc_setError("Expected string identifier for argument");
return false;
}
byref_type_exception[type_exception_index].exception_used = true;
vm_asm.push_back("ptr$ !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
break;
case ID_TYPE_BYREF_USER:
//cout << "start up" << endl;
if(args[n].substr(0,1).compare("u")!=0)
{
rc_setError("Expected defined type identifier for argument: " + rc_intToString(id[expr_id].fn_arg_utype[n]));
return false;
}
//cout << "yolo: " << expr_id << " ~ " << id.size() << " -- " << id[expr_id].num_args << endl;
byref_type_exception[type_exception_index].exception_used = true;
vm_asm.push_back("uref_ptr !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
//cout << "testing" << endl;
break;
}
else
switch(id[expr_id].fn_arg_type[n])
{
case ID_TYPE_BYREF_NUM:
if(resolveID_id_type[resolve_index] != ID_TYPE_NUM && resolveID_id_type[resolve_index] != ID_TYPE_ARR_NUM && resolveID_id_type[resolve_index] != ID_TYPE_BYREF_NUM && resolveID_id_type[resolve_index] != ID_TYPE_USER_NUM && resolveID_id_type[resolve_index] != ID_TYPE_USER_NUM_ARRAY)
{
rc_setError("Expected number identifier for argument");
return false;
}
vm_asm.push_back("ptr !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + resolveID_id_reg[resolve_index]);
break;
case ID_TYPE_BYREF_STR:
if(resolveID_id_type[resolve_index] != ID_TYPE_STR && resolveID_id_type[resolve_index] != ID_TYPE_ARR_STR && resolveID_id_type[resolve_index] != ID_TYPE_BYREF_STR && resolveID_id_type[resolve_index] != ID_TYPE_USER_STR && resolveID_id_type[resolve_index] != ID_TYPE_USER_STR_ARRAY)
{
rc_setError("Expected string identifier for argument");
return false;
}
vm_asm.push_back("ptr$ !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + resolveID_id_reg[resolve_index]);
break;
case ID_TYPE_BYREF_USER:
if(resolveID_id_type[resolve_index] != ID_TYPE_USER && resolveID_id_type[resolve_index] != ID_TYPE_BYREF_USER)
{
rc_setError("Expected defined type identifier for argument: " + rc_intToString(id[expr_id].fn_arg_utype[n]));
return false;
}
vm_asm.push_back("uref_ptr !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + resolveID_id_reg[resolve_index]);
break;
}
}
else if(id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_USER)
{
//cout << "BYREF USER TYPE CHECK" << endl;
//check if byref_type_exception
bool type_exception_found = false;
//cout << "CHECK EXCEPTION: " << args[n] << endl;
for(int bt_i = 0; bt_i < byref_type_exception.size(); bt_i++)
{
if(args[n].compare(byref_type_exception[bt_i].tk_reg)==0)
{
//cout << "FOUND EXCEPTION: " << args[n] << endl;
byref_type_exception[bt_i].tk_reg = "";
type_exception_found = true;
}
//else
//cout << "NO MATCH (" << args[n] << ", " << byref_type_exception[bt_i].tk_reg << ")" << endl;
}
//----------------
int ut_info = -1;
int ut_index = -1;
getRegInfo(args[n], ut_info, ut_index);
if(n==1 && StringToLower(id[expr_id].name).compare("typearraycopy")==0)
{
int uti_1 = -1;
int utx_1 = -1;
getRegInfo(args[0], uti_1, utx_1);
if(byref_type_exception.size()>=2)
{
byref_type_exception[0].exception_used = true;
byref_type_exception[1].exception_used = true;
}
if(utx_1 < 0 || (uti_1 != ID_TYPE_USER && uti_1 != ID_TYPE_BYREF_USER) || (ut_info != ID_TYPE_USER && ut_info != ID_TYPE_BYREF_USER) )
{
rc_setError("Invalid identifier for ByRef argument");
return false;
}
//cout << id[expr_id].name << " ARGS = " << ut_index << ", " << utx_1 << endl;
if(ut_index != utx_1)
{
rc_setError("Expected \"" + utype[utx_1].name + "\" identifier for ByRef argument");
return false;
}
}
if(ut_index != id[expr_id].fn_arg_utype[n] && (!byref_type_generic(utype[id[expr_id].fn_arg_utype[n]].name)))
{
rc_setError("Expected \"" + utype[id[expr_id].fn_arg_utype[n]].name + "\" identifier for ByRef argument");
return false;
}
//cout << "BYREF USER MATCH ID: " << id[expr_id].fn_arg[n] << " ==> " << args[n] << endl;
vm_asm.push_back("uref_ptr !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
}
else if(id[expr_id].fn_arg_type[n] == ID_TYPE_NUM)
{
if(args[n].substr(0,1).compare("n")!=0)
{
rc_setError("Expected number expression for argument");
return false;
}
//vm_asm.push_back("mov " + id[expr_id].fn_arg[n] + "->" + id[expr_id].fn_reg[n] + " " + args[n]);
vm_asm.push_back("mov !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
}
else if(id[expr_id].fn_arg_type[n] == ID_TYPE_STR)
{
if(args[n].substr(0,1).compare("s")!=0)
{
rc_setError("Expected string expression for argument");
return false;
}
//vm_asm.push_back("mov " + id[expr_id].fn_arg[n] + "->" + id[expr_id].fn_reg[n] + " " + args[n]);
vm_asm.push_back("mov$ !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
}
else if(id[expr_id].fn_arg_type[n] == ID_TYPE_USER)
{
//TODO: NEED TO CHECK UTYPE FOR ARG
if(args[n].substr(0,1).compare("u")!=0)
{
rc_setError("Expected expression of type \"" + utype[id[expr_id].fn_arg_utype[n]].name + "\" for argument");
return false;
}
int ut_info = -1;
int ut_index = -1;
getRegInfo(args[n], ut_info, ut_index);
if(ut_index != id[expr_id].fn_arg_utype[n] && (!byref_type_generic(utype[id[expr_id].fn_arg_utype[n]].name)))
{
rc_setError("Expected \"" + utype[id[expr_id].fn_arg_utype[n]].name + "\" identifier for argument");
return false;
}
//vm_asm.push_back("mov " + id[expr_id].fn_arg[n] + "->" + id[expr_id].fn_reg[n] + " " + args[n]);
vm_asm.push_back("mov_type !" + rc_intToString(id[expr_id].fn_arg_vec[n]) + " " + args[n]);
}
}
//check if any exceptions weren't used and return error if there are any left
for(int bt_i = 0; bt_i < byref_type_exception.size(); bt_i++)
{
if(byref_type_exception[bt_i].tk_reg.compare("")!=0)
{
rc_setError(byref_type_exception[bt_i].error_log);
return false;
}
}
//-----------------------------------------------------------------------------
string token_replace = "";
if(id[expr_id].isBuiltin)
vm_asm.push_back("func !" + rc_intToString(id[expr_id].vmFunctionIndex));
else
{
for(int n = 0; n < n_reg; n++)
{
vm_asm.push_back("push n" + rc_intToString(n));
n_tmp.push_back("n"+rc_intToString(n));
}
for(int n = 0; n < s_reg; n++)
{
vm_asm.push_back("push$ s" + rc_intToString(n));
s_tmp.push_back("s" + rc_intToString(n));
}
for(int n = 0; n < u_reg; n++)
{
vm_asm.push_back("push_t u" + rc_intToString(n));
u_tmp.push_back("u" + rc_intToString(n));
}
vm_asm.push_back("gosub @" + id[expr_id].name);
}
int ptr_count = 0;
for(int n = 0; n < id[expr_id].fn_arg.size(); n++)
{
if(id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_NUM || id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_STR || id[expr_id].fn_arg_type[n] == ID_TYPE_BYREF_USER)
ptr_count++;
}
if(ptr_count > 0)
{
vm_asm.push_back("pop_ptr !" + rc_intToString(ptr_count));
}
if(id[expr_id].type == ID_TYPE_FN_NUM)
{
token_replace = "n" + rc_intToString(n_reg);
vm_asm.push_back("pop " + token_replace);
inc_n(1);
}
else if(id[expr_id].type == ID_TYPE_FN_STR)
{
token_replace = "s" + rc_intToString(s_reg);
vm_asm.push_back("pop$ " + token_replace);
inc_s(1);
}
else if(id[expr_id].type == ID_TYPE_FN_USER)
{
token_replace = "u" + rc_intToString(u_reg);
//vm_asm.push_back("dim_type " + token_replace + " " + rc_intToString(id[expr_id].type_index)); NOTE: I decided to have pop_t free the memory for the variable before setting it
vm_asm.push_back("pop_t " + token_replace);
resolveID_id_reg.push_back(token_replace);
resolveID_id_type.push_back(ID_TYPE_USER);
resolveID_id_ut_index.push_back(id[expr_id].type_index);
resolveID_id_vec_pos.push_back(expr_id);
inc_u(1);
}
else if(id[expr_id].type == ID_TYPE_SUB)
{
token_replace = "?";
}
//cout << "start_dbg USER DT" << endl;
if(!id[expr_id].isBuiltin)
{
for(int n = n_tmp.size()-1; n >= 0; n--)
{
vm_asm.push_back("pop " + n_tmp[n]);
}
for(int n = s_tmp.size()-1; n >= 0; n--)
{
vm_asm.push_back("pop$ " + s_tmp[n]);
}
for(int n = u_tmp.size()-1; n >= 0; n--)
{
vm_asm.push_back("pop_t " + u_tmp[n]);
}
n_tmp.clear();
s_tmp.clear();
u_tmp.clear();
}
//cout << "end dbg" << endl;
// if(isInFunctionScope)
// {
// for(int n = id[expr_id].fn_var.size()-1; n >= 0; n--)
// {
// if(id[expr_id].fn_var[n].type == ID_TYPE_NUM || id[expr_id].fn_var[n].type == ID_TYPE_BYREF_NUM || id[expr_id].fn_var[n].type == ID_TYPE_ARR_NUM)
// {
// vm_asm.push_back("pop " + id[expr_id].fn_var[n].vec_str);
// }
// else
// {
// vm_asm.push_back("pop$ " + id[expr_id].fn_var[n].vec_str);
// }
// }
// }
for(int p = arr_token_start; p <= arr_token_end; p++)
token[p] = "";
if(token_replace.compare("")==0)
{
rc_setError("Could not resolve function " + id[expr_id].name);
return false;
}
token[arr_token_start] = token_replace;
//cout << "the end of function: " << i << ", " << end_token << " ---> " << token[i] << endl;
//if token is <child> then I am going to subtract 1 from i so that when it goes back through the loop and increments i, it will be child
i--;
}
}
else if(token[i].compare("<child>")==0)
{
//cout << "USER DEFINED TYPE REGISTER ARGUMENT" << endl;
n = "n" + rc_intToString(n_reg);
s = "s" + rc_intToString(s_reg);
u = "u" + rc_intToString(u_reg);
string expr_ureg = "";
bool should_eval = false;
string expr_member = "";
if(i < end_token)
expr_member = token[i+1];
if(expr_member.find_first_of(">") != string::npos)
expr_member = expr_member.substr(expr_member.find_first_of(">")+1);
for(int t = i-1; t >= 0; t--)
{
if(token[t].compare("")!=0)
{
if(token[t].substr(0,1).compare("u")==0)
{
expr_ureg = token[t];
should_eval = true;
token[t] = "";
}
//cout << "break token = " << token[t] << " :: " << should_eval << endl;
break;
}
}
if(!should_eval)
{
continue;
}
else
{
//cout << "EVAL SUPER UDT" << endl;
//continue;
}
//user type expression from another user type expression (ie. something already stored in u register)
//cout << "-Parsing User Variable: " << id[expr_id].name << endl;
// cout << "----------------------------------------------- : " << eval_udt << endl;
bool udt_id_init = false;
vm_asm.push_back("obj_usr_init " + expr_ureg);
token[i] = "";
int ureg_index = getResolveReg(expr_ureg);
int ureg_id = resolveID_id_vec_pos[ureg_index];
string tmp_scope = id[ureg_id].scope + "." + id[ureg_id].name;
/*
cout << "Resolve = " << ureg_id << ": " << tmp_scope << endl;
for(int t = i; t < token.size(); t++)
{
try
{
cout << t << ":" << token.at(t) << endl;
}
catch(out_of_range& e)
{
cout << "Token Out of Range Error: " << e.what() << endl;
}
}
*/
int tmp_id = 0;
bool has_child = false;
for(int t = i+1; t <= end_token; t++)
{
if(token[t].substr(0,4).compare("<id>")==0)
{
//cout << "FIGURE IT OUT: " << t << token[t] << endl;
string args[3];
int arg_count = 0;
string full_id = token[t].substr(4);
token[t] = "";
tmp_id = getIDInScope_ByIndex_TypeMatch(full_id, tmp_scope);
//cout << "\ntmp_id = " << tmp_id << endl;
if(tmp_id < 0)
{
rc_setError(tmp_scope.substr(5) + " does not have member \"" + full_id + "\"");
return false;
}
//cout << "Scope = " << id[tmp_id].scope << " ID = " << full_id << " -- " << tmp_id << endl << endl;
tmp_scope += "." + full_id;
//get arguments (ie. the dimensions of an array
int t2 = t+1;
if(t2 < end_token)
{
int arr_scope = 0;
if(token[t2].compare("!<square>")==0)
{
token[t2] = "";
args[0] = "";
args[1] = "";
args[2] = "";
arg_count = 0;
arr_scope = 1;
t2++;
//cout << "T2 = " << t2 << endl << endl;
for(; t2 <= end_token; t2++)
{
//cout << "DBG ARR: " << t2 << ", " << end_token << " : " << token[t2] << endl;
if(token[t2].compare("!</square>")==0)
arr_scope--;
else if(token[t2].compare("!<square>")==0)
arr_scope++;
else if(token[t2].compare("!<comma>")==0)
arg_count++;
else if(token[t2].substr(0,1).compare("n")==0)
{
if(args[arg_count].compare("")==0)
args[arg_count] = token[t2];
else
{
rc_setError("Error parsing array dimension: " + args[arg_count] + " :: " + token[t2] + " -- " + rc_intToString(t2) + ", " + rc_intToString(arg_count));
return false;
}
}
token[t2] = "";
if(arg_count >= 3)
{
rc_setError("Too many dimensions in array");
return false;
}
if(arr_scope == 0)
break;
}
if(arr_scope > 0)
{
rc_setError("Expected ]] in expression: " + rc_intToString(arr_scope));
return false;
}
arg_count++;
}
}
has_child = false;
if((t2+1) < token.size())
{
if(token[t2+1].compare("<child>")==0)
{
has_child = true;
}
}
if(arg_count != id[tmp_id].num_args)
{
if(!type_delete_flag)
{
rc_setError("[0]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name);
return false;
}
else
{
if(has_child)
{
rc_setError("[1]Expected " + rc_intToString(id[tmp_id].num_args) + " dimension in " + id[tmp_id].name);
return false;
}
arg_count = id[tmp_id].num_args;
//vm_asm.push_back("mov n" + rc_intToString(n_reg) + " 0");
//args[0] = "n" + rc_intToString(n_reg);
//args[1] = args[0];
//args[2] = args[0];
//inc_n(1);
}
}
if(type_delete_flag && (!has_child))
{
//DO NOTHING
//cout << "NO CHILD: " << id[tmp_id].name << endl;
}
else
{
//if(type_delete_flag)
// cout << "TESTING STUFF" << endl;
switch(arg_count)
{
case 0:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init !" + rc_intToString(id[tmp_id].vec_pos));
else
vm_asm.push_back("obj_usr !" + rc_intToString(id[tmp_id].vec_pos));
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n !" + rc_intToString(id[tmp_id].vec_pos));
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s !" + rc_intToString(id[tmp_id].vec_pos));
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 1:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else
vm_asm.push_back("obj_usr1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s1 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 2:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else
vm_asm.push_back("obj_usr2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s2 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
case 3:
if(id[tmp_id].type == ID_TYPE_USER || id[tmp_id].type == ID_TYPE_BYREF_USER)
{
if(udt_id_init)
vm_asm.push_back("obj_usr_init3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else
vm_asm.push_back("obj_usr3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
}
else if(id[tmp_id].type == ID_TYPE_USER_NUM)
vm_asm.push_back("obj_usr_n3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else if(id[tmp_id].type == ID_TYPE_USER_STR)
vm_asm.push_back("obj_usr_s3 !" + rc_intToString(id[tmp_id].vec_pos) + " " + args[0] + " " + args[1] + " " + args[2]);
else
{
rc_setError("Invalid type in User Defined Type");
return false;
}
break;
}
udt_id_init = false;
}
}
else if(token[t].compare("<child>")==0)
{
token[t] = "";
continue;
}
else if(token[t].compare("")!=0)
{
break;
}
}
//START HERE
if(type_delete_flag && (!has_child))
{
//cout << "DELETE_VAR = " << id[tmp_id].name << endl;
type_delete_arg = "!" + rc_intToString(id[tmp_id].vec_pos);
}
else
switch(id[tmp_id].type)
{
case ID_TYPE_USER:
case ID_TYPE_BYREF_USER:
vm_asm.push_back("obj_usr_get " + u);
token[i] = u;
resolveID_id_reg.push_back(token[i]);
resolveID_id_type.push_back(id[tmp_id].type);
resolveID_id_ut_index.push_back(id[tmp_id].type_index);
resolveID_id_vec_pos.push_back(tmp_id);
inc_u(1);
break;
case ID_TYPE_USER_NUM:
vm_asm.push_back("obj_usr_get " + n);
token[i] = n;
inc_n(1);
break;
case ID_TYPE_USER_STR:
vm_asm.push_back("obj_usr_get " + s);
token[i] = s;
inc_s(1);
break;
default:
break;
}
/*
cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
for(int t = 0; t < token.size(); t++)
{
try
{
cout << t << ":" << token.at(t) << endl;
}
catch(out_of_range& e)
{
cout << "Token Out of Range Error: " << e.what() << endl;
}
}
cout << "-----------------------------------------------" << endl;
*/
//for(int t = 0; t < id.size(); t++)
// if(id[t].type == ID_TYPE_USER) cout << "ID[" << id[t].name << "] SCOPE=" << id[t].scope << " -- " << id[t].vec_pos << endl;
}
}
return true;
}
// I really hate Wal-Mart
struct block_argument
{
int arg_start = -1;
int arg_end = -1;
};
vector<block_argument> block_args;
vector<string> block_arg_data;
bool getArgBlockStuff(int start_block, int& arg_count)
{
block_args.clear();
int end_block = -1;
arg_count = 0;
//string block_type = token[start_block];
//string block_end_type = "";
block_argument b_arg;
// if(block_type.compare("<square>")==0)
// block_end_type = "</square>";
// else if(block_type.compare("<par>")==0)
// block_end_type = "</par>";
// else if(block_type.compare("<curly>")==0)
// block_end_type = "</curly>";
// else
// {
// rc_setError("Expected Start of Control Block");
// return false;
// }
if(token.size() > start_block)
{
//if its not a bracketed block then there is no need to check for arguments
if(token[start_block].compare("!<par>")!=0 && token[start_block].compare("!<square>")!=0 && token[start_block].compare("!<curly>")!=0)
{
arg_count = 0;
return true;
}
int scope = 1;
b_arg.arg_start = start_block + 1;
for(int i = start_block+1; i < token.size(); i++)
{
if(token[i].compare("!<par>")==0 || token[i].compare("!<square>")==0 || token[i].compare("!<curly>")==0)
scope++;
else if(token[i].compare("!</par>")==0 || token[i].compare("!</square>")==0 || token[i].compare("!</curly>")==0)
scope--;
if(scope == 0)
{
//getBlock should take care of this check already
//
//if(token[i].compare(block_end_type)!=0)
//{
// rc_setError("Block was not ended correctly");
// return false;
//}
//else
// end_block = i;
arg_count++;
b_arg.arg_end = i - 1;
block_args.push_back(b_arg);
break;
}
else if(scope == 1)
{
if(token[i].compare("<comma>")==0)
{
token[i] = "!" + token[i];
arg_count++;
b_arg.arg_end = i-1;
block_args.push_back(b_arg);
b_arg.arg_start = i + 1;
}
}
}
}
return true;
}
bool getBlockArg(int arg_num, int& start_arg, int& end_arg)
{
if(arg_num < block_args.size())
{
start_arg = block_args[arg_num].arg_start;
end_arg = block_args[arg_num].arg_end;
}
else
{
start_arg = -1;
end_arg = -1;
return false;
}
return true;
}
string multi_arg[64];
int multi_arg_count = 0;
bool eval_expression(int start_token = 0, int end_token = 0, bool allow_multi_arg = false)
{
int start_block = start_token; //will hold the index of the token the current block starts on
int end_block = end_token; //will hold the index of the token the current block ends on
int arg_start = 0;
int arg_end = 0;
int arg_count = 0;
multi_arg[0] = "";
multi_arg[1] = "";
multi_arg[2] = "";
expr_result = "";
int current_block_start = 0;
int current_block_end = 0;
if(end_token==0)
end_token = token.size()-1;
pre_parse(start_token, end_token);
//cout << "EXPRESSION" << endl;
//output_tokens();
//cout << "------------------------" << endl;
//cout << "POST PRE_PARSE" << endl;
//for(int i = start_token; i <= end_token; i++)
//cout << "Token[" << i << "]= " << token[i] << endl;
string arg_result = "";
multi_arg_count = 0;
do
{
getBlock(start_token, end_token, start_block, end_block); //sets the current start_block and end_block
//cout << "\nstart pp" << endl;
if(!pre_parse(start_block, end_block, PP_FLAG_ARRAY, true))
{
return false;
}
//cout << "end pp" << endl;
getArgBlockStuff(start_block, arg_count);
//cout << "block arg count --> " << arg_count << endl;
//cout << "start block = " << start_token << endl << endl; cout << "end block = " << end_token << endl;
if(end_block < 0) //if end_block is less than 0 then an error occurred so this function will return false
{
//cout << "End block < 0" << endl;
//rc_setError("Could not evaluate expression");
return false;
}
/* ORDER OF OPERATIONS
1. powers
2. multiplication, division, modulous
3. addition, subtraction
*/
if(arg_count > 1)
{
//cout << "arg_count = " << arg_count << endl;
for(int i = 0; i < arg_count; i++)
{
getBlockArg(i, arg_start, arg_end);
if(!eval_not(start_block, end_block))
return false;
if(!eval_pow(arg_start, arg_end))
return false;
if(!eval_muldiv(arg_start, arg_end))
return false;
if(!eval_addsub(arg_start, arg_end))
return false;
if(!eval_bitshift(arg_start, arg_end))
return false;
if(!eval_cmp(arg_start, arg_end))
return false;
if(!eval_andor(arg_start, arg_end))
return false;
arg_result = "";
for(int n = arg_start; n <= arg_end; n++)
{
if(token[n].size()>0)
{
if(token[n].substr(0,1).compare("n")==0 || token[n].substr(0,1).compare("s")==0 || token[n].substr(0,1).compare("u")==0 || token[n].substr(0,4).compare("<id>") == 0)
{
if(arg_result.compare("")==0)
arg_result = token[n];
else
{
rc_setError("Found multiple args not separated by a comma");
return false;
}
}
}
token[n] = "";
}
token[arg_start] = arg_result;
}
}
else
{
//cout << "start" << endl;
if(!eval_not(start_block, end_block))
return false;
if(!eval_pow(start_block, end_block))
return false;
if(!eval_muldiv(start_block, end_block))
return false;
if(!eval_addsub(start_block, end_block))
return false;
if(!eval_bitshift(start_block, end_block))
return false;
if(!eval_cmp(start_block, end_block))
return false;
if(!eval_andor(start_block, end_block))
return false;
//cout << "end here" << endl;
}
//cout << "start block end = " << start_token << endl;
}while(!(start_block==start_token && end_block==end_token));
int result_count = 0;
//cout << "Get RESULTS" << endl;
for(int i = start_token; i <= end_token; i++)
{
//cout << "TOK[" << i << "] = " << token[i] << endl;
if(token[i].length()>0)
{
if(token[i].substr(0,1).compare("n")==0 || token[i].substr(0,1).compare("s")==0 ||
token[i].substr(0,1).compare("u")==0 || token[i].substr(0,1).compare("?")==0)
{
expr_result = token[i];
multi_arg[multi_arg_count] = token[i];
multi_arg_count++;
result_count++;
}
else if(token[i].substr(0,1).compare("!")!=0)
{
rc_setError("--Could not evaluate expression: " + token[i]);
return false;
}
}
if(result_count > 1 && !allow_multi_arg)
{
//cout << "ST:ET = " << start_block << ", " << end_block << endl;
rc_setError("++Could not evaluate expression");
return false;
}
}
return true;
}
int constant_arg[64];
int constant_arg_count = 0;
bool eval_constantExpression(int start_token, int end_token)
{
//cout << "constant_start = " << token[start_token] << endl;
//cout << "constant_end = " << token[end_token] << endl;
constant_arg_count = 0;
constant_arg[0] = 0;
constant_arg[1] = 0;
constant_arg[2] = 0;
for(int i = start_token; i <= end_token; i++)
{
if(rc_substr(token[i], 0, 5).compare("<num>")==0)
{
constant_arg[constant_arg_count] = rc_stringToInt(token[i].substr(5));
//cout << "array dim[" << constant_arg_count << "] = " << constant_arg[constant_arg_count] << endl;
if(token.size() > (i+1))
{
if(token[i+1].compare("<comma>")!=0 && token[i+1].compare("</square>")!=0)
{
//cout << "Next token is " << token[i+1] << endl;
rc_setError("Expected <comma> after number constant");
return false;
}
}
}
else if(rc_substr(token[i],0, 7).compare("<comma>")==0)
{
constant_arg_count++;
if(constant_arg_count >= 3)
{
rc_setError("Too many arguments in member definition");
return false;
}
}
else
{
rc_setError("Expected constant in member definition");
return false;
}
}
constant_arg_count++;
return true;
}
int findFirstDelimiter(string line)
{
for(int i = 0; i < line.length(); i++)
{
if(line[i] == '.' || line[i] == '[' || line[i] == ']' || line[i] == ' ')
return i;
}
return line.length()-1;
}
bool isDelimiter(char c)
{
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '^':
case ',':
case '=':
case '<':
case '>':
case ' ':
return true;
break;
}
return false;
}
void clearRegs()
{
n_reg = 0;
s_reg = 0;
u_reg = 0;
resolveID_id_reg.clear();
resolveID_id_type.clear();
resolveID_id_ut_index.clear();
resolveID_id_vec_pos.clear();
}
bool check_rule()
{
if(token.size()>0)
{
if(current_block_state == BLOCK_STATE_TYPE)
{
if(token[0].compare("<dim>")!=0 && token[0].compare("<end>")!=0)
{
rc_setError("Expected DIM in TYPE definition");
return false;
}
}
else if(current_block_state != BLOCK_STATE_MAIN)
{
if(token[0].compare("<type>")==0)
{
rc_setError("TYPE cannot be declared in the current scope");
return false;
}
else if(token[0].compare("<function>")==0)
{
rc_setError("FUNCTION cannot be declared in the current scope");
return false;
}
else if(token[0].compare("<subp>")==0)
{
rc_setError("SUB ROUTINE cannot be declared in the current scope");
return false;
}
}
if(token[0].compare("<const>")==0)
{
if(token.size() < 3)
{
rc_setError("Incomplete Constant Expression");
return false;
}
if(token[1].substr(0,4).compare("<id>")!=0)
{
rc_setError("Expected Identifier after CONST");
return false;
}
string id_name = token[1].substr(4);
if(!isValidIDName(id_name))
{
rc_setError("Invalid Identifier after CONST");
return false;
}
if(token[2].compare("<equal>")!=0)
{
rc_setError("Expected \"=\" in CONST expression");
return false;
}
int c_id = create_constant(StringToUpper(id_name));
if(c_id < 0)
{
rc_setError("CONST identifier already exists");
return false;
}
for(int i = 3; i < token.size(); i++)
add_const_token(c_id, token[i]);
return true;
}
else if(token[0].compare("<dim>")==0)
{
//cout << "DIM RULE FOUND" << endl; //'DIM' [ID]; '[' #; #; # ']' ; 'AS' [TYPE]; '=' (VALUE)
string id_name = "";
int id_type = ID_TYPE_NUM;
string id_type_name = "";
int dimensions = 0;
//check if the next token is a identifier
if(token.size() > 1)
{
if(token[1].substr(0,4).compare("<id>")==0)
{
//if the identifier is not a valid name then return false
id_name = token[1].substr(4);
id_type = ID_TYPE_NUM;
id_type_name = "";
dimensions = 0;
if(!isValidIDName(id_name))
{
rc_setError("Invalid Identifier name");
return false;
}
//check if the data type is a string
if(id_name.substr(id_name.length()-1).compare("$")==0)
id_type = ID_TYPE_STR;
//if the identifier already exists and current_block state is not type then return false
if(idExistsInScope(id_name))
{
rc_setError("Identifier already defined in current scope");
return false;
}
//cout << "db1\n";
//if there are only two tokens then return here because there is nothing left to check
if(token.size()==2)
{
if(current_block_state == BLOCK_STATE_TYPE)
{
//cout << "adding type member: " << id_name << ", " << id_type << endl;
if(!add_type_member(id_name, id_type, "", 0))
{
//std::cout << "error" << std::endl;
//cout << rc_getError() << endl;
return false;
}
}
else if(isInFunctionScope)
{
if(!create_function_variable(id_name, id_type, ""))
{
//cout << rc_getError() << endl;
return false;
}
}
else
{
if(!create_variable(id_name, id_type))
{
//cout << rc_getError() << endl;
return false;
}
}
//cout << "return true here" << endl;
return true;
}
//cout << "db2\n";
//current token
int token_index = 2;
//check for the next rule; must be [], AS, or =
//cout << "token = " << token[token_index] << endl;
if(token[token_index].compare("<square>")==0 && current_block_state == BLOCK_STATE_TYPE)
{
//token_index++;
int end_token = token_index+1;
int sq_scope = 1;
for(; end_token < token.size(); end_token++)
{
if(token[end_token].compare("<square>")==0)
sq_scope++;
else if(token[end_token].compare("</square>")==0)
sq_scope--;
if(sq_scope==0)
break;
}
if(sq_scope != 0)
{
rc_setError("Expected ] in array definition");
return false;
}
/*if(end_token > token_index)
end_token--;
else
{
rc_setError("Expected atleast 1 parameter in member array definition");
return false;
}*/
//if(eval_constantExpression(token_index, end_token))
//cout << "EVAL EXPR" << endl;
if(eval_expression(token_index, end_token, true))
{
dimensions = multi_arg_count;
}
else
{
rc_setError("Expected constant for type member array");
return false;
}
token_index = end_token+1;
//cout << "DBG token = " << token[token_index] << std::endl;
if(token.size() > token_index)
{
if(token[token_index].compare("<as>")==0)
{
token_index++;
if(token[token_index].substr(0,4).compare("<id>")!=0)
{
rc_setError("Invalid type identifier name in DIM");
return false;
}
id_type = ID_TYPE_USER;
id_type_name = token[token_index].substr(4);
//cout << "Add member (" << id_name << ") of type (" << id_type_name << ") with " << dimensions << " dimensions [" << constant_arg[0] << "," << constant_arg[1] << "," << constant_arg[2] << "]" << endl;
//if(!add_type_member(id_name, id_type, id_type_name, dimensions, constant_arg[0], constant_arg[1], constant_arg[2]))
if(!add_type_member(id_name, id_type, id_type_name, dimensions, multi_arg[0], multi_arg[1], multi_arg[2]))
return false;
}
else
{
rc_setError("Invalid member array declaration in DIM");
return false;
}
}
else
{
//cout << "Add member (" << id_name << ") of type (num/str) with " << dimensions << " dimensions [" << constant_arg[0] << "," << constant_arg[1] << "," << constant_arg[2] << "]" << endl;
//if(!add_type_member(id_name, id_type, "", dimensions, constant_arg[0], constant_arg[1], constant_arg[2]))
if(!add_type_member(id_name, id_type, "", dimensions, multi_arg[0], multi_arg[1], multi_arg[2]))
return false;
}
return true;
}
else if(token[token_index].compare("<square>")==0)
{
multi_arg[0] = "";
multi_arg[1] = "";
multi_arg[2] = "";
multi_arg_count = 0;
int end_token = token_index+1;
int sq_scope = 1;
for(; end_token < token.size(); end_token++)
{
if(token[end_token].compare("</square>")==0)
sq_scope--;
else if(token[end_token].compare("<square>")==0)
sq_scope++;
if(sq_scope==0)
break;
}
if(sq_scope != 0)
{
rc_setError("Expected ] in array definition");
return false;
}
if(!eval_expression(token_index, end_token, true))
{
rc_setError("Could not evaluate expression in array definition");
return false;
}
if(multi_arg_count <= 0 || multi_arg_count > 3)
{
rc_setError("Expected 1 to 3 Arguments for array definition, Found " + rc_intToString(multi_arg_count));
return false;
}
else
{
//cout << "M_ARG[0] = " << multi_arg[0] << endl;
//cout << "M_ARG[1] = " << multi_arg[1] << endl;
//cout << "M_ARG[2] = " << multi_arg[2] << endl;
dimensions = multi_arg_count;
}
token_index = end_token+1;
if(token.size()>token_index)
{
if(token[token_index].compare("<as>")==0)
{
token_index++;
if(token.size()>token_index)
{
if(token[token_index].substr(0,4).compare("<id>")!=0)
{
rc_setError("Invalid type identifier in DIM");
return false;
}
id_type_name = token[token_index].substr(4);
//cout << "DIM <" << id_name << "> AS < " << id_type_name << " [";
switch(dimensions)
{
case 1:
//cout << multi_arg[0] << "] >" << endl;
break;
case 2:
//cout << multi_arg[0] << ", " << multi_arg[1] << "] >" << endl;
break;
case 3:
//cout << multi_arg[0] << ", " << multi_arg[1] << ", " << multi_arg[2] << "] >" << endl;
break;
default:
rc_setError("Too many arguments in DIM");
return false;
}
create_array(id_name, ID_TYPE_USER, id_type_name, dimensions, multi_arg[0], multi_arg[1], multi_arg[2]);
//vm_asm.push_back("preset_t !" + )
//cout << "Create FN USER ARRAY - " << id_name << endl;
return true;
}
else
{
rc_setError("Expected type identifier in DIM");
return false;
}
}
else
{
rc_setError("Invalid array type definition");
return false;
}
}
}
else if(token[token_index].compare("<as>")==0)
{
id_type = ID_TYPE_USER;
if(token.size() != 4)
{
rc_setError("Expected single type identifier in DIM");
return false;
}
else if(token[3].substr(0,4).compare("<id>")!=0)
{
rc_setError("Invalid type identifier name in DIM");
return false;
}
if(current_block_state == BLOCK_STATE_TYPE)
{
//cout << "create member (" << id_name << ") of type " << token[3].substr(4) << endl;
if(!add_type_member(id_name, ID_TYPE_USER, token[3].substr(4), 0))
return false;
}
else
{
//cout << "create variable (" << id_name << ") of type " << token[3].substr(4) << endl;
if(!create_variable(id_name, id_type, token[3].substr(4)))
return false;
}
return true;
}
if(token.size()>token_index)
{
rc_setError("Invalid variable definition: " + token[token_index] + ", " + rc_intToString(current_block_state) + " <--> " + rc_intToString(BLOCK_STATE_TYPE));
return false;
}
}
else
{
//if the next token is not an id then the syntax is incorrect and false is returned
rc_setError("Expected Identifier name");
return false;
}
if(dimensions > 0)
{
switch(id_type)
{
case ID_TYPE_NUM:
id_type = ID_TYPE_ARR_NUM;
break;
case ID_TYPE_STR:
id_type = ID_TYPE_ARR_STR;
break;
}
if(isInFunctionScope)
{
if(!create_function_array(id_name,id_type, dimensions, multi_arg[0], multi_arg[1], multi_arg[2]))
{
return false;
}
}
else if(!create_array(id_name, id_type, id_type_name, dimensions, multi_arg[0], multi_arg[1], multi_arg[2]))
{
//cout << rc_getError() << endl;
return false;
}
//cout << "Created Array: " << id_name << " of type " << id_type << endl;
}
else
{
if(!create_variable(id_name, id_type, id_type_name))
{
//cout << rc_getError() << endl;
return false;
}
}
}
else
{
//if the size of the token vector is not greater than one then the syntax for the line is incomplete so I return false
rc_setError("Expected Identifier name");
return false;
}
}
else if(token[0].compare("<redim>")==0)
{
//cout << "REDIM RULE FOUND" << endl; //'DIM' [ID]; '[' #; #; # ']' ; 'AS' [TYPE]; '=' (VALUE)
string id_name = "";
int id_type = ID_TYPE_NUM;
string id_type_name = "";
int dimensions = 0;
int id_index = -1;
//check if the next token is a identifier
if(token.size() > 1)
{
if(token[1].substr(0,4).compare("<id>")==0)
{
//if the identifier is not a valid name then return false
id_name = token[1].substr(4);
id_type = ID_TYPE_NUM;
id_type_name = "";
dimensions = 0;
if(!isValidIDName(id_name))
{
rc_setError("Invalid Identifier name");
return false;
}
id_index = getIDInScope_ByIndex(id_name);
//cout << "debug 0: " << id_index << " -> " << id[id_index].name << " --- " << id[id_index].vec_pos << endl;
//if the identifier already exists and current_block state is not type then return false
if(id_index < 0)
{
rc_setError("Identifier was not defined in current scope");
return false;
}
if(id[id_index].num_args <= 0)
{
rc_setError("REDIM expected array identifier");
return false;
}
id_type = id[id_index].type;
type_redim_arg_type = 0;
//cout << "db1\n";
//if there are only two tokens then return here because there is nothing left to check
if(token.size()==2)
{
rc_setError("Dimensions must be specified for REDIM");
//cout << "return true here" << endl;
return false;
}
//cout << "db2\n";
//current token
int token_index = 2;
//check for the next rule; must be [], AS, or =
if(token[token_index].compare("<square>")==0 && current_block_state == BLOCK_STATE_TYPE)
{
token_index++;
int end_token = token_index;
int sq_scope = 1;
for(; end_token < token.size(); end_token++)
{
if(token[end_token].compare("<square>")==0)
sq_scope++;
else if(token[end_token].compare("</square>")==0)
sq_scope--;
if(sq_scope==0)
break;
}
if(sq_scope != 0)
{
rc_setError("Expected ] in array definition");
return false;
}
if(end_token > token_index)
end_token--;
else
{
rc_setError("Expected atleast 1 parameter in member array definition");
return false;
}
if(eval_constantExpression(token_index, end_token))
{
dimensions = constant_arg_count;
}
else
{
rc_setError("Expected constant for type member array");
return false;
}
token_index = end_token+2;
}
else if(token[token_index].compare("<square>")==0)
{
multi_arg[0] = "";
multi_arg[1] = "";
multi_arg[2] = "";
multi_arg_count = 0;
int end_token = token_index+1;
int sq_scope = 1;
bool has_child = false;
for(; end_token < token.size(); end_token++)
{
if(token[end_token].compare("</square>")==0)
sq_scope--;
else if(token[end_token].compare("<square>")==0)
sq_scope++;
if( (end_token+1) < token.size() )
{
if(token[end_token+1].compare("<child>")==0 || token[end_token].compare("<child>")==0)
{
has_child = true;
continue;
}
else if(token[end_token+1].compare("<square>")==0)
continue;
}
if(sq_scope==0)
break;
}
if(sq_scope != 0)
{
rc_setError("Expected ] in array definition");
return false;
}
//cout << "DEBUG TOKENS: " << endl;
//cout << "----------------------" << endl;
//for(int tk = token_index; tk < end_token; tk++) cout << token[tk] << endl;
//cout << "-------------------------------------" << endl;
if(has_child)
{
token_index = 1;
type_redim_flag = true;
type_redim_arg_type = 0;
}
else
type_redim_flag = false;
//cout << "debug 1: " << id_index << endl;
if(!eval_expression(token_index, end_token, true))
{
rc_setError("Could not evaluate expression in array definition");
return false;
}
//cout << "debug 2: " << id_index << endl;
if(type_redim_flag)
{
if(type_redim_dim_count <= 0)
{
rc_setError("Expected 1 to 3 Arguments for array re-dimension, Found " + rc_intToString(multi_arg_count));
return false;
}
dimensions = type_redim_dim_count;
multi_arg[0] = type_redim_dim[0];
multi_arg[1] = type_redim_dim[1];
multi_arg[2] = type_redim_dim[2];
//cout << "type arg = " << type_redim_arg << " type = " << type_redim_arg_type << " utype = " << type_redim_arg_utype << endl;
}
else if(multi_arg_count <= 0 || multi_arg_count > 3)
{
rc_setError("Expected 1 to 3 Arguments for array re-dimension, Found " + rc_intToString(multi_arg_count));
return false;
}
else
{
//cout << "M_ARG[0] = " << multi_arg[0] << endl;
//cout << "M_ARG[1] = " << multi_arg[1] << endl;
//cout << "M_ARG[2] = " << multi_arg[2] << endl;
dimensions = multi_arg_count;
}
token_index = end_token+1;
//cout << "debug 3: " << id_index << endl;
}
else
{
rc_setError("Expected dimensions for REDIM");
return false;
}
if(token.size()>token_index)
{
rc_setError("Invalid use of REDIM");
return false;
}
//cout << "debug 4: " << id_index << endl;
}
else
{
//if the next token is not an id then the syntax is incorrect and false is returned
rc_setError("Expected Identifier name");
return false;
}
if(!type_redim_flag) //if type_redim_flag is set, then this error will get raised in the pre_parse step
{
if(dimensions != id[id_index].num_args) // no longer allowing the user to change dimensions since it can lead to unnecessary confusion
{
rc_setError("Expected " + rc_intToString(id[id_index].num_args) + " dimensions but found " + rc_intToString(dimensions));
return false;
}
}
type_redim_flag = false;
if(dimensions > 0)
{
//cout << "debug 5: " << id_index << endl;
switch(id_type)
{
case ID_TYPE_NUM:
id_type = ID_TYPE_ARR_NUM;
break;
case ID_TYPE_STR:
id_type = ID_TYPE_ARR_STR;
break;
}
//cout << "debug 6: " << id_index << endl;
//if(id[id_index].num_args != dimensions)
//{
// id[id_index].num_args = dimensions;
//}
//cout << "debug 7: " << id_index << " -- " << id[id_index].type << endl;
if(type_redim_arg_type == ID_TYPE_USER)
{
switch(dimensions)
{
case 1:
vm_asm.push_back("redim_type1 " + type_redim_arg + " " + type_redim_arg_utype + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim_type2 " + type_redim_arg + " " + type_redim_arg_utype + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim_type3 " + type_redim_arg + " " + type_redim_arg_utype + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else if(type_redim_arg_type == ID_TYPE_USER_NUM || type_redim_arg_type == ID_TYPE_USER_NUM_ARRAY)
{
switch(dimensions)
{
case 1:
vm_asm.push_back("redim_type_n1 " + type_redim_arg + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim_type_n2 " + type_redim_arg + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim_type_n3 " + type_redim_arg + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else if(type_redim_arg_type == ID_TYPE_USER_STR || type_redim_arg_type == ID_TYPE_USER_STR_ARRAY)
{
switch(dimensions)
{
case 1:
vm_asm.push_back("redim_type_s1 " + type_redim_arg + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim_type_s2 " + type_redim_arg + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim_type_s3 " + type_redim_arg + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else if(id[id_index].type == ID_TYPE_USER)
{
vm_asm.push_back("redim_top"); //This will set the top level flag for redim_type
//cout << "debug 8" << endl;
switch(dimensions)
{
case 1:
vm_asm.push_back("redim_type1 !" + rc_intToString(id[id_index].vec_pos) + " !" + rc_intToString(id[id_index].type_index) + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim_type2 !" + rc_intToString(id[id_index].vec_pos) + " !" + rc_intToString(id[id_index].type_index) + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim_type3 !" + rc_intToString(id[id_index].vec_pos) + " !" + rc_intToString(id[id_index].type_index) + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else if(id[id_index].type == ID_TYPE_NUM || id[id_index].type == ID_TYPE_ARR_NUM)
{
//cout << "debug 8" << endl;
switch(dimensions)
{
case 1:
vm_asm.push_back("redim1 !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim2 !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim3 !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else if(id[id_index].type == ID_TYPE_STR || id[id_index].type == ID_TYPE_ARR_STR)
{
switch(dimensions)
{
case 1:
vm_asm.push_back("redim1$ !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("redim2$ !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("redim3$ !" + rc_intToString(id[id_index].vec_pos) + " " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
default:
rc_setError("Invalid number of dimensions in REDIM");
return false;
}
}
else
{
rc_setError("Invalid type for REDIM: " + rc_intToString(id[id_index].type));
return false;
}
//cout << "balls" << endl;
return true;
}
else
{
rc_setError("Expected dimensions in REDIM");
return false;
}
}
else
{
//if the size of the token vector is not greater than one then the syntax for the line is incomplete so I return false
rc_setError("Expected Identifier name");
return false;
}
//cout << "debug final" << endl;
}
else if(token[0].compare("<end>")==0)
{
if(token.size()==1)
{
vm_asm.push_back("end");
return true;
}
if(token[1].compare("<function>")==0)
{
if(token.size()>2)
{
rc_setError("Expected End of Line in END FUNCTION");
return false;
}
if(current_block_state != BLOCK_STATE_FUNCTION)
{
rc_setError("Cannot exit function from this scope");
return false;
}
//int ptr_count = 0;
//for(int n = 0; n < id[current_fn_index].fn_arg.size(); n++)
//{
// if(id[current_fn_index].fn_arg_type[n] == ID_TYPE_BYREF_NUM || id[current_fn_index].fn_arg_type[n] == ID_TYPE_BYREF_STR)
// {
// ptr_count++;
// }
//}
//if(ptr_count > 0)
// vm_asm.push_back("pop_ptr !" + rc_intToString(ptr_count));
if(id[current_fn_index].type == ID_TYPE_FN_NUM)
{
vm_asm.push_back("push 0");
vm_asm.push_back("return");
vm_asm.push_back(".code");
vm_asm.n_stack_count = 0;
}
else if(id[current_fn_index].type == ID_TYPE_FN_STR)
{
vm_asm.push_back("push_empty$");
vm_asm.push_back("return");
vm_asm.push_back(".code");
vm_asm.s_stack_count = 0;
}
else if(id[current_fn_index].type == ID_TYPE_FN_USER)
{
vm_asm.push_back("dim_type u0 !" + rc_intToString(id[current_fn_index].type_index));
vm_asm.push_back("push_t u0");
vm_asm.push_back("return");
vm_asm.push_back(".code");
vm_asm.u_stack_count = 0;
}
block_state.pop();
current_block_state = BLOCK_STATE_MAIN;
isInFunctionScope = false;
current_scope = "main";
for(uint64_t i = 0; i < id[current_fn_index].fn_arg.size(); i++)
{
uint64_t id_vec = id[current_fn_index].fn_arg_vec[i];
uint64_t id_type = id[current_fn_index].fn_arg_type[i];
uint64_t id_utype = id[current_fn_index].fn_arg_utype[i];
if(id_type == ID_TYPE_USER)
{
vm_asm.push_back("dim_type !" + rc_intToString(id_vec) + " !" + rc_intToString(id_utype));
}
}
current_fn_index++;
}
else if(token[1].compare("<subp>")==0)
{
if(token.size()>2)
{
rc_setError("Expected End of Line in END SUB");
return false;
}
if(current_block_state != BLOCK_STATE_SUB)
{
rc_setError("Cannot exit sub routine from this scope");
return false;
}
//int ptr_count = 0;
//for(int n = 0; n < id[current_fn_index].fn_arg.size(); n++)
//{
// if(id[current_fn_index].fn_arg_type[n] == ID_TYPE_BYREF_NUM || id[current_fn_index].fn_arg_type[n] == ID_TYPE_BYREF_STR)
// {
// ptr_count++;
// }
//}
//if(ptr_count > 0)
// vm_asm.push_back("pop_ptr !" + rc_intToString(ptr_count));
vm_asm.push_back("return");
vm_asm.push_back(".code");
block_state.pop();
current_block_state = BLOCK_STATE_MAIN;
isInFunctionScope = false;
current_scope = "main";
for(uint64_t i = 0; i < id[current_fn_index].fn_arg.size(); i++)
{
uint64_t id_vec = id[current_fn_index].fn_arg_vec[i];
uint64_t id_type = id[current_fn_index].fn_arg_type[i];
uint64_t id_utype = id[current_fn_index].fn_arg_utype[i];
if(id_type == ID_TYPE_USER)
{
vm_asm.push_back("dim_type !" + rc_intToString(id_vec) + " !" + rc_intToString(id_utype));
}
}
current_fn_index++;
}
else if(token[1].compare("<type>")==0)
{
if(token.size()>2)
{
rc_setError("Expected End of Line in END TYPE");
return false;
}
if(current_block_state != BLOCK_STATE_TYPE)
{
rc_setError("Cannot exit TYPE definition from this scope");
return false;
}
block_state.pop();
current_block_state = BLOCK_STATE_MAIN;
current_scope = "main";
}
else if(token[1].compare("<if>")==0)
{
if(token.size() > 2)
{
rc_setError("Expected End of Line in END IF");
return false;
}
if(current_block_state != BLOCK_STATE_IF)
{
rc_setError("Cannot END IF without starting an IF Block");
return false;
}
block_state.pop();
current_block_state = block_state.top();
vm_asm.push_back("label ELSE:" + rc_intToString(if_block.top().index) + "->CONDITION:" + rc_intToString(if_block.top().condition));
vm_asm.push_back("label ENDIF:" + rc_intToString(if_block.top().index));
if_block.pop();
exit_scope(1);
}
else if(token[1].compare("<select>")==0)
{
if(token.size() > 2)
{
rc_setError("Expected End of Line in END SELECT");
return false;
}
if(current_block_state != BLOCK_STATE_SELECT)
{
rc_setError("Cannot END SELECT without starting a SELECT Block");
return false;
}
block_state.pop();
current_block_state = block_state.top();
vm_asm.push_back("label SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index));
vm_asm.push_back("label SELECT:" + rc_intToString(select_block.top().index) + "->END");
if(select_block.top().case_type==ID_TYPE_STR)
{
string compare_case = "s" + rc_intToString(s_reg);
vm_asm.push_back("pop$ " + compare_case);
inc_s(1);
}
else
{
string compare_case = "n" + rc_intToString(n_reg);
vm_asm.push_back("pop " + compare_case);
inc_n(1);
}
select_block.pop();
exit_scope(1);
}
else
{
if(!eval_expression(1, token.size()-1))
{
rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected a number expression");
return false;
}
vm_asm.push_back("end_x " + expr_result);
return true;
}
}
else if(token[0].compare("<function>")==0)
{
if(isInFunctionScope)
{
rc_setError("Cannot declare FUNCTION from this scope");
return false;
}
if(token.size()<2)
{
rc_setError("Expected identifier for FUNCTION declaration");
return false;
}
string fn_name = rc_substr(token[1], 4, token[1].length());
if(!isValidIDName(fn_name) )
{
rc_setError(fn_name + " is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_name))
{
rc_setError("Identifier " + fn_name + " already exists in this scope");
return false;
}
int fn_type = ID_TYPE_FN_NUM;
if(fn_name.substr(fn_name.length()-1,1).compare("$")==0)
fn_type = ID_TYPE_FN_STR;
string fn_type_name = "";
if(token.size()>2)
{
if(token[token.size()-2].compare("<as>")==0)
{
fn_type = ID_TYPE_FN_USER;
if(token[token.size()-1].substr(0,4).compare("<id>")==0)
fn_type_name = token[token.size()-1].substr(4);
else
{
rc_setError("Invalid return type in FUNCTION definition");
return false;
}
token.pop_back();
token.pop_back();
}
}
if(!create_function(fn_name, fn_type, fn_type_name))
{
rc_setError("Could not create FUNCTION \"" + fn_name + "\" of type \"" + fn_type_name + "\"");
return false;
}
current_block_state = BLOCK_STATE_FUNCTION;
block_state.push(current_block_state);
string fn_arg = "";
int fn_arg_type = ID_TYPE_NUM;
string fn_arg_user_type = "";
bool fn_byref = false;
int end_token = 0;
for(int i = 3; i < token.size(); i++)
{
if(token[i].compare("<byref>")==0)
{
fn_byref = true;
}
else if(rc_substr(token[i], 0, 4).compare("<id>")==0)
{
fn_arg += token[i];
if(fn_arg.substr(fn_arg.length()-1,1).compare("$")==0)
fn_arg_type = ID_TYPE_STR;
else
fn_arg_type = ID_TYPE_NUM;
}
else if(token[i].compare("<as>")==0)
{
i++;
fn_arg_type = ID_TYPE_USER;
fn_arg_user_type = "";
int arg_type_index = -1;
if(i < token.size())
if(token[i].substr(0,4).compare("<id>")==0)
fn_arg_user_type = token[i].substr(4);
if(fn_arg_user_type.compare("")==0)
{
rc_setError("Invalid Type in FUNCTION Definition");
return false;
}
}
else if(token[i].compare("<comma>")==0)
{
//cout << "ADD ARG: " << fn_arg << endl;
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("FUNCTION argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("FUNCTION argument identifier already exists in current scope");
return false;
}
//cout << "CHECK 1" << endl;
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_function_arg(fn_arg, fn_arg_type, fn_arg_user_type))
{
return false;
}
fn_arg = "";
fn_byref = false;
//cout << "DONE" << endl;
}
else if(token[i].compare("</par>")==0)
{
if((i+1) < token.size())
{
rc_setError("Expected End of FUNCTION Declaration");
return false;
}
if(fn_arg.compare("")==0)
{
end_token = i+1;
break;
}
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("FUNCTION argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("FUNCTION argument identifier already exists in current scope");
return false;
}
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_function_arg(fn_arg, fn_arg_type, fn_arg_user_type))
{
return false;
}
fn_arg = "";
fn_byref = false;
end_token = i+1;
break;
}
else
{
rc_setError("Argument to FUNCTION must be a valid identifier: " + token[i]);
}
}
if(token.size()>end_token)
{
rc_setError("Expected end of FUNCTION declaration");
return false;
}
}
else if(token[0].compare("<subp>")==0)
{
if(isInFunctionScope)
{
rc_setError("Cannot declare SUB ROUTINE from this scope");
return false;
}
if(token.size()<2)
{
rc_setError("Expected identifier for SUB ROUTINE declaration");
return false;
}
string fn_name = rc_substr(token[1], 4, token[1].length());
if(!isValidIDName(fn_name) )
{
rc_setError(fn_name + " is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_name))
{
rc_setError("Identifier " + fn_name + " already exists in this scope");
return false;
}
int fn_type = ID_TYPE_SUB;
string fn_type_name = "";
if(!create_function(fn_name, fn_type, fn_type_name))
{
rc_setError("Could not create SUB ROUTINE \"" + fn_name + "\"");
return false;
}
current_block_state = BLOCK_STATE_SUB;
block_state.push(current_block_state);
string fn_arg = "";
int fn_arg_type = ID_TYPE_NUM;
string fn_arg_user_type = "";
bool fn_byref = false;
int end_token = 0;
for(int i = 3; i < token.size(); i++)
{
if(token[i].compare("<byref>")==0)
{
fn_byref = true;
}
else if(rc_substr(token[i], 0, 4).compare("<id>")==0)
{
fn_arg += token[i];
if(fn_arg.substr(fn_arg.length()-1,1).compare("$")==0)
fn_arg_type = ID_TYPE_STR;
else
fn_arg_type = ID_TYPE_NUM;
}
else if(token[i].compare("<as>")==0)
{
i++;
fn_arg_type = ID_TYPE_USER;
fn_arg_user_type = "";
int arg_type_index = -1;
if(i < token.size())
if(token[i].substr(0,4).compare("<id>")==0)
fn_arg_user_type = token[i].substr(4);
if(fn_arg_user_type.compare("")==0)
{
rc_setError("Invalid Type in SUB ROUTINE Definition");
return false;
}
}
else if(token[i].compare("<comma>")==0)
{
//cout << "ADD ARG: " << fn_arg << endl;
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("SUB ROUTINE argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("SUB ROUTINE argument identifier already exists in current scope");
return false;
}
//cout << "CHECK 1" << endl;
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_function_arg(fn_arg, fn_arg_type, fn_arg_user_type))
{
return false;
}
fn_arg = "";
fn_byref = false;
//cout << "DONE" << endl;
}
else if(token[i].compare("</par>")==0)
{
if((i+1) < token.size())
{
rc_setError("Expected End of SUB ROUTINE Declaration");
return false;
}
if(fn_arg.compare("")==0)
{
end_token = i+1;
break;
}
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("SUB ROUTINE argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("SUB ROUTINE argument identifier already exists in current scope");
return false;
}
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_function_arg(fn_arg, fn_arg_type, fn_arg_user_type))
{
return false;
}
fn_arg = "";
fn_byref = false;
end_token = i+1;
break;
}
else
{
rc_setError("Argument to SUB ROUTINE must be a valid identifier: " + token[i]);
}
}
if(token.size()>end_token)
{
rc_setError("Expected end of SUB ROUTINE declaration");
return false;
}
}
else if(token[0].compare("<return>")==0)
{
string tmp_scope = current_scope;
stack<select_data> tmp_select_stack = select_block;
int fnID = -1;
if(current_block_state != BLOCK_STATE_FUNCTION && current_block_state != BLOCK_STATE_SUB)
{
string scope_type = "";
int scope_start = current_scope.find_last_of(".");
while(scope_start > 0)
{
scope_type = current_scope.substr(scope_start+1);
//cout << "\nSCOPE_TYPE->" << scope_type << endl << endl;
if(rc_substr(scope_type, 0, 5).compare("#FOR:")==0)
{
vm_asm.push_back("pop_loop_stack");
}
else if(rc_substr(scope_type, 0, 8).compare("#SELECT:")==0)
{
if(tmp_select_stack.top().case_type == ID_TYPE_STR)
{
vm_asm.push_back("pop$ s0"); //doesnt matter which reg I use since EXIT does not allow expressions
}
else
{
vm_asm.push_back("pop n0");
}
tmp_select_stack.pop();
}
else
{
fnID = getIDInScope_ByIndex(scope_type);
if(fnID < 0)
{
exit_scope(1);
scope_start = current_scope.find_last_of(".");
continue;
}
int ptr_count = 0;
for(int n = 0; n < id[fnID].fn_arg.size(); n++)
{
if(id[fnID].fn_arg_type[n] == ID_TYPE_BYREF_NUM || id[fnID].fn_arg_type[n] == ID_TYPE_BYREF_STR)
{
ptr_count++;
}
}
//if(ptr_count > 0)
// vm_asm.push_back("pop_ptr !" + rc_intToString(ptr_count));
//cout << "\nRETURN FROM FUNCTION" << id[fnID].name << endl << endl;
if(id[fnID].type == ID_TYPE_FN_NUM || id[fnID].type == ID_TYPE_FN_STR || id[fnID].type == ID_TYPE_FN_USER)
{
break;
}
else if(id[fnID].type == ID_TYPE_SUB)
{
if(token.size() > 1)
{
rc_setError("Cannot return a value from a SUB ROUTINE, You should use a FUNCTION instead");
return false;
}
else
{
current_scope = tmp_scope;
vm_asm.push_back("return");
return true;
}
}
else
{
rc_setError("Cannot return from this scope");
return false;
}
}
exit_scope(1);
scope_start = current_scope.find_last_of(".");
}
if(fnID < 0)
{
rc_setError("Cannot return outside of a FUNCTION or SUB");
return false;
}
current_scope = tmp_scope;
//rc_setError("cannot return from outside of a function of sub routine");
//return false;
}
if(id[current_fn_index].type == ID_TYPE_SUB)
{
if(token.size() > 1)
{
rc_setError("Cannot return a value from a SUB Routine, You should use a FUNCTION instead");
return false;
}
current_scope = tmp_scope;
vm_asm.push_back("return");
return true;
}
if(!eval_expression(1, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(id[current_fn_index].type == ID_TYPE_FN_NUM)
{
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Must return a number");
return false;
}
vm_asm.push_back("push " + expr_result);
vm_asm.push_back("return");
}
else if(id[current_fn_index].type == ID_TYPE_FN_STR)
{
if(expr_result.substr(0,1).compare("s")!=0)
{
rc_setError("Must return a string");
return false;
}
vm_asm.push_back("push$ " + expr_result);
vm_asm.push_back("return");
}
else if(id[current_fn_index].type == ID_TYPE_FN_USER)
{
if(expr_result.substr(0,1).compare("u")!=0)
{
rc_setError("Must return a \"" + utype[id[current_fn_index].type_index].name + "\"");
return false;
}
int fn_type = -1;
int u_type_index = -1;
getRegInfo(expr_result, fn_type, u_type_index);
if(u_type_index != id[current_fn_index].type_index)
{
rc_setError("+Must return a \"" + utype[id[current_fn_index].type_index].name + "\"");
return false;
}
vm_asm.push_back("push_t " + expr_result);
vm_asm.push_back("return");
}
}
else if(token[0].compare("<exit>")==0)
{
string tmp_scope = current_scope;
stack<select_data> tmp_select_stack = select_block;
string scope_type = "";
string exit_type = "";
if(token.size()==1)
{
rc_setError("Expected {DO | FOR | WHILE} in EXIT statement");
return false;
}
if(token[1].compare("<do>")==0)
exit_type = "#DO:";
else if(token[1].compare("<for>")==0)
exit_type = "#FOR:";
else if(token[1].compare("<while>")==0)
exit_type = "#WHILE:";
else
{
rc_setError("Expected {DO | FOR | WHILE} in EXIT statement");
return false;
}
int scope_start = current_scope.find_last_of(".");
bool canExit = false;
while(scope_start > 0)
{
scope_type = current_scope.substr(scope_start+1);
if(rc_substr(scope_type, 0, 5).compare("#FOR:")==0)
{
vm_asm.push_back("pop_loop_stack");
}
else if(rc_substr(scope_type, 0, 8).compare("#SELECT:")==0)
{
if(tmp_select_stack.top().case_type == ID_TYPE_STR)
{
vm_asm.push_back("pop$ s0"); //doesnt matter which reg I use since EXIT does not allow expressions
}
else
{
vm_asm.push_back("pop n0");
}
tmp_select_stack.pop();
}
if(scope_type.substr(0,4).compare("#DO:")==0 && exit_type.compare("#DO:")==0)
{
canExit = true;
vm_asm.push_back("jmp @" + do_end.top());
break;
}
else if(scope_type.substr(0,5).compare("#FOR:")==0 && exit_type.compare("#FOR:")==0)
{
canExit = true;
vm_asm.push_back("jmp @" + for_end.top());
break;
}
else if(scope_type.substr(0,7).compare("#WHILE:")==0 && exit_type.compare("#WHILE:")==0)
{
canExit = true;
vm_asm.push_back("jmp @" + while_end.top());
break;
}
exit_scope(1);
scope_start = current_scope.find_last_of(".");
}
if(!canExit)
{
rc_setError("Cannot EXIT this scope");
return false;
}
current_scope = tmp_scope;
}
else if(token[0].compare("<while>")==0)
{
if(token.size()<2)
{
rc_setError("Expected expression in WHILE");
return false;
}
current_block_state = BLOCK_STATE_WHILE;
block_state.push(current_block_state);
string start_label = current_scope + ".#WHILE:" + rc_intToString(current_while_index);
string end_label = current_scope + ".#WEND:" + rc_intToString(current_while_index);
current_scope = start_label;
while_end.push(end_label);
current_while_index++;
vm_asm.push_back("label " + start_label);
if(!eval_expression(1, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected a boolean expression");
return false;
}
vm_asm.push_back("while " + expr_result + " @" + end_label);
}
else if(token[0].compare("<continue>")==0)
{
string tmp_scope = current_scope;
stack<select_data> tmp_select_stack = select_block;
string scope_type = "";
int scope_start = current_scope.find_last_of(".");
bool canContinue = false;
while(scope_start > 0)
{
scope_type = current_scope.substr(scope_start+1);
if(rc_substr(scope_type, 0, 5).compare("#FOR:")==0)
{
canContinue = true;
vm_asm.push_back("next @" + current_scope);
vm_asm.push_back("jmp @" + for_end.top());
break;
}
if(scope_type.substr(0,4).compare("#DO:")==0)
{
canContinue = true;
vm_asm.push_back("loop @" + current_scope);
vm_asm.push_back("jmp @" + do_end.top());
break;
}
if(scope_type.substr(0,7).compare("#WHILE:")==0)
{
canContinue = true;
vm_asm.push_back("jmp @" + current_scope);
vm_asm.push_back("jmp @" + while_end.top());
break;
}
else if(rc_substr(scope_type, 0, 8).compare("#SELECT:")==0)
{
if(tmp_select_stack.top().case_type == ID_TYPE_STR)
{
vm_asm.push_back("pop$ s0"); //doesnt matter which reg I use since EXIT does not allow expressions
}
else
{
vm_asm.push_back("pop n0");
}
tmp_select_stack.pop();
}
exit_scope(1);
scope_start = current_scope.find_last_of(".");
}
if(!canContinue)
{
rc_setError("CONTINUE can only be used within a loop");
return false;
}
current_scope = tmp_scope;
}
else if(token[0].compare("<wend>")==0)
{
if(token.size() > 1)
{
rc_setError("Expected end of line in WEND");
return false;
}
if(current_block_state != BLOCK_STATE_WHILE)
{
rc_setError("Cannot use WEND outside of WHILE");
return false;
}
vm_asm.push_back("jmp @" + current_scope);
vm_asm.push_back("label " + while_end.top());
while_end.pop();
block_state.pop();
current_block_state = block_state.top();
exit_scope(1);
}
else if(token[0].compare("<do>")==0)
{
if(token.size() > 1)
{
rc_setError("Expected end of line in DO");
return false;
}
current_block_state = BLOCK_STATE_DO;
block_state.push(current_block_state);
string start_label = current_scope + ".#DO:" + rc_intToString(current_do_index);
string end_label = current_scope + ".#LOOP:" + rc_intToString(current_do_index);
current_scope = start_label;
do_end.push(end_label);
current_do_index++;
vm_asm.push_back("label " + start_label);
}
else if(token[0].compare("<loop>")==0)
{
if(current_block_state != BLOCK_STATE_DO)
{
rc_setError("Cannot use LOOP outside of DO");
return false;
}
if(token.size()==1)
{
vm_asm.push_back("loop @" + current_scope);
vm_asm.push_back("label " + do_end.top());
do_end.pop();
block_state.pop();
current_block_state = block_state.top();
exit_scope(1);
}
else if(token[1].compare("<while>")==0)
{
if(!eval_expression(2, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected boolean expression: " + expr_result);
return false;
}
vm_asm.push_back("loop_while " + expr_result + " @" + current_scope);
vm_asm.push_back("label " + do_end.top());
do_end.pop();
block_state.pop();
current_block_state = block_state.top();
exit_scope(1);
}
else if(token[1].compare("<until>")==0)
{
if(!eval_expression(2, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected boolean expression");
return false;
}
vm_asm.push_back("loop_until " + expr_result + " @" + current_scope);
vm_asm.push_back("label " + do_end.top());
do_end.pop();
block_state.pop();
current_block_state = block_state.top();
exit_scope(1);
}
else
{
rc_setError("Expected WHILE or UNTIL before expression");
return false;
}
}
else if(token[0].compare("<for>")==0)
{
current_block_state = BLOCK_STATE_FOR;
block_state.push(BLOCK_STATE_FOR);
string start_label = current_scope + ".#FOR:" + rc_intToString(current_for_index);
string end_label = current_scope +".#NEXT:" + rc_intToString(current_for_index);
current_scope = start_label;
for_end.push(end_label);
current_for_index++;
for(int i = token.size(); i < 6; i++)
token.push_back("");
int counter_id = -1;
string counter_var = "";
string start_value = "";
string end_value = "";
string step_value = "";
bool d_type_counter = false;
int d_type_equal_index = 0;
if(rc_substr(token[1], 0, 4).compare("<id>")==0)
{
counter_var = token[1].substr(4);
counter_id = getIDInScope_ByIndex(counter_var);
if(counter_id < 0)
{
if(!isValidIDName(counter_var) || rc_substr(counter_var, counter_var.length()-1,1).compare("$")==0)
{
rc_setError("Invalid identifier name in FOR");
return false;
}
if(isInFunctionScope)
{
if(!create_function_variable(counter_var, ID_TYPE_NUM,""))
{
rc_setError("could not create identifier " + counter_var);
return false;
}
}
else if(!create_variable(counter_var, ID_TYPE_NUM))
{
rc_setError("Could not create identifier " + counter_var);
return false;
}
}
else if(id[counter_id].type == ID_TYPE_USER)
{
//cout << "FOR debug: " << token[1].substr(4) << endl;
int end_token = 0;
int scope = 0;
bool expr_start = false;
for(end_token = 0; end_token < token.size(); end_token++)
{
if(token[end_token].compare("<square>")==0 || token[end_token].compare("<par>")==0)
scope++;
else if(token[end_token].compare("</square>")==0 || token[end_token].compare("</par>")==0)
scope--;
if(scope == 0 && token[end_token].compare("<equal>")==0)
{
d_type_equal_index = end_token;
end_token--;
expr_start = true;
break;
}
}
if(!expr_start)
{
rc_setError("[0]Could not evaluate defined type member in FOR identifier");
return false;
}
if(!eval_expression(1, end_token))
{
rc_setError("[1]Could not evaluate defined type member in FOR identifier");
return false;
}
if(multi_arg_count != 1)
{
rc_setError("[2]Could not evaluate defined type member in FOR identifier");
return false;
}
if(multi_arg[0].substr(0,1).compare("n") != 0)
{
rc_setError("[3]Could not evaluate defined type member in FOR identifier");
return false;
}
d_type_counter = true;
}
else if(id[counter_id].type != ID_TYPE_NUM && id[counter_id].type != ID_TYPE_BYREF_NUM && id[counter_id].type != ID_TYPE_ARR_NUM)
{
rc_setError("Expected number identifier in for");
return false;
}
else if(id[counter_id].type == ID_TYPE_ARR_NUM && token[2].compare("<square>") != 0)
{
rc_setError("Expected \"[\" in array");
return false;
}
if(d_type_counter)
{
//DO STUFF HERE
create_variable("!FOR_TYPE_COUNTER[" + rc_intToString(current_for_index) + "]", ID_TYPE_NUM,"");
counter_id = getIDInScope_ByIndex("!FOR_TYPE_COUNTER[" + rc_intToString(current_for_index) + "]");
if(counter_id < 0)
{
rc_setError("RCBasic Compiler ERROR: Type member in FOR caused internal error");
return false;
}
vm_asm.push_back("ptr !" + rc_intToString(id[counter_id].vec_pos) + " " + multi_arg[0]);
for_counter.push(counter_id);
}
else
{
counter_id = getIDInScope_ByIndex(counter_var);
for_counter.push(counter_id);
}
}
else
{
rc_setError("Expected identifier after FOR");
return false;
}
int for_equal_op_offset = 2;
int for_counter_args = 0;
if(d_type_counter)
for_equal_op_offset = d_type_equal_index;
if(id[counter_id].type == ID_TYPE_ARR_NUM || id[counter_id].type == ID_TYPE_BYREF_NUM)
{
if(token[2].compare("<square>") == 0)
{
int f_scope = 1;
int token_start = 2;
int token_end = 3;
multi_arg[0] = "";
multi_arg[1] = "";
multi_arg[2] = "";
multi_arg_count = 0;
for(int i = 3; i < token.size(); i++)
{
if(token[i].compare("<square>")==0)
f_scope++;
else if(token[i].compare("</square>")==0)
f_scope--;
if(f_scope == 0)
{
token_end = i;
for_equal_op_offset = i+1;
if(token[for_equal_op_offset].compare("<equal>")==0)
break;
else
{
rc_setError("Expected \"=\" in FOR");
return false;
}
}
}
if(!eval_expression(token_start, token_end, true))
{
rc_setError("Error evaluating counter in FOR");
return false;
}
if(id[counter_id].type == ID_TYPE_ARR_NUM && id[counter_id].num_args != multi_arg_count)
{
rc_setError("Invalid number of dimensions in FOR counter array");
return false;
}
else if(id[counter_id].type == ID_TYPE_BYREF_NUM && multi_arg_count != 1)
{
rc_setError("Expected 1 argument in FOR counter ByRef array");
return false;
}
switch(multi_arg_count)
{
case 1:
vm_asm.push_back("for_offset_arr1 " + multi_arg[0]);
break;
case 2:
vm_asm.push_back("for_offset_arr2 " + multi_arg[0] + " " + multi_arg[1]);
break;
case 3:
vm_asm.push_back("for_offset_arr3 " + multi_arg[0] + " " + multi_arg[1] + " " + multi_arg[2]);
break;
}
for(int i = token_start; i <= token_end; i++)
{
//cout << "remove token: " << token[i] << endl;
token[i] = "";
}
}
else
vm_asm.push_back("for_offset_0");
}
if(token[for_equal_op_offset].compare("<equal>")!=0)
{
rc_setError("Expected = in FOR");
return false;
}
int ft_count = 0;
string ftokens[] = {"", ""};
for(int i = for_equal_op_offset+1; i < token.size(); i++)
{
if(token[i].compare("<to>")==0 || token[i].compare("<step>")==0)
{
if(ft_count >= 2)
{
rc_setError("Illegal Syntax in FOR");
return false;
}
ftokens[ft_count] = token[i];
ft_count++;
token[i] = "!<comma>";
}
}
if(ftokens[0].compare("<to>")!=0)
{
rc_setError("Expected to after initialize expression");
return false;
}
if(ftokens[1].compare("<step>")!=0 && ftokens[1].compare("") != 0)
{
rc_setError("Expected STEP or end of FOR line");
return false;
}
if(!eval_expression(for_equal_op_offset+1, token.size()-1, true))
{
//rc_setError("Could not evaluate expression");
return false;
}
start_value = multi_arg[0];
end_value = multi_arg[1];
if(multi_arg_count == 2)
{
step_value = "n" + rc_intToString(n_reg);
vm_asm.push_back("mov " + step_value + " 1");
}
else if(multi_arg_count == 3)
{
step_value = multi_arg[2];
}
else
{
rc_setError("To many arguments in FOR");
return false;
}
if(start_value.substr(0,1).compare("n")!=0 || end_value.substr(0,1).compare("n")!=0 || step_value.substr(0,1).compare("n")!=0)
{
rc_setError("Expected number expression in FOR");
return false;
}
//cout << "FOR_RESULT" << endl << "------------------" << endl;
//cout << "identifier = " << id[counter_id].vec_pos << endl;
//cout << "start = " << start_value << endl;
//cout << "end = " << end_value << endl;
//cout << "step = " << step_value << endl << endl;
if(for_counter.size() > max_for_count)
max_for_count = for_counter.size();
vm_asm.push_back("for !" + rc_intToString(id[counter_id].vec_pos) + " " + start_value + " " + end_value + " " + step_value);
vm_asm.push_back("lval @" + end_label);
vm_asm.push_back("label " + start_label);
}
else if(token[0].compare("<next>")==0)
{
if(current_block_state != BLOCK_STATE_FOR)
{
rc_setError("Cannot use NEXT outside of a FOR loop");
return false;
}
if(token.size() > 1)
{
rc_setError("Expected end of line in NEXT");
return false;
}
uint64_t counter_id = for_counter.top();
for_counter.pop();
string next_label = for_end.top();
for_end.pop();
block_state.pop();
current_block_state = block_state.top();
vm_asm.push_back("next @" + current_scope);
vm_asm.push_back("label " + next_label);
//cout << "next_addr = " << vm_asm.current_address[CODE_SEGMENT] << endl;
exit_scope(1);
}
else if(token[0].compare("<if>")==0)
{
current_block_state = BLOCK_STATE_IF;
block_state.push(current_block_state);
if_data if_start;
if_start.index = current_if_index;
if_start.condition = 0;
if_block.push(if_start);
string start_label = current_scope + ".#IF:" + rc_intToString(if_start.index);
current_scope = start_label;
int if_then = -1;
for(int i = 0; i < token.size(); i++)
{
if(token[i].compare("<then>")==0)
{
if_then = i;
break;
}
}
if(if_then < 0)
{
//rc_setError("Expected THEN in IF statement");
//return false;
token.push_back("<then>"); //This will make THEN optional
if_then = token.size()-1;
}
if(token.size() > (if_then+1))
{
rc_setError("Expected End of Line after THEN");
return false;
}
if(if_then < 2)
{
rc_setError("Expected expression in IF");
return false;
}
if(!eval_expression(1, if_then-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected Boolean expression");
return false;
}
string else_label = "ELSE:" + rc_intToString(if_block.top().index) + "->CONDITION:" + rc_intToString(if_block.top().condition);
vm_asm.push_back("cmp " + expr_result + " 0");
vm_asm.push_back("je @" + else_label);
//vm_asm.push_back("");
current_if_index++;
}
else if(token[0].compare("<elseif>")==0)
{
if(if_block.top().else_set)
{
rc_setError("Cannot use ELSEIF after ELSE in the same IF Block");
return false;
}
string start_label = "ELSE:" + rc_intToString(if_block.top().index) + "->CONDITION:" + rc_intToString(if_block.top().condition);
vm_asm.push_back("jmp @ENDIF:" + rc_intToString(if_block.top().index) );
vm_asm.push_back("label " + start_label);
if_block.top().condition++;
exit_scope(1);
current_scope += ".#" + start_label;
int if_then = -1;
for(int i = 0; i < token.size(); i++)
{
if(token[i].compare("<then>")==0)
{
if_then = i;
break;
}
}
if(if_then < 0)
{
//rc_setError("Expected THEN in IF statement");
//return false;
token.push_back("<then>"); //This will make THEN optional
if_then = token.size()-1;
}
if(token.size() > (if_then+1))
{
rc_setError("Expected End of Line after THEN");
return false;
}
if(if_then < 2)
{
rc_setError("Expected expression in IF");
return false;
}
if(!eval_expression(1, if_then-1))
{
rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")!=0)
{
rc_setError("Expected Boolean expression");
return false;
}
string else_label = "ELSE:" + rc_intToString(if_block.top().index) + "->CONDITION:" + rc_intToString(if_block.top().condition);
vm_asm.push_back("cmp " + expr_result + " 0");
vm_asm.push_back("je @" + else_label);
//vm_asm.push_back("");
}
else if(token[0].compare("<else>")==0)
{
if(token.size()>1)
{
rc_setError("Expected end of line in ELSE");
return false;
}
string start_label = "ELSE:" + rc_intToString(if_block.top().index) + "->CONDITION:" + rc_intToString(if_block.top().condition);
vm_asm.push_back("jmp @ENDIF:" + rc_intToString(if_block.top().index) );
vm_asm.push_back("label " + start_label);
//vm_asm.push_back("");
if_block.top().else_set = true;
if_block.top().condition++;
exit_scope(1);
current_scope += ".#" + start_label;
}
else if(token[0].compare("<select>")==0)
{
if(token.size() < 3)
{
rc_setError("Incomplete SELECT CASE statement");
return false;
}
if(token[1].compare("<case>")!=0)
{
rc_setError("Expected CASE in SELECT CASE statement");
return false;
}
if(!eval_expression(2, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
select_data select_start;
select_start.index = current_select_index;
select_start.case_index = 0;
select_start.default_set = false;
if(expr_result.substr(0,1).compare("s")==0)
{
select_start.case_type = ID_TYPE_STR;
vm_asm.push_back("push$ " + expr_result);
}
else
{
select_start.case_type = ID_TYPE_NUM;
vm_asm.push_back("push " + expr_result);
}
select_block.push(select_start);
string select_label = "SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index);
vm_asm.push_back("jmp @" + select_label);
current_select_index++;
current_scope += ".#" + select_label;
current_block_state = BLOCK_STATE_SELECT;
block_state.push(current_block_state);
//vm_asm.push_back("");
}
else if(token[0].compare("<case>")==0)
{
if(token.size()==1)
{
rc_setError("Expected expression in CASE");
return false;
}
if(current_block_state != BLOCK_STATE_SELECT)
{
rc_setError("Cannot set CASE outside of a SELECT BLOCK");
return false;
}
select_block.top().case_set = true;
string compare_case = "";
string case_end = "SELECT:" + rc_intToString(select_block.top().index) + "->END";
string case_label = "SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index);
exit_scope(1);
current_scope += ".#" + case_label;
select_block.top().case_index++;
string next_case_label = "SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index);
vm_asm.push_back("jmp @" + case_end);
vm_asm.push_back("label " + case_label);
if(select_block.top().case_type==ID_TYPE_STR)
{
compare_case = "s" + rc_intToString(s_reg);
vm_asm.push_back("pop$ " + compare_case);
vm_asm.push_back("push$ " + compare_case);
inc_s(1);
}
else
{
compare_case = "n" + rc_intToString(n_reg);
vm_asm.push_back("pop " + compare_case);
vm_asm.push_back("push " + compare_case);
inc_n(1);
}
for(int i = 0; i < token.size(); i++)
{
if(token[i].compare("<comma>")==0)
token[i] = "!<comma>";
}
if(!eval_expression(1, token.size()-1, true))
{
//rc_setError("Could not evaluate expression");
return false;
}
string case_reg_type = "n";
if(select_block.top().case_type == ID_TYPE_STR)
case_reg_type = "s";
string cmp_or_result = "n" + rc_intToString(n_reg);
inc_n(1);
string case_flag_result = "n" + rc_intToString(n_reg);
inc_n(1);
vm_asm.push_back("mov " + cmp_or_result + " 0");
for(int i = 0; i < multi_arg_count; i++)
{
if(multi_arg[i].substr(0,1).compare(case_reg_type)!=0)
{
rc_setError("Mismatch type in CASE: " + multi_arg[i]);
return false;
}
if(case_reg_type.compare("s")==0)
{
vm_asm.push_back("cmp$ " + compare_case + " " + multi_arg[i]);
vm_asm.push_back("mov " + case_flag_result + " %EQUAL_FLAG");
vm_asm.push_back("or " + cmp_or_result + " " + case_flag_result);
}
else
{
vm_asm.push_back("cmp " + compare_case + " " + multi_arg[i]);
vm_asm.push_back("mov " + case_flag_result + " %EQUAL_FLAG");
vm_asm.push_back("or " + cmp_or_result + " " + case_flag_result);
}
}
vm_asm.push_back("cmp " + cmp_or_result + " 0");
vm_asm.push_back("je @" + next_case_label);
//vm_asm.push_back("");
}
else if(token[0].compare("<default>")==0)
{
if(token.size()>1)
{
rc_setError("Expected End of Line for default");
return false;
}
if(current_block_state != BLOCK_STATE_SELECT)
{
rc_setError("Cannot set DEFAULT outside of a SELECT BLOCK");
return false;
}
select_block.top().case_set = true;
string compare_case = "";
string case_end = "SELECT:" + rc_intToString(select_block.top().index) + "->END";
string case_label = "SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index);
exit_scope(1);
current_scope += ".#" + case_label;
select_block.top().case_index++;
string next_case_label = "SELECT:" + rc_intToString(select_block.top().index) + "->CASE:" + rc_intToString(select_block.top().case_index);
vm_asm.push_back("jmp @" + case_end);
vm_asm.push_back("label " + case_label);
//vm_asm.push_back("");
}
else if(token[0].compare("<print>")==0)
{
string last_token = token[token.size()-1];
if(token.size()==1)
{
rc_setError("Expected expression for PRINT");
return false;
}
int start_token = 1;
if(token[token.size()-1].compare("<semi>")!=0)
token.push_back("<semi>");
for(int i = 0; i < token.size(); i++)
{
if(token[i].compare("<semi>")==0)
{
token[i] = "";
if(!eval_expression(start_token, i))
{
//rc_setError("Could not evaluate expression");
//output_tokens();
cout << endl << endl;
return false;
}
if(expr_result.substr(0,1).compare("n")==0)
vm_asm.push_back("print " + expr_result);
else if(expr_result.substr(0,1).compare("s")==0)
vm_asm.push_back("print$ " + expr_result);
else
{
rc_setError("Invalid expression in PRINT");
return false;
}
start_token = i;
}
}
if(start_token < (token.size()-1 ) )
{
if(!eval_expression(start_token, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(expr_result.substr(0,1).compare("n")==0)
vm_asm.push_back("print " + expr_result);
else if(expr_result.substr(0,1).compare("s")==0)
vm_asm.push_back("print$ " + expr_result);
else
{
rc_setError("Invalid expression in PRINT");
return false;
}
}
if(last_token.compare("<semi>")!=0)
vm_asm.push_back("println");
}
else if(token[0].compare("<delete>")==0)
{
if(token.size() < 2)
{
rc_setError("Expected single identifier in DELETE statement");
return false;
}
if(token[1].substr(0,4).compare("<id>")!=0)
{
rc_setError("Expected single identifier in DELETE statement");
return false;
}
int id_index = getIDInScope_ByIndex(token[1].substr(4));
if(id_index < 0)
{
rc_setError("Identifier does not exists in current scope: " + token[1].substr(4) + ", SCOPE=" + current_scope);
return false;
}
if(id[id_index].type == ID_TYPE_ARR_NUM || id[id_index].type == ID_TYPE_NUM)
{
if(token.size() != 2)
{
rc_setError("Expected single identifier in DELETE statement");
return false;
}
vm_asm.push_back("delete !" + rc_intToString(id[id_index].vec_pos));
}
else if(id[id_index].type == ID_TYPE_ARR_STR || id[id_index].type == ID_TYPE_STR)
{
if(token.size() != 2)
{
rc_setError("Expected single identifier in DELETE statement");
return false;
}
vm_asm.push_back("delete$ !" + rc_intToString(id[id_index].vec_pos));
}
else if(id[id_index].type == ID_TYPE_USER)
{
token[0] = "";
type_delete_flag = true;
type_delete_arg = "";
type_delete_arg_whole = true;
if(!eval_expression())
{
rc_setError("Could not evaluate identifer");
return false;
}
if(type_delete_arg.substr(0,1).compare("!")!=0)
{
rc_setError("Could not determine Identifier Type in DELETE: " + type_delete_arg);
return false;
}
string d_type = "!";
string top_level_flag = "!0";
if(!type_delete_arg_whole)
top_level_flag = "!1";
if(type_delete_arg_type == ID_TYPE_USER_STR || type_delete_arg_type == ID_TYPE_USER_STR_ARRAY)
{
cout << "DELETE STRING" << endl;
d_type += "1";
}
else if(type_delete_arg_type == ID_TYPE_USER_NUM || type_delete_arg_type == ID_TYPE_USER_NUM_ARRAY)
{
cout << "DELETE NUMBER" << endl;
d_type += "0";
}
else if(type_delete_arg_type == ID_TYPE_USER)
{
cout << "DELETE USER TYPE" << endl;
d_type += "2";
}
else
{
rc_setError("Cannot delete identifier of this type or within this scope");
return false;
}
vm_asm.push_back("delete_t " + type_delete_arg + " " + top_level_flag + " " + d_type);
type_delete_flag = false;
type_delete_arg_whole = true;
}
else
{
rc_setError("Cannot delete identifier of this type");
return false;
}
//id[id_index].name = "";
}
else if(token[0].compare("<type>")==0)
{
if(current_scope.compare("main")!=0)
{
rc_setError("TYPE cannot be defined in this scope");
return false;
}
if(token.size() != 2)
{
rc_setError("Expected TYPE Identifier in TYPE statement");
return false;
}
if(token[1].substr(0,4).compare("<id>")!=0)
{
rc_setError("Expected TYPE Identifier in TYPE statement");
return false;
}
int id_index = getIDInScope_ByIndex(token[1].substr(4));
if(id_index >= 0)
{
rc_setError("TYPE Identifier exists in current scope");
return false;
}
create_type(token[1].substr(4));
current_block_state = BLOCK_STATE_TYPE;
block_state.push(current_block_state);
string start_label = current_scope + ".#TYPE:" + token[1].substr(4);
current_scope = start_label;
}
else if(token.size() > 2)
{
//cout << "token[1] = " << token[1] << endl;
if(token[0].substr(0,4).compare("<id>")==0)
{
int id_index = getIDInScope_ByIndex(token[0].substr(4));
if(id_index >= 0)
{
//cout << "DBG TYPE: name = " << id[id_index].name << " -- type = " << id[id_index].type << " -- scope = " << id[id_index].scope << endl;
if( ID_TYPE_USER_ALL(id_index) )
{
//NOTE: PARSING TYPE VAR HERE
string full_id = "";
int tmp_scope = 0;
int end_token = -1;
int op_token = -1;
//getting the id to parse
for(int i = 0; i < token.size(); i++)
{
//cout << "DEBUG TOKEN[" << i << "] = " << token[i] << endl;
if(token[i].compare("<square>")==0 || token[i].compare("!<square>")==0 ||
token[i].compare("<par>")==0 || token[i].compare("!<par>")==0)
tmp_scope++;
else if(token[i].compare("</square>")==0 || token[i].compare("!</square>")==0 ||
token[i].compare("</par>")==0 || token[i].compare("!</par>")==0)
tmp_scope--;
else if(tmp_scope == 0 && isOperatorToken2(i))
{
//cout << "PARSE ID = \n" << full_id << endl;
op_token = i;
end_token = i-1;
break;
}
}
if(end_token < 0)
{
end_token = 0;
}
string op = "";
if(op_token >= 0)
{
op = token[op_token];
token[op_token] = "";
if(end_token==0)
end_token++;
}
if(!eval_expression(0, end_token))
{
rc_setError("[1] Could not evaluate Identifier: " + rc_intToString(end_token));
return false;
}
if(op_token >= 0)
token[op_token] = op;
bool set_val = false;
string id_arg = "";
if(op_token >= 0)
if(token[op_token].compare("<equal>")==0)
{
//cout << "BALLS" << endl;
set_val = true;
id_arg = token[0];
for(int i = 0; i <= op_token; i++)
token[i] = "";
//for(int i = op_token+1; i < token.size(); i++)
// cout << "SUPER T[" << i << "] = " << token[i] << endl;
}
if(!eval_expression())
{
rc_setError("Could not evaluate expression");
return false;
}
//cout << endl << "NEW SET" << endl;
//cout << "-----------------------" << endl;
//for(int i = 0; i < token.size(); i++)
// cout << i << ":" << token[i] << endl;
//cout << endl;
//I will do something with this eventually
int var_type = -1;
//cout << "Set Val = " << set_val << endl;
if(set_val)
{
if(expr_result.substr(0,1).compare(id_arg.substr(0,1))!=0)
{
rc_setError("[0]Expression type does not match identifier");
return false;
}
int ut_info = 0;
int ut1 = -1;
int ut2 = -1;
var_type = id_arg.substr(0,1).compare("n")==0 ? ID_TYPE_NUM : -1;
var_type = (var_type < 0) ? (id_arg.substr(0,1).compare("s")==0 ? ID_TYPE_STR : -1) : var_type;
var_type = (var_type < 0) ? (id_arg.substr(0,1).compare("u")==0 ? ID_TYPE_USER : -1) : var_type;
switch(var_type)
{
case ID_TYPE_NUM:
vm_asm.push_back("mov_r " + id_arg + " " + expr_result);
break;
case ID_TYPE_STR:
vm_asm.push_back("mov_r$ " + id_arg + " " + expr_result);
break;
case ID_TYPE_USER:
getRegInfo(id_arg, ut_info, ut1);
getRegInfo(expr_result, ut_info, ut2);
if(ut1 != ut2)
{
rc_setError("[1]Expression type does not match identifier in assignment");
return false;
}
vm_asm.push_back("mov_type " + id_arg + " " + expr_result);
break;
default:
//cout << "VAR_TYPE = " << var_type << endl;
break;
}
return true;
}
}
}
}
if(token[1].compare("<equal>")==0)
{
string var_id = "";
int var_type = ID_TYPE_NUM;
int var_ut_index = -1;
int var_id_index = -1;
if(rc_substr(token[0], 0, 1).compare("n")==0 || rc_substr(token[0], 0, 1).compare("s")==0)
{
for(int i = 0; i < resolveID_id_reg.size(); i++)
{
if(resolveID_id_reg[i].compare(token[0])==0)
{
var_id = "~" + token[0];
if(token[0].substr(0,1).compare("s")==0)
var_type = ID_TYPE_STR;
else if(resolveID_id_type[i] == ID_TYPE_USER)
{
var_type = ID_TYPE_USER;
var_ut_index = resolveID_id_ut_index[i];
}
else
var_type = resolveID_id_type[i];
break;
}
}
if(var_id.compare("")==0)
{
rc_setError("Expected identifier for variable assignment");
return false;
}
}
else if(rc_substr(token[0], 0, 4).compare("<id>")==0)
{
var_id = token[0].substr(4);
var_type = (var_id.substr(var_id.length()-1).compare("$")==0) ? ID_TYPE_STR : ID_TYPE_NUM; //length() will always be atleast 1 so there is no need to check
// if(var_id.substr(var_id.length()-1,1).compare("$")==0)
// {
// //cout << "looking for: " << var_id.substr(0, var_id.length()-1) << endl;
// var_id_index = getIDInScope(var_id.substr(0, var_id.length()-1));
// if(var_id_index >= 0)
// var_type = id[var_id_index].type;
// //cout << "var_index = " << var_id_index << endl;
// }
if(var_id_index < 0)
{
var_id_index = getIDInScope_ByIndex(var_id);
if(var_id_index >= 0)
var_type = id[var_id_index].type;
}
if(var_id_index < 0)
{
if(!isValidIDName(var_id))
{
rc_setError(var_id + " is not a valid identifier");
return false;
}
if(isInFunctionScope)
{
if(!create_function_variable(var_id, var_type, ""))
{
rc_setError("Could not create " + var_id);
return false;
}
}
else if(!create_variable(var_id, var_type))
{
rc_setError("Could not create " + var_id);
return false;
}
var_id_index = getIDInScope_ByIndex(var_id);
if(var_id_index < 0)
{
rc_setError("Unexpected error");
return false;
}
}
}
if(var_type == ID_TYPE_BYREF_NUM)
var_type = ID_TYPE_NUM;
else if(var_type == ID_TYPE_BYREF_STR)
var_type = ID_TYPE_STR;
if(var_type != ID_TYPE_NUM && var_type != ID_TYPE_STR)
{
bool id_type_match = false;
if(token.size()!=3)
{
rc_setError("Expected identifier of same type in assignment");
return false;
}
for(int i = 0; i < resolveID_id_reg.size(); i++)
{
if(resolveID_id_reg[i].compare(token[2])==0)
{
if(resolveID_id_type[i] == var_type)
{
if(var_type == ID_TYPE_USER && var_ut_index == resolveID_id_ut_index[i])
{
id_type_match = true;
}
else if(var_type == ID_TYPE_ARR_NUM || var_type == ID_TYPE_ARR_STR)
{
id_type_match = true;
}
}
}
}
if(!id_type_match)
{
rc_setError("Expected identifier of same type in assignment");
return false;
}
vm_asm.push_back("mov_type " + var_id.substr(1) + " " + token[2]);
return true;
}
if(!eval_expression(2))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(var_type == ID_TYPE_NUM && expr_result.substr(0,1).compare("n")!=0 )
{
rc_setError("Must set number variable to number expression");
return false;
}
else if(var_type == ID_TYPE_STR && expr_result.substr(0,1).compare("s")!=0 )
{
rc_setError("Must set string variable to string expression");
return false;
}
if(var_id.substr(0,1).compare("~")==0)
{
switch(var_type)
{
case ID_TYPE_NUM:
vm_asm.push_back("mov_r " + var_id.substr(1) + " " + expr_result);
break;
case ID_TYPE_STR:
vm_asm.push_back("mov_r$ " + var_id.substr(1) + " " +expr_result);
break;
default:
//cout << "VAR_TYPE = " << var_type << endl;
break;
}
}
else
{
if(var_id_index >= 0 && var_id_index < id.size())
{
switch(var_type)
{
case ID_TYPE_NUM:
vm_asm.push_back("mov !" + rc_intToString(id[var_id_index].vec_pos) + " " + expr_result);
break;
case ID_TYPE_STR:
vm_asm.push_back("mov$ !" + rc_intToString(id[var_id_index].vec_pos) + " " + expr_result);
break;
}
}
else
{
rc_setError("Identifier \"" + var_id + "\" could not be resolved");
return false;
}
}
}
else if(rc_substr(token[0], 0, 4).compare("<id>")==0 && token.size() > 5)
{
//cout << "dbg 1" << endl;
int expr_id = getIDInScope_ByIndex(token[0].substr(4));
if(expr_id < 0)
{
rc_setError("Identifier \"" + token[0].substr(4) + "\" was not declared in this scope");
return false;
}
int start_token = 0;
int end_token = 0;
int s_scope = 1;
if(token[1].compare("<square>")==0)
{
for(int i = 2; i < token.size(); i++)
{
if(token[i].compare("</square>")==0)
s_scope--;
else if(token[i].compare("<square>")==0)
s_scope++;
if(s_scope == 0)
{
end_token = i;
//for(int i2 = start_token; i2 <= end_token; i2++)
// cout << "token: " << i2 << token[i2] << endl;
break;
}
}
if(s_scope != 0)
{
rc_setError("Expected ] in array assignment");
return false;
}
}
else
{
//cout << "dbg 2" << endl;
if(!eval_expression())
{
rc_setError("Could not evaluate expression");
return false;
}
}
if(!eval_expression(start_token, end_token))
{
rc_setError("Could not resolve array identifier");
return false;
}
string var = expr_result;
end_token++;
bool isAssignment = false;
if(token.size()>end_token)
{
if(token[end_token].compare("<equal>")==0)
{
isAssignment = true;
start_token = end_token+1;
}
}
string var_result = "";
if(isAssignment)
{
if(!eval_expression(start_token, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
if(var.substr(0,1).compare("n")==0 && expr_result.substr(0,1).compare("n")==0)
{
vm_asm.push_back("mov_r " + var + " " + expr_result);
return true;
}
else if(var.substr(0,1).compare("s")==0 && expr_result.substr(0,1).compare("s")==0)
{
vm_asm.push_back("mov_r$ " + var + " " + expr_result);
return true;
}
else
{
rc_setError("Identifier type does not match assignment type");
return false;
}
}
else
{
if(!eval_expression(start_token, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
}
}
else
{
//cout << "debug problem here" << endl;
//output_tokens();
if(!eval_expression())
{
//rc_setError("Could not evaluate expression");
return false;
}
}
}
else
{
if(!eval_expression(0, token.size()-1))
{
//rc_setError("Could not evaluate expression");
return false;
}
//cout <<"THIS IS A TEST" << endl;
}
}
return true;
}
bool check_rule_embedded()
{
if(token.size() > 0)
{
if(current_block_state == BLOCK_STATE_TYPE)
{
if(token[0].compare("<dim>")!=0 && token[0].compare("<end>")!=0)
{
rc_setError("Expected DIM in TYPE definition");
return false;
}
}
else if(current_block_state != BLOCK_STATE_MAIN)
{
if(token[0].compare("<type>")==0)
{
rc_setError("TYPE cannot be declared in the current scope");
return false;
}
else if(token[0].compare("<function>")==0)
{
rc_setError("FUNCTION cannot be declared in the current scope");
return false;
}
else if(token[0].compare("<subp>")==0)
{
rc_setError("SUB ROUTINE cannot be declared in the current scope");
return false;
}
}
if(token[0].compare("<function>")==0)
{
if(token.size()<2)
{
rc_setError("Expected identifier for function declaration");
return false;
}
string fn_name = rc_substr(token[1], 4, token[1].length());
if(!isValidIDName(fn_name) )
{
rc_setError(fn_name + " is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_name))
{
rc_setError("Identifier " + fn_name + " already exists in this scope");
return false;
}
int fn_type = ID_TYPE_FN_NUM;
if(fn_name.substr(fn_name.length()-1,1).compare("$")==0)
fn_type = ID_TYPE_FN_STR;
string fn_type_name = "";
if(token.size()>2)
{
if(token[token.size()-2].compare("<as>")==0)
{
fn_type = ID_TYPE_FN_USER;
if(token[token.size()-1].substr(0,4).compare("<id>")==0)
fn_type_name = token[token.size()-1].substr(4);
else
{
rc_setError("Invalid return type in FUNCTION definition");
return false;
}
token.pop_back();
token.pop_back();
}
}
if(!embed_function(fn_name, fn_type, getUType(fn_type_name)))
{
rc_setError("Could not create FUNCTION \"" + fn_name + "\" of type \"" + fn_type_name + "\"");
return false;
}
current_block_state = BLOCK_STATE_FUNCTION;
block_state.push(current_block_state);
string fn_arg = "";
int fn_arg_type = ID_TYPE_NUM;
string fn_arg_user_type = "";
bool fn_byref = false;
int end_token = 0;
for(int i = 3; i < token.size(); i++)
{
if(token[i].compare("<byref>")==0)
{
fn_byref = true;
}
else if(rc_substr(token[i], 0, 4).compare("<id>")==0)
{
fn_arg += token[i];
if(fn_arg.substr(fn_arg.length()-1,1).compare("$")==0)
fn_arg_type = ID_TYPE_STR;
else
fn_arg_type = ID_TYPE_NUM;
}
else if(token[i].compare("<as>")==0)
{
i++;
fn_arg_type = ID_TYPE_USER;
fn_arg_user_type = "";
int arg_type_index = -1;
if(i < token.size())
if(token[i].substr(0,4).compare("<id>")==0)
fn_arg_user_type = token[i].substr(4);
if(fn_arg_user_type.compare("")==0)
{
rc_setError("Invalid Type in FUNCTION Definition");
return false;
}
}
else if(token[i].compare("<comma>")==0)
{
//cout << "ADD ARG: " << fn_arg << endl;
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("FUNCTION argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("FUNCTION argument identifier already exists in current scope");
return false;
}
//cout << "CHECK 1" << endl;
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_embedded_arg(fn_arg, fn_arg_type, getUType(fn_arg_user_type)))
{
return false;
}
fn_arg = "";
fn_byref = false;
//cout << "DONE" << endl;
}
else if(token[i].compare("</par>")==0)
{
if((i+1) < token.size())
{
rc_setError("Expected End of FUNCTION Declaration");
return false;
}
if(fn_arg.compare("")==0)
{
end_token = i+1;
break;
}
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("FUNCTION argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("FUNCTION argument identifier already exists in current scope");
return false;
}
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_embedded_arg(fn_arg, fn_arg_type, getUType(fn_arg_user_type)))
{
return false;
}
fn_arg = "";
fn_byref = false;
end_token = i+1;
break;
}
else
{
rc_setError("Argument to FUNCTION must be a valid identifier: " + token[i]);
}
}
current_block_state = BLOCK_STATE_MAIN;
current_scope = "main";
block_state.pop();
isInFunctionScope = false;
current_fn_index++;
if(token.size()>end_token)
{
rc_setError("Expected end of function declaration");
return false;
}
}
else if(token[0].compare("<subp>")==0)
{
if(token.size()<2)
{
rc_setError("Expected identifier for function declaration");
return false;
}
string fn_name = rc_substr(token[1], 4, token[1].length());
if(!isValidIDName(fn_name) )
{
rc_setError(fn_name + " is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_name))
{
rc_setError("Identifier " + fn_name + " already exists in this scope");
return false;
}
int fn_type = ID_TYPE_SUB;
string fn_type_name = "";
if(!embed_function(fn_name, fn_type, getUType(fn_type_name)))
{
rc_setError("Could not create SUB ROUTINE \"" + fn_name + "\"");
return false;
}
current_block_state = BLOCK_STATE_SUB;
block_state.push(current_block_state);
string fn_arg = "";
int fn_arg_type = ID_TYPE_NUM;
string fn_arg_user_type = "";
bool fn_byref = false;
int end_token = 0;
for(int i = 3; i < token.size(); i++)
{
if(token[i].compare("<byref>")==0)
{
fn_byref = true;
}
else if(rc_substr(token[i], 0, 4).compare("<id>")==0)
{
fn_arg += token[i];
if(fn_arg.substr(fn_arg.length()-1,1).compare("$")==0)
fn_arg_type = ID_TYPE_STR;
else
fn_arg_type = ID_TYPE_NUM;
}
else if(token[i].compare("<as>")==0)
{
i++;
fn_arg_type = ID_TYPE_USER;
fn_arg_user_type = "";
int arg_type_index = -1;
if(i < token.size())
if(token[i].substr(0,4).compare("<id>")==0)
fn_arg_user_type = token[i].substr(4);
if(fn_arg_user_type.compare("")==0)
{
rc_setError("Invalid Type in SUB ROUTINE Definition");
return false;
}
}
else if(token[i].compare("<comma>")==0)
{
//cout << "ADD ARG: " << fn_arg << endl;
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("SUB ROUTINE argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("SUB ROUTINE argument identifier already exists in current scope");
return false;
}
//cout << "CHECK 1" << endl;
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_embedded_arg(fn_arg, fn_arg_type, getUType(fn_arg_user_type)))
{
return false;
}
fn_arg = "";
fn_byref = false;
//cout << "DONE" << endl;
}
else if(token[i].compare("</par>")==0)
{
if((i+1) < token.size())
{
rc_setError("Expected End of SUB ROUTINE Declaration");
return false;
}
if(fn_arg.compare("")==0)
{
end_token = i+1;
break;
}
fn_arg = rc_substr(fn_arg, 4, fn_arg.length()-1);
if(!isValidIDName(fn_arg))
{
rc_setError("SUB ROUTINE argument is not a valid identifier name");
return false;
}
if(idExistsInScope(fn_arg))
{
rc_setError("SUB ROUTINE argument identifier already exists in current scope");
return false;
}
if(fn_byref)
{
if(fn_arg_type == ID_TYPE_NUM)
fn_arg_type = ID_TYPE_BYREF_NUM;
else if(fn_arg_type == ID_TYPE_STR)
fn_arg_type = ID_TYPE_BYREF_STR;
else
fn_arg_type = ID_TYPE_BYREF_USER;
}
if(!add_embedded_arg(fn_arg, fn_arg_type, getUType(fn_arg_user_type)))
{
return false;
}
fn_arg = "";
fn_byref = false;
end_token = i+1;
break;
}
else
{
rc_setError("Argument to SUB ROUTINE must be a valid identifier: " + token[i]);
}
}
current_block_state = BLOCK_STATE_MAIN;
current_scope = "main";
block_state.pop();
isInFunctionScope = false;
current_fn_index++;
if(token.size()>end_token)
{
rc_setError("Expected end of function declaration");
return false;
}
}
else if(token[0].compare("<type>")==0)
{
if(current_scope.compare("main")!=0)
{
rc_setError("TYPE cannot be defined in this scope");
return false;
}
if(token.size() != 2)
{
rc_setError("Expected TYPE Identifier in TYPE statement");
return false;
}
if(token[1].substr(0,4).compare("<id>")!=0)
{
rc_setError("Expected TYPE Identifier in TYPE statement");
return false;
}
int id_index = getIDInScope_ByIndex(token[1].substr(4));
if(id_index >= 0)
{
rc_setError("TYPE Identifier exists in current scope");
return false;
}
create_type(token[1].substr(4));
current_block_state = BLOCK_STATE_TYPE;
block_state.push(current_block_state);
string start_label = current_scope + ".#TYPE:" + token[1].substr(4);
current_scope = start_label;
}
else if(token[0].compare("<dim>")==0)
{
if(current_block_state != BLOCK_STATE_TYPE)
{
rc_setError("DIM can only be used for type members when embedding");
return false;
}
//cout << "DIM RULE FOUND" << endl; //'DIM' [ID]; '[' #; #; # ']' ; 'AS' [TYPE]; '=' (VALUE)
string id_name = "";
int id_type = ID_TYPE_NUM;
string id_type_name = "";
int dimensions = 0;
//check if the next token is a identifier
if(token.size() > 1)
{
if(token[1].substr(0,4).compare("<id>")==0)
{
//if the identifier is not a valid name then return false
id_name = token[1].substr(4);
id_type = ID_TYPE_NUM;
id_type_name = "";
dimensions = 0;
if(!isValidIDName(id_name))
{
rc_setError("Invalid Identifier name");
return false;
}
//check if the data type is a string
if(id_name.substr(id_name.length()-1).compare("$")==0)
id_type = ID_TYPE_STR;
//if the identifier already exists and current_block state is not type then return false
if(idExistsInScope(id_name))
{
rc_setError("Identifier already defined in current scope");
return false;
}
//cout << "db1\n";
//if there are only two tokens then return here because there is nothing left to check
if(token.size()==2)
{
if(current_block_state == BLOCK_STATE_TYPE)
{
//cout << "adding type member" << endl;
if(!add_type_member_embedded(id_name, id_type, "", 0, 0, 0, 0))
{
//cout << rc_getError() << endl;
return false;
}
}
//cout << "return true here" << endl;
return true;
}
//cout << "db2\n";
//current token
int token_index = 2;
int t_dim_arg[3];
t_dim_arg[0] = 0;
t_dim_arg[1] = 0;
t_dim_arg[2] = 0;
//check for the next rule; must be [], AS, or =
//cout << "token = " << token[token_index] << endl;
if(token[token_index].compare("<square>")==0 && current_block_state == BLOCK_STATE_TYPE)
{
//token_index++;
int end_token = token_index+1;
int sq_scope = 1;
multi_arg_count = 0;
int arg_index = 0;
t_dim_arg[0] = 0;
t_dim_arg[1] = 0;
t_dim_arg[2] = 0;
for(; end_token < token.size(); end_token++)
{
if(token[end_token].compare("<square>")==0)
sq_scope++;
else if(token[end_token].compare("</square>")==0)
sq_scope--;
else if(token[end_token].substr(0,5).compare("<num>")==0)
{
if(arg_index > 2)
{
rc_setError("Too many dimensions in type member declaration for embedded");
return false;
}
multi_arg[arg_index] = token[end_token].substr(5);
t_dim_arg[arg_index] = rc_stringToInt(multi_arg[arg_index]);
multi_arg_count = arg_index+1;
}
else if(token[end_token].compare("<comma>")==0)
arg_index++;
else
{
rc_setError("Expected number constant in type member declaration for embedded: " + token[end_token]);
return false;
}
if(sq_scope==0)
break;
}
if(sq_scope != 0)
{
rc_setError("Expected ] in array definition");
return false;
}
dimensions = multi_arg_count;
token_index = end_token+1;
//cout << "DBG token = " << token[token_index] << std::endl;
if(token.size() > token_index)
{
if(token[token_index].compare("<as>")==0)
{
token_index++;
if(token[token_index].substr(0,4).compare("<id>")!=0)
{
rc_setError("Invalid type identifier name in DIM");
return false;
}
id_type = ID_TYPE_USER;
id_type_name = token[token_index].substr(4);
//cout << "Add member (" << id_name << ") of type (" << id_type_name << ") with " << dimensions << " dimensions [" << constant_arg[0] << "," << constant_arg[1] << "," << constant_arg[2] << "]" << endl;
//if(!add_type_member(id_name, id_type, id_type_name, dimensions, constant_arg[0], constant_arg[1], constant_arg[2]))
if(!add_type_member_embedded(id_name, id_type, id_type_name, dimensions, t_dim_arg[0], t_dim_arg[1], t_dim_arg[2]))
return false;
}
else
{
rc_setError("Invalid member array declaration in DIM");
return false;
}
}
else
{
//cout << "Add member (" << id_name << ") of type (num/str) with " << dimensions << " dimensions [" << constant_arg[0] << "," << constant_arg[1] << "," << constant_arg[2] << "]" << endl;
//if(!add_type_member(id_name, id_type, "", dimensions, constant_arg[0], constant_arg[1], constant_arg[2]))
if(!add_type_member_embedded(id_name, id_type, "", dimensions, t_dim_arg[0], t_dim_arg[1], t_dim_arg[2]))
return false;
}
return true;
}
else if(token[token_index].compare("<as>")==0)
{
token_index++;
if(token_index >= token.size())
{
rc_setError("Invalid member declaration");
return false;
}
if(token[token_index].substr(0,4).compare("<id>")!=0)
{
rc_setError("Invalid type identifier name in DIM");
return false;
}
id_type = ID_TYPE_USER;
id_type_name = token[token_index].substr(4);
//cout << "Add member (" << id_name << ") of type (" << id_type_name << ") with " << dimensions << " dimensions [" << constant_arg[0] << "," << constant_arg[1] << "," << constant_arg[2] << "]" << endl;
//if(!add_type_member(id_name, id_type, id_type_name, dimensions, constant_arg[0], constant_arg[1], constant_arg[2]))
if(!add_type_member_embedded(id_name, id_type, id_type_name, 0, 0, 0, 0))
return false;
return true;
}
if(token.size()>token_index)
{
rc_setError("Invalid variable definition: " + token[token_index] + ", " + rc_intToString(current_block_state) + " <--> " + rc_intToString(BLOCK_STATE_TYPE));
return false;
}
}
else
{
//if the next token is not an id then the syntax is incorrect and false is returned
rc_setError("Expected Identifier name");
return false;
}
}
else
{
//if the size of the token vector is not greater than one then the syntax for the line is incomplete so I return false
rc_setError("Expected Identifier name");
return false;
}
}
else if(token[0].compare("<end>")==0)
{
if(token.size()==1)
{
rc_setError("END can only be used to end TYPE when embedding");
return false;
}
if(token[1].compare("<type>")==0)
{
if(token.size()>2)
{
rc_setError("Expected End of Line in END TYPE");
return false;
}
if(current_block_state != BLOCK_STATE_TYPE)
{
rc_setError("Cannot exit TYPE definition from this scope");
return false;
}
block_state.pop();
current_block_state = BLOCK_STATE_MAIN;
current_scope = "main";
}
else
{
rc_setError("END can only be used to end TYPE when embedding");
return false;
}
}
}
return true;
}
#endif // PARSER_H_INCLUDED