orga-comp/parser.cpp

300 lines
6.2 KiB
C++

#include "orga-comp.h"
#include <iostream>
struct token *
parser::parse_tokens() {
// LR(k) parsing.
// Pushea al stack hasta encontrar una cantidad de token suficiente
// como para saber que hacer.
// El parse a su vez arma un abstract syntax tree.
if(pos < _tokens.size()) {
_stack.push(_tokens[pos]);
pos++;
//_stack.push(tok);
switch (_stack.top()->tok_type) {
case token::TOK_ID:
statement();
break;
case token::STM_COMPOUND:
break;
case token::TOK_IF:
std::cout << "ENTERING COND REDUCTION";
conditional(); // conditional follows the form of IF EXP DO STM END
break;
case token::TOK_END:
break;
default:
std::cout << "ERROR PARSING\n";
err();
break;
}
parse_tokens();
}
return _stack.top();
//check if reduce is possible, if it is reduce.
}
parser::parser(std::vector<struct token*> tokens) {
_tokens = tokens;
pos = 0;
}
void
parser::reduce() {
if(_stack.size() <= 1) return;
struct token *tok = pop();
std::cout << str_token(*tok) << " ";
switch (tok->tok_type) {
case token::TOK_NUM:
// std::cout << "reduzco numero\n";
reduce_num(tok);
// reduce();
break;
case token::EXP_ID:
case token::EXP_OPERATION:
case token::EXP_NUMBER:
// EL SIGUIENTE ES UN OP O UN ASSIGN
reduce_exp(tok);
break;
case token::TOK_ID:
reduce_id(tok);
break;
case token::TOK_SEMI:
// reduce();
break;
case token::STM_CJUMP:
std::cout << "CJUMP 44\n";
reduce_blck();
break;
case token::STM_ASSIGN:
reduce_stm(tok);
default: break;
}
reduce();
}
void
parser::reduce_stm(struct token *stm) {
struct token *tok = pop();
struct token *tmp;
switch (tok->tok_type) {
case token::STM_CJUMP:
case token::STM_ASSIGN:
case token::STM_COMPOUND:
tmp = new struct token;
tmp->tok_type = token::STM_COMPOUND;
tmp->rvalue = stm;
tmp->lvalue = tok;
push(tmp);
// std::cout << "CHAD STM REDUCER " << str_token(*tmp);
break;
default:
std::cout << "ERROR REDUCING STM\n";
std::cout << str_token(*tok) << "\n";
err();
break;
}
}
void
parser::reduce_id(struct token *id) {
struct token *tmp = new struct token;
tmp->tok_type = token::EXP_ID;
tmp->value = id->value;
push(tmp);
}
void
parser::reduce_num(struct token *num) {
struct token *tmp = new struct token;
tmp->tok_type = token::EXP_NUMBER;
tmp->value = num->value;
push(tmp);
}
void
parser::reduce_exp(struct token *exp) {
// std::cout << "reducing exp: " << str_token(*exp) << "\n";
struct token *modifier = pop();
struct token *tmp;
struct token *stm;
switch (modifier->tok_type) {
case token::TOK_ASSIGN:
std::cout << "assign found\n";
if(_stack.top()->tok_type != token::TOK_ID) err();
// std::cout << str_token(*_stack.top()) << "\n";
stm = new struct token;
stm->tok_type = token::STM_ASSIGN;
stm->rvalue = exp;
stm->value = pop()->value;
push(stm);
break;
case token::TOK_EQ:
std::cout << "CMP_EXP\n";
if(_stack.top()->tok_type == token::TOK_NUM) {
reduce_num(pop());
}
if(_stack.top()->tok_type == token::TOK_ID) {
reduce_id(pop());
}
stm = new struct token;
stm->tok_type = token::EXP_COMPARE;
stm->value = modifier->value;
stm->rvalue = exp;
stm->lvalue = pop();
push(stm);
std::cout << "\n" << str_token(*stm) << '\n';
break;
case token::TOK_OP:
if(_stack.top()->tok_type == token::TOK_NUM) {
reduce_num(pop());
}
if(_stack.top()->tok_type == token::TOK_ID) {
reduce_id(pop());
}
stm = new struct token;
stm->tok_type = token::EXP_OPERATION;
stm->value = modifier->value;
stm->rvalue = exp;
stm->lvalue = pop();
push(stm);
break;
default:
std::cout << "ERROR REDUCING EXP\n";
err();
}
std::cout << "\nTOKENS " << pos << '\n';
print_tokens(_tokens);
}
struct token *
parser::pop() {
struct token *tmp = _stack.top();
_stack.pop();
return tmp;
}
void
parser::push(struct token *tok) {
_stack.push(tok);
}
void
parser::statement() {
_stack.push(_tokens[pos]);
pos++;
assert(_stack.top()->tok_type == token::TOK_ASSIGN);
expression();
}
void
parser::expression() {
_stack.push(_tokens[pos]);
pos++;
switch (_stack.top()->tok_type) {
case token::TOK_ID:
case token::TOK_NUM:
expression();
break;
case token::EXP_ID:
case token::EXP_NUMBER:
case token::EXP_OPERATION:
std::cout << "This shouldn't be here...\n";
err();
break;
case token::TOK_EQ:
case token::TOK_OP:
expression();
break;
case token::TOK_SEMI:
reduce();
break;
case token::TOK_DO:
std::cout << "Found do\n";
reduce_blck();
break;
default:
err();
break;;
}
}
void
parser::reduce_blck() {
if(_stack.size() == 1) return;
struct token *tok = pop();
std::cout << "\n--REDUCING BLOCK--\n";
std::cout << str_token(*tok) << "\n";
struct token *tmp;
switch (tok->tok_type) {
case token::STM_CJUMP:
case token::STM_COMPOUND:
case token::STM_ASSIGN:
reduce_stm(tok);
break;
case token::EXP_COMPARE:
assert(_stack.top()->tok_type == token::TOK_IF);
pop();
tmp = new struct token;
tmp->tok_type = token::STM_CJUMP;
tmp->rvalue = parse_until_tok_end();
tmp->lvalue = tok;
std::cout << str_token(*tmp->lvalue) << "\n";
std::cout << str_token(*tmp) << "\n";
std::cout << "CJUMP 5\n";
push(tmp);
break;
case token::TOK_NUM:
reduce_num(tok);
break;
case token::TOK_ID:
reduce_id(tok);
break;
case token::EXP_ID:
case token::EXP_OPERATION:
case token::EXP_NUMBER:
// EL SIGUIENTE ES UN OP O UN ASSIGN
reduce_exp(tok);
break;
default: break;
}
reduce_blck();
}
void
parser::conditional() {
push(_tokens[pos]);
pos++;
expression();
}
void
parser::err() {
std::cout
<< "unexpected symbol: "
<< str_token(*_stack.top())
<< '\n';
exit(-1);
}
struct token*
parser::parse_until_tok_end() {
std::vector<struct token*> tokens;
int depth = 0;
while (depth >= 0) {
tokens.push_back(_tokens[pos]);
if(_tokens[pos]->tok_type == token::TOK_DO) depth++;
if(_tokens[pos]->tok_type == token::TOK_END) depth--;
pos++;
}
tokens.pop_back();
parser pars(tokens);
std::cout << "NESTED PARSING BEGIN \n";
return pars.parse_tokens();
}
parser::~parser() {
// free_tree(pop());
}