Mam taki prosty "kompilator" działań typu mnożenie i dodawanie. Pracuje na getchar, więc powinno sie do niego wrzucać znaki pojedynczo, a na koniec ma wypluć pseudo komendy assemblera. Np dla: [pomiedzy 3 a 4, i 2 a nawiasy jest znak mnozenia gwiazdka, forum go usuwa] (2*((3 * 4) +9)) powinien wypluć:
PUSH 2
PUSH 3
PUSH 4
MULT
PUSH 9
ADD
MULT
PRINT
Niestety tego nie robi. Gdy wklepuje każdy z powyższych znaków pojedynczo (czyli: lewy cudzysłow enter, 2 enter, * enter itp) to dochodze do ostatniego cudzysłowa po którym kompilator powinien wypluć output wyżej. Niestety nie wypluwa nic, jedyny sposób na zakończenie programu tp wstawienie losowego znaku, po którym drukuje "Garbage at the end of file". Możecie mi powiedzieć dlaczego tak sie dzieje? Kod niżej
#include <stdio.h>
#include <stdlib.h>
#define DIGIT 257
#define EoF 256
typedef int Operator;
typedef struct _expression
{
char type;
int value;
struct _expression *left, *right;
Operator oper;
} Expression;
struct _token { int class; char repr; } Token;
//typedef Token_type Token;
typedef Expression AST_node;
//typedef Token_type *Token;
static int ls_layout_char(int ch) {
switch (ch)
{
case ' ': case '\t': case '\n': return 1;
default: return 0;
}
}
void error(char* error) {
printf("%s\n",error);
exit(1);
}
void get_next_token(void) {
int ch;
do {
ch=getchar();
if(ch<0) {
Token.class = EoF;
Token.repr='#';
return;
}
} while(ls_layout_char(ch));
if('0'<= ch && ch <= '9') Token.class=DIGIT;
else Token.class=ch;
Token.repr=ch;
}
static void Code_gen_expression(Expression *expr) {
switch (expr->type)
{
case 'D':
printf("PUSH %d\n", expr->value);
break;
case 'P':
Code_gen_expression(expr->left);
Code_gen_expression(expr->right);
switch (expr->oper)
{
case '+': printf("ADD\n"); break;
case '*': printf("MULT\n"); break;
}
break;
}
}
void Process(AST_node *icode) {
Code_gen_expression(icode);
printf("PRINT\n");
}
static int Interpret_expression(Expression *expr) {
switch (expr->type)
{
case 'D':
return expr->value;
break;
case 'P': {
int e_left = Interpret_expression(expr->left);
int e_right=Interpret_expression(expr->right);
switch (expr->oper)
{
case '+': return e_left+e_right;
case '*': return e_left*e_right;
}
}
break;
}
}
/*
void Process(AST_node *icode) {
printf("%d\n", Interpret_expression(icode));
}
*/
static Expression *new_expression() {
return (Expression*)malloc(sizeof(Expression));
}
static void free_expression(Expression *expr) {
free((void*) expr);
}
static int Parse_operator(Operator *oper) {
if(Token.class =='+') {
*oper='+';
get_next_token();
return 1;
}
if(Token.class=='*') {
*oper='*';
get_next_token();
return 1;
}
return 0;
}
static int Parse_expression(Expression **expr_p) {
Expression *expr = *expr_p = new_expression();
if(Token.class==DIGIT) {
expr->type='D';
//printf("%d \n", Token.repr-'0');
expr->value=Token.repr-'0';
get_next_token();
return 1;
}
if(Token.class=='(') {
expr->type ='P';
get_next_token();
if(!Parse_expression(&expr->left)) error("Missing expression");
if(!Parse_operator(&expr->oper)) error("Missing operator");
if(!Parse_expression(&expr->right)) error("Missing expression");
if(Token.class !=')') error("Missing )");
get_next_token();
return 1;
}
free_expression(expr);
return 0;
}
int Parse_program(AST_node **icode_p) {
Expression *expr;
get_next_token();
if(Parse_expression(&expr)) {
if(Token.class!=EoF) {
error("Garbage after end of program\n");
}
*icode_p=expr;
return 1;
}
return 0;
}
int main() {
AST_node *icode;
if(!Parse_program(&icode)) printf("ERROR");
Process(icode);
return 0;
}