252 lines
4.9 KiB
C
252 lines
4.9 KiB
C
#include<stdio.h>
|
|
#include<stdlib.h>
|
|
#include"run.h"
|
|
#include"state.h"
|
|
|
|
void gen_run_eval(const Vec*tokens);
|
|
|
|
void gen_run(Gen*gen,const PNode*pn,FILE*file)
|
|
{
|
|
if(!pn)
|
|
{
|
|
err_log("NULL PNode passed to gen_run");
|
|
return;
|
|
}
|
|
|
|
if(!file)
|
|
{
|
|
err_log("NULL FILE* passed to gen_run");
|
|
return;
|
|
}
|
|
|
|
/* printf("pn: %p\nfile: %p\n",pn,file); */
|
|
|
|
switch(pn->type)
|
|
{
|
|
|
|
case PRET:
|
|
case PVARDECL:
|
|
case PEXPRESSION:
|
|
{
|
|
printf("%p: ",pn);
|
|
printf("%s\n",partype_names[pn->type]);
|
|
|
|
if(pn->tokens.size>0)
|
|
{
|
|
for(size_t i=0;i<pn->tokens.size;++i)
|
|
printf("%s ",vec_at(&pn->tokens,i,const Tok*)->str.buffer);
|
|
printf("\n");
|
|
gen_run_eval(&pn->tokens);
|
|
}
|
|
|
|
if(pn->pnodes.size>0)
|
|
{
|
|
for(size_t i=0;i<pn->pnodes.size;++i)
|
|
gen_run(gen,vec_at(&pn->pnodes,i,const PNode*),file);
|
|
printf("\n");
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
printf("%p: ",pn);
|
|
printf("%s\n",partype_names[pn->type]);
|
|
|
|
if(pn->tokens.size>0)
|
|
{
|
|
for(size_t i=0;i<pn->tokens.size;++i)
|
|
printf("%s ",vec_at(&pn->tokens,i,const Tok*)->str.buffer);
|
|
printf("\n");
|
|
}
|
|
|
|
if(pn->pnodes.size>0)
|
|
{
|
|
for(size_t i=0;i<pn->pnodes.size;++i)
|
|
gen_run(gen,vec_at(&pn->pnodes,i,const PNode*),file);
|
|
printf("\n");
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// Convert infix to RPN
|
|
// Vec<Tok>
|
|
Vec gen_run_i2r(const Vec*tokens)
|
|
{
|
|
Vec stack=vec_new(sizeof(const Tok));
|
|
Vec operators=vec_new(sizeof(const Tok));
|
|
int precedence[1024]={0};
|
|
precedence['(']=5;
|
|
precedence[')']=5;
|
|
precedence['+']=10;
|
|
precedence['-']=10;
|
|
precedence['*']=20;
|
|
precedence['/']=20;
|
|
|
|
if(tokens->size>0)
|
|
{
|
|
for(size_t i=0;i<tokens->size;++i)
|
|
{
|
|
|
|
// identifiers
|
|
if(vec_at(tokens,i,const Tok*)->type==LIDENTIFIER)
|
|
vec_push(&stack,vec_at(tokens,i,const Tok*));
|
|
|
|
// integers
|
|
if(vec_at(tokens,i,const Tok*)->type==LINTEGER)
|
|
vec_push(&stack,vec_at(tokens,i,const Tok*));
|
|
// operators
|
|
else if(vec_at(tokens,i,const Tok*)->type==LOPERATOR)
|
|
{
|
|
|
|
// '('
|
|
if(vec_at(tokens,i,const Tok*)->subtype==LLPAREN)
|
|
{
|
|
vec_push(&operators,vec_at(tokens,i,const Tok*));
|
|
}
|
|
|
|
// ')'
|
|
else if(vec_at(tokens,i,const Tok*)->subtype==LRPAREN)
|
|
{
|
|
while(operators.size>0&&vec_at(&operators,operators.size-1,const Tok*)->subtype!=LLPAREN)
|
|
{
|
|
const Tok*newtok=vec_at(&operators,operators.size-1,const Tok*);
|
|
vec_push(&stack,newtok);
|
|
vec_pop(&operators);
|
|
}
|
|
vec_pop(&operators);
|
|
}
|
|
|
|
// Default operators
|
|
else
|
|
{
|
|
|
|
// Pop operators from operators ==> stack
|
|
// who have higher precedence than current
|
|
// operator
|
|
while(operators.size>0&&precedence[(uint32_t)vec_at(&operators,operators.size-1,const Tok*)->str.buffer[0]]>=precedence[(uint32_t)vec_at(tokens,i,const Tok*)->str.buffer[0]])
|
|
{
|
|
const Tok*newtok=vec_at(&operators,operators.size-1,const Tok*);
|
|
vec_push(&stack,newtok);
|
|
vec_pop(&operators);
|
|
}
|
|
vec_push(&operators,vec_at(tokens,i,const Tok*));
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
while(operators.size>0)
|
|
{
|
|
const Tok*newtok=vec_at(&operators,operators.size-1,const Tok*);
|
|
vec_push(&stack,newtok);
|
|
vec_pop(&operators);
|
|
}
|
|
|
|
/* printf("s:"); */
|
|
/* vec_print_tokens(&stack); */
|
|
/* printf("o:"); */
|
|
/* vec_print_tokens(&operators); */
|
|
|
|
/* vec_free(&stack); */
|
|
vec_free(&operators);
|
|
|
|
// move ownership to caller
|
|
return stack;
|
|
}
|
|
|
|
// Convert to infix, then evaluate
|
|
void gen_run_eval(const Vec*tokens)
|
|
{
|
|
Vec rpn_stack={0};
|
|
Vec stack=vec_new(sizeof(const int));
|
|
|
|
rpn_stack=gen_run_i2r(tokens);
|
|
|
|
vec_print_tokens(&rpn_stack);
|
|
|
|
// Evaluate RPN
|
|
if(rpn_stack.buffer&&rpn_stack.size>0)
|
|
{
|
|
|
|
for(size_t i=0;i<rpn_stack.size;++i)
|
|
{
|
|
|
|
/* vec_print(&stack,"%d"); */
|
|
|
|
switch(vec_at(&rpn_stack,i,const Tok*)->type)
|
|
{
|
|
|
|
case LIDENTIFIER:
|
|
{
|
|
printf("ignoring '%s'\n",vec_at(&rpn_stack,i,const Tok*)->str.buffer);
|
|
}
|
|
break;
|
|
|
|
case LINTEGER:
|
|
{
|
|
int32_t d=atoi(vec_at(&rpn_stack,i,const Tok*)->str.buffer);
|
|
vec_pushi(&stack,d);
|
|
}
|
|
break;
|
|
|
|
case LOPERATOR:
|
|
|
|
/* printf("op:'%s'\n",vec_at(&rpn_stack,i,const Tok*)->str.buffer); */
|
|
|
|
if(stack.size>1)
|
|
{
|
|
|
|
int32_t i1=0;
|
|
int32_t i2=0;
|
|
int32_t res=0;
|
|
|
|
i1=*vec_at(&stack,stack.size-1,const int*);
|
|
vec_pop(&stack);
|
|
i2=*vec_at(&stack,stack.size-1,const int*);
|
|
vec_pop(&stack);
|
|
|
|
printf("%d%s%d\n",
|
|
i2,
|
|
vec_at(&rpn_stack,i,const Tok*)->str.buffer,
|
|
i1
|
|
);
|
|
|
|
switch(vec_at(&rpn_stack,i,const Tok*)->str.buffer[0])
|
|
{
|
|
|
|
case '+':res=i2+i1;break;
|
|
case '-':res=i2-i1;break;
|
|
case '*':res=i2*i1;break;
|
|
case '/':res=i2/i1;break;
|
|
|
|
}
|
|
|
|
vec_pushi(&stack,res);
|
|
}
|
|
/* else */
|
|
/* printf("stack less than 2\n"); */
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(stack.size>0)
|
|
{
|
|
int32_t res=*vec_at(&stack,stack.size-1,const int32_t*);
|
|
printf("%d\n",res);
|
|
}
|
|
/* printf("s:"); */
|
|
/* vec_print(&stack,"%s"); */
|
|
|
|
vec_free(&rpn_stack);
|
|
vec_free(&stack);
|
|
}
|