Para algumas (ou uma) pessoa que não acredita que neste forum àpessoas capazes de criar um compilador, aqui vai o código (separado em posts por cada secção do ficheiro com a explicação do que faz cada um no inÃÂcio do post):
Enunciado:
QuoteA linguagem LYSP (Lex and Yacc very Simple lisPÃ,Âlike language) consiste num muito pequeno subconjunto de funcionalidades inspiradas na linguagem Lisp. Existem apenas três comandos:
ââ,¬â€œ defun ââ,¬â€œ sintaxe exactamente como na linguagem Lisp (defun <nome da função>
(argumentos) <corpo da função>), serve para definir uma função que poderá a partir daàser utilizada por outras funções. Por exemplo, podemos definir a função ââ,¬Å"sumââ,¬Â, que recebe dois argumentos (X e Y) e os soma:
(defun sum (X Y)
(+ X Y))
ââ,¬â€œ if ââ,¬â€œ sintaxe exactamente como na linguagem Lisp (if <condição> <corpo do then> [<corpo do else>]), é uma instrução de selecção. Caso a condição seja verdadeira, executa o corpo do then, caso contrário, executa o corpo do else, se este existir. Por exemplo, se quisermos fazer uma divisão de X por Y apenas se Y for diferente de 0 (se for igual a zero, devolver -9999999):
(if (= Y 0)
Ã,Â9999999
(/ X Y))
ââ,¬â€œ deflocal ââ,¬â€œ comando para criar uma variável. A sintaxe será ( deflocal <lista
de pares identificador/valor>). O def local terá um scope correspondente ao nÃÂvel em que está inserido, ou a subnÃÂveis em que é chamado (ou seja, se for dentro de uma função, será ââ,¬Å"visÃÂvelââ,¬Â apenas dentro dela; se for no toplevel, acaba por ser uma variável global). Se quisermos definir 3 variáveis (X, Y e Z), atribuindoÃ,Âlhes os valores de inicialização (0, 1 e Ã,Â1, respectivamente):
(deflocal X 0 Y 1 Z Ã,Â1)
Nesta linguagem, existe um e um só tipo de variável: inteiro. Ou seja, não existem valores reais nem strings (ou até mesmo listas). Como tal, é uma linguagem funcional:
cada função devolve um e um só valor; não existe qualquer comando de ciclo ( for, do ou while) portanto as repetições terão que ser baseadas em chamadas recursivas às funções;
todos os comandos são, em última análise, funções. Por exemplo, um comando defun deverá devolver 0, um comando if deverá devolver o resultado da chamada a then ou else (0, caso não haja parte else e a condição for falsa), e o comando deflocal deverá devolver o último valor atribuÃÂdo.
Para além destes comandos, existem também as operações aritméticas básicas (+, Ã,Â, /, *), que podem ser aplicadas a listas de números/variáveis:
(+ 2 3 4 5) Ã,ÂÃ,Â> devolve 2+3+4+5=14
(Ã, 2 3 4 5) Ã,ÂÃ,Â> devolve 2Ã,Â3Ã,Â4Ã,Â5=Ã,Â10
(/ 2 3 4 5) Ã,ÂÃ,Â> devolve 2/3/4/5=0 (divisão inteira)
(* 2 3 4 5) Ã,ÂÃ,Â> devolve 2*3*4*5=120
Existem também os operadores de comparação básicos (=, <, >, <=, >=), que podem ser aplicados a pares de funções:
(> 1 0) Ã,ÂÃ,Â> devolve 1
(< 1 0) Ã,ÂÃ,Â> devolve 0
Assim, poderá fazer composição destes comandos e operadores para fazer funções de alguma complexidade. Por exemplo, a função abaixo calcula o factorial de um número.
(defun factorial (n)
(if (= n 0)
1
(* n (factorial (Ã, n 1)))))
Um programa em LYSP consistirá numa sequência de chamadas executadas no toplevel, ou seja o programa deverá executar o primeiro comando, depois o segundo, depois o terceiro e assim sucessivamente. Cada uma destas execuções deverá resultar na impressão para o output do valor obtido. Por exemplo, um pequeno programa para calcular o factorial de 9, 6 e 3:
(defun factorial (n)
(if (= n 0)
1
(* n (factorial (Ã, n 1)))))
(factorial 9)
(factorial 6)
(factorial 3)
Ao correr este programa, o output gerado seria:
0
362880
720
6
O facto de as execuções serem feitas em sequência implica que uma variável (ou uma função) não pode ser utilizada antes de ser declarada. Por exemplo,
(+ x 8)
(deflocal x 0)
A variável ââ,¬Å"xââ,¬Â não é conhecida quando é feita a soma. Teria que ser ao contrário:
(deflocal x 0)
(+ x 8)
O resultado seria então
0
8
Código Lex:
Realiza a análise lexical (identificação dos tokens e o seu envio para o Yacc com a label correspondente).
LYSP.l
%{
#include "structures.h"
#include "y.tab.h"
#include
#include
void lowercase(char string[]);
%}
%%
";".*n {line++;}
"-"?[0-9]+ {yylval.value = atoi(yytext); return NUMBER;}
"if" {return IF;}
"defun" {return DEFUN;}
"deflocal" {return DEFLOCAL;}
"and" {return AND;}
"or" {return OR;}
"not" {return NOT;}
"xor" {return XOR;}
"<=" {return MENOR_EQ;}
">=" {return MAIOR_EQ;}
[a-zA-Z][a-zA-Z0-9_]* {lowercase(yytext); yylval.var = (char*) strdup(yytext); return VAR;}
[ t] ;
n {line++;}
. return yytext[0];
%%
int yywrap()
{
return 1;
}
void lowercase(char string[])
{
int i;
for (i = 0; string[i]; i++)
string[i] = tolower(string[i]);
}
Código Yacc:
Realiza a análise sintática (verifica se os tokens estão bem posicionados na sintáxe, caso contrário dá erro de sintaxe - o código foi mal construido, logo não é aceite).
LYSP.y:
%{
#include
#include
#include "structures.h"
#include "functions.h"
#include "symbol_table.h"
#include "semantic.h"
#include "translation.h"
//table_element *table;
is_statement *myprogram;
//table_element *search_el(char *str);
//table_element *insert_el(char *str);
%}
%token NUMBER
%token VAR
%token IF
%token DEFUN
%token DEFLOCAL
%token AND
%token OR
%token XOR
%token NOT
%token MAIOR_EQ
%token MENOR_EQ
%union{
int value;
char *var;
is_statement *statement;
is_function *function;
is_single_exp *single_exp;
is_function_not *function_not;
is_arg_list *args;
is_function_defun *function_defun;
is_deflocal *deflocal;
is_function_deflocal *expressiondef;
is_function_if_comp *function_if_comp;
is_function_if_simp *function_if_simp;
is_single_exp_list *expression;
is_function_user *function_user;
is_function_op *function_op;
}
%type statement
%type function
%type function_op
%type ressiondef> function_deflocal
%type ressiondef> expressiondef
%type function_defun
%type function_if_comp
%type function_if_simp
%type function_user
%type function_not
%type ression> expression
%type single_exp
%type args
%type deflocal
%%
statement: single_exp {$$ = insert_statement($1, NULL); myprogram = $$;}
| statement single_exp {$$ = insert_statement($2, $1);}
;
function: function_op {$$ = insert_op_function($1);}
| function_deflocal {$$ = insert_deflocal_function($1);}
| function_defun {$$ = insert_defun_function($1);}
| function_if_simp {$$ = insert_if_simp_function($1);}
| function_if_comp {$$ = insert_if_comp_function($1);}
| function_user {$$ = insert_user_function($1);}
| function_not {$$ = insert_not_function($1);}
;
function_op: \\'(\\' \\'+\\' expression single_exp \\')\\' {$$ = insert_function_op(is_SOMA, $3, $4);}
| \\'(\\' \\'-\\' expression single_exp \\')\\' {$$ = insert_function_op(is_SUB, $3, $4);}
| \\'(\\' \\'*\\' expression single_exp \\')\\' {$$ = insert_function_op(is_MULT, $3, $4);}
| \\'(\\' \\'/\\' expression single_exp \\')\\' {$$ = insert_function_op(is_DIV, $3, $4);}
| \\'(\\' \\'<\\' expression single_exp \\')\\' {$$ = insert_function_op(is_MENOR, $3, $4);}
| \\'(\\' \\'>\\' expression single_exp \\')\\' {$$ = insert_function_op(is_MAIOR, $3, $4);}
| \\'(\\' MENOR_EQ expression single_exp \\')\\' {$$ = insert_function_op(is_MENOR_IGUAL, $3, $4);}
| \\'(\\' MAIOR_EQ expression single_exp \\')\\' {$$ = insert_function_op(is_MAIOR_IGUAL, $3, $4);}
| \\'(\\' \\'=\\' expression single_exp \\')\\' {$$ = insert_function_op(is_IGUAL, $3, $4);}
| \\'(\\' AND expression single_exp \\')\\' {$$ = insert_function_op(is_AND, $3, $4);}
| \\'(\\' OR expression single_exp \\')\\' {$$ = insert_function_op(is_OR, $3, $4);}
| \\'(\\' XOR expression single_exp \\')\\' {$$ = insert_function_op(is_XOR, $3, $4);}
;
function_defun: \\'(\\' DEFUN VAR \\'(\\' args \\')\\' expression \\')\\' {$$ = insert_function_defun(line, $3, $5, $7);}
| \\'(\\' DEFUN VAR \\'(\\' \\')\\' expression \\')\\' {$$ = insert_function_defun(line, $3, NULL, $6);}
;
function_deflocal: \\'(\\' DEFLOCAL expressiondef \\')\\' {$$ = $3;}
;
function_if_simp: \\'(\\' IF single_exp single_exp \\')\\' {$$ = insert_function_if_simp($3, $4);}
;
function_if_comp: \\'(\\' IF single_exp single_exp single_exp \\')\\' {$$ = insert_function_if_comp($3, $4, $5);}
;
function_user: \\'(\\' VAR expression \\')\\' {$$ = insert_function_user(line, $2, $3);}
| \\'(\\' VAR \\')\\' {$$ = insert_function_user(line, $2, NULL);}
;
function_not: \\'(\\' NOT function \\')\\' {$$ = insert_not_function_exp($3);}
| \\'(\\' NOT NUMBER \\')\\' {$$ = insert_not_number_exp($3);}
| \\'(\\' NOT VAR \\')\\' {$$ = insert_not_var_exp(line, $3);}
;
expression: expression single_exp {$$ = insert_single_exp_list($2, $1);}
| single_exp {$$ = insert_single_exp_list($1, NULL);}
;
single_exp: function {$$ = insert_function_exp($1);}
| NUMBER {$$ = insert_number_exp($1);}
| VAR {$$ = insert_var_exp(line, $1);}
;
expressiondef: expressiondef deflocal {$$ = insert_function_deflocal($2, $1);}
| deflocal {$$ = insert_function_deflocal($1, NULL);}
;
deflocal: VAR single_exp {$$ = insert_deflocal($1, $2, line);}
;
args: args VAR {$$ = insert_arg_list(line, $2, $1);}
| VAR {$$ = insert_arg_list(line, $1, NULL);}
;
%%
int main()
{
int parsingOK;
line = 1;
successful_semantic = 1;
parsingOK = yyparse();
if (!parsingOK)
{
prog_env *pe = semantic_analysis(myprogram);
if (successful_semantic)
translate(myprogram, pe);
}
}
void yyerror (char *s)
{
printf("%s - line: %dn", s, line);
}
Inserts:
Código que constroi a árvore de sintaxe abstracta (consoante as chamadas do Yacc a este código).
structures.h:
#ifndef _STRUCTURES_
#define _STRUCTURES_
int line;
int successful_semantic;
typedef struct _e1 is_single_exp;
typedef struct _e2 is_function;
typedef struct _a1 is_function_not;
typedef struct _a2 is_arg_list;
typedef struct _a3 is_function_defun;
typedef struct _a4 is_deflocal;
typedef struct _a5 is_function_deflocal;
typedef struct _a6 is_function_if_comp;
typedef struct _a7 is_function_if_simp;
typedef struct _a8 is_single_exp_list;
typedef struct _a9 is_function_user;
typedef struct _a10 is_function_op;
typedef struct _a11 is_statement;
typedef enum {is_SOMA, is_SUB, is_MULT, is_DIV, is_MENOR, is_MAIOR, is_MENOR_IGUAL, is_MAIOR_IGUAL, is_IGUAL, is_AND, is_OR, is_XOR} is_op;
typedef enum {d_function, d_NUMBER, d_VAR} disc_single_exp;
struct _e1 {
disc_single_exp disc_se;
union {
is_function *function;
int number;
char *var;
} data_exp;
int codeline;
};
typedef enum {d_function_op, d_function_deflocal, d_function_defun, d_function_if_simp, d_function_if_comp, d_function_user, d_function_not} disc_function;
struct _e2 {
disc_function disc_f;
union {
is_function_op *op;
is_function_deflocal *deflocal;
is_function_defun *defun;
is_function_if_simp *if_simp;
is_function_if_comp *if_comp;
is_function_user *user;
is_function_not *not;
} data_exp;
};
/*typedef enum {d_not_function, d_not_NUMBER, d_not_VAR} disc_function_not;*/
struct _a1 {
disc_single_exp disc_fn;
union {
is_function *function;
int number;
char *var;
} data_exp;
int codeline;
};
struct _a2 {
char *arg;
int codeline;
struct _a2 *next;
};
struct _a3 {
char *var;
int codeline;
is_arg_list *args;
is_single_exp_list *exp;
};
struct _a4 {
char *var;
is_single_exp *exp;
int codeline;
};
struct _a5 {
is_deflocal *def;
struct _a5 *next;
};
struct _a6 {
is_single_exp *test;
is_single_exp *return_true;
is_single_exp *return_false;
};
struct _a7 {
is_single_exp *test;
is_single_exp *return_true;
};
struct _a8 {
is_single_exp *exp;
struct _a8 *next;
};
struct _a9 {
char *var;
int codeline;
is_single_exp_list *exp;
};
struct _a10 {
is_op op;
is_single_exp_list *exp;
is_single_exp *exp_;
};
struct _a11 {
is_single_exp *exp;
struct _a11 *next;
};
#endif
functions.h:
#include
#include
#include "structures.h"
is_single_exp *insert_function_exp(is_function *exp);
is_single_exp *insert_number_exp(int number);
is_single_exp *insert_var_exp(int line, char *var);
is_function *insert_op_function(is_function_op *op);
is_function *insert_deflocal_function(is_function_deflocal *deflocal);
is_function *insert_defun_function(is_function_defun *defun);
is_function *insert_if_simp_function(is_function_if_simp *if_simp);
is_function *insert_if_comp_function(is_function_if_comp *if_comp);
is_function *insert_user_function(is_function_user *user);
is_function *insert_not_function(is_function_not *not);
is_function_not *insert_not_function_exp(is_function *function);
is_function_not *insert_not_number_exp(int number);
is_function_not *insert_not_var_exp(int line, char *var);
is_arg_list *insert_arg_list(int line, char *arg, is_arg_list *next);
is_function_defun *insert_function_defun(int line, char *var, is_arg_list *args, is_single_exp_list *exp);
is_deflocal *insert_deflocal(char *var, is_single_exp *exp, int line);
is_function_deflocal *insert_function_deflocal(is_deflocal *def, is_function_deflocal *next);
is_function_if_comp *insert_function_if_comp(is_single_exp *test, is_single_exp *return_true, is_single_exp *return_false);
is_function_if_simp *insert_function_if_simp(is_single_exp *test, is_single_exp *return_true);
is_single_exp_list *insert_single_exp_list(is_single_exp *exp, is_single_exp_list *next);
is_function_user *insert_function_user(int line, char *var, is_single_exp_list *exp);
is_function_op *insert_function_op(is_op op, is_single_exp_list *exp, is_single_exp *exp_);
is_statement *insert_statement(is_single_exp *exp, is_statement *next);
functions.c:
#include "functions.h"
is_single_exp *insert_function_exp(is_function *function)
{
is_single_exp *ise = (is_single_exp*) malloc(sizeof(is_single_exp));
ise->disc_se = d_function;
ise->data_exp.function = function;
return ise;
}
is_single_exp *insert_number_exp(int number)
{
is_single_exp *ise = (is_single_exp*) malloc(sizeof(is_single_exp));
ise->disc_se = d_NUMBER;
ise->data_exp.number = number;
return ise;
}
is_single_exp *insert_var_exp(int line, char *var)
{
is_single_exp *ise = (is_single_exp*) malloc(sizeof(is_single_exp));
ise->disc_se = d_VAR;
ise->data_exp.var = (char*) strdup(var);
ise->codeline = line;
return ise;
}
/* function structure */
is_function *insert_op_function(is_function_op *op)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_op;
is_f->data_exp.op = op;
return is_f;
}
is_function *insert_deflocal_function(is_function_deflocal *deflocal)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_deflocal;
is_f->data_exp.deflocal = deflocal;
return is_f;
}
is_function *insert_defun_function(is_function_defun *defun)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_defun;
is_f->data_exp.defun = defun;
return is_f;
}
is_function *insert_if_simp_function(is_function_if_simp *if_simp)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_if_simp;
is_f->data_exp.if_simp = if_simp;
return is_f;
}
is_function *insert_if_comp_function(is_function_if_comp *if_comp)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_if_comp;
is_f->data_exp.if_comp = if_comp;
return is_f;
}
is_function *insert_user_function(is_function_user *user)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_user;
is_f->data_exp.user = user;
return is_f;
}
is_function *insert_not_function(is_function_not *not)
{
is_function *is_f = (is_function*) malloc(sizeof(is_function));
is_f->disc_f = d_function_not;
is_f->data_exp.not = not;
return is_f;
}
/* Not */
is_function_not *insert_not_function_exp(is_function *function)
{
is_function_not *ifn = (is_function_not*) malloc(sizeof(is_function_not));
ifn->disc_fn = d_function;
ifn->data_exp.function = function;
return ifn;
}
is_function_not *insert_not_number_exp(int number)
{
is_function_not *ifn = (is_function_not*) malloc(sizeof(is_function_not));
ifn->disc_fn = d_NUMBER;
ifn->data_exp.number = number;
return ifn;
}
is_function_not *insert_not_var_exp(int line, char *var)
{
is_function_not *ifn = (is_function_not*) malloc(sizeof(is_function_not));
ifn->disc_fn = d_VAR;
ifn->data_exp.var = (char*) strdup(var);
ifn->codeline = line;
return ifn;
}
/* WTV */
is_arg_list *insert_arg_list(int line, char *arg, is_arg_list *next)
{
is_arg_list *ial = (is_arg_list*) malloc(sizeof(is_arg_list));
ial->arg = (char*) strdup(arg);
ial->codeline = line;
if (next == NULL)
return ial;
is_arg_list *aux;
for (aux = next; aux->next != NULL; aux = aux->next);
aux->next = ial;
return next;
}
is_function_defun *insert_function_defun(int line, char *var, is_arg_list *args, is_single_exp_list *exp)
{
is_function_defun *ifd = (is_function_defun*) malloc(sizeof(is_function_defun));
ifd->var = (char*) strdup(var);
ifd->args = args;
ifd->exp = exp;
ifd->codeline = line;
return ifd;
}
is_deflocal *insert_deflocal(char *var, is_single_exp *exp, int line)
{
is_deflocal *id = (is_deflocal*) malloc(sizeof(is_deflocal));
id->var = (char*) strdup(var);
id->exp = exp;
id->codeline = line;
return id;
}
is_function_deflocal *insert_function_deflocal(is_deflocal *def, is_function_deflocal *next)
{
is_function_deflocal *ifd = (is_function_deflocal*) malloc(sizeof(is_function_deflocal));
ifd->def = def;
if (next == NULL)
return ifd;
is_function_deflocal *aux;
for (aux = next; aux->next != NULL; aux = aux->next);
aux->next = ifd;
return next;
}
is_function_if_comp *insert_function_if_comp(is_single_exp *test, is_single_exp *return_true, is_single_exp *return_false)
{
is_function_if_comp *ific = (is_function_if_comp*) malloc(sizeof(is_function_if_comp));
ific->test = test;
ific->return_true = return_true;
ific->return_false = return_false;
return ific;
}
is_function_if_simp *insert_function_if_simp(is_single_exp *test, is_single_exp *return_true)
{
is_function_if_simp *ifis = (is_function_if_simp*) malloc(sizeof(is_function_if_simp));
ifis->test = test;
ifis->return_true = return_true;
return ifis;
}
is_single_exp_list *insert_single_exp_list(is_single_exp *exp, is_single_exp_list *next)
{
is_single_exp_list *isel = (is_single_exp_list*) malloc(sizeof(is_single_exp_list));
isel->exp = exp;
if (next == NULL)
return isel;
is_single_exp_list *aux;
for (aux = next; aux->next != NULL; aux = aux->next);
aux->next = isel;
return next;
}
is_function_user *insert_function_user(int line, char *var, is_single_exp_list *exp)
{
is_function_user *ifu = (is_function_user*) malloc(sizeof(is_function_user));
ifu->var = (char*) strdup(var);
ifu->exp = exp;
ifu->codeline = line;
return ifu;
}
is_function_op *insert_function_op(is_op op, is_single_exp_list *exp, is_single_exp *exp_)
{
is_function_op *ifo = (is_function_op*) malloc(sizeof(is_function_op));
ifo->op = op;
ifo->exp = exp;
ifo->exp_ = exp_;
return ifo;
}
is_statement *insert_statement(is_single_exp *exp, is_statement *next)
{
is_statement *is = (is_statement*) malloc(sizeof(is_statement));
is->exp = exp;
if (next == NULL)
return is;
is_statement *aux;
for (aux = next; aux->next != NULL; aux = aux->next);
aux->next = is;
return next;
}
Semântica:
Realiza a análise semântica, verificando se as variáveis são declaradas (se necessário), o nÃ,º de argumentos das funções corresponde, se estão a ser atribuidos valores às variáveis que são do mesmo tipo que as variáveis,... Caso haja um erro a função correspondente devolve-o.
symbol_table.h:
#ifndef _SYMBOL_TABLE_
#define _SYMBOL_TABLE_
typedef struct _t1 {
char *name;
int offset;
struct _t1 *next;
} table_element;
typedef struct _t3 {
char *name;
struct _t3 *next;
table_element *args;
table_element *locals;
} user_functions;
typedef struct _t4 {
user_functions *ufunctions;
table_element *global;
} prog_env;
#endif
semantic.h:
#include "structures.h"
#include "symbol_table.h"
#include
#include
#include
prog_env* semantic_analysis(is_statement *is);
void semantic_analysis_function(prog_env *pe, is_function *function);
void semantic_analysis_op(prog_env *pe, is_function_op *op);
void semantic_analysis_deflocal(prog_env *pe, is_function_deflocal *deflocal);
void semantic_analysis_vardeflocal(prog_env *pe, is_deflocal *def);
void semantic_analysis_defun(prog_env *pe, is_function_defun *defun);
void semantic_analysis_arg_list(is_arg_list *args);
void semantic_analysis_arg(int offset, char *arg, int line);
void semantic_analysis_if_simp(prog_env *pe, is_function_if_simp *if_simp);
void semantic_analysis_if_comp(prog_env *pe, is_function_if_comp *if_comp);
void semantic_analysis_user(prog_env *pe, is_function_user *user);
void semantic_analysis_not(prog_env *pe, is_function_not *not);
int semantic_analysis_single_exp_list(prog_env *pe, is_single_exp_list *isel);
void semantic_analysis_single_exp(prog_env *pe, is_single_exp *ise);
table_element* create_symbol(int offset, char* name);
table_element* lookup(table_element* table, char *str);
user_functions* lookup_uf(user_functions* table, char *str);
semantic.c:
#include "semantic.h"
// offsets global e de função (local)
int global_offset = 0;
int function_offset = 0;
int local_offset = 0;
// Flag para impedir defuns condicionais
int if_scope = 0;
// Função actual (ou NULL). Serve como flag para impedir defuns dentro de defuns
user_functions *flag_function = NULL;
prog_env* semantic_analysis(is_statement *is)
{
is_statement *aux;
prog_env *pe = (prog_env*) malloc(sizeof(prog_env));
// Precorre as funções uma a uma (statements)
for (aux = is; aux; aux = aux->next)
{
function_offset = 0;
semantic_analysis_single_exp(pe, aux->exp);
}
return pe;
}
void semantic_analysis_function(prog_env *pe, is_function *function)
{
is_function_op *op = function->data_exp.op;
is_function_defun *defun = function->data_exp.defun;
is_function_deflocal *deflocal = function->data_exp.deflocal;
is_function_if_simp *if_simp = function->data_exp.if_simp;
is_function_if_comp *if_comp = function->data_exp.if_comp;
is_function_user *user = function->data_exp.user;
is_function_not *not = function->data_exp.not;
switch (function->disc_f)
{
case d_function_op: semantic_analysis_op(pe, op); break;
case d_function_deflocal: semantic_analysis_deflocal(pe, deflocal); break;
case d_function_defun:
// Se já estamos a definir uma função... ou se a definição é condicional...
if (flag_function)
{
printf("Line: %d - Error: Defun inside a defun: %s.n", defun->codeline, defun->var);
successful_semantic = 0;
}
else if (if_scope)
{
printf("Line: %d - Error: Conditional defun: %s.n", defun->codeline, defun->var);
successful_semantic = 0;
}
else
semantic_analysis_defun(pe, defun);
break;
case d_function_if_simp: semantic_analysis_if_simp(pe, if_simp); break;
case d_function_if_comp: semantic_analysis_if_comp(pe, if_comp); break;
case d_function_user: semantic_analysis_user(pe, user); break;
case d_function_not: semantic_analysis_not(pe, not); break;
}
}
void semantic_analysis_op(prog_env *pe, is_function_op *op)
{
semantic_analysis_single_exp_list(pe, op->exp);
semantic_analysis_single_exp(pe, op->exp_);
}
void semantic_analysis_deflocal(prog_env *pe, is_function_deflocal *deflocal)
{
is_function_deflocal *aux;
for(aux = deflocal; aux; aux = aux->next)
semantic_analysis_vardeflocal(pe, aux->def);
}
void semantic_analysis_vardeflocal(prog_env *pe, is_deflocal *def)
{
table_element *te;
// Está dentro de um defun?
if (flag_function)
{
// Já há variáveis na tabela?
if (flag_function->locals)
{
// Já está definida?
if (!lookup(flag_function->locals, def->var))
{
for (te = flag_function->locals; te->next; te = te->next);
te->next = create_symbol(local_offset++, def->var);
}
}
else
flag_function->locals = create_symbol(local_offset++, def->var);
}
else
{
// Já há variáveis na tabela?
if (pe->global)
{
// Já está definida?
if (!lookup(pe->global, def->var))
{
for (te = pe->global; te->next; te = te->next);
te->next = create_symbol(global_offset++, def->var);
}
}
else
pe->global = create_symbol(global_offset++, def->var);
}
semantic_analysis_single_exp(pe, def->exp);
}
void semantic_analysis_defun(prog_env *pe, is_function_defun *defun)
{
user_functions *aux_uf;
table_element *aux;
flag_function = lookup_uf(pe->ufunctions, defun->var);
if (flag_function)
{
// Se a função existir, dá erro.
printf("Line: %d - Error: Function already defined: %s.n", defun->codeline, defun->var);
successful_semantic = 0;
flag_function = NULL;
return;
}
else
// Se não existir, aloca espaço na memória para o criar
flag_function = (user_functions*) malloc(sizeof(user_functions));
flag_function->name = (char*) strdup(defun->var);
// Adiciona a função àlista de funções (ufunctions) do ambiente do programa (prog_env)
if (pe->ufunctions == NULL)
pe->ufunctions = flag_function;
else
{
for (aux_uf = pe->ufunctions; aux_uf->next; aux_uf = aux_uf->next);
aux_uf->next = flag_function;
}
semantic_analysis_arg_list(defun->args);
semantic_analysis_single_exp_list(pe, (is_single_exp_list*) defun->exp);
flag_function = NULL;
local_offset = 0;
}
void semantic_analysis_arg_list(is_arg_list *args)
{
is_arg_list *aux;
for (aux = args; aux; aux = aux->next)
semantic_analysis_arg(function_offset++, aux->arg, aux->codeline);
}
// Os argumentos apenas existem em defuns, logo flag_function não pode ser NULL
// Como os argumentos são as primeiras variáveis de um defun a serem adicionadas é possÃÂvel impedir
// repetições de nomes de argumentos na lista de argumentos apenas verificando se na lista de variáveis
// da função ela já existe ou não.
// De resto é possÃÂvel alterar o valor de uma argumento, dentro da função.
void semantic_analysis_arg(int offset, char *arg, int line)
{
table_element *aux;
// Verifica se já existe uma variável com o mm nome, rejeita
if (lookup(flag_function->args, arg))
{
printf("Line: %d - Error: Argument "%s" already defined.n", line, arg);
successful_semantic = 0;
}
else
// Se a tabela não está vazia...
if (flag_function->args)
{
for (aux = flag_function->args; aux->next; aux = aux->next);
aux->next = create_symbol(offset, arg);
}
else
flag_function->args = create_symbol(offset, arg);
}
// É possÃÂvel a condição de teste de um if ser um defun, mas não é possÃÂvel a existência de defuns
// condicionais (dentro dos campos de resultados).
void semantic_analysis_if_simp(prog_env *pe, is_function_if_simp *if_simp)
{
semantic_analysis_single_exp(pe, if_simp->test);
if_scope++;
semantic_analysis_single_exp(pe, if_simp->return_true);
if_scope--;
}
void semantic_analysis_if_comp(prog_env *pe, is_function_if_comp *if_comp)
{
semantic_analysis_single_exp(pe, if_comp->test);
if_scope++;
semantic_analysis_single_exp(pe, if_comp->return_true);
semantic_analysis_single_exp(pe, if_comp->return_false);
if_scope--;
}
void semantic_analysis_user(prog_env *pe, is_function_user *user)
{
int given_args, function_args = 0;
user_functions *uf = lookup_uf(pe->ufunctions, user->var);
table_element *te;
// Verifica se existe a função na tabela user_functions
if (!uf)
{
printf("Line: %d - Error: Unknown function: %s.n", user->codeline, user->var);
successful_semantic = 0;
}
else
{
given_args = semantic_analysis_single_exp_list(pe, user->exp);
for (te = uf->args; te; te = te->next)
function_args++;
if (given_args != function_args)
{
printf("Line: %d - Error: Function "%s" has an incorrect number of arguments: %d given, %d needed.n", user->codeline, user->var, given_args, function_args);
successful_semantic = 0;
}
}
}
void semantic_analysis_not(prog_env *pe, is_function_not *not)
{
// Vai ver que tipo de expressão é (função, variável ou número)
// Os números são imediatamente aceites
// Se for uma função, analiza a função, mas dá-lhe um scope local
// Se for uma variável, verifica se está numa das tabelas (global ou local)
if (not->disc_fn == d_function)
{
semantic_analysis_function(pe, not->data_exp.function);
}
else if (not->disc_fn == d_VAR)
{
// Verifica se a variável está na tabela local, caso esteja num defun
// Caso negativo, verifica se está na tabela global
// Caso negativo, mostra a mensagem de erro
if (flag_function)
if (flag_function->locals || flag_function->args)
if (lookup(flag_function->locals, not->data_exp.var) || lookup(flag_function->args, not->data_exp.var))
return;
if (!lookup(pe->global, not->data_exp.var))
{
printf("Line: %d - Error: Unknown variable: %s.n", not->codeline, not->data_exp.var);
successful_semantic = 0;
}
}
}
int semantic_analysis_single_exp_list(prog_env *pe, is_single_exp_list *isel)
{
is_single_exp_list *aux;
int count = 0;
for (aux = isel; aux; aux = aux->next) {
semantic_analysis_single_exp(pe, aux->exp);
count++;
}
return count;
}
void semantic_analysis_single_exp(prog_env *pe, is_single_exp *ise)
{
// Vai ver que tipo de expressão é
// Os números são imediatamente aceites
// Se for uma função, analiza a função, mas dá-lhe um scope de 1 para evitar defuns dentro de outras funções
// Se for uma variável, verifica se está numa das tabelas (global ou local)
if (ise->disc_se == d_function)
{
semantic_analysis_function(pe, ise->data_exp.function);
}
else if (ise->disc_se == d_VAR)
{
// Verifica se a variável está na tabela local, caso esteja num defun
// Caso negativo, verifica se está na tabela global
// Caso negativo, mostra a mensagem de erro
if (flag_function)
if (flag_function->locals || flag_function->args)
if (lookup(flag_function->locals, ise->data_exp.var) || lookup(flag_function->args, ise->data_exp.var))
return;
if (!lookup(pe->global, ise->data_exp.var))
{
printf("Line: %d - Error: Unknown variable: %s.n", ise->codeline, ise->data_exp.var);
successful_semantic = 0;
}
}
}
table_element* create_symbol(int offset, char* name)
{
table_element *elem = (table_element*) malloc(sizeof(table_element));
elem->name = strdup(name);
elem->next = NULL;
elem->offset = offset;
return elem;
}
table_element* lookup(table_element* table, char *str)
{
table_element *aux;
for (aux = table; aux; aux = aux->next)
if (strcmp(aux->name, str) == 0)
return aux;
return 0;
}
user_functions* lookup_uf(user_functions* table, char *str)
{
user_functions *aux;
for (aux = table; aux; aux = aux->next)
if (strcmp(aux->name, str) == 0)
return aux;
return 0;
}
Tradução:
Realiza a tradução do código em C (neste caso, por ser um cross-compiler para C). A conversão é feita para um C muito simplificado (extremamente semelhante a código assembly). Pode-se observar que cada instução em C corresponde práticamente a uma instrução assembly.
translation.h:
#include "symbol_table.h"
#include "structures.h"
#include "semantic.h"
#include
void translate(is_statement *stat, prog_env *pe);
void translate_header(FILE *dest);
void translate_statement(FILE *dest, prog_env *pe, is_statement *is);
void translate_function(FILE *dest, prog_env *pe, is_function *function);
void translate_defun(FILE *dest, prog_env *pe, is_function_defun *defun);
void translate_op(FILE *dest, prog_env *pe, is_function_op *op, is_function_if_simp *if_simp, is_function_if_comp *if_comp);
void translate_deflocal(FILE *dest, prog_env *pe, is_function_deflocal *deflocal);
void translate_vardeflocal(FILE *dest, prog_env *pe, is_deflocal *def);
void translate_if_simp(FILE *dest, prog_env *pe, is_function_if_simp *if_simp);
void translate_if_comp(FILE *dest, prog_env *pe, is_function_if_comp *if_comp);
void translate_user(FILE *dest, prog_env *pe, is_function_user *user);
void translate_not(FILE *dest, prog_env *pe, is_function_not *not, is_function_if_simp *if_simp, is_function_if_comp *if_comp);
void translate_single_exp(FILE *dest, prog_env *pe, is_single_exp *ise, int backup);
void translate_footer(FILE *dest);
void translate_redirector(FILE *dest);
void translate_simple_if_simp(FILE *dest, prog_env *pe, is_function_if_simp *if_simp);
void translate_simple_if_comp(FILE *dest, prog_env *pe, is_function_if_comp *if_comp);translation.c:
[code]
#include "translation.h"
// Função actual...
user_functions *current_function_def;
user_functions *current_function_defun;
int return_counter;
int branch_counter_global;
int if_expr;
void translate(is_statement *stat, prog_env *pe)
{
current_function_def = NULL;
current_function_defun = NULL;
return_counter = 0;
branch_counter_global = 0;
if_expr = 0;
FILE *dest;
dest = fopen("result.c", "w");
translate_header(dest);
translate_statement(dest, pe, stat);
translate_footer(dest);
fclose(dest);
}
void translate_header(FILE *dest)
{
fprintf(dest, "#include "frame.h"n");
fprintf(dest, "#include
n");
fprintf(dest, "#include nn");
fprintf(dest, "int main()n{n");
fprintf(dest, "tint _ra;n");
fprintf(dest, "tframe *gp, *sp, *fp;n");
// Registos
fprintf(dest, "tint _r6, _r7;nn");
// Frames
fprintf(dest, "tgp = (frame*) malloc(sizeof(frame));n");
fprintf(dest, "tfp = gp;n");
fprintf(dest, "tsp = gp;nn");
fprintf(dest, "tgp->current_backup = 0;nn");
}
void translate_statement(FILE *dest, prog_env *pe, is_statement *is)
{
is_statement *aux;
for (aux = is; aux; aux = aux->next) {
translate_single_exp(dest, pe, aux->exp, 0);
fprintf(dest, "tprintf("%%d\\n", _r7);n");
}
}
void translate_function(FILE *dest, prog_env *pe, is_function *function)
{
is_function_op *op = function->data_exp.op;
is_function_defun *defun = function->data_exp.defun;
is_function_deflocal *deflocal = function->data_exp.deflocal;
is_function_if_simp *if_simp = function->data_exp.if_simp;
is_function_if_comp *if_comp = function->data_exp.if_comp;
is_function_user *user = function->data_exp.user;
is_function_not *not = function->data_exp.not;
switch (function->disc_f)
{
case d_function_op: translate_op(dest, pe, op, NULL, NULL); break;
case d_function_deflocal: translate_deflocal(dest, pe, deflocal); break;
case d_function_defun: translate_defun(dest, pe, defun); break;
case d_function_if_simp: translate_if_simp(dest, pe, if_simp); break;
case d_function_if_comp: translate_if_comp(dest, pe, if_comp); break;
case d_function_user: translate_user(dest, pe, user); break;
case d_function_not: translate_not(dest, pe, not, NULL, NULL); break;
}
}
void translate_defun(FILE *dest, prog_env *pe, is_function_defun *defun)
{
fprintf(dest, "tgoto %s_skip;nn", defun->var);
fprintf(dest, "%s:n", defun->var);
fprintf(dest, "tfp = sp;n");
fprintf(dest, "tsp = (frame*) malloc(sizeof(frame));n");
fprintf(dest, "tsp->parent = fp;n");
fprintf(dest, "tsp->current_backup = 0;n");
fprintf(dest, "tsp->return_addr = _ra;n");
current_function_defun = lookup_uf(pe->ufunctions, defun->var);
is_single_exp_list *aux;
for (aux = defun->exp; aux; aux = aux->next)
translate_single_exp(dest, pe, aux->exp, 0);
current_function_defun = NULL;
fprintf(dest, "t_ra = sp->return_addr;n");
fprintf(dest, "tsp = sp->parent;n");
fprintf(dest, "tif (sp->parent) fp = sp->parent;n");
fprintf(dest, "tgoto REDIRECTOR;nn");
fprintf(dest, "%s_skip:n", defun->var);
fprintf(dest, "t_r7 = 0;n", defun->var);
}
// BRB
void translate_op(FILE *dest, prog_env *pe, is_function_op *op, is_function_if_simp *if_simp, is_function_if_comp *if_comp)
{
is_single_exp_list *aux = op->exp;
int branch_counter = branch_counter_global++;
translate_single_exp(dest, pe, aux->exp, 0);
switch (op->op)
{
case is_SOMA:
case is_SUB:
case is_MULT:
case is_DIV:
case is_MAIOR:
case is_MENOR:
case is_MAIOR_IGUAL:
case is_MENOR_IGUAL:
case is_IGUAL:
case is_XOR:
fprintf(dest, "t_r6 = _r7;n");
break;
case is_AND: fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter); break;
case is_OR: fprintf(dest, "tif (_r7) goto IF%dT;n", branch_counter); break;
}
for (aux = aux->next; aux; aux = aux->next)
{
translate_single_exp(dest, pe, aux->exp, 1);
switch (op->op)
{
case is_SOMA: fprintf(dest, "t_r6 = _r6 + _r7;n"); break;
case is_SUB: fprintf(dest, "t_r6 = _r6 - _r7;n"); break;
case is_MULT: fprintf(dest, "t_r6 = _r6 * _r7;n"); break;
case is_DIV: fprintf(dest, "t_r6 = _r6 / _r7;n"); break;
case is_MAIOR:
fprintf(dest, "t_r6 = _r6 > _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
break;
case is_MENOR:
fprintf(dest, "t_r6 = _r6 < _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
break;
case is_MAIOR_IGUAL:
fprintf(dest, "t_r6 = _r6 >= _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
break;
case is_MENOR_IGUAL:
fprintf(dest, "t_r6 = _r6 <= _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
break;
case is_IGUAL: fprintf(dest, "tif (_r6 != _r7) goto IF%dF;n", branch_counter); break;
case is_AND: fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter); break;
case is_OR: fprintf(dest, "tif (_r7) goto IF%dT;n", branch_counter); break;
case is_XOR:
fprintf(dest, "t_r7 = _r7 && _r6;n");
fprintf(dest, "tif (_r7) goto IF%dF;n", branch_counter);
fprintf(dest, "tif (_r7) _r6 = _r7;n", branch_counter);
break;
}
}
translate_single_exp(dest, pe, op->exp_, 1);
switch (op->op)
{
case is_SOMA: fprintf(dest, "t_r7 = _r6 + _r7;n"); break;
case is_SUB: fprintf(dest, "t_r7 = _r6 - _r7;n"); break;
case is_MULT: fprintf(dest, "t_r7 = _r6 * _r7;n"); break;
case is_DIV: fprintf(dest, "t_r7 = _r6 / _r7;n"); break;
case is_MAIOR:
fprintf(dest, "t_r7 = _r6 > _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_MENOR:
fprintf(dest, "t_r7 = _r6 < _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_MAIOR_IGUAL:
fprintf(dest, "t_r7 = _r6 >= _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_MENOR_IGUAL:
fprintf(dest, "t_r7 = _r6 <= _r7;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_IGUAL:
fprintf(dest, "tif (_r6 != _r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_AND:
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
case is_OR:
fprintf(dest, "tif (_r7) goto IF%dT;n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "tgoto IF%dF;n", branch_counter);
fprintf(dest, "IF%dT:n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "IF%dF:n", branch_counter);
break;
case is_XOR:
fprintf(dest, "t_r7 = _r7 && _r6;n");
fprintf(dest, "tif (_r7) goto IF%dF;n", branch_counter);
fprintf(dest, "t_r7 = _r7 || _r6;n");
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
break;
}
}
void translate_deflocal(FILE *dest, prog_env *pe, is_function_deflocal *deflocal)
{
is_function_deflocal *aux;
for(aux = deflocal; aux; aux = aux->next)
translate_vardeflocal(dest, pe, aux->def);
fprintf(dest, "t_r7 = 0;n");
}
void translate_vardeflocal(FILE *dest, prog_env *pe, is_deflocal *def)
{
table_element *te;
if (current_function_defun)
{
te = lookup(current_function_defun->locals, def->var);
if (te)
{
translate_single_exp(dest, pe, def->exp, 0);
fprintf(dest, "tsp->locals[%d] = _r7;n", te->offset);
}
else
{
te = lookup(pe->global, def->var);
translate_single_exp(dest, pe, def->exp, 0);
fprintf(dest, "tgp->locals[%d] = _r7;n", te->offset);
}
}
else if (current_function_def)
{
te = lookup(current_function_def->locals, def->var);
if (te)
{
translate_single_exp(dest, pe, def->exp, 0);
fprintf(dest, "tsp->locals[%d] = _r7;n", te->offset);
}
else
{
te = lookup(pe->global, def->var);
translate_single_exp(dest, pe, def->exp, 0);
fprintf(dest, "tgp->locals[%d] = _r7;n", te->offset);
}
}
else
{
te = lookup(pe->global, def->var);
translate_single_exp(dest, pe, def->exp, 0);
fprintf(dest, "tgp->locals[%d] = _r7;n", te->offset);
}
}
void translate_if_simp(FILE *dest, prog_env *pe, is_function_if_simp *if_simp)
{
is_function *function = NULL;
if (if_simp->test->disc_se == d_function)
{
function = if_simp->test->data_exp.function;
if (function->disc_f == d_function_not)
translate_not(dest, pe, function->data_exp.not, if_simp, NULL);
else if (function->disc_f == d_function_op)
{
switch (function->data_exp.op->op)
{
case is_MAIOR:
case is_MENOR:
case is_MAIOR_IGUAL:
case is_MENOR_IGUAL:
case is_IGUAL:
case is_AND:
case is_OR:
case is_XOR:
translate_op(dest, pe, function->data_exp.op, if_simp, NULL); break;
default:
translate_simple_if_simp(dest, pe, if_simp);
}
}
else
translate_simple_if_simp(dest, pe, if_simp);
}
else
translate_simple_if_simp(dest, pe, if_simp);
}
void translate_simple_if_simp(FILE *dest, prog_env *pe, is_function_if_simp *if_simp)
{
int branch_counter = branch_counter_global++;
translate_single_exp(dest, pe, if_simp->test, 0);
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
translate_single_exp(dest, pe, if_simp->return_true, 0);
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
}
void translate_if_comp(FILE *dest, prog_env *pe, is_function_if_comp *if_comp)
{
is_function *function = NULL;
if (if_comp->test->disc_se == d_function)
{
function = if_comp->test->data_exp.function;
if (function->disc_f == d_function_not)
translate_not(dest, pe, function->data_exp.not, NULL, if_comp);
else if (function->disc_f == d_function_op)
{
switch (function->data_exp.op->op)
{
case is_MAIOR:
case is_MENOR:
case is_MAIOR_IGUAL:
case is_MENOR_IGUAL:
case is_IGUAL:
case is_AND:
case is_OR:
case is_XOR:
translate_op(dest, pe, function->data_exp.op, NULL, if_comp); break;
default:
translate_simple_if_comp(dest, pe, if_comp);
}
}
else
translate_simple_if_comp(dest, pe, if_comp);
}
else
translate_simple_if_comp(dest, pe, if_comp);
}
void translate_simple_if_comp(FILE *dest, prog_env *pe, is_function_if_comp *if_comp)
{
int branch_counter = branch_counter_global++;
translate_single_exp(dest, pe, if_comp->test, 0);
fprintf(dest, "tif (!_r7) goto IF%dF;n", branch_counter);
translate_single_exp(dest, pe, if_comp->return_true, 0);
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
translate_single_exp(dest, pe, if_comp->return_false, 0);
fprintf(dest, "IF%dT:n", branch_counter);
}
void translate_user(FILE *dest, prog_env *pe, is_function_user *user)
{
current_function_def = lookup_uf(pe->ufunctions, user->var);
// Colocar argumentos no outgoing da frame actual.
is_single_exp_list *aux;
int offset = 0;
for (aux = user->exp; aux; aux = aux->next) {
translate_single_exp(dest, pe, aux->exp, 0);
fprintf(dest, "tsp->outgoing[%d] = _r7;n", offset++);
}
// Ir para o código da função.
fprintf(dest, "t_ra = %d;n", return_counter);
fprintf(dest, "tgoto %s;nn", user->var);
fprintf(dest, "RETURN%d:n", return_counter);
return_counter++;
current_function_def = NULL;
}
void translate_not(FILE *dest, prog_env *pe, is_function_not *not, is_function_if_simp *if_simp, is_function_if_comp *if_comp)
{
table_element *te;
int branch_counter = branch_counter_global++;
switch (not->disc_fn)
{
case d_function:
translate_function(dest, pe, not->data_exp.function);
break;
case d_VAR:
if (current_function_defun)
{
te = lookup(current_function_defun->locals, not->data_exp.var);
if (te)
{
fprintf(dest, "t_r7 = sp->locals[%d];n", te->offset);
}
else
{
te = lookup(current_function_defun->args, not->data_exp.var);
if (te)
{
fprintf(dest, "t_r7 = fp->outgoing[%d];n", te->offset);
}
else
{
te = lookup(pe->global, not->data_exp.var);
fprintf(dest, "t_r7 = gp->locals[%d];n", te->offset);
}
}
}
else if (current_function_def)
{
te = lookup(current_function_def->locals, not->data_exp.var);
if (te)
{
fprintf(dest, "t_r7 = sp->locals[%d];n", te->offset);
}
else
{
te = lookup(pe->global, not->data_exp.var);
fprintf(dest, "t_r7 = sp->locals[%d];n", te->offset);
}
}
else
{
te = lookup(pe->global, not->data_exp.var);
fprintf(dest, "t_r7 = sp->locals[%d];n", te->offset);
}
break;
case d_NUMBER: fprintf(dest, "t_r7 = %d;n", not->data_exp.number); break;
}
fprintf(dest, "tif (_r7) goto IF%dF;n", branch_counter);
if (if_simp || if_comp)
{
if (if_simp)
translate_single_exp(dest, pe, if_simp->return_true, 0);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_true, 0);
}
else
fprintf(dest, "t_r7 = 1;n");
fprintf(dest, "tgoto IF%dT;n", branch_counter);
fprintf(dest, "IF%dF:n", branch_counter);
if (if_comp)
translate_single_exp(dest, pe, if_comp->return_false, 0);
else
fprintf(dest, "t_r7 = 0;n");
fprintf(dest, "IF%dT:n", branch_counter);
}
void translate_single_exp(FILE *dest, prog_env *pe, is_single_exp *ise, int backup)
{
table_element *te;
switch (ise->disc_se)
{
case d_function:
if (backup)
{
fprintf(dest, "tsp->register_backup[sp->current_backup] = _r6;n");
fprintf(dest, "tsp->current_backup++;n");
}
translate_function(dest, pe, ise->data_exp.function);
if (backup)
{
Frame:
Sendo isto um cross-compiler, é necessário um ficheiro extra que representa a memória no assembly. Este ficheiro é necessário para compilar o result.c (ficheiro com o resultado da compilação).
frame.h:
typedef struct _f1 {
struct _f1* parent;
int return_addr;
int current_backup;
int register_backup[128];
int locals[64];
int outgoing[32];
} frame;
Quote from: KhAoTiK_TaChYoNPara algumas (ou uma) pessoa que não acredita que neste forum àpessoas capazes de criar um compilador
[/quote]
Todo mundo é capaz para fazer tal ato, mas tem que estudar é claro.
Enquanto ao compilador, parabéns!