std::vector<Foperand> Cclsh::Rparse_expression() {
std::vector<Foperand> expression;
Foperand operand = this->Rparse_operand();
expression.push_back(operand);
while (this->Ris_operator()) {
Ftoken oper = this->Rparse_token();
int oper_code = this->code_table[oper.token];
Foperand op;
op.code = oper_code;
expression.push_back(op);
operand = this->Rparse_operand();
expression.push_back(operand);
}
return expression;
}
Foperand Cclsh::Rparse_operand() {
Foperand operand;
operand.string = "";
operand.number = 0;
operand.address = 0;
operand.index = 0;
operand.field = "";
operand.type = this->code_table["n"];
// Now proceed with the parsing.
if (this->Ris_number()) {
operand.type = this->code_table["n"];
operand.number = this->Rparse_number();
}
else if (this->Ris_address()) {
operand.type = this->code_table["a"];
operand.address = this->Rparse_address();
}
else if (this->Ris_field()) {
operand.type = this->code_table["f"];
Ffield field = this->Rparse_field();
operand.address = field.value;
operand.field = field.name;
}
else if (this->Ris_list()) {
operand.type = this->code_table["l"];
Flist list = this->Rparse_list();
operand.address = list.address;
operand.index = list.index;
operand.field = list.field;
}
else if (this->Ris_string()) {
operand.type = this->code_table["s"];
operand.string = this->Rparse_string();
}
else if (this->Ris_num_placeholder()) {
operand.type = this->code_table["n"];
operand.num_placeholder = this->Rparse_token();
}
else if (this->Ris_addr_placeholder()) {
operand.type = this->code_table["a"];
operand.addr_placeholder = this->Rparse_addr_placeholder();
}
else if (this->Ris_field_placeholder()) {
operand.type = this->code_table["f"];
std::vector<std::string> tokens = this->Rparse_field_placeholder();
operand.addr_placeholder = tokens[0];
operand.field = tokens[1];
}
else if (this->Ris_list_placeholder()) {
operand.type = this.code_table["l"];
std::vector<std::string> tokens = this->Rparse_list_placeholder();
operand.addr_placeholder = tokens[0];
operand.index_placeholder = tokens[1];
operand.field = tokens[2];
}
else {
this->Rgenerate_error("Operand is invalid. (" + this->Rpeek_token().token + ")");
}
return operand;
}
Fcondition Cclsh::Rparse_condition(Fblock& block) {
Fcondition condition;
condition.left = 0;
condition.right = 0;
condition.test = 0;
// The expression is stored in the expression list.
std::vector<Foperand> left_exp = this->Rparse_expression();
block.expressions.push_back(left_exp);
condition.left = block.expressions.size() - 1; // Just point to expression.
std::string test = this->Rparse_test();
condition.test = this->code_table[test];
std::vector<Foperand> right_exp = this->Rparse_expression();
block.expressions.push_back(right_exp);
condition.right = block.expressions.size() - 1;
return condition;
}
std::string Cclsh::Rparse_test() {
Ftoken token = this->Rparse_token();
std::string test = "";
if ((token.token == "eq") ||
(token.token == "ne") ||
(token.token == "lt") ||
(token.token == "gt") ||
(token.token == "le") ||
(token.token == "ge")) {
test = token.token;
}
else {
this->Rgenerate_error(token.token + " is not a valid test.");
}
return test;
}
std::vector<Fcondition> Cclsh::Rparse_conditional(Fblock& block) {
std::vector<Fcondition> conditional;
Fcondition condition = this->Rparse_condition(block);
conditional.push_back(condition);
while (this->Ris_logic()) {
Ftoken logic = this->Rparse_token();
Fcondition logic_code;
logic_code.logic = this->code_table[logic.token];
conditional.push_back(logic_code);
condition = this->Rparse_condition(block);
conditional.push_back(condition);
}
return conditional;
}
void Cclsh::Rparse_command() {
if (this->prgm_counter < this->memory_size) {
Ftoken code = this->Rparse_token();
if (code.token == "remark") { // Comment
// Parse all the way to end.
Ftoken end_tok = this->Rpeek_token();
while (end_tok.token != "end") {
this->Rparse_token(); // Remove comment token.
end_tok = this->Rpeek_token();
}
// Remove end command.
this->Rparse_token();
}
else if (code.token == "define") { // define <name> as <number>
Ftoken name = this->Rparse_token();
this->Rparse_keyword("as");
int value = this->Rparse_number();
this->symtab[name.token] = value;
}
else if (code.token == "label") { // label <name>
Ftoken name = this->Rparse_token();
this->symtab[name.token] = this->prgm_counter; // Update with current address.
}
else if (code.token == "var") { // var <name>
Ftoken name = this->Rparse_token();
this->symtab[name.token] = this->prgm_counter++; // Skip one block.
}
else if (code.token == "list") { // list <name> alloc <blocks>
Ftoken name = this->Rparse_token();
this->symtab[name.token] = this->prgm_counter;
this->Rparse_keyword("alloc");
int count = this->Rparse_number();
// Allocate free blocks for the list.
this->prgm_counter += count;
}
else { // Possible commands.
if (this->parse_table.find(code.token) != this->parse_table.end()) {
Fparse_obj command = this->parse_table[code.token];
Fblock block = this->memory[this->prgm_counter++];
// Clear out the block.
this->Rclear_block(block);
// Assign block code.
block.code = command.code;
if (command.pattern.length() > 0) {
std::vector<std::string> entries = this->Rsplit_line(command.pattern);
int entry_count = entries.size();
for (int entry_index = 0; entry_index < entry_count; entry_index++) {
std::string entry = entries[entry_index];
if (entry == "<c>") {
block.conditional = this->Rparse_conditional(block);
}
else if (entry == "<e>") {
block.expressions.push_back(this->Rparse_expression());
}
else if (entry == "<s>") {
block.strings.push_back(this->Rparse_string());
}
else { // This will be treated as keyword.
this->Rparse_keyword(entry);
}
}
}
// Record debug info.
this.debug_symbols.push_back(code.token);
}
else {
this->Rgenerate_error("Invalid command " + code.token + ".");
}
}
}
else {
// Should probably not be called.
this->Rgenerate_error("Program too big for memory.");
}
}