95
Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1 : Domanda relativa alle esercitazioni 05/02/2008 COGNOME: ............................................................. NOME: .......................................... Matricola: ............. Iscritto a: Laurea Specialistica V. O. Laurea Triennale Al- tro:..... Sezione: Prof. Breveglieri Prof. Crespi Prof.Morzenti Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’implementazione del compilatore Acse che viene fornita insieme al compito. Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex, quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengono necessarie delle modifiche in modo da estendere il compilatore Acse con la possibilit`a di gestire un costrutto iterativo di tipo per ogni, del quale viene qui fornito un esempio. int a[100]; int x; int y; ... for(x:a){ y=y+x; } write( y ); ... Questo tipo di costrutto for non eplicita l’indice del vettore. Alla prima itera- zione la variabile x vale a[0], alla seconda a[1] e cos` ı via per tutti gli elementi di a. Nell’esempio sopra, il frammento calcola e stampa la somma di tutti gli elementi di a. Le modifiche devono mettere il compilatore Acse in condizione di analizzare la correttezza sintattica dei costrutti sopra descritti e di generare una traduzione corretta nel linguaggio assembler della macchina Mace. Per risolvere il problema si consiglia di utilizzare la funzione getNewRegister di axe engine.[h,c], la quale restituisce il numero di un registro (del banco di registri infinito) non ancora assegnato. /* get a register still not used. This function returns 1 Tempo 45’. Libri e appunti personali possono essere consultati. ` E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi. 1 * the ID of the register found */ int getNewRegister(t_program_infos *program); 2

Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Embed Size (px)

Citation preview

Page 1: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, MorzentiProva scritta1: Domanda relativa alle esercitazioni

05/02/2008

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro:.....Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire un costrutto iterativo di tipo per ogni, del quale viene quifornito un esempio.

int a[100];

int x;

int y;

...

for(x:a){

y = y + x;

}

write( y );

...

Questo tipo di costrutto for non eplicita l’indice del vettore. Alla prima itera-zione la variabile x vale a[0], alla seconda a[1] e cosı via per tutti gli elementi dia. Nell’esempio sopra, il frammento calcola e stampa la somma di tutti gli elementidi a.

Le modifiche devono mettere il compilatore Acse in condizione di analizzarela correttezza sintattica dei costrutti sopra descritti e di generare una traduzionecorretta nel linguaggio assembler della macchina Mace.

Per risolvere il problema si consiglia di utilizzare la funzione getNewRegister

di axe engine.[h,c], la quale restituisce il numero di un registro (del banco diregistri infinito) non ancora assegnato.

/* get a register still not used. This function returns

1Tempo 45’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

* the ID of the register found */

int getNewRegister(t_program_infos *program);

2

Page 2: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta.

Il token for, l’unico nuovo rispetto al linguaggio, e gia definitosia in Acse.lex che Acse.y.

2. Definire le regole sintattiche necessarie per ottenere la funzionalita richiesta.

Si definisce una regola per il nuovo costrutto

foreach statement : FOR LPAR IDENTIFIER COLONIDENTIFIER RPAR code block ;

che va inserito come alternativa per control statement :

control statement : . . .| foreach statement

;

3. Definire le modifiche alle strutture dati (se necessarie) per supportate lafunzionalita richiesta.

In axe struct.h:

typedef struct {

t_axe_label *label; /* Label at the beginning

of the loop */

int index; /* Register for the index */

int length; /* Array length */

} t_foreach_statement;

In Acse.y:

%token <foreach_stmt> FOR

%union {

...

t_foreach_statement foreach_stmt;

}

3

4. Definire le azioni semantiche necessarie per ottenere la funzionalita richiesta.

foreach statement : FOR LPAR IDENTIFIER COLONIDENTIFIER RPAR

{

int loopvar, tempreg; /* Registers */

t_axe_variable *looparray;

t_axe_expression expr;

loopvar = get_symbol_location( program, $3, 0 );

looparray = getVariable( program, $5 );

if (! looparray->isArray) {

fprintf( stderr, "Variable %s is not an array\n",

looparray->ID );

notifyError( -1 );

}

$1.index = getNewRegister( program );

$1.length = looparray->arraySize;

/* index = 0; */

gen_add_instruction( program, $1.index, REG_0, REG_0,

CG_DIRECT_ALL );

/* var = array[index]; */

$1.label = assignNewLabel( program );

expr = create_expression ( $1.index, REGISTER);

tempreg = loadArrayElement( program, $5, expr );

gen_add_instruction( program, loopvar, REG_0, tempreg,

CG_DIRECT_ALL );

free( $3 );

free( $5 );

}

code block

{

int reg;

/* index = index + 1; */

gen_addi_instruction( program, $1.index, $1.index, 1 );

/* reg = index - array_length; */

reg = getNewRegister( program );

gen_subi_instruction( program, reg, $1.index, $1.length );

/* BLT beginning; */

gen_blt_instruction( program, $1.label, 0 );

}

;

4

Page 3: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Il codice generato crea una variabile temporanea in un registro(campo index della struttura) che viene fatto variare su tutti ivalori legatli per l’indice dell’array. Il codice

for (var : array) {/* body */

}

viene tradotto in (usando un misto di pseudo-codice e assembly):

index := 0label :

var := array[index]/* body */index := index + 1index - array lengthBLT label

dove index e la variabile temporanea descritta prima, e array length

e la lunghezza dell’array. Si noti che il risultato della sottrazioneviene in realta assegnato a un registro temporaneo.

5. Bonus (da svolgersi solo a termine dei punti precedenti). Si vieti qualsiasiassegnamento alla variabile di induzione (x, nell’esempio) all’interno del corpodel ciclo.

Viene brevemente descritto lo schema di una possibile soluzio-ne.

Si crea una lista globale, inizialmente vuota, i cui nodi con-tengono ognuno un identificatore (una stringa). Prima del corpodel ciclo for, cioe nella prima azione semantica al punto preceden-te, si aggiunge un nodo alla lista contente il nome della variabiledi ciclo ($3); mentre alla fine di ogni ciclo, nella seconda azionesemantica, si elimina tale nodo. Questa lista permette di avere di-sponibili ovunque le informazioni sulle variabili di ciclo a un datopasso della traduzione.

Va quindi aggiunto un controllo nelle azioni semantiche dellaregole gia esistenti

assign statement : IDENTIFIER ASSIGN exp ;read statement : READ LPAR IDENTIFIER RPAR ;

che verifichi che IDENTIFIER non sia presente nella lista, e generiun errore in caso contrario. Un analogo controllo va fatto nellaprima azione semantica del ciclo for, per evitare che due cicli for

innestati utilizzino la stessa variabile di ciclo.

5

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question - ACSE05/03/2008

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof. Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to handle a new construct switch resembling the one inthe following sample.

int a;

...

switch (a) {

case 0:

...

break;

case 1:

... /* Code block without any "break" statement */

case 2:

...

break;

default:

...

}

...

The switch construct is built out of an arbitrary number of case blocks andmay include an optional default block. The switch construct has the followingsemantics: the value of the variable between round brackets is checked for a matchagainst the values indicated in the case statements. On a successful match, thecorresponding code block is executed. The break statement brings the executionto the first instruction after the switch construct. In case a code block does notcontain any break statement, the next case block (in declaration order) is executed.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

Page 4: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

If there are no more case blocks left, the code must exit the switch construct. Ifthere is no match between the switch variable and the case values, the executionflow jumps to the default block (if present) or exits from the switch construct.At least a case block has to be declared. Switch blocks may be nested.

For instance: if we assign the value 0 to the variable a in the example, only thefirst code block (the one corresponding to case 0) will be ran. In case a evaluatesas 1, the blocks related to both case 1 and case 2 will be executed. In case thevalue of a differs from 0, 1, 2 the execution jumps to the default block.

Your modifications have to allow the Acse compiler to both correctly analyze thesyntactical correctness of the aforementioned constructs and to generate a correcttranslation in the Mace assembly language.

2

The first step, before answering any question, is to devise a translationof the new construct into the assembly language. The solution chosen ispresented in the following schema:

switch (var) { ADDI Ry var reg ♯0BT begin test

case const1: begin case1:. . . . . .break; BT switch end

case const2: begin case2:. . . . . ./* Block with no break */

case const3: begin case3:. . . . . .break; BT switch end

default: default label:. . . . . .

} BT switch endbegin test:

SUBI Rz Ry const1

BEQ begin case1SUBI Rz Ry const2

BEQ begin case2SUBI Rz Ry const3

BEQ begin case3BT default label

switch end:

where Rz and Ry are two temporary registers. In order to produce such atranslation, we have to accumulate information about the various cases insome structures and finally produce the code between the labels begin test

and switch end. switch constructs can be nested, therefore those struc-tures should be contained in a global stack.

3

Page 5: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Define the tokens and the Acse.lex and Acse.y declarations needed toachieve the required functionality. (3 points)

In Acse.lex:

"switch" { return SWITCH; }

"break" { return BREAK; }

"case" { return CASE; }

"default" { return DEFAULT; }

In Acse.y:

%token SWITCH

%token BREAK

%token CASE

%token DEFAULT

4

2. Define the syntactic rules needed to achieve the required functionality. (8 points)

The switch construct is generated by the new non-terminal switch statement,which is expanded by a few new rules:

switch statement : SWITCH LPAR IDENTIFIER RPARLBRACE switch block RBRACE ;

switch block : case statements| case statements default statement ;

case statements : case statements case statement| case statement

;

case statement : CASE NUMBER COLON statements ;

default statement : DEFAULT COLON statements ;

switch statement is added as a new possibility for the non-terminalcontrol statement; moreover, the break statement must be added asa possible statement:

control statement : . . .| break statement SEMI| switch statement

;

break statement : BREAK ;

Please notice that the break statement is an ordinary statement,which could be appear anywhere, even inside an if construct forexample. A semantic check will be provided to avoid that a break

appears outside any switch.

5

Page 6: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Define the semantic actions needed to achieve the required functionality,without considering the break and default statements. (10 points)

We have to define a few structures in axe struct.h:

typedef struct

{

t_axe_label *begin_case_label;

int number;

} t_case_statement;

typedef struct

{

int cmp_register;

t_list *cases; /* List of t_case_statement elements;

* each element contains the constant

* number and the label for a case */

t_axe_label *switch_end; /* Label of the end of the

* switch construct */

t_axe_label *begin_test; /* Label of the tests */

} t_switch_statement;

and in Acse.y:

%{

...

t_list *switchStack = NULL; /* Elements are of type

* t_switch_statement */

%}

%union {

...

t_switch_statement *switch_stmt;

}

%token <switch_stmt> SWITCH

The stack for the switch structures uses the functions contained incollections.h.

6

The semantic actions that produce the above translation:

switch_statement : SWITCH LPAR IDENTIFIER RPAR LBRACE

{

$1 = (t_switch_statement *)malloc(

sizeof(t_switch_statement));

$1->cmp_register = getNewRegister(program);

gen_addi_instruction(program, $1->cmp_register,

get_symbol_location(program,$3,0), 0);

$1->begin_test = reserveLabel(program);

$1->switch_end = reserveLabel(program);

switchStack = addFirst(switchStack, $1); // PUSH

gen_bt_instruction(program, $1->begin_test, 0);

}

switch_block RBRACE

{

t_list *p;

int cmpReg; // This is the Rz register above

fixLabel(program, $1->begin_test);

cmpReg = getNewRegister(program);

p = $1->cases;

while (p!=NULL) {

gen_subi_instruction(program, cmpReg,

$1->cmp_register,

((t_case_statement *)p->data)->number);

gen_beq_instruction(program,

((t_case_statement *)p->data)

->begin_case_label, 0);

p = p->next;

}

fixLabel(program,$1->switch_end);

switchStack = removeFirst(switchStack); // POP

}

;

switch_block : case_statements

{

gen_bt_instruction(program,

((t_switch_statement *)LDATA(

getFirst(switchStack)))->switch_end, 0);

}

;

7

Page 7: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

case_statement: CASE NUMBER COLON

{

t_case_statement *c = (t_case_statement *)

malloc(sizeof(t_case_statement));

c->number = $2;

c->begin_case_label = assignNewLabel(program);

((t_switch_statement *)LDATA(

getFirst(switchStack)))->cases =

addLast(((t_switch_statement *)LDATA(

getFirst(switchStack)))->cases, c);

}

statements

;

8

4. Define the semantic actions needed to handle the optional default block.(6 points)

The structure in axe struct.h must be extended with a new field:

typedef struct

{

...

t_axe_label *default_label; /* Label of the default

* block (can be NULL) */

} t_switch_statement;

The actions for the rules related to the default block:

switch_block : ...

| case_statements default_statement

{

gen_bt_instruction(program,

((t_switch_statement *)LDATA(

getFirst(switchStack)))->switch_end, 0);

}

;

default_statement: DEFAULT COLON

{

((t_switch_statement *)LDATA(

getFirst(switchStack)))->default_label =

assignNewLabel(program);

}

statements

;

and the generation of the jump to the default block (if any), justbefore the switch end label:

switch_statement : SWITCH LPAR IDENTIFIER RPAR LBRACE

{ ... }

switch_block RBRACE

{

...

if ($1->default_label != NULL)

gen_bt_instruction(program,

$1->default_label, 0);

// fixLabel(program,$1->switch_end);

...

}

;

9

Page 8: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. Define the semantic actions needed to handle the break construct. (6 points)

break_statement : BREAK

{

if (switchStack == NULL) {

// If there is no active switch,

// GENERATE AN ERROR!!!!

abort();

} else {

gen_bt_instruction( program,

((t_switch_statement *)LDATA(

getFirst(switchStack)))->switch_end, 0 );

}

}

;

10

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, MorzentiWritten exam1: laboratory question

28/06/2008

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof. Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance lan-guage with the ability to handle a new iterative construct computed goto resemblingthe one in the following sample.

int a;

...

label3: ...

...

goto a in label1,label2,label3;

...

label1: ...

...

label2: ...

...

The semantic of the construct is the following one: if the runtime value of thecontrol variable (a in the example) is a positive integer n , then the goto structurejumps to the n-th label after the keyword in (e.g.: if a = 1 the control flow jumpsto “label1” in the aforementioned code). If the control variable assumes either avalue less than 1, or a value greater than the number of labels, no alterations inthe control flow are made and the program continues its execution.

Your modifications have to allow the Acse compiler to both correctly analyzethe syntactical correctness of the aforementioned construct and generate a correcttranslation in the Mace assembly language.

In order to correctly solve the question we suggest you to use the getNewRegisterfunction contained in axe engine.[h,c], which is able to reserve a free register foryour purposes. The prototype of the function is the following one.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

Page 9: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

/* get a register still not used. This function returns

* the ID of the register found */

int getNewRegister(t_program_infos *program);

The integer returned by the function represents, in a non ambiguous way, theregister which has been allocated.

2

Please notice that the present solution is more verbose than what

is needed to get the maximum grade.

As usual, there are many different possible ways to generate assembly codethat complies with the specifications. The most straightforward one is thefollowing:

Lance Assembly

label3: label3:. . . . . .goto a in

label1, SUBI Ry Rx ♯1BEQ label1

mylabel, SUBI Ry Rx ♯2BEQ mylabel

label3; SUBI Ry Rx ♯3BEQ label3

. . . . . .label1: label1:. . . . . .mylabel: mylabel:. . . . . .

where Rx is the register associated with variable a and Ry is a temporaryregister. The assembly code compares the value of the variable a with1, 2, 3. . . (SUBI instructions), and it jumps to the correspondent labelwhen the terms of a comparison are equal (i.e., a subtraction returns 0).

There are two points in the above code that need some attention: thegeneration of the constants 1, 2, 3. . . to be associated to the labels inthe goto statement, and the correspondence between Lance and assemblylabels. For the first point, the label list in the goto statement should begenerated by the grammar with left recursion; a synthesized attribute caneasily count the positions of the labels in the list. For the second point, wecan make use of the symbol table already present in the Acse compiler;we add a new type of entries, label, which associates names of labels inthe Lance language with assembly labels.

3

Page 10: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Define the tokens and the Acse.lex and Acse.y declarations needed to achievethe required functionality. (3 points)

The new construct makes use of two new keywords, goto and in. Theexisting token IDENTIFIER can be used anywhere a label appears.

In Acse.lex we add:

"goto" { return GOTO; }

"in" { return IN; }

and in Acse.y:

% token GOTO

% token IN

2. Define the syntactic rules needed to achieve the required functionality. (8points)

A new possibility for the non-terminal statement generates labeledstatements:

statement : . . .| labeled statement

;

labeled statement : IDENTIFIER COLON statement ;

In this way, a label has always a statement unambiguously associatedto it.

The goto statements are generated by a new possible expansion forthe non-terminal control statement:

control statement : . . .| goto statement

;

goto statement : GOTO IDENTIFIER IN goto list SEMI ;

goto list : goto list COMMA IDENTIFIER| IDENTIFIER

;

The list of labels uses left recursion, so that the SUBI and BEQ

instructions can be generated in the correct order.

4

3. Define the semantic actions needed to achieve the required functionality. (17points)

We have to define new functions to handle the insertion and thelook-up of labels in the symbol table, similar to set new variables

and get symbol location:

t_axe_label *new_lance_label( t_program_infos *program,

char *id );

t_axe_label *get_lance_label( t_program_infos *program,

char *id );

new lance label creates a new label (by calling reserveLabel,add it as an entry of the new type label in the symbol table, andreturns it. get lance label search a label entry in the symbol tableby name and returns it; if it does not find any label with the givenname, it returns NULL.

(As an alternative, a modified version of get lance label couldreplace the two functions as they are described above: The modi-fied get lance label also creates a new entry in the symbol tablewhenever it does not find the requested label in the table.)

Some global definitions. We define the synthesized attribute used tocount the labels in a goto statement:

%union {

...

int count; // Counter for labels in goto statements

}

%type <count> goto_list

We need also an inherited attribute to pass the register that containsthe value of the goto variable (a, in the example) to the actions ofthe non-terminal goto list, which are responsible for the generationof the SUBI instructions. In Bison, where there is no support forinherited attributes, we have to rely on global structures. In thiscase there is no recursion (a goto statement cannot contain otherstatements inside), so a simple global variable is enough:

%{

...

int goto_var_reg; // Register associated with the

// variable in a goto statement

// (i.e., the register Rx in the

// translation scheme)

%}

5

Page 11: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

The semantic action for the labeled statement rule sets the addressof a label. We have to handle both the case when the label is alreadypresent in the symbol table (because of a previous goto statement)and the case when the label is new.

labeled_statement : IDENTIFIER COLON

{

t_axe_label *lab =

get_lance_label( program, $1 );

if (! lab)

lab = new_lance_label( program, $1 );

fixLabel( program, lab );

}

statement ;

The action for the goto statement rule just sets the goto var reg

variable.

goto_statement : GOTO IDENTIFIER

{

goto_var_reg = get_symbol_location( program,

$2, 0 );

}

IN goto_list SEMI ;

The actions of the non-terminal goto list count the labels presentin the list, and use the value of the counter to generate the SUBI

instructions with the correct arguments. The labels contained in alist may or may not be already present in the symbol; labels not yetpresent are created by calling new lance label (but they are notassigned by calling fixLabel; labels are just referenced when theyoccurs in a goto statement).

goto_list : goto_list COMMA IDENTIFIER

{

int reg; // Temporary register

t_axe_label *lab; // Assembly label

reg = getNewRegister( program );

lab = get_lance_label( program, $3 );

if (! lab)

lab = new_lance_label( program, $3 );

gen_subi_instruction( program, reg,

goto_var_reg, $1 + 1 );

gen_beq_instruction( program, lab, 0 );

$$ = $1 + 1; // Position in the label list

}

6

| IDENTIFIER

{

int reg; // Temporary register

t_axe_label *lab; // Assembly label

reg = getNewRegister( program );

lab = get_lance_label( program, $1 );

if (! lab)

lab = new_lance_label( program, $1 );

gen_subi_instruction( program, reg,

goto_var_reg, 1 );

gen_beq_instruction( program, lab, 0 );

$$ = 1; // Position in the label list

}

;

4. Define the semantic actions needed to raise an error if there are undeclaredlabels within the goto statement. (5 points)

The above solution does not check that a label referenced in a goto

statement is assigned somewhere in the program source, nor does itcheck that no label is declared twice. So, we have to keep track ofwhich labels are not declared, and raise an error whenever a label isdeclared for the second time; also, if there is any undeclared label leftat the end of the parsing, an error is to be raised.

We add a new field declared to the entries of the symbol table; thisfield is initialized to 0 in calls to new lance label. The action ofthe non-terminal labeled statement first checks the declared field,to ensure that the label is not already declared. Then, the actionmarks the label as declared by setting the declared field to 1.

At the end of the parsing, i.e., at the beginning of action of the non-terminal program), we run through all the labels in the symbol tableand check if there is any undeclared label.

7

Page 12: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta1: Domanda relativa alle esercitazioni11/09/2008

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro:.....Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire gli operatori di referenziazione e dereferenziazione con laseguente sintassi (C-like).

int *a;

int c;

...

a = &c;

c = *a;

...

Si ipotizzi che la grammatica sia gia in grado di gestire

• il tipo puntatore ad intero

• dichiarazioni di variabili di tipo puntatore ad intero

Si implementino soltanto gli operatori unari & e * rispettando i seguenti vincoli:

• Gli operatori & e * sono associativi a destra

• Gli operatori & e * NON possono essere utilizzati per comporre il left-valuedi un assegnamento

• Gli operatori & e * NON possono essere associati ad array

• Gli operatori & e * possono soltanto essere associati ad identificativi di vari-abili

• NON deve essere possibile dichiarare puntatori multipli

1Tempo 45’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Esempi:

a = &b; /* corretto */

a = *b; /* corretto */

a = *b + *c; /* corretto */

a = *b + 10; /* corretto */

a = *(b + 10); /* non corretto */

a = **b; /* non corretto */

*a = b; /* non corretto */

&a = b; /* non corretto */

*(a + b) = c; /* non corretto */

a = &c + 10; /* corretto */

a = &b[5]; /* non corretto */

a = *b[2]; /* non corretto */

Le modifiche devono mettere il compilatore Acse in condizione di analizzare lacorrettezza sintattica degli operatori sopra descritti e di generare una traduzionecorretta nel linguaggio assembler della macchina Mace.

Per risolvere il problema si consiglia di utilizzare le seguenti funzioni di axe engine.[h,c]:

• getNewRegister : restituisce il numero di un registro (del banco di registriinfinito) non ancora assegnato;

/* get a register still not used. This function returns

* the ID of the register found */

int getNewRegister(t_program_infos *program);

• getLabelFromVariableID : restituisce la “t axe label” che marca l’indirizzodi memoria di una variabile.

/* retrieves the label associated to the ID which is passed as parameter*/

t_axe_label * getLabelFromVariableID (t_program_infos *program, char *ID);

Si ricorda inoltre che :

• La macro REG O identifica il registro R0 che contiene sempre il valore 0

• L’ istruzione assembly MOVA puo essere utilizzata per copiare un indirizzo inun registro

• I possibili modi di indirizzamento per le operazioni aritmetiche a 3 registrisono :

– CG DIRECT ALL : tutti i registri usati non contengono indirizzi

– CG INDIRECT ALL : il registro destinazione e il secondo registro sorgentecontengono indirizzi

– CG INDIRECT DEST : il registro destinazione contiene un indirizzo

– CG INDIRECT SRC : il secondo registro sorgente contiene un indirizzo

2

Page 13: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire (9 punti):

• I token (e le relative dichiarazioni in Acse.lex e Acse.y) aggiuntivi, solo

se necessari, per implementare l’operatore di dereferenziazione (*).

• Le regole sintattiche necessarie per implementare l’operatore di deref-erenziazione (*).

• Le modifiche alle strutture dati (solo se necessarie) per supportatel’operatore di dereferenziazione (*).

• Definire le azioni semantiche necessarie per supportate l’operatore didereferenziazione (*).

Non e necessario introdurre nuovi token lessicali.

Non e necessario dichiarare ulteriori strutture dati a supporto del processodi traduzione.

Bisogna introdurre la seguente regola alla grammatica Acse:

exp : MUL_OP IDENTIFIER

L’azione semantica e definita di seguito:

exp : MUL_OP IDENTIFIER {

/* Il registro che memorizza il valore della

variabile identificata da $3 (IDENTIFIER) */

int regID;

/* Il registro che conterra il risultato

dell’operazione di dereferenziazione */

int regDest;

/* recupera il registro in cui e memorizzato IDENTIFIER */

regID = get_symbol_location (program, $2);

/* ottiene un nuovo registro temporaneo */

regDest = getNewRegister (program);

/* Sposta nel registro ‘regDest’ in contenuto della

* locazione di memoria puntata dall’indirizzo in ‘regID’ */

gen_add_instruction (program, regDest, REG_0, regID, CG_INDIRECT_SRC);

$$ = create_expression (regDest, REGISTER);

}

3

2. Definire (9 punti):

• I token (e le relative dichiarazioni in Acse.lex e Acse.y) aggiuntivi, solo

se necessari, per implementare l’operatore di referenziazione (&).

• Le regole sintattiche necessarie per implementare l’operatore di referen-ziazione (&).

• Le modifiche alle strutture dati (solo se necessarie) per supportatel’operatore di referenziazione (&).

• Definire le azioni semantiche necessarie per supportate l’operatore direferenziazione (&).

Non e necessario introdurre nuovi token lessicali.

Non e necessario dichiarare ulteriori strutture dati a supporto del processodi traduzione.

Bisogna introdurre la seguente regola alla grammatica Acse:

exp : AND_OP IDENTIFIER

L’azione semantica e definita di seguito:

exp : AND_OP IDENTIFIER {

t_axe_label *label;

int movaReg;

/* recupera la label associata alla variabile $2 */

label = getLabelFromVariableID (program, $2);

movaReg = getNewRegister (program);

/* sposta in ‘movaReg’ l’indirizzo di

memoria associato alla label ‘label‘ */

gen_mova_instruction (program, movaReg, label, 0);

$$ = create_expression (movaReg, REGISTER);

}

4

Page 14: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Si ipotizzi di avere a disposizione le seguenti funzioni di libreria:

• int is address expression ( t axe expression * exp ) : resti-tuisce 1 se exp e un puntatore.

• void set address expression ( t axe expression * exp ) : mar-ca l’ espressione come puntatore.

• void invalid operation found() : segnala l’ uso errato di puntatorie blocca il processo di traduzione.

Modificare le azioni semantiche delle seguenti regole Bison (5 punti)

exp : exp MINUS exp { ... }

| exp DIV_OP exp { ... }

affinche :

• Non si possano dividere puntatori.

• Gli operandi della sottrazione possano essere puntatori.

• Le operazioni di sottrazione in cui soltanto uno degli operandi e unpuntatore, diano come risultato un puntatore.

• Le operazioni di sottrazione in cui entrambi gli operandi sono puntatoriNON diano come risultato un puntatore.

• Ogni infrazione delle regole sia segnalata e la traduzione interrotta.

Esempio :

int *b;

b-7; /* sottrazione valida */

b/7; /* divisione non consentita */

E necessario ridefinire l’azione semantica della regola

exp : exp PLUS exp;

nel modo seguente:

exp : exp MINUS exp

{

$$ = perform_bin_numeric_op(program, $1, $3, SUB);

if (is_address_expression ($1)

^^ is_address_expression ($3) )

{

set_address_expression ($$);

}

};

5

E necessario ridefinire l’azione semantica della regola

exp : exp DIV_OP exp;

nel modo seguente:

exp : exp DIV_OP exp

{

if ( is_address_expression ($1)

|| is_address_expression ($3) )

{

invalid_operation_found ();

}

$$ = perform_bin_numeric_op(program, $1, $3, MUL);

};

6

Page 15: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Dato il seguente codice sorgente :

int b=0;

while(b < 36)

{

b = b + 2 * b;

}

scrivere l’ albero sintattico generato dalla grammatica Bison definita in Acse.yignorando le dichiarazioni e partendo dall’ analisi del nonterminale statements

(5 punti)

7

Fig

ura

1:A

lber

osi

nta

ttic

o

8

Page 16: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Facoltativo) (5 punti) Implementare il supporto all’ aritmetica dei puntatoriC-like per la sottrazione : nel caso di sottrazione mista tra un operando ditipo puntatore e uno di tipo intero, l’ intero va moltiplicato per 4 primadi sottrarlo (in quanto la dimensione della parola della macchina Mace e 4bytes). Allo scopo e possibile modificare la regola di sottrazione definita alpunto 3.

9

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta1: Domanda relativa alle esercitazioni24/09/2008

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro:.....Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire il seguente costrutto condizionale con la sintassi (C-like).

int a;

int b;

...

b = a<7 ? 5 : 3;

...

Il significato semantico del costrutto precedentemente illustrato e : se a ha valoreinferiore a 7 , allora assegna a b il valore 5, altrimenti assegna il valore 3. Piu ingenerale, il costrutto valuta la condizione che precede l’ operatore ? e, nel casoabbia valore diverso da 0 propaga il valore dell’ espressione immediatamente asinistra dell’ operatore :, altrimenti propaga il valore dell’ espressione a destra dell’operatore :.

I vincoli implementativi sono :

• Il costrutto va gestito come un’ espressione e non come un generico statementdel linguaggio

• Gli operatori ? e : hanno priorita minima , i.e. inferiore a qualsiasi altrooperatore

• Gli operatori ? e : sono associativi a destra

• La condizione valutata (la parte prima dell’ operatore ?) puo fare utiliz-zo di qualsiasi tipo di operatore aritmetico/logico tranne l’ operatore diassegnamento

1Tempo 45’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 17: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

• Ogni elemento del costrutto non puo essere uno statement generico ma soloun’espressione.

Esempi:

c = (a==7) ? 20 : a + c; /* corretto */

c = a+b*c ? 37*v : 5; /* corretto */

c = a+b ? d=5 : e; /* statement generico non consentito */

c = (a=b+c) ? h : i ; /* assegnamento di a non consentito */

c = (if (a==3){c=2} else {c=1}) ? 7 : m; /* statement generico non consentito */

c = ((2*b) || ! (2*b)) ? t : f ; /* corretto */

Le modifiche devono mettere il compilatore Acse in condizione di analizzarela correttezza sintattica del costrutto sopra descritto e di generare una traduzionecorretta nel linguaggio assembler della macchina Mace.

Per risolvere il problema si ricordano le seguenti funzioni di axe engine.[h,c]:

• getNewRegister : restituisce il numero di un registro (del banco di registriinfinito) non ancora assegnato;

/* get a register still not used. This function returns

* the ID of the register found */

int getNewRegister(t_program_infos *program);

• reserveLabel : riserva una nuova etichetta assembly

/* reserve a new label identifier and return the identifier to the caller */

extern t_axe_label * reserveLabel(t_program_infos *program);

• fixLabel : assegna un’ etichetta alla prossima istruzione assembly

/* assign the given label identifier to the next instruction. Returns

* the label assigned; otherwise (an error occurred) LABEL_UNSPECIFIED */

extern t_axe_label * fixLabel(t_program_infos *program, t_axe_label *label);

• assignNewLabel : esegue nell’ ordine una reserveLabel e una fixLabel

/* reserve and fix a new label. It returns either the label assigned or the

* value LABEL_UNSPECIFIED if an error occurred */

extern t_axe_label * assignNewLabel(t_program_infos *program);

Si ricorda inoltre che :

• La macro REG O identifica il registro R0 che contiene sempre il valore 0

• I possibili modi di indirizzamento per le operazioni aritmetiche a 3 registrisono :

– CG DIRECT ALL : tutti i registri usati non contengono indirizzi

2

– CG INDIRECT ALL : il registro destinazione e il secondo registro sorgentecontengono indirizzi

– CG INDIRECT DEST : il registro destinazione contiene un indirizzo

– CG INDIRECT SRC : il secondo registro sorgente contiene un indirizzo

3

Page 18: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire (16 punti):

• I token (e le relative dichiarazioni in Acse.lex e Acse.y) aggiuntivi, solo

se necessari, per implementare il nuovo costrutto.

• Le regole sintattiche necessarie per implementare il nuovo costrutto.

• Le modifiche alle strutture dati (solo se necessarie) per supportate ilnuovo costrutto.

• Definire le azioni semantiche necessarie per supportate il nuovo costrut-to.

Si assuma di avere a disposizione una funzione di liberia:

void propagate_expression (int regdest, t_axe_expression expr)

Questa funzione genera automaticamente il codice necessario a propagare ilvalore dell’ espressione expr (indipendentemente dal fatto che expr sia unimmediato o un registro) nel registro regdest.

In Acse.lex e necessario aggiungere un token identificativo del simbolo didomanda ‘?’:

"?" { return QUESTIONMARK; }

Non e necessario aggiungere ulteriori tokens in quanto il simbolo ‘:’ e giagestito.

In axe struct.h aggiungiamo la seguente struttura dati:

typedef struct t_cond_expr

{

t_axe_label *label_false;

t_axe_label *label_end;

int result_register;

} t_cond_expr;

In Acse.y si aggiunge la seguente dichiarazione di token:

%token <cond_expr> QUESTIONMARK

Si aggiunge inoltre la seguente regola di precedenza facendo in modo che siala prima ad apparire nell’elenco delle regole di precedenza:

%right COLON QUESTIONMARK

La regola bison da aggiungere al file Acse.y e la seguente:

4

exp : exp QUESTIONMARK {

$2.label_false = reserveLabel(program);

$2.label_end = reserveLabel(program);

$2.result_register = getNewRegister(program);

gen_beq_instruction (program, $2.label_false, 0);

} exp COLON {

propagate_expression ($2.result_register, $4);

gen_bt_instruction (program, $2.label_end, 0);

fixLabel(program, $2.label_false);

} exp {

propagate_expression ($2.result_register, $7);

fixLabel(program, $2.label_end);

$$ = create_expression($2.result_register, REGISTER);

}

5

Page 19: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

2. Modificando la grammatica ottenuta al punto precedente fare in modo chenon sia possibile utilizzare operatori diversi da == e != in qualsiasi punto delcostrutto. Seguono alcuni esempi di codice. Per ciascuna delle nuove regolenon e necessario specificare le azioni semantiche. (7 punti):

c = a+b ? d : e; /* non corretto */

c = a ? d+b : e; /* non corretto */

c = a ? d : e+b; /* non corretto */

c = a==b ? d : e; /* corretto */

c = (a!=b)+c ? t : f ; /* non corretto */

c = (a!=b) ? t : f ; /* corretto */

c = (a==b) || (a!=b) ? t : f ; /* non corretto */

Introduciamo le seguenti regole sintattiche:

cond_expr : NUMBER

| IDENTIFIER

| cond_expr NOTEQ cond_expr

| cond_expr EQ cond_expr

| cond_expr QUESTIONMARK cond_expr COLON cond_expr

| LPAR cond_expr RPAR

;

Modifichiamo infine la grammatica del costrutto ottenuto al punto precedentenel modo seguente:

exp : cond_expr QUESTIONMARK cond_expr COLON cond_expr

Sono state considerate corrette anche soluzioni che non prevedano la formu-lazione della seguente regola sintattica:

cond_expr : cond_expr QUESTIONMARK cond_expr COLON cond_expr

6

3. Dato il seguente codice sorgente :

int a = 10;

int b = 20;

do {

a = b / a * a;

} while (a!=0)

scrivere l’ albero sintattico generato dalla grammatica Bison definita in Acse.ypartendo dal nonterminale statements (5 punti)

7

Page 20: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Fig

ura

1:A

lber

osi

nta

ttic

o

8

4. (Facoltativo) (5 punti) Dato il seguente codice sorgente :

d = 5 < 7 ? a ? b : c ? a : b : a;

scrivere l’ albero sintattico generato dalla grammatica Bison modificata alpunto 2 partendo dal nonterminale assign statement

9

Page 21: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question06/02/2009

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to handle simple macros resembling #define constructfor the C preprocessor :

define ANSWER 42;

define QUESTION 9;

int x;

read( x );

x = ANSWER * x;

write( x );

The first line of the sample code snippet defines the macro ANSWER as the integervalue 42. The expected behaviour of this program is to print the number providedin input multiplied by 42.

The solution needs to comply to the following specifications:

• The macros are parameter-free and each macro can only bind to a singleinteger value

• An arbitrary number of macros may be defined

• Macros may be employed everywhere an integer constant can be used in theoriginal Acse language

• Macros cannot be modified by assignments

An optimal solution shouldn’t generate any additional assembly code for aLance program using macros with respect to one which isn’t.

In case a double definition of the same macro is detected, implement a sensiblestrategy (either ignore or overwrite the former definition).

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

You may specify any further (sensible) assumption useful to complete the givenspecification list.

You may use the functions in collections.h if you are in need of a set ofready-made helpers for dealing with lists. If you prefer, you may also use thesefunctions in order to handle lists of DATA typed elements. In the latter case, definethe structure DATA.

void initList( t_list *list );

void addFirst( t_list *list, DATA *element );

void addLast( t_list *list, DATA *element );

DATA *getFirstElement( t_list *list );

DATA *getLastElement( t_list *list );

DATA *getElementAt( t_list *list, unsigned int position );

2

Page 22: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Define the tokens (and the related declarations in Acse.lex e Acse.y). (3points)

In Acse.lex add:

"define" { return DEFINE; }

In Acse.y:

%token DEFINE

2. Define the syntactic rules or the modifications required to the existing ones.(8 points)

macro def : DEFINE IDENTIFIER NUMBER SEMICO-LON ;

macro defs : macro defs macro def

| ;

Modify the existing rule:

program : macro defs var declarations statements ;

Add new alternatives to existing rules:

declaration : . . .| IDENTIFIER ASSIGN IDENTIFIER| IDENTIFIER LSQUARE IDENTIFIER RSQUARE

;

exp : . . .| NOT OP IDENTIFIER

;

3

3. Define the semantic actions needed to implement macros. (13 points for aworking solution, 19 for the optimal one)

In case of duplicate definition, we report an error.

In Acse.y:

%{

...

t_list macros;

%}

...

typedef struct {

char *id;

int val;

} DATA;

...

int main() {

initList( &macros );

...

}

Let us assume that we have the function with prototype:

DATA *getMacro( const char *id );

This function returns the structure of the macro identified by id, orNULL if the macro does not exist.

Semantic actions:

macro_def : DEFINE IDENTIFIER NUMBER SEMICOLON

{

DATA *p;

p = getMacro( $2 );

if (p) {

/* Report a duplicate-definition error */

}

p = malloc( sizeof(DATA) );

addList( &macros, p );

p->id = $2;

p->val = $3;

}

;

4

Page 23: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

declaration : IDENTIFIER ASSIGN IDENTIFIER

{

DATA *p = getMacro( $3 );

if (! p) {

/* Report an error */

}

$$ = alloc_declaration( $1, 0, 0, p->val );

}

| IDENTIFIER LSQUARE IDENTIFIER RSQUARE

{

DATA *p = getMacro( $3 );

if (! p) {

/* Report an error */

}

$$ = alloc_declaration( $1, 1, p->val, 0 );

}

;

exp : IDENTIFIER

{

DATA *p = getMacro( $1 );

if (! p) {

/* Code of the old action */

} else {

$$ = create_expression( p->val, IMMEDIATE );

}

}

| NOT_OP IDENTIFIER

{

DATA *p = getMacro( $1 );

if (! p) {

/* Report an error */

}

$$ = create_expression( p->val == 0, IMMEDIATE );

}

;

5

4. Bonus: Modify the existing solution in order to allow recursive definition ofmacros; for instance, the following program

define ULTIMATE_ANSWER 42;

define ANSWER ULTIMATE_ANSWER;

int x;

x = ANSWER;

write( x );

prints “42”. (5 points)

Add an alternative:

macro_def : ...

| DEFINE IDENTIFIER IDENTIFIER SEMICOLON

{

DATA *p1, p2;

p1 = getMacro( $2 );

if (p1) {

/* Report a duplicate-definition error */

}

p1 = malloc( sizeof(DATA) );

p2 = getMacro( $3 );

if (! p2) {

/* Report a undefined-macro error */

}

addList( &macros, p1 );

p1->id = $2;

p1->val = p2->val;

}

;

6

Page 24: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

A solution like the one given above is little verbose, but it is worth themaximum grade. Here some more details are given to help students.

The solution forces macro definitions to appear before any code. A solutionthat considers a macro definition as any other instruction has problems.For example,

statement : . . .| macro def

;

allows the production of code whose semantics is not clear, like this:

if (x == 3)

define MACRO 45;

The compiler always considers the macro definition (it does not know thevalue of x, so this is the only option), but this is contrary to the semanticsof the if statement.

All actions are at end rule; this and the use of a global macro list macrosavoid the need of introducing new semantic attributes.

The function getMacro() can be written as:

DATA *getMacro( const char *id ) {

unsigned int i = 0;

DATA *p;

do {

p = getElementAt( &macros, i );

if (0 != strcmp( id, p->id ))

return p;

++i;

} while (p != NULL);

return NULL;

}

where we assume that getElementAt() returns NULL when the givenindex is past the end of the list.

The given solution does not check if there is clash between a macroand a variable definition. This check could have been introduced at thebeginning of the actions of the non-terminal declaration in this way:

DATA *p1;

p1 = getMacro( $1 );

if (p1) {

/* Report a duplicate-definition error */

}

...

7

It is possible to write a more general solution, which complies also withthe specifications of the bonus question. This solution defines macro def

in this way:

macro def : DEFINE IDENTIFIER exp ;

This solution allows to define the value of a macro as a constant expression.The semantic action is:

macro_def : DEFINE IDENTIFIER exp

{

DATA *p;

if ($3.expression_type != IMMEDIATE) {

/* Report an error: expression is not constant */

}

p = getMacro( $2 );

if (p) {

/* Report a duplicate-definition error */

}

p = malloc( sizeof(DATA) );

addList( &macros, p );

p->id = $2;

p->val = $3.value;

}

;

8

Page 25: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Formal Languages and CompilersProff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question27/06/2009

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof. Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to use assignments as a part of an expression with thefollowing syntax (the same as C programming language):

int x, y, z, a[3];

x = y = z = a[0] = 1;

write( x = y + 3 );

z = (y = 2) * x;

x = z + y;

write( x );

Compiling this code snippet and executing it would result in a printout of thevalues “4” and “10”.

The solution must comply with the following specifications:

• The assignment operator has the lowest priority and is right associative.

• An assignment expression may appear in the grammar everywhere a nonter-minal expression does (i.e., everywhere a nonterminal exp is placed).

• The left hand side of an assignment may be either a variable or an elementof an array.

• The right hand side of an assignment may be any valid expression of thelanguage, including an assignment.

Your modifications have to allow the Acse compiler to both correctly analyze thesyntactical correctness of the aforementioned constructs and to generate a correcttranslation in the Mace assembly language.

Take care not to build an ambiguous grammar.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

The answers given here are generally more verbose than those regarded asfully satisfactory during the evaluation of a student’s work.

1. Define the syntactic rules needed (or the modifications to the existing ones)in order to obtain the required functionalities, including possible directivesfor precedence and associativity. (7 points)

As any expression can be an assignment, add two possible expansionsto the exp non-terminal:

exp : . . .| IDENTIFIER ASSIGN exp

| IDENTIFIER LSQUARE exp RSQUARE ASSIGNexp

;

There is already a statement setting the correct precedence for theassignment:

%left ASSIGN

The grammar specified above is not ambiguous, as any assignmentexpression has an identifier as the first operand, so there is no needto modify the associativeness2. Modifying the above statement in

%right ASSIGN

is okay, though.

An alternative solution is to make use of the non-terminal assign statement:

exp : . . .| assign statement

;

Again, the grammar is not ambiguous, for the same reason as above.

2If the rule were “exp : exp ASSIGN exp” the resulting grammar would be ambiguous,

and the associativeness must be specified correctly.

2

Page 26: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

2. Define the semantic actions needed (or the modifications to the existing ones)in order to obtain the required functionalities. (8 points)

The semantic actions for the new rules are basically a copy of the ac-tions for assign statement, with the addition of the code to propagatethe value of the expression:

exp : IDENTIFIER LSQUARE exp RSQUARE ASSIGN exp

{

storeArrayElement(program, $1, $3, $6);

free($1);

$$ = $6;

}

| IDENTIFIER ASSIGN exp

{

int location;

t_axe_instruction *instr;

location = get_symbol_location(program, $1, 0);

if ($3.expression_type == IMMEDIATE)

instr = gen_addi_instruction

(program, location, REG_0, $3.value);

else

instr = gen_add_instruction

(program, location, REG_0, $3.value, CG_DIRECT_ALL);

free($1);

$$ = $3;

}

;

3

The alternative solution requires to add a semantic attribute to thenon-terminal assign statement

%type <expr> assign_statement

and to perform the propagation of the value of the expression bothin the new expansion for exp and in the actions for assign statement:

assign_statement : IDENTIFIER LSQUARE exp RSQUARE ASSIGN exp

{

...

$$ = $6;

}

| IDENTIFIER ASSIGN exp

{

...

$$ = $3;

}

;

exp : assign_statement

{

$$ = $1;

}

;

4

Page 27: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Given the following code snippet:

int a = 2;

int b;

b = a*5 + (a = a - 1) + a*2;

write( b )

(a) Write down the syntactic tree of the assignment statement on the thirdline, starting from the non-terminal statements according to the gram-mar specified before. (4 points)

(b) According to the grammar specified before, write down the evaluationorder of the operations performed in the aforementioned statement andcompute the final value of the variable b. (5 points)

(a) See figure 1

(b) In an LR parser the tree is built bottom-up starting from theleft, in the order that is the reverse of the rightmost derivation.Therefore, the operations are evaluated in the following order:Expression Expr. value Value of a

a ∗ 5 10 2a - 1 1 2a = a - 1 1 1

a ∗ 5 + (a = a - 1) 6 1

a ∗ 2 2 1

a ∗ 5 + (a = a - 1) + a ∗ 2 13 1

5

stat

emen

ts

stat

emen

t

assi

gnst

atem

ent

SE

MI

IDE

NT

IFIE

RA

SSIG

Nex

p;

b=

PLU

Sex

p

exp

+ex

pM

UL

exp

exp

PLU

Sex

pID

EN

TIF

IER

*N

UM

BE

R

exp

MU

Lex

p+

LPA

Rex

pR

PA

Ra

2

IDE

NT

IFIE

R*

NU

MB

ER

(ID

EN

TIF

IER

ASSIG

Nex

p)

a5

a=

exp

MIN

US

exp

IDE

NT

IFIE

R-

NU

MB

ER

a1

Figure 1: Syntactic tree of the statement b = a*5 + (a = a - 1) + a*2;

6

Page 28: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. In the code snippet reported in the question 3 the value of b depends onthe order in which the operands are evaluated. Since a typical programminglanguage doesn’t suffer from such issues, delineate which semantic check maybe applied by the compiler in order to produce a warning in situations likethe ones in the example. It is not required to write the actual code, but thesemantic actions and the structures involved must be specified correctly. (9points)

The problem happens whenever a variable is both used and assignedin the same expression (but it is okay to use a variable to compute thevalue to assign to the same variable, as in a = a + 1). Briefly, weneed to keep track of the variables used and assigned in expressions,and raise a warning whenever the intersection between the two setsis not empty.

A way to do this is to add two fields to the t axe expression

structure: assigned and used. They are both sets of identifiers.

In the rules

exp : IDENTIFIERexp : NOT OP IDENTIFIER

used is initialized with the identifier, while assigned is empty. In

exp : NUMBERexp : NOT OP NUMBER

both sets are empty.

In the rule

exp : IDENTIFIER ASSIGN exp {$$.assigned = $3.assigned ∪ { $1 }$$.used = $3.assigned \ { $1 }

}

the identifier is added to assigned and removed from used. Theremoval from used is needed to avoid issuing warning in case ofexpressions like a = a + 1, which are safe to use. A check isperformed to make sure the assigned variable is not already presentin the assigned set of the right-hand exp. This check discoversdouble assignments, as in a = 1 + (a = 2).

For the rules of the type

exp : exp OPERATOR exp {$$.assigned = $1.assigned ∪ $3.assigned$$.used = $1.used ∪ $3.used

}

The value of assigned and used of the left-hand side exp is theunion of values on the right-hand side. Two checks are performed inthese rules:

7

(a) The intersection of assigned sets on the right side should beempty. This is to avoid double assignments as in (a = 3) +

(a = 4).

(b) The intersection of the assigned and used should be empty.This is to avoid the assignment and the use of the same variablein one expression, as in a + (a = 3).

In rules where there is one exp in the right-hand side, the values ofassigned and used are propagated unchanged.

The above solution does not address the problem related to the useand assignment of array elements. Array identifiers could be addedto the assigned and used sets and handled in the same way asvariables. Such a solution generates false positives, because it doesnot distinguish between individual elements of the array. This isunavoidable, as array could be index with variables, whose values isnot known at compile time.

8

Page 29: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e CompilatoriProff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta1: Domanda relativa alle esercitazioni11/09/2009

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-

tro:.....

Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof. Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare

l’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,

quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si

ritengono necessarie delle modifiche in modo da estendere il compilatore Acse con

la nuova istruzione write array che stampi a video tutti gli elementi di un array.

Ecco un esempio:

int a[3];

a[0] = 11;

a[1] = 2;

a[2] = 4;

write_array( a );

Se tale programma venisse compilato e fatto girare, allora verrebbero stampati

in uscita nell’ordine i valori “11”, “2” e “4”.

La soluzione deve accettare la sintassi dell’esempio. Si faccia attenzione che

ovviamente mentre la dimensione dell’array e sempre nota a tempo di compilazione,

i valori contenuti nell’array vanno letti a tempo di esecuzione.

1Tempo 45’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) neces-sari per ottenere le funzionalita richieste. (3 punti) In Acse.lex bisognaaggiungere

"write_array" {return WRITEALL;}

In Acse.y bisogna aggiungere

%token WRITEALL

2. Definire le regole sintattiche (e/o le modifiche a quelle esistenti) necessarieper ottenere le funzionalita richieste. (6 punti)

In Acse.y bisogna riscrivere la regola “read write statement” nel seguentemodo:

read_write_statement : read_statement { /* does nothing */ }

| write_statement { /* does nothing */ }

| write_array_statement { /* does nothing */ }

write_array_statement : WRITEALL LPAR IDENTIFIER RPAR

2

Page 30: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Definire le azioni semantiche (e/o le modifiche a quelle esistenti) necessarieper ottenere le funzionalita richieste. (21 punti)

write_array_statement : WRITEALL LPAR IDENTIFIER RPAR {

t_axe_label *l;

t_axe_variable *arrayVar;

int value,index,temp,arraySize;

t_axe_expression index_expr;

arrayVar = getVariable(program, $3);

arraySize = gen_load_immediate(program, arrayVar->arraySize);

index = getNewRegister(program);

index_expr = create_expression(index, REGISTER);

gen_addi_instruction(program, index, REG_0, 0);

l = assignNewLabel(program);

value = loadArrayElement(program, $3, index_expr);

gen_write_instruction (program, value);

gen_addi_instruction(program, index, index, 1);

temp = getNewRegister(program);

gen_sub_instruction(program, temp, index, arraySize, CG_DIRECT_ALL);

gen_bne_instruction (program, l, 0);

}

3

4. (Bonus) Inserire un controllo semantico in modo tale che venga dato unerrore nel caso in cui il parametro nella write array non sia un array mauna variabile semplice. (3 punti)

write_array_statement : WRITEALL LPAR IDENTIFIER RPAR {

...

arrayVar = getVariable(program, $3);

if (! arrayVar->isArray) {

notifyError(AXE_INVALID_INSTRUCTION);

abort();

}

...

}

4

Page 31: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question06/07/2010

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to handle the eval-unless construct:

int x, y;

read(x);

y = 0;

eval {

y = 1;

} unless x==5;

write(y);

Between eval and unless there is a code block. The unless keyword is followedby an expression. If the expression evaluates to false, the code block is executed.If the condition is true, the code block is not executed.

In the code sample above, if the x variable is initialized with the value 5, theexecution will end printing 0 on the screen. For every other value in x, the codeblock containing y = 1 will be executed and the execution will end printing 1 onthe screen.

Explicit any other assumption you made to implement the support for theeval-unless construct.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

1. Define the tokens (and the related declarations in Acse.lex e Acse.y). (1points)

Two tokens are needed, and they have to be declared in the Acse.lex file,adding the following lines.

"eval" { return EVAL; }

"unless" { return UNLESS; }

2. Define the syntactic rules or the modifications required to the existing ones.(4 points)

Declare a new structure in the axe struct.h file. It will contain the labelsneeded to generate the code for the construct:

typedef struct t_unless_stmt {

t_axe_label *label_condition;

t_axe_label *label_code;

t_axe_label *label_end;

} t_unless_stmt;

Then, modify the Acse.y as described hereafter. Expand the semantic recordwith a reference to the t unless stmt structure:

%union {

...

t_unless_stmt unless_stmt;

}

Declare the tokens. The eval token will contain an unless stmt record.

%token UNLESS

%token <unless_stmt> EVAL

The unless statement is a new kind of control statement:

control_statement : if_statement { /* does nothing */ }

| while_statement { /* does nothing */ }

| do_while_statement SEMI { /* does nothing */ }

| return_statement SEMI { /* does nothing */ }

| unless_statement SEMI { /* does nothing */ }

;

Finally, here is the rule describing the unless statement:

unless_statement : EVAL code_block UNLESS exp

;

2

Page 32: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Define the semantic actions needed to implement the required functionality.(20 points)

unless_statement : EVAL

{

$1.label_condition = newLabel(program);

/* Jump to the evaluation of the expression */

gen_bt_instruction(program, $1.label_condition, 0);

/* Set the label that identifies the code block */

$1.label_code = newLabel(program);

assignLabel(program, $1.label_code);

} code_block

{

$1.label_end = newLabel(program);

gen_bt_instruction (program, $1.label_end, 0);

} UNLESS

{

/* Set the label that identifies the condition evaluation */

assignLabel(program, $1.label_condition);

}

exp

{

if ($7.expression_type == IMMEDIATE)

gen_load_immediate(program, $7.value);

else

gen_andb_instruction(program, $7.value

, $7.value, $7.value, CG_DIRECT_ALL);

/* If the expression is FALSE, jump back to

* the execution of the code block */

gen_beq_instruction (program, $1.label_code, 0);

/* Label identifying the end of the construct */

assignLabel(program, $1.label_end);

}

;

3

4. Given the following code snipped:

b = c || d && e | f

Write down the syntactic tree generated during the parsing with the Bisongrammar described in Acse.y starting from the assign statement nonter-

minal. (5 points)

4

Page 33: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Is it possible to produce optimized code for the eval-unless con-struct in case the value of the condition is already known at compile time(i.e. it is constant)? Explain your answer. (3 points)

In order to produce optimized code it should be possible to disable the gen-eration of the code block (in case at compile time the condition is known tobe true) or to generate the code block but not the condition computation(in case the condition is known to be true). Unfortunately, in this construct,the condition appears after the code block, therefore it is evaluated after thecode of the code block has already been generated, and there is no way tooptimize it with a single parsing pass.

5

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni02/09/2010

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire le operazioni di somma e sottrazione tra vettori.

1 int a[10];

2 int b[10];

3 int c[10];

4

5 vec_add(c, a, b);(a) Somma

1 int a[10];

2 int b[10];

3 int c[10];

4

5 vec_sub(c, a, b);(b) Sottrazione

Figura 1: Operazioni vettoriali. Figura 1(a) computa la somma vettorialec = a + b utilizzando vec_add. In maniera analoga, Figura 1(b) calcola ladifferenza vettoriale c = a− b sfruttando vec_sub.

Le operazioni vettoriali sono identificate dalle keyword vec_add e vec_sub:

Somma vettoriale vec_add(c, a, b) calcola la somma elemento per elementotra a e b salvandone il risultato in c. Il generico elemento c[i] sara quindipari ad a[i] + b[i]

Differenza vettoriale vec_sub(c, a, b) calcola la differenza elemento per ele-mento tra a e b salvandone il risultato in c. Il generico elemento c[i] saraquindi pari ad a[i] - b[i]

Le nuove operazioni agiscono su vettori aventi la stessa lunghezza. Negli esempidi Figura 1 i tre operandi delle operazioni vettoriali contengono tutti 10 elementi.

1Tempo 45’. Libri e appunti personali possono essere consultati.E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 34: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Se i vettori non hanno la stessa lunghezza la traduzione non puo essere eseguita ede necessario generare un errore a compile-time.

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria acompletare la specifica data.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

La soluzione e riportata nella patch allegata.

2

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

La soluzione e riportata nella patch allegata.

3

Page 35: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

4

4. Dato il codice di Figura 2:

1 if(a == 4)

2 a = 7;

Figura 2: Costrutto if.

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale statements. (5 punti)

La soluzione e riportata in Figura 3.

5

Page 36: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

statements

statement

control_statement

if_statement

IF

if

LPAR

(

exp

exp

IDENTIFIER

a

EQ

==

exp

NUMBER

4

RPAR

)

code_block

statement

assign_statement

IDENTIFIER

a

ASSIGN

=

exp

NUMBER

7

Figura 3: Albero sintattico di uno statement if.

6

5. (Bonus) Si supponga che il linguaggio targettato dal compilatore Acse siastato esteso in modo da supportare istruzioni che operano con vettori dilunghezza 4 elementi. Di conseguenza sono disponibili dei registri vettorialivect_t e le relative funzioni per manipolarli, riportate in Figura 4.

1 vect_t

2 getNewVectRegister(

3 t_program_infos* program );

4

5 vect_t

6 loadArrayChunk(

7 t_program_infos* program ,

8 char* ID ,

9 t_axe_expression index);

10

11 void

12 storeArrayChunk(

13 t_program_infos* program ,

14 char* ID ,

15 t_axe_expression index ,

16 vect_t r_source );

17

18 t_axe_instruction*

19 gen_addv_instruction(

20 t_program_infos* program ,

21 vect_t r_dest ,

22 vect_t r_source1 ,

23 vect_t r_source2 );

Figura 4: Assembly vettoriale. Il comportamento delle tre funzioni e analogoa quelle gia disponibili in Acse, ma invece che operare con registri scalarioperano con registri vettoriali.

E possibile ottenere nuovi registri vettoriali tramite la funzionegetNewVectRegister. La funzione loadArrayChunk permette di caricare 4elementi di un array, partendo dall’indice index, in un registro vettoriale; essaritorna il registro destinazione. La sua duale, storeArrayChunk permette disalvare il contenuto di un registro vettoriale in un array, sovrascrivendo 4 ele-menti partendo dall’indice index. Infine la funzione gen_addv_instructiongenera il codice necessario per sommare i registri vettoriali r_source1 er_source2 e salvare il risultato in r_dest.

7

Page 37: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Avendo a disposizione queste primitive, come le si puo sfruttare per imple-mentare le operazioni vettoriali?

La soluzione proposta nei punti precedenti spezza la somma vettoriale

in tante piccole somme scalari tra i corrispondenti elementi degli array

operandi.

Le nuove istruzioni possono essere sfruttate in modo da spezzare gli

operandi in blocchi di 4 elementi ciascuno, che poi verranno processati

dalle istruzioni vettoriali.

Ovviamente bisogna tenere conto del fatto che non tutti gli array pos-

so essere spezzati in blocchi di 4 elementi. Per questi casi patologici

bisogna ancora ricorrere alla soluzione precedente.

Ad esempio, un array contenete 11 elementi puo essere spezzato in

3 blocchi. I primi 2, contenenti gli elementi con indice compreso tra

0 e 7, possono essere trattati con le nuove istruzioni vettoriali. I

restanti 3 elementi, quelli con indice compreso tra 8 e 10, devono

essere trattati con istruzioni scalari.

8

Applicare una patch

Sul sito del corso e disponibile una patch contenente la soluzione del tema d’esameper quanto riguarda la modifica della macchina Acse.

Per applicare la patch:

1. scaricare la macchina Acse versione 1.1.0

2. scaricare la patch soluzione-02-09-10.diff

3. scompattare l’archivio contenente la macchina Acse

4. usando il terminale, portarsi nella directory in cui e stata estratta la macchinaAcse

5. copiare in tale cartella la patch

6. applicare la patch tramite il comando

patch -p1 < soluzione-02-09-10.diff

La patch e un normalissimo file di testo, contenente le differenze tra la versionedi Acse con implementata la soluzione dell’esame e la versione 1.1.0.

Le righe che iniziano con il carattere + sono state aggiunte, mentre quelle conil carattere - sono state rimosse.

9

Page 38: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 1

In Acse.lex:

"vec_add" { return VEC_ADD; } "vec_sub" { return VEC_SUB; } In Acse.y:

%token VEC_ADD %token VEC_SUB PUNTO 2

statement: ... | vec_statement SEMI | SEMI ; vec_statement: vec_add_statement | vec_sub_statement ; vec_add_statement: VEC_ADD LPAR IDENTIFIER COMMA IDENTIFIER COMMA IDENTIFIER RPAR { handle_vec_op (program, $3, $5, $7, VADD); } ; vec_sub_statement: VEC_SUB LPAR IDENTIFIER COMMA IDENTIFIER COMMA IDENTIFIER RPAR { handle_vec_op (program, $3, $5, $7, VSUB); } ; PUNTO 3

#define VADD 100 #define VSUB 101 void handle_vec_op(t_program_infos *program,char *destID, char *sourceID1, char *sourceID2, int vec_op){ t_axe_variable *dest_var = getVariable (program, destID); t_axe_variable *source_var1 = getVariable (program, sourceID1); t_axe_variable *source_var2 = getVariable (program, sourceID2); if (!dest_var->isArray || !source_var1->isArray ||

!source_var2->isArray) notifyError (AXE_INVALID_TYPE);

if (dest_var->arraySize != source_var1->arraySize || dest_var->arraySize != source_var2->arraySize) notifyError (AXE_INVALID_ARRAY_SIZE); int index_register, dest_register; t_axe_expression index, dest; t_axe_label *start, *end; /* inizia il loop counter */ index_register = getNewRegister (program); index = create_expression (index_register, REGISTER); gen_mova_instruction (program, index_register, NULL, dest_var->arraySize); /* abbiamo bisogno di un registro temporaneo "tmp" */ dest_register = getNewRegister (program); dest = create_expression (dest_register, REGISTER); start = assignNewLabel (program); end = newLabel (program); /* qualora l’array è stato completamente scansionato */ gen_andb_instruction (program, index_register, index_register, index_register, CG_DIRECT_ALL); gen_beq_instruction (program, end, 0); /* calcolo l’indice */ gen_subi_instruction (program, index_register, index_register, 1); /* carico gli operandi */ int src1_register = loadArrayElement (program, sourceID1, index); int src2_register = loadArrayElement (program, sourceID2, index); /* operazioni */ switch (vec_op){

case VADD: gen_add_instruction (program, dest_register, src1_register, src2_register, CG_DIRECT_ALL); break; case VSUB: gen_sub_instruction (program, dest_register, src1_register, src2_register, CG_DIRECT_ALL); break;

default: notifyError (AXE_INVALID_OPCODE); } /* memorizza i dati nell’array */ storeArrayElement (program, destID, index, dest); /* jump to header */ gen_bt_instruction (program, start, 0); /* fix exit label */ assignLabel (program, end); }

Page 39: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question16/09/2010

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to handle the after-do construct:

1 int a;

2 int b;

3

4 a = 0;

5 b = 0;

6 after 3 do {

7 a=5;

8 b=7;

9 }

10 while(a<10) {

11 a=a+1;

12 }

13 b=1;

14 write(a);

15 write(b);

(a) after-do construct

1 int a;

2 int b;

3

4 a = 0;

5 b = 0;

6 while(a<10) {

7 a=a+1;

8 }

9 b=1;

10 a=5;

11 b=7;

12 write(a);

13 write(b);

(b) Equivalent code

With the after-do construct, the code specified in the code block after thedo keyword is executed k statements after the end of the code block itself, insteadof being executed in the position where it is written. Note that k is a positiveimmediate constant and that the number of statements is counted statically (itis referred to the number of statements as appearing in the source code of theprogram, not to the number of executed statements).

1Time 45’. Textbooks and notes can be used.Pencil writing is allowed. Write your name on any additional sheet.

1

In the code sample of Figure 1(a), the instructions a=5 and b=7 will be exe-cuted after b=1 and before write(a), as it can be seen looking at the semanticallyequivalent code of Figure 1(b) .

Assume that in a program there can be at most one after-do construct.Explicit any other assumption you made to implement the support for the

after-do construct.

1. Define the tokens (and the related declarations in Acse.lex e Acse.y). (1points)

The solution can be found in the attached patch.

2. Define the syntactic rules or the modifications required to the existing ones.(4 points)

The solution can be found in the attached patch.

3. Define the semantic actions needed to implement the required functionality.(20 points) The solution can be found in the attached patch.

4. Given the following code snipped:

do

a=0;

while ( !a );

Write down the syntactic tree generated during the parsing with the Bisongrammar described in Acse.y starting from the statement nonterminal. (5points)

2

Page 40: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

���������

���������������

��� ������������� ����

�� ��������� ����� ���� ��� ����

�� ���������

����!�����������

���"#�$��� ����%" ���

� & "'�(��

)

��� * "�#��� ���"#�$���

+ �

,

5. (Bonus) Describe how it would be possible to implement support for havingmultiple after-do constructs in a single program. (3 points)

To have multiple after-do constructs, the labels they need should be storedinto a dynamically linked list.

Each element of the list is a struct containing two labels, and one counter.The counter marks the statement distance from the the after-do construct.

When the right distance (for each instance of the construct) has been reached,the right labels and jumps are generated, as in the single-construct version.

Beware that, in order for the semantics of the construct to be unchanged,statements generated by the construct itself should not be accounted whencomputing the distance.

3

PUNTO 1

In Acse.lex:

"after" { return AFTER_OP; } In Acse.y:

%token <label> AFTER_OP PUNTO 2

insigned int instr_contdown = 0; t_axe_label *after_stmt_return = NULL; t_axe_label *after_stmt_code = NULL; statement: statement2 {

if(after_stmt_code != NULL && instr_countdown == 0){ gen_bt_instruction(program, after_stmt_code, 0); assignLabel(program, after_stmt_return); } instr_countdown--; } ; statement2: ... | after_stmt SEMI | SEMI ; PUNTO 3

after_stmt: AFTER_OP exp DO

{ if ($2.expression_type != IMMEDIATE || $2.value < 0) { printMessage("Errore valore negativo"); abort(); } if (after_stmt_code != NULL) { printMessage("Ci può essere un solo after-do"); abort(); } $1 = newLabel(program); gen_bt_instruction(program, $1, 0); after_stmt_code = assignNewLabel(program); } code_block { instr_countdown = $2.value; after_stmt_return = newLabel(program); gen_bt_instruction(program, after_stmt_return, 0); assignLabel(program, $1); }

Page 41: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni04/03/2011

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire una forma semplificata di eccezioni.

1 try {

2 ...

3 throw;

4 ...

5 } catch {

6 ...

7 }

Figura 1: Esempio di eccezione

All’interno di un sorgente Acse deve essere possibile definire una regione dicodice protetta dal costrutto try catch. Esso e analogo ai costrutti di gestionedelle eccezioni dei linguaggi mainstream, con alcune semplificazioni:

• il blocco try e obbligatoriamente seguito da un blocco catch

• se nel blocco try viene eseguita l’istruzione throw, allora viene eseguito ilblocco catch

Per semplicita, si considerino inoltre le seguenti limitazioni:

• l’istruzione throw non accetta alcun argomento

• il blocco catch cattura tutte le eccezioni lanciate nel blocco try associato

1Tempo 45’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

• per quanto riguarda la definizione delle azioni semantiche, si supponga che icostrutti try catch non si possano innestare

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria acompletare la specifica data.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

La soluzione e riportata nella patch allegata.

2

Page 42: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

La soluzione e riportata nella patch allegata.

3

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

4

Page 43: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Dato il codice di Figura 2:

1 ptr = ptr | (fast_locked << 1) | gc_locked;

Figura 2: Esempio di pointer-packing

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale statement. (5 punti)

La soluzione e riportata in Figura 3.

5

statement

assign_statement

IDENTIFIER

ptr

ASSIGN

=

exp

exp

exp

IDENTIFIER

ptr

OR_OP

|

exp

LPAR

(

exp

exp

IDENTIFIER

fast_lockedSHL_OP

<<

exp

NUMBER

1

RPAR

)

OR_OP

|

exp

IDENTIFIER

gc_locked

SEMI

;

Figura 3: Albero sintattico del codice riportato in Figura 2

6

Page 44: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Si supponga di voler permettere la gestione di blocchi try catch

annidati. Come deve essere modificata la soluzione proposta precedentemen-te?

La soluzione proposta si appoggia alla variabile cur_try per accedere

al blocco try catch correntemente attivo. Nel caso in cui si annidino

piu costrutti l’uno all’interno dell’altro si puo naturalmente estendere

l’algoritmo in modo da tracciare il costrutto try catch attivo al

livello corrente di annidamento. La struttura dati necessaria per tale

compito e un semplice pila. Si veda la patch allegata per i dettagli

implementativi.

7

Applicare una patch

Sul sito del corso e disponibile una patch contenente la soluzione del tema d’esameper quanto riguarda la modifica della macchina Acse.

Per applicare la patch:

1. scaricare la macchina Acse versione 1.1.0

2. scaricare la patch soluzione-04-03-10.diff

3. scompattare l’archivio contenente la macchina Acse

4. usando il terminale, portarsi nella directory in cui e stata estratta la macchinaAcse

5. copiare in tale cartella la patch

6. applicare la patch tramite il comando

patch -p1 < soluzione-04-03-10.diff

La patch e un normalissimo file di testo, contenente le differenze tra la versionedi Acse con implementata la soluzione dell’esame e la versione 1.1.0.

Le righe che iniziano con il carattere + sono state aggiunte, mentre quelle conil carattere - sono state rimosse.

8

Page 45: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 1

In Acse.lex:

"try" { return TRY; } "catch" { return CATCH; } "throw" { return THROW; } In Acse.y:

%token <try_catch_stmt> TRY %token CATCH %token THROW PUNTO 2

/* Try-catch statement attualmente attivo */ t_try_catch_statement *cur_try = NULL; t_try_catch_statement try_catch_stmt; control_statement: ... | try_catch_statement | throw_statement SEMI ; PUNTO 3

try_catch_statement: TRY { /* creo un nuovo try-catch statement */ $1 = create_try_catch_statement(); $1.label_catcher = newLabel(program); $1.label_end = newLabel(program); /* remember it, for throw translation */ cur_try = &$1; } code_block { /* alla fine del try block devo andare al catch block */ gen_bt_instruction(program, $1.label_end, 0); /* reset try-catch pointer */ cur_try = NULL; /* qui parte il catch block */ assignLabel(program, $1.label_catcher); } CATCH code_block { /* fix end label */ assignLabel(program, $1.label_end); } ;

throw_statement: THROW { /* se throw block non è dentro il try block */ if(!cur_try) notifyError(AXE_SYNTAX_ERROR); /* jump to catcher */ gen_bt_instruction(program, cur_try->label_catcher, 0); } ; t_try_catch_statement create_try_catch_statement(){

t_try_catch_statement statement; statement.label_catcher = NULL; statement.label_end = NULL; return statement; } typedef struct t_try_catch_statement { /* label che punta al catch block */ t_axe_label *label_catcher; /* label che punta alla prima istruzione dopo il catch block */ t_axe_label *label_end; } t_try_catch_statement; /* create an instance that will maintain info about a try-catch statement */ extern t_try_catch_statement create_try_catch_statement(); PUNTO 4

"try" { return TRY; } "catch" { return CATCH; } "throw" { return THROW; } %token <try_catch_stmt> TRY %token CATCH %token THROW /* stack of try-catch statement */ t_list *try_stack = NULL; t_try_catch_statement try_catch_stmt; control_statement: ... | try_catch_statement | throw_statement SEMI ;

Page 46: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

try_catch_statement: TRY { /* crea un nuovo try-catch statement */ $1 = create_try_catch_statement(); $1.label_catcher = newLabel(program); $1.label_end = newLabel(program); /* push it, for throw translation */ try_stack = addFirst(try_stack, &$1); } code_block { /* end of try block, need to jump the catcher */ gen_bt_instruction(program, $1.label_end, 0); /* pop try-catch pointer */ removeFirst(try_stack); /* here starts the catch block */ assignLabel(program, $1.label_catcher); } CATCH code_block { /* fix end label */ assignLabel(program, $1.label_end); } ; throw_statement: THROW { /* stack empty, throw not inside a try block */ if(!getLength(try_stack)) notifyError(AXE_SYNTAX_ERROR); /* jump to catcher */ t_try_catch_statement *stmt = try_stack->data; gen_bt_instruction(program, stmt->label_catcher, 0); } ; t_try_catch_statement create_try_catch_statement() { t_try_catch_statement statement; statement.label_catcher = NULL; statement.label_end = NULL; return statement; } typedef struct t_try_catch_statement { /* label che punta al catch block */ t_axe_label *label_catcher; /* label che punta alla prima istruzione dopo il catch block */ t_axe_label *label_end; } t_try_catch_statement; extern t_try_catch_statement create_try_catch_statement();

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni20/06/2011

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire gli operatori ship e in.

1 a = b <=> c;(a) Operatore ship

1 a = b in c:d;(b) Operatore in

Figura 1: Esempi di operatori ship ed in

L’operatore ship permette di confrontare due espressioni. La semantica dell’e-spressione a <=> b e definita dalla funzione ship(a, b):

ship(a, b) =

−1 se a < b

0 se a = b

1 se a > b

L’operatore in e anch’esso un operatore di confronto e permette di verificare seil valore di una espressione e contenuto all’interno di un intervallo. La semanticaassociata all’espressione a in b:c e definita dalla funzione in(a, b, c):

in(a, b, c) =

{

0 se a < b ∨ a > c

1 se b ≤ a ≤ c

Per semplicita si assumano che i bound b, c siano ordinati, cioe sia sempre veroche b ≤ c.

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria acompletare la specifica data.

1Tempo 45’. Libri e appunti personali possono essere consultati.E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 47: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

La soluzione e riportata nella patch allegata.

2

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

La soluzione e riportata nella patch allegata.

3

Page 48: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

4

4. Dato il codice di Figura 2:

1 a = a + b << c + d;

Figura 2: Addizioni e scorrimenti

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale exp a precedenza piu bassa. (5 punti)

La soluzione e riportata in Figura 3.

5

Page 49: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

exp

exp

IDENTIFIER

a

PLUS

+

exp

exp

exp

IDENTIFIER

b

SHL_OP

<<

exp

IDENTIFIER

c

PLUS

+

exp

IDENTIFIER

d

Figura 3: Albero sintattico del codice riportato in Figura 2

6

5. (Bonus) Si supponga di voler implementare una versione dell’operatore ship

di modo che supporti il confronto tra array.

• Che semantica avrebbe tale operatore?

• Come dovrebbe essere implementato?

• Esiste un costrutto simile a voi noto?

L’operatore ship esteso agli array non e altro che la funzione strcmp

della libreria C delle stringhe. Essa confronta due stringhe (a.k.aarray di caratteri), mentre l’operatore ship esteso supporta array diinteri:

ship(A, B) =

−1 se ∃i | pref(A, i) = pref(B, i) ∧Ai < Bi

0 se A = B

1 altrimenti

Dove la funzione pref(A, i) restituisce il prefisso di lunghezza i delvettore A.

L’implementazione e banale. Basta generare del codice che iteri sul-l’array A fino a quando l’elemento Ai e uguale all’elemento Bi. Seper un j si trovano due elementi Aj , Bj tali che Aj < Bj alloral’array A e “piu piccolo” dell’array B. Se tale elemento non vienetrovato, oppure si raggiunge la fine dell’array B allora l’array A e“piu grande” dell’array B. Ovviamente, se i due array sono identici,l’operatore ship ritorna 0.

7

Page 50: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Applicare una patch

Sul sito del corso e disponibile una patch contenente la soluzione del tema d’esameper quanto riguarda la modifica della macchina Acse.

Per applicare la patch:

1. scaricare la macchina Acse versione 1.1.0

2. scaricare la patch soluzione-20-06-11.diff

3. scompattare l’archivio contenente la macchina Acse

4. usando il terminale, portarsi nella directory in cui e stata estratta la macchinaAcse

5. copiare in tale cartella la patch

6. applicare la patch tramite il comando

patch -p1 < soluzione-20-06-11.diff

La patch e un normalissimo file di testo, contenente le differenze tra la versionedi Acse con implementata la soluzione dell’esame e la versione 1.1.0.

Le righe che iniziano con il carattere + sono state aggiunte, mentre quelle conil carattere - sono state rimosse.

8

PUNTO 1

In Acse.lex:

"<=>" { return SHIP_OP; } "in" { return IN_OP; } In Acse.y:

%token IN_OP SHIP_OP %left LT GT LTEQ GTEQ SHIP_OP IN_OP PUNTO 2 e 3

exp: ... | exp SHIP_OP exp { /* effettuo i tre confronti */ t_axe_expressione lt = handle_binary_comparison(program, $1, $3, _LT_); t_axe_expressione eq = handle_binary_comparison(program, $1, $3, _EQ_); t_axe_expressione gt = handle_binary_comparison(program, $1, $3, _GT_); /* definisco i pesi */ t_axe_expression lt_weight = create_expression(-1, IMMEDIATE); t_axe_expression eq_weight = create_expression(0, IMMEDIATE); t_axe_expression gt_weight = create_expression(1, IMMEDIATE); /* calcolo i pesi delle espressioni */

t_axe_expression lt_fact = handle_bin_numeric_op(program,lt,lt_weight,MUL); t_axe_expression eq_fact = handle_bin_numeric_op(program,eq,eq_weight,MUL); t_axe_expression gt_fact = handle_bin_numeric_op(program,gt,gt_weight,MUL); /* calcolo il risultato */ t_axe_expression tmp = handle_bin_numeric_op(program,lt_fact,eq_fact,ADD); $$= handle_bin_numeric_op(program, tmp, gt_fact, ADD); } | exp IN_OP exp COLON exp %prec IN_OP { /* check bounds */ t_axe_expression lb = handle_binary_comparison(program, $1, $3, _GTEQ_); t_axe_expression up = handle_binary_comparison(program, $1, $5, _LTEQ_); /* controllo (ANDB) se è valida la condizione che restituirà 0 o 1 */ $$ = handle_bin_numeric_op(program, lb, up, ANDB); } ;

Page 51: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni08/09/2011

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire gli operatori di shift-rotate.

1 a = 3;

2 b = a $>>$ 1;

3 c = b $<<$ 1;

(a) Codice

Variabile

Linea a b c

1 0 . . . 112 undef undef2 0 . . . 112 10 . . . 012 undef3 0 . . . 112 10 . . . 012 0 . . . 112

(b) Contenuto delle varibili

Figura 1: Esempio di operatori di shift-rotate

Gli operatori di shift standard, << e >>, effettuano uno scorrimento a sinistra/-destra di un valore. Sia op uno dei due operatori. Calcolare il valore dell’espressionea op b equivale a spostare a sinistra/destra i bit di a di b posizioni. I bit in eccessosono scartati, mentre i bit lasciati liberi dallo spostamento sono impostati a 0.

Gli operatori di shift-rotate, $<<$ e $>>$, hanno un comportamento analogo:effettuano uno spostamento di un valore. A differenza degli operatori di shift stan-dard essi non scartano alcun bit. I bit che normalmente sono eliminati perchespostati oltre un confine, vengono reintrodotti dall’altro. Figura 1(a) contiene unesempio, mentre in Figura 1(b) e riportato il valore delle variabili dopo l’esecuzionedell’istruzione riportata in Figura 1(a) nella linea corrispondente.

Nell’implementazione, si ricordi che tutte le espressioni in Acse hanno tipo int.

1Tempo 45’. Libri e appunti personali possono essere consultati.E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria acompletare la specifica data.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

La soluzione e riportata nella patch allegata.

2

Page 52: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

La soluzione e riportata nella patch allegata.

3

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione di questo tema d’esame dipende quindi dal tipo di datocon il quale si lavora. Per osservare l’effetto degli shift-rotate comeriportato nell’esempio di Figura 1(b) e necessario avere a disposizionedei tipi di dato senza segno. Sfortunatamente la macchina Acsesupporta come unico tipo di dato l’intero con segno.

Essendo costretto ad utilizzare un tipo di dato non corretto, il com-pilatore, l’assemblatore e l’interprete eseguono operazioni corrette sudati scorretti! Ne consegue, che l’output del programma non e quelloatteso.

Posto di avere a disposizione il supporto ai tipi di dato senza segno,la soluzione proposta e corretta. Si controlli l’output del compilatore,output.asm per verificare che le istruzioni generate siano corrette.

Per ulteriori informazioni, si veda lo standard ISO/EIC 9899:TC3(C99), alla Sezione 6.2.6.2, Integer types.

La soluzione proposta modifica il framework delle espressioni di mododa introdurre due nuove istruzioni simulate. E ovviamente possibilenon introdurre alcuna nuova istruzione ed utilizzare il framework delleespressioni senza modificarlo, agendo ad un livello piu alto.

4

Page 53: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Dato il codice di Figura 2:

1 b || c | d && b

Figura 2: Operazioni logiche

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale exp a precedenza piu bassa. (5 punti)

La soluzione e riportata in Figura 3.

5

exp

exp

IDENTIFIER

b

OROR

||

exp

exp

exp

IDENTIFIER

c

OR_OP

|

exp

IDENTIFIER

d

ANDAND

&&

exp

IDENTIFIER

b

Figura 3: Albero sintattico del codice riportato in Figura 2

6

Page 54: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Si supponga di voler implementare una direttiva del compilatore chepermette di selezionare il comportamento degli operatori di scorrimento <<

e >>:

1 #pragma acse shift X

2

3 int a = 7;

4 a = a << 4;

Figura 4: Esempio d’uso della direttiva shift

Il token X puo assumere due valori:

classic - gli operatori di scorrimento si comportano usualmente

rotate - gli operatori di scorrimento si comportano come degli shift-rotate

Come bisogna modificare il compilatore Acse per supportare questa caratte-ristica?

La modifica al compilatore e banale. Inizialmente bisogna introdurrele definizioni dei token e le regole grammaticali per riconoscere lanuova direttiva.

Successivamente, allo stato del compilatore e necessario aggiungereuna variabile shift_mode che indica il comportamento degli opera-tori. Il suo valore di default equivale al comportamento classic.

L’azione semantica associata alla regola di riconoscimento della di-rettiva imposta opportunamente la variabile shift_mode.

Infine bisogna modificare l’azione semantica associata al riconosci-mento delle espressioni exp SHL_OP exp e exp SHR_OP exp in mo-do che venga generato il codice corrispondente al comportamentoclassic piuttosto che a quello rotate.

7

Applicare una patch

Sul sito del corso e disponibile una patch contenente la soluzione del tema d’esameper quanto riguarda la modifica della macchina Acse.

Per applicare la patch:

1. scaricare la macchina Acse versione 1.1.0

2. scaricare la patch soluzione-08-09-11.diff

3. scompattare l’archivio contenente la macchina Acse

4. usando il terminale, portarsi nella directory in cui e stata estratta la macchinaAcse

5. copiare in tale cartella la patch

6. applicare la patch tramite il comando

patch -p1 < soluzione-08-09-11.diff

La patch e un normalissimo file di testo, contenente le differenze tra la versionedi Acse con implementata la soluzione dell’esame e la versione 1.1.0.

Le righe che iniziano con il carattere + sono state aggiunte, mentre quelle conil carattere - sono state rimosse.

8

Page 55: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 1

In Acse.lex:

"$<<$" { return RSHL_OP; } "$>>$" { return RSHR_OP; } In Acse.y:

%token RSHL_OP RSHR_OP %left SHL_OP SHR_OP RSHL_OP RSHR_OP PUNTO 2

exp: ... | exp RSHL_OP exp { $$ = handle_bin_numeric_op(program, $1, $3, RSHL); } | exp RSHR_OP exp { $$ = handle_bin_numeric_op(program, $1, $3, RSHR); } ; PUNTO 3

#define RSHL 63 #define RSHR 64 case RSHL: gen_rshli_emulation (program, output_register, exp1.value, exp2.value); break; case RSHR: gen_rshri_emulation (program, output_register, exp1.value, exp2.value); break; case RSHL : /* we have to load into a register the immediate value */ other_reg = getNewRegister(program); /* in order to load the immediate inside a new /* register we have to insert an ADDI instr. */ gen_addi_instruction (program, output_register, REG_0, exp1.value); /* we have to emulate a RSHL instruction */ gen_rshl_emulation (program, output_register, other_reg, exp2.value, CG_DIRECT_ALL); break; case RSHR : /* we have to load into a register the immediate value */ other_reg = getNewRegister(program); /* in order to load the immediate inside a new /* register we have to insert an ADDI instr. */ gen_addi_instruction (program, output_register, REG_0, exp1.value); /* we have to emulate a RSHR instruction */ gen_rshr_emulation (program, output_register, other_reg, exp2.value, CG_DIRECT_ALL); break;

case RSHL: gen_rshl_emulation (program, output_register, exp1.value, exp2.value, CG_DIRECT_ALL); break; case RSHR: gen_rshr_emulation (program, output_register, exp1.value, exp2.value, CG_DIRECT_ALL); break; case RSHL: { int res = (val1 >> (sizeof(int) * 8 - val2)) | (val1 << val2); return create_expression (res, IMMEDIATE); } case RSHR: { int res = (val1 << (sizeof(int) * 8 - val2)) | (val1 >> val2); return create_expression (res, IMMEDIATE); } void gen_rshli_emulation(t_program_infos *program, int r_dest, int r_source1, int immediate){ gen_rshi_emulation(program, r_dest, r_source1, immediate, RSHL); } void gen_rshri_emulation(t_program_infos *program, int r_dest, int r_source1, int immediate){ gen_rshi_emulation(program, r_dest, r_source1, immediate, RSHR); } void gen_rshl_emulation (t_program_infos *program, int r_dest, int r_source1, int r_source2, int flags){ gen_rsh_emulation(program, r_dest, r_source1, r_source2, flags, RSHL); } void gen_rshr_emulation (t_program_infos *program, int r_dest, int r_source1, int r_source2, int flags){ gen_rsh_emulation(program, r_dest, r_source1, r_source2, flags, RSHR); } void gen_rshi_emulation (t_program_infos *program, int r_dest, int r_source1, int immediate, int shift_op){ int r_tmp1, r_tmp2; /* the shift amount is constant, fold at compile-time. */ int discarded_shift = sizeof(int) * 8 - immediate; /* move discarded bits into the right place. */ r_tmp1 = getNewRegister(program); switch(shift_op){ case RSHL: gen_shri_instruction(program, r_tmp1, r_source1, discarded_shift); break; case RSHR: gen_shli_instruction(program, r_tmp1, r_source1, discarded_shift); break; default: notifyError(AXE_INVALID_INSTRUCTION); }

Page 56: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

/* move not discarded bits into the right place. */ r_tmp2 = getNewRegister(program); switch(shift_op){ case RSHL: gen_shli_instruction(program, r_tmp2, r_source1, immediate); break; case RSHR: gen_shri_instruction(program, r_tmp2, r_source1, immediate); break; default: notifyError(AXE_INVALID_INSTRUCTION); } /* combine the two values. */ gen_orb_instruction(program, r_dest, r_tmp1, r_tmp2, CG_DIRECT_ALL); } void gen_rsh_emulation (t_program_infos *program, int r_dest, int r_source1, int r_source2, int flags, int shift_op){ /* we support only direct addressing, for now. */ if(flags != CG_DIRECT_ALL) notifyError(AXE_INVALID_INSTRUCTION); int r_tmp1, r_tmp2, r_tmp3, r_tmp4; /* the shift amount must be computed at run-time. */ r_tmp3 = getNewRegister(program); r_tmp4 = getNewRegister(program); gen_addi_instruction(program, r_tmp3, REG_0, sizeof(int) * 8); gen_sub_instruction(program, r_tmp4, r_tmp3, r_source2, CG_DIRECT_ALL); /* move discarded bits into the right place. */ r_tmp1 = getNewRegister(program); switch(shift_op){ case RSHL: gen_shr_instruction(program, r_tmp1, r_source1, r_tmp4, CG_DIRECT_ALL); break; case RSHR: gen_shl_instruction(program, r_tmp1, r_source1, r_tmp4, CG_DIRECT_ALL); break; default: notifyError(AXE_INVALID_INSTRUCTION); } /* move not discarded bits into the right place. */ r_tmp2 = getNewRegister(program); switch(shift_op){ case RSHL: gen_shl_instruction(program, r_tmp2, r_source1, r_source2, CG_DIRECT_ALL); break; case RSHR: gen_shr_instruction(program, r_tmp2, r_source1, r_source2, CG_DIRECT_ALL); break; default: notifyError(AXE_INVALID_INSTRUCTION); } /* Combine the two values. */ gen_orb_instruction(program, r_dest, r_tmp1, r_tmp2, CG_DIRECT_ALL); }

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni30/09/2011

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire aflex, quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti percui si ritengono necessarie delle modifiche in modo da estendere il compilatoreAcse con la possibilita di gestire l’ esecuzione di codice pilotata da un bit dellaprogram status word (PSW) tramite il costrutto on <flag> run, dove <flag> ∈{neg, zero, pos, notzero}.

1 int a,b,c;

2 on zero run a=0;

3 c= 5 * a + 7;

4 on neg run {

5 while(c>0){

6 c = c-a;

7 }

8 }

(a) Codice

Flag Bit della PSW

nonzero Z clearzero Z setpos N clearneg N set

(b) riferimento ProgramStatus Word

Figura 1: Esempio di uso del costrutto on <flag> run

Il costrutto on <flag> run consente l’ esecuzione del blocco di codice dopola parola chiave run solo se il corrispondente bit della program status word delprocessore e nello stato indicato. In particolare, la tabella di corrispondenza trail valore di <flag> e lo stato del bit della program status word che ne consentel’ esecuzione e riportata in Tabella 1(b). Il costrutto on <flag> run puo esserearbitrariamente annidato in altri costrutti.

1Tempo 45’. Libri e appunti personali possono essere consultati.E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 57: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria acompletare la specifica data.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

La soluzione e riportata nella patch allegata.

2

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

La soluzione e riportata nella patch allegata.

3

Page 58: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

L’ implementazione del costrutto richiesto e sostanzialmente quelladi un costrutto if molto semplificato.

In particolare, il costrutto decisionale in questione non ha la possi-bilita di fare salti condizionati rispetto a un’ espressione, ma si basasolamente sul controllare il valore di un bit della parola di stato. Cioe possibile direttamente utilizzando le istruzioni di salto condizionatoofferte dall’ architettura.

Inoltre, a differenza del comune costrutto if non vi e la possibilitadi specificare un ramo else.

Di conseguenza l’ implementazione del costrutto richiesto si riducea generare un salto condizionato con la condizione corretta ad unetichetta che va poi assegnata alla fine del blocco di codice che even-tualmente non va eseguito. Va curato il fatto che la condizione delsalto deve essere quella opposta a quella specificata dalla flag, inquanto si tratta di un salto usato per evitare l’ esecuzione del bloccodi codice che segue.

La soluzione completa e riportata nella patch allegata.

4

4. Dato il codice di Figura 2:

1 c & a * b == d

Figura 2: Espressioni miste

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale exp a precedenza piu bassa. (5 punti)

La soluzione e riportata in Figura 3.

5

Page 59: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

exp

exp

IDENTIFIER

c

AND_OP

&

exp

exp

exp

IDENTIFIER

a

MUL_OP

*

exp

IDENTIFIER

b

EQ

==

exp

IDENTIFIER

d

Figura 3: Albero sintattico del codice riportato in Figura 2

6

5. (Bonus) Si supponga di voler supportare un estensione del costrutto on

<flag> run da realizzarsi come on (<flag1>,<flag2>) run. Questo co-strutto consente l’ esecuzione del codice solamente nel caso in cui le condi-zioni dettate da entrambe le <flag>.Quali modifiche andrebbero apportate al compilatore Acse per supportarequesto costrutto esteso?Quale ottimizzazione sarebbe possibile implementare per gestire il caso on

(pos,neg) run?

E possibile implementare il costrutto semplicemente generando duebranch consecutivi, uno per flag seguendo la stessa logica utilizzataper realizzare il costrutto base; i token da aggiungere non cambiano.Una possibile ottimizzazione per il caso on (pos,neg) run e rea-lizzabile assegnando valori semantici ai token delle flag e, nel casovi siano due condizioni logicamente opposte, generare semplicementeun’ istruzione di salto incondizionato alla fine del blocco di codice(che viene comunque generato dall’ espansione di code block).

7

Page 60: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Applicare una patch

Sul sito del corso e disponibile una patch contenente la soluzione del tema d’esameper quanto riguarda la modifica della macchina Acse.

Per applicare la patch:

1. scaricare la macchina Acse versione 1.1.0

2. scaricare la patch soluzione-30-09-11.diff

3. scompattare l’archivio contenente la macchina Acse

4. usando il terminale, portarsi nella directory in cui e stata estratta la macchinaAcse

5. copiare in tale cartella la patch

6. applicare la patch tramite il comando

patch -p1 < soluzione-30-09-11.diff

La patch e un normalissimo file di testo, contenente le differenze tra la versionedi Acse con implementata la soluzione dell’esame e la versione 1.1.0.

Le righe che iniziano con il carattere + sono state aggiunte, mentre quelle conil carattere - sono state rimosse.

8

PUNTO 1

In Acse.lex:

"on" { return ON; } "zero" { return ZERO_FLAG; } "notzero" { return NOTZERO_FLAG; } "neg" { return NEG_FLAG; } "pos" { return POS_FLAG; } "run" { return RUN; } In Acse.y:

%token <label> ON %token ZERO_FLAG %token NOTZERO_FLAG %token NEG_FLAG %token POS_FLAG %token RUN PUNTO 2

control_statement: ... | onflag_statement ; PUNTO 3

onflag_statement: ON ZERO_FLAG RUN { $1=newLabel(program); gen_bne_instruction(program,$1,0); } code_block { assignLabel(program,$1); } | ON NOTZERO_FLAG RUN { $1=newLabel(program); gen_beq_instruction(program,$1,0); } code_block { assignLabel(program,$1); } | ON POS_FLAG RUN { $1=newLabel(program); gen_bmi_instruction(program,$1,0); } code_block { assignLabel(program,$1); } | ON NEG_FLAG RUN { $1=newLabel(program); gen_bpl_instruction(program,$1,0); }

Page 61: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

code_block { assignLabel(program,$1); } ; Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question02/02/2012

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to perform shift-rotate operations on arrays.

/* Example 1 */

a >> 3;

/* Example 2 */

a << x;

As shown in the code, an array shift-rotate is a statement formed by the nameof an array, an operator (<< for left shift-rotate, >> for right shift-rotate) and anexpression indicating the shift amount.

The array shift-rotate statement moves the elements of an array to the left(<<) or to the right (>>). The elements are moved k cells in the specified direction,where k is the value of the second operand of the statement. No element is discarted.Elements moved beyond one of the boundaries of the array, are reintroduced fromthe opposite boundary.

So, if a is a 6 elements array initialized as [0, 1, 2, 3, 4, 5]:

• the result of Example 1 is a=[3, 4, 5, 0, 1, 2].

• assuming x= 2, the result of Example 2 is a=[2, 3, 4, 5, 0, 1].

If the identifier to the left of the shift operator does not refer to an array, Acseshould print an error message and terminate. Implement the array shift-rotate asa statement, not as an expression.

Explicit any other assumption you made to implement the support for condi-tional instructions.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

Page 62: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Define the tokens (and the related declarations in Acse.lex e Acse.y). (3points)

2. Define the syntactic rules or the modifications required to the existing ones.(5 points)

2

3. Define the semantic actions needed to implement the required functionality.(17 points)

3

Page 63: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Given the following code snipped:

a == b - c && d > e

(a) Write down the syntactic tree generated during the parsing with theBison grammar described in Acse.y starting from the exp nonterminal

with the lowest priority. (5 points)

4

5. (Bonus) What modifications are needed to allow the result of the shift-rotateto be assigned to another array, without modifying the original one? (3points)

Example:

b = a << 2;

If a=[0, 1, 2, 3, 4, 5], after the statement is executed you’ll have:

a = [0, 1, 2, 3, 4, 5] and b=[2, 3, 4, 5, 0, 1]

5

Page 64: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 2 statement: ... | shift_statement SEMI ; shift_statement: IDENTIFIER SHR_OP exp | IDENTIFIER SHL_OP exp ; PUNTO 3 Abbiamo 3 possibili soluzioni diverse per implementare quanto richiesto! Soluzione 1 – SHL_OP (manca la parte con SHR_OP): shift_statement: IDENTIFIER SHL_OP exp { t_axe_expression shiftAmount = $3;

/* $1 è l’array */ t_axe_variable *id = getVariable(program, $1); /* non posso fare shift se non ho un array */

if(! id->isArray) { printMessage("Trying to shift a non-array variable"); exit(-1); }

/* first_exp rappresenta il primo elemento dell’array, /* ad ogni iterazione del loop */

t_axe_expression first_exp = create_expression(0, IMMEDIATE);

/* last_exp rappresenta l’ultimo elemento dell’array, /* ad ogni iterazione del loop */

t_axe_expression last_exp = create_expression(id->arraySize -1, IMMEDIATE);

int tempReg; /* serve start perchè abbiamo dei loop */ t_axe_label *start = assignNewLabel(program); tempReg = loadArrayElement(program, $1, first_exp);

/* devo spostare gli elementi a partire dall’indice fino ad

/* arrivare all’indice ; dalla prossima iterazione

/* al posto di avrò */ t_axe_expression i_exp = create_expression(1, IMMEDIATE); t_axe_label *inner_start = assignNewLabel(program); t_axe_expression j_exp = create_expression(i_exp.value – 1, IMMEDIATE);

/* metto nel registro il primo elemento da spostare che

/* coincide con l’elemento di indice */ int temp1Reg = loadArrayElement(program, $1, i_exp); /* metto temp1_exp perchè la storeArrayElement vuole /* un’espressione come parametro, non un registro! */ t_axe_expression temp1_exp = create_expression(temp1Reg, REGISTER); /* metto l’elemento contenuto in temp1_exp nella posizione /* rappresentata da j_exp dell’array $1 /* (nella prima iterazione metto il valore contenuto nella /* posizione 1 dentro la posizione 0) */ storeArrayElement(program, $1, j_exp, temp1_exp);

/* incremento di 1 per passare alla prossima iterazione */ i_exp = create_expression(i_exp.value + 1, IMMEDIATE);

/* controllo se allora vado avanti a iterare /* perché non ho scandito tutto il vettore, altrimenti esco /* dal ciclo interno */ handle_binary_comparison(program, i_exp, last_exp, _LT_);

/* salto a inner_start fino a quando */ gen_bne_instruction(program, inner_start, 0); t_axe_expression temp_exp = create_expression(tempReg,

REGISTER); storeArrayElement(program, $1, last_exp, temp_exp); /* creo un’espressione che mi serve per incrementare di /* una unità lo shiftAmount */ t_axe_expression one_exp = create_expression(1, IMMEDIATE); /* decremento shiftAmount di 1 ad ogni iterazione */ shiftAmount = handle_bin_numeric_op(program, shiftAmount,

one_exp, SUB);

/* salto a start fino a quando */ gen_bne_instruction(program, start, 0);

}

Soluzione 2 – SHL_OP (manca la parte con SHR_OP): shift_statement: IDENTIFIER SHL_OP exp { t_axe_expression shiftAmount = $3; /* $1 è l’array */ t_axe_variable *id = getVariable(program, $1); /* non posso fare shift se non ho un array */

if(! id->isArray) exit(-1);

Page 65: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

int N; if(shiftAmount.expression_type == IMMEDIATE) gen_addi_instruction(program, N, REG_0, shiftAmount.value); else gen_add_instruction(program, N, REG_0, shiftAmount.value, CG_DIRECT_ALL); char *tmpArray; /* l’1 come secondo elemento indica che abbiamo a che fare /* con un array */ alloc_declaration(tmpArray, 1, id->arraySize, 0); t_axe_expression i_exp = create_expression(0, IMMEDIATE); /* serve un’etichetta che indichi l’inizio del ciclo /* quando abbiamo dei loop */ t_axe_label *L1 = assignNewLabel(program); int tempReg = loadArrayElement(program, $1, i_exp); t_axe_expression temp_exp = crate_expression(tempReg,

REGISTER); storeArrayElement(program, tmpArray, i_exp, temp_exp); /* utilizzata per incrementare di 1 la i_exp */ t_axe_expression one_exp = create_expression(1, IMMEDIATE);

/* incremento di 1 per passare alla prossima iterazione */ i_exp = handle_bin_numeric_op(program, i_exp, one_exp, ADD);

/* controllo se (dove shiftAmount è la /* dimensione dell’array) allora vado avanti a iterare /* perché non ho scandito tutto il vettore, altrimenti esco /* dal ciclo */ handle_binary_comparison(program, i_exp, shiftAmount, _LT_);

/* salto a L1 fino a quando */ /* quando esco dal ciclo significa che ho copiato i primi k /* elementi nel tmpArray, posso quindi procedure a fare lo /* shift dei rimanenti */ gen_bne_instruction(program, L1, 0);

/* il primo elemento da shiftare è quello in posizione /* shiftAmount, il quale andrà messo in posizione 0 t_axe_expression from_exp = shiftAmount; t_axe_expression to_exp = create_expression(0, IMMEDIATE);

/* serve un’etichetta che indichi l’inizio del ciclo /* quando abbiamo dei loop */ t_axe_label *L2 = assignNewLabel(program); tempReg = loadArrayElement(program, $1, from_exp); /* metto l’elemento contenuto in temp_exp nella posizione /* rappresentata da to_exp dell’array $1 /* temp_exp era già stato precedentemente associato a tempReg /* aggiornando tempReg si aggiorna automaticamente temp_exp */ storeArrayElement(program, $1, to_exp, temp_exp);

from_exp = handle_bin_numeric_op(program, from_exp, one_exp, ADD);

to_exp = handle_bin_numeric_op(program, to_exp, one_exp,

ADD); t_axe_expression size_exp = create_expression(id->arraySize,

IMMEDIATE);

/* controllo se /* ovvero controllo di aver ciclato su tutto l’array originale /* nelle parti che mi interessano */ handle_binary_comparison(program, from_exp, size_exp, _LT_);

/* salto a L2 fino a quando */ /* quando esco dal ciclo significa che ho shiftato gli /* elementi dal k-esimo fino all’ultima posizione (etichetta /* size_exp), posso quindi procedere a mettere nelle ultime k posizioni gli elementi presenti in tmpArray */ gen_bne_instruction(program, L2, 0);

to_exp = create_expression(id->arraySize - 1, IMMEDIATE); to_exp = handle_bin_numeric_op(program, from_exp, shiftAmount,

SUB); /* il primo elemento dell’array originale che può ospitare il

/* primo elemento di tmpArray è in posizione

/* (per ottenere ciò faccio prima e poi ci /* tolgo con la SUB il valore di from_exp vecchio che sarà pari /* a k) */ from_exp = create_expression(0, IMMEDIATE); /* serve un’etichetta che indichi l’inizio del ciclo /* quando abbiamo dei loop */ t_axe_label *L3 = assignNewLabel(program); tempReg = loadArrayElement(program, tmpArray, from_exp); /* metto l’elemento contenuto in temp_exp nella posizione /* rappresentata da to_exp dell’array $1 */ storeArrayElement(program, $1, to_exp, temp_exp); from_exp = handle_bin_numeric_op(program, from_exp, one_exp,

ADD); to_exp = handle_bin_numeric_op(program, to_exp, one_exp,

ADD);

/* controllo se /* ovvero controllo di aver ciclato su tutto l’array originale /* nelle parti che mi interessano */ handle_binary_comparison(program, from_exp, size_exp, _LT_);

/* salto a L3 fino a quando */ gen_bne_instruction(program, L3, 0);

}

Page 66: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Soluzione 3 – quella del prof sul tde: shift_statement: IDENTIFIER SHR_OP exp { t_axe_variable *id = getVariable(program, $1);

if(! id->isArray) { printMessage("Trying to shift a non-array variable"); exit(-1); }

t_axe_expression e_zero = create_expression(0, IMMEDIATE); t_axe_expression e_arraysize = create_expression(id->arraySize, IMMEDIATE); mirrorArray(program, id, e_zero, e_arraysize); mirrorArray(program, id, e_zero, $3); mirrorArray(program, id, $3, e_arraysize);

}

| IDENTIFIER SHL_OP exp { t_axe_variable *id = getVariable(program, $1); if(! id->isArray) { printMessage("Trying to shift a non-array variable"); exit(-1); } t_axe_expression e_zero = create_expression(0, IMMEDIATE); t_axe_expression e_arraysize = create_expression(id->arraySize, IMMEDIATE); t_axe_expression e_split = handle_bin_numeric_op(program,

e_arraysize, $3, SUB); mirrorArray(program, id, e_zero, e_arraysize); mirrorArray(program, id, e_zero, e_split); mirrorArray(program, id, e_split, e_arraysize); }

; extern void mirrorArray(t_program_infos *program, t_axe_variable* array, t_axe_expression start, t_axe_expression end){ int from_reg, to_reg, result, el1_reg, el2_reg; t_axe_expression from_expr, to_expr, el1_expr, el2_expr; t_axe_label *condition_label, *end_label; /* indicizzazione iniziale */ if(start.expression_type == IMMEDIATE) from_reg = gen_load_immediate(program, start.value); else{ from_reg = getNewRegister(program); gen_andb_instruction(program, from_reg, start.value, start.value,

CG_DIRECT_ALL); }

from_expr = create_expression(from_reg, REGISTER); if(end.expression_type == IMMEDIATE) to_reg = gen_load_immediate(program, end.value); else{ to_reg = getNewRegister(program); gen_andb_instruction(program, to_reg, end.value, end.value,

CG_DIRECT_ALL); } to_expr = create_expression(to_reg, REGISTER); gen_subi_instruction(program, to_reg, to_reg, 1); /* check condition */ condition_label = assignNewLabel(program); result = getNewRegister(program); gen_sub_instruction(program, result, to_reg, from_reg, CG_DIRECT_ALL); end_label = newLabel(program); gen_ble_instruction(program, end_label, 0); /* swap */ el1_reg = loadArrayElement(program, array->ID, from_expr); el1_expr = createExpression(el1_reg, REGISTER); el2_reg = loadArrayElement(program, array->ID, to_expr); el2_expr = createExpression(el2_reg, REGISTER); storeArrayElement(program, array->ID, to_expr, el1_expr); storeArrayElement(program, array->ID, from_expr, el2_expr); /* update indices */ gen_addi_instruction(program, from_reg, from_reg, 1); gen_subi_instruction(program, to_reg, to_reg, 1); /* go back to the condition check */ gen_bt_instruction(program, condition_label, 0); /* the End */ assignLabel(program, end_label); }

Page 67: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Formal Languages and Compilers

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Written exam1: laboratory question17/03/2012

SURNAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NAME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Student ID: . . . . . . . . . . . .Course: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Other:.....Instructor: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof Morzenti

The laboratory question must be answered taking into account the implemen-tation of the Acse compiler given with the exam text.

Modify the specification of the lexical analyzer (flex input) and the syntacticanalyzer (bison input) and any other source file required to extend the Lance

language with the ability to perform the shift operation over arrays:

/* Example 1 */

a >> 2;

/* Example 2 */

a << x;

As shown in the code, an array-shift is a statement formed by the name of anarray, an operator (<< for left shift, >> for right shift) and an expression indicatingthe amount of the shift. The array-shift statement moves the elements of an arrayto the left (<<) or to the right (>>). The elements are moved k cells in the specifieddirection, where k is the value of the second operand of the statement. The elementsmoved beyond one of the boundaries of the array, are discarded. All the places inthe array where no number is shifted in from the original one are to be padded withzeros.

So, if a is a 6 elements array initialized as [0, 1, 2, 3, 4, 5]:

• the result of Example 1 is a=[0, 0, 0, 1, 2, 3].

• assuming x=4, the result of Example 2 is a=[4, 5, 0, 0, 0, 0].

If the operand on the left hand side of the shift operator is not an array, Acseshould print an error message and terminate.

Implement the array-shift as a statement, not as an expression.Explicit any other assumption you made to implement the support for the

array-shift operator.

1Time 45’. Textbooks and notes can be used.

Pencil writing is allowed. Write your name on any additional sheet.

1

1. Define the tokens (and the related declarations in Acse.lex e Acse.y). (1points)

The solution can be found in the attached patch.

2. Define the syntactic rules or the modifications required to the existing ones.(4 points)

The solution can be found in the attached patch.

2

Page 68: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Define the semantic actions needed to implement the required functionality.(20 points)

The solution can be found in the attached patch.

3

4. Given the following code snipped:

if(x>0)

a=b*2-c+3;

Write down the syntactic tree generated during the parsing with the Bisongrammar described in Acse.y starting from the statement nonterminal withlower priority. (5 points)

���

��� �����

�������� ���

���

� �

����������������

���

���������

���

�������

���

��� �� �

��� ����� � ���

����� �� � �������

!������� ���

" #

���������

!$��%$&����������

�'����������

�'�����

�� ��(� ��(� !$)��"&$!*

�'

(����

+

,

-

.

4

Page 69: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Describe how it would be possible to implement the support for ex-plicitly indicating which element should be inserted into the empty positionsinstead of the zeros. (3 points)

Example:

a << 2 (x)

If, for example, a=[0, 1, 2, 3, 4, 5] and x=2, after the execution of the state-ment it will result:a=[2, 3, 4, 5, 1, 1].As another example, if a=[0, 1, 2, 3, 4, 5] and x=7, after the statement exe-cution it will result:a=[2, 3, 4, 5, 7, 7].

The syntactic rule for the array-shift operation must be modified as follows:

array_shift_statement : IDENTIFIER SHL_OP exp LPAR exp RPAR

| IDENTIFIER SHR_OP exp LPAR exp RPAR

In the semantic action, the rule should copy the computed value bound to$5 in all the cells left without a shifted-in value.This can be accomplished through employing a loop structure, exploiting thecomputed value bound to $3 to know how many cells should be padded (sincea shift by x positions will leave exactly x cells without a defined value).It is not possible to generate a sequence of stores as the number of cells tobe padded with the specific value is not known at compile time, thus the useof a proper loop structure is mandatory in this case.

5

PUNTO 2

statement: ... | array_shift_statement SEMI ; array_shift_statement: IDENTIFIER SHL_OP exp {

shift_array(program, $1, $3, LEFT);

} | IDENTIFIER SHR_OP exp { shift_array(program, $1, $3, RIGHT);

} ; PUNTO 3

void shift_array(t_program_infos *program, char *ID, t_axe_expression shift, int direction){ /* definisco la variabile per l’array */ t_axe_variable id = getVariable(program, ID); /* se non è un array non posso fare shifting (errore) */ if(! id->isArray){ printMessage("Errore"); exit(-1); } /* registro di appoggio */ int sha_reg = getNewRegister(program); /* espressione che servirà per mettere gli 0 nell’array */ t_axe_expression zero_exp = create_expression(0, IMMEDIATE); /* registro che contiene la dimensione dell’array */ int size_reg = gen_load_immediate(program, id->arraySize); /* se l’espressione di shift è un valore numerico allora siamo nel caso /* IMMEDIATE (Esempio 1), altrimenti (Esempio 2) /* in ogni caso carico in sha_reg il valore di shift */ if(shift.expression_type == IMMEDIATE) gen_addi_instruction(program, sha_reg, REG_0, shift.value); else gen_add_instruction(program, sha_reg, REG_0, shift.value, CG_DIRECT_ALL); int temp_reg; int tr = getNewRegister(program); /* src_index contiene il primo valore da shiftare */ int src_index = getNewRegister(program); /* dest_index contiene il primo valore (caso LEFT) o l’ultimo valore /* (caso RIGHT) da shiftare */ int dest_index = getNewRegister(program);

Page 70: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

t_axe_expression src_exp, dest_exp; src_exp = create_expression(src_index, REGISTER); dest_exp = create_expression(dest_index, REGISTER); if(direction == LEFT){ gen_add_instruction(program, src_index, REG_0, sha_reg, CG_DIRECT_ALL); gen_add_instruction(program, dest_index, REG_0, REG_0, CG_DIRECT_ALL); }

else{ gen_subi_instruction(program, dest_index, size_reg, 1); gen_sub_instruction(program,src_index,dest_index,sha_reg,CG_DIRECT_ALL); }

/* imposto il punto da cui continuare a shiftare */ t_axe_label stop_shifting = newLabel(program); t_axe_label continue_shifting = assignNewLabel(program); /* controllo se ho raggiunto il limite superiore o inferiore */ if(direction == LEFT){ gen_sub_instruction(program, tr, size_reg, src_index, CG_DIRECT_ALL); gen_beq_instruction(program, stop_shifting, 0); }

else{ gen_andb_instruction(program, src_index, src_index, src_index,

CG_DIRECT_ALL); gen_blt_instruction(program, stop_shifting, 0); } /* carico il primo valore in un registro temporaneo */ temp_reg = loadArrayElement(program, ID, src_exp); t_axe_expression temp_exp = create_expression(temp_reg, REGISTER); /* copio il valore nella posizione di destinazione */ storeArrayElement(program, ID, dest_exp, temp_exp); /* aggiorno le posizioni iniziali e finali */ if(direction == LEFT){ gen_addi_instruction(program, src_index, src_index, 1); gen_addi_instruction(program, dest_index, dest_index, 1); } else{ gen_subi_instruction(program, src_index, src_index, 1); gen_subi_instruction(program, dest_index, dest_index, 1); } gen_bt_instruction(program, continue_shifting, 0); assignLabel(program, stop_shifting); /* riempio le posizioni vuote con gli 0 partendo da dest_index */ t_axe_label *stop_filling = newLabel(program); t_axe_label *continue_filling = assignNewLabel(program); if(direction == LEFT){ gen_sub_instruction(program, tr, size_reg, dest_index, CG_DIRECT_ALL); gen_beq_instruction(program, stop_filling, 0); storeArrayElement(program, ID, dest_exp, zero_exp); gen_addi_instruction(program, dest_index, dest_index, 1); }

else{ gen_andb_instruction(program, dest_index, dest_index, dest_index,

CG_DIRECT_ALL); gen_blt_instruction(program, stop_filling, 0); storeArrayElement(program, ID, dest_exp, zero_exp); gen_subi_instruction(program, dest_index, dest_index, 1); } gen_bt_instruction(program, continue_filling, 0); assignLabel(program, stop_filling); }

Page 71: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta1: Domanda relativa alle esercitazioni10/07/2012

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro:.....Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di supportare lo statement continue.

int sum=0;

int a=0;

while(a<20) {

a = a+1;

if ((a/2)*2 != a) {

/* If a is odd */

continue;

}

sum = sum + a;

}

write(sum);

int sum=0;

int a=0;

do {

a = a+1;

if ((a/2)*2 != a) {

/* If a is odd */

continue;

}

sum = sum + a;

} while (a<20);

write(sum);

La semantica di continue e la stessa che nel linguaggio C: quando continue

viene eseguito, tutti gli statement rimanenti dell’iterazione corrente del loop piuinterno vengono ignorati, la condizione viene nuovamente valutata e si passa adeseguire la prossima iterazione del loop.

Lo statement continue deve essere supportato sia per i cicli while sia per icicli do-while.

Se continue e utilizzato al di fuori di un loop, il compilatore deve stampare unmessaggio d’errore ed uscire.

1Tempo 60’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (1 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (2 punti)

2

Page 72: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (17 punti)

3

4. Dato il seguente codice:

if(a == b << c) ; else g = 0;

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dal non-terminale if statement. (10 punti)

4

Page 73: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Implementare il supporto per supportare lo statement continue aprofondita di annidamento variabile, definito come segue. (3 punti)

Esempio 1int a,i;

a = 0;

i = 0;

while (a < 20) /*Ciclo 1*/

{

a = a + 1;

i = -1;

while(i < a) {/*Ciclo 2*/

i = i + 1;

if ((i/2)*2 != i) {

continue 0;

}

write(i);

}

write(a);

}

Esempio 2int a,i;

a = 0;

i = 0;

while (a < 20) /*Ciclo 1*/

{

a = a + 1;

i = -1;

while(i < a) {/*Ciclo 2*/

i = i + 1;

if ((i/2)*2 != i) {

continue 1;

}

write(i);

}

write(a);

}

Quando continue e invocato con parametro 0 (come nell’Esempio 1), eequivalente al continue tradizionale, ossia l’esecuzione salta alla prossimaiterazione del Ciclo 2.

Quando continue e invocato con parametro 1 (come nell’Esempio 2), l’ese-cuzione salta al ciclo che si trova 1 livello prima nell’annidamento dei loop(quindi, alla prossima iterazione del Ciclo 1).

In generale,

continue K;

salta alla prossima iterazione del loop che si trova K livelli prima nell’annida-mento dei loop.

NB: si consideri K come un valore immediate.

5

PUNTO 1

In Acse.lex:

"continue" { return CONTINUE; } In Acse.y:

%token CONTINUE

PUNTO 2

/* loop_nest è una lista che contiene i puntatori alle varie iterazioni del ciclo /* in questo modo, nel momento in cui viene invocata l’istruzione continue, posso /* saltare le istruzioni dell’iterazione corrente e passare a quella successiva */ t_list *loop_nest = NULL;

statement: ... | continue_statement SEMI ; PUNTO 3

continue_statement: CONTINUE { /* se continue si trova al di fuori di un ciclo non va bene /* (errore) */ if(loop_nest == NULL){

printMessage("This continue is outside cycles!\n"); exit(1); } /* se continue si trova all’interno di un ciclo, allora

/* prendo il valore della prossima iterazione dalla lista /* loop_nest e salto a quell’istruzione */

t_axe_label *next_iter = loop_nest->data; gen_bt_instruction(program, next_iter, 0); } ; while_statement: WHILE

{ ... }

LPAR exp RPAR {

... loop_nest = addFirst(loop_nest, $1.label_condition); } code_block { ... loop_nest = removeFirst(loop_nest); } ;

Page 74: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

do_while_statement: DO { ... t_axe_label *condition = newLabel(program); loop_nest = addFirst(loop_nest, condition); } code_block { ... t_axe_label *condition = loop_nest->data; assignLabel(program, condition); loop_nest = removeFirst(loop_nest); } WHILE LPAR exp RPAR { ...

} ; REGOLA WHILE: WHILE {*} LPAR exp RPAR {**} code_block {***}; **: nuova iterazione del ciclo quindi faccio qui addFirst ***: fine iterazione del ciclio quindi faccio qui removeFirst REGOLA DO WHILE: DO {*} code_block {**} WHILE LPAR exp RPAR {***}; *: nuova iterazione del ciclo quindi faccio qui addFirst **: fine iterazione del ciclio quindi faccio qui removeFirst

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni18/09/2012

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . .Iscritto a: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Al-tro: . . .Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzarel’implementazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui siritengono necessarie delle modifiche in modo da estendere il compilatore Acse conla possibilita di gestire l’ esistenza di una variabile implicita, a cui vengono assegnatii risultati di espressioni secondo la seguente semantica: se un’ espressione e presentecome unico elemento all’ interno di una riga di codice, il risultato viene stoccatoall’ interno della variabile implicita.

E possibile accedere in lettura al contenuto della variabile implicita allo scopodi utilizzarla come una comune variabile tramite la parola chiave implicit, come daesempi qui a seguito:

1 int a= 20;

2 int b= 20;

3 a+b;

4 write(implicit );(a) Variabile Implicita

1 int a= 20;

2 int b= 20;

3 int implicit;

4 implicit=a+b;

5 write(implicit );(b) Codice Equivalente

Figura 1: Esempio di utilizzo della variabile implicita.

Il codice in Figura 1(a) stocca il risultato della somma tra a e b nella variabileimplicita e successivamente lo stampa a video usando la keyword implicit per ac-cedervi. La Figura 1(b) riporta il codice equivalente, indicando esplicitamente lavariabile. N.B.: la sintassi di Figura 1(b) non e valida secondo la specifica data,in quanto implicit e una parola chiave. Il frammento di codice in Figura 1(b) e daintendersi solamente come chiarimento della semantica del frammento con sintassicorretta in Figura 1(a).

1Tempo 60’. Libri e appunti personali possono essere consultati.E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 75: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

La variabile implicita e unica per tutto il programma.Si espliciti ogni eventuale ulteriore assunzione che sia ritenuta necessaria a

completare la specifica data.

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessariper ottenere la funzionalita richiesta. (3 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

2

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

3

Page 76: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Dato il codice di Figura 2:

1 int a,b;

2 ;

Figura 2: Dichiarazioni di variabili.

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definitain Acse.y iniziando dall’ assioma program. (5 punti)

4

5. (Bonus) Si descriva come e possibile implementare una versione alternativadella variabile implicita la cui visibilita, o scope sia limitata al solo code block

in cui questa viene assegnata. (3 punti)

5

Page 77: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 2

var_declarations: var_declarations var_declaration | { /* durante la creazione delle variabili aggiungo la variabile

/* implicita, il cui nome deve essere sempre accessibile */ t_axe_declaration *implicit_decl = NULL; t_list *stub_list = NULL; /* creo una struttura per la dichiarazione della variabile */ implicit_decl = alloc_declaration(strdup("implicit",0,0,0)); /* aggiungo alla lista il puntatore implicit */ stub_list = addElement(NULL, implicit_decl, -1); /* creo la variabile per ogni dichiarazione axe all'interno

/* della lista set_new_variables(program, INTEGER_TYPE, stub_list); } ; statement: ... | implicit_var_statement SEMI ; PUNTO 3

implicit_var_statement: exp { /* dato un identifier ritorna il registro dove è /* presente implicit */ int implicit_var_location; implicit_var_location = get_symbol_location(program,

strdup("implicit"), 0); /* salvo nel registro di implicit il valore /* dell'espressione */

t_axe_instruction *instr; instr = gen_add_instruction(program,

implicit_var_location, REG_0, $1.value, CG_DIRECT_ALL);

} ; if_statement: ... | IMPLICIT

{ int location; location = get_symbol_location(program, “implicit”, 0); $$ = create_expression(location, REGISTER); }

;

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni

28/02/2013

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . . . . .Corso: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Altro: . . .

Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’imple-mentazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengononecessarie delle modifiche in modo da estendere il compilatore Acse con la possibilitadi gestire il tipo di dato matrice. Si consideri il seguente snippet di codice:

int matrix[3, 2]; // 3 rows, 2 columns

int i = 1;

matrix[i - 1, 0] = 1;

matrix[i - 1, 1] = 2;

matrix[i, 0] = matrix[i - 1, 0] * 2;

matrix[i, 1] = matrix[i - 1, 1] * 3;

Analogamente agli array, una matrice e dichiarata con dimensioni costanti. E possi-bile assegnare ed utilizzare il valore di una singola cella specificandone l’indice di riga e

di colonna.Per implementare tale supporto e necessario linearizzare la matrice, ovvero mappare glielementi della stessa in elementi di un array monodimensionale equivalente la cui lun-ghezza e pari al numero di elementi della matrice. Si richiede che le matrici siano

linearizzate per colonne. A tal fine si assuma che:

• nelle strutture t axe variable e t axe declaration siano presenti anchei campi di tipo intero isMatrix, rows, columns, utilizzabili per tracciare leinformazioni del tipo matrice,

• internamente il compilatore supporti tali informazioni e le propaghi correttamente.

1Tempo 60’. Libri e appunti personali possono essere consultati.

E’ consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 78: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta. (1 punto)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (3 punti)

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (16 punti)

La soluzione e riportata nella patch allegata.

2 3

Page 79: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Si consideri la seguente funzione:

void createVariable(t_program_infos *program, char *ID, int type,

int isArray, int arraySize, int init_val) {

t_axe_variable *var;

if (program == NULL)

notifyError(AXE_PROGRAM_NOT_INITIALIZED);

var = alloc_variable(ID, type, isArray, arraySize, init_val);

if (var == NULL)

notifyError(AXE_OUT_OF_MEMORY);

var->labelID = newLabel(program);

addVariable(program, var);

}

Figura 1: Funzione createVariable.

e il seguente snippet di codice estratto dalla funzione set new variables:

while (current_element != NULL) {

current_decl = (t_axe_declaration *) LDATA(current_element);

if (current_decl == NULL) {

free_new_variables(variables);

notifyError(AXE_NULL_DECLARATION);

}

createVariable(program, current_decl->ID, varType,

current_decl->isArray, current_decl->arraySize,

current_decl->init_val);

current_element = LNEXT(current_element);

}

Figura 2: Porzione di codice di set new variables.

Si proponga una modifica dello snippet estratto dalla funzione set new variables

al fine di gestire correttamente il tipo matrice. (5 punti)

La soluzione e riportata nella patch allegata.

4 5

Page 80: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. Data il seguente snippet di codice Lance:

int a, b = 0; int x[3]; ;

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definita inAcse.y. (5 punti)

program

var declarations

var declarations

var declarations

ε

var declaration

TYPE

int

declaration list

declaration list

declaration

IDENTIFIER

a

COMMA

,

declaration

IDENTIFIER

b

ASSIGN

=

NUMBER

0

SEMI

;

var declaration

TYPE

int

declaration list

declaration

IDENTIFIER

x

LSQUARE

[

NUMBER

3

RSQUARE

]

SEMI

;

statements

statement

SEMI

;

6

6. (Bonus) Descrivere come modificare la soluzione proposta in modo da estendere ilsupporto al tipo matrice rendendo possibile la specifica del tipo di linearizzazionedesiderata (per righe o colonne) al momento della dichiarazione:

int matrix_A[3, 5] by rows;

int matrix_B[3, 5] by cols;

7

Page 81: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 2

exp: ... | IDENTIFIER LSQUARE NUMBER COMMA NUMBER RSQUARE { /* creo una nuova istanza di t_axe_declaration */ $$ = alloc_declaration_matrix($1, $3, $5); if($$ == NULL) notifyError(AXE_OUT_OF_MEMORY); } | IDENTIFIER LSQUARE exp COMMA exp RSQUARE ASSIGN exp { /* calcolo l'indice per l'array linearizzato */ t_axe_expression linearIndex = matrixLinearIndex(program, $1, $3, $5); /* carico nell'array il risultato */ storeArrayElement(program, $1, linearIndex, $8); /* libero la memoria associata all’IDENTIFIER */ free($1); } | IDENTIFIER LSQUARE exp COMMA exp RSQUARE { int reg; t_axe_expression linearIndex = matrixLinearIndex(program, $1, $3, $5); /* carico il valore IDENTIFIER[exp] in arrayElement */ reg = loadArrayElement(program, $1, linearIndex); /* creo una nuova espressione */

$$= create_expression(reg, REGISTER); /* libero la memoria associata all’IDENTIFIER */ free($1); } ; PUNTO 3

t_axe_expression matrixLinearIndex(t_program_infos *program, char *ID, t_axe_expression row, t_axe_expression col){ /* creo una variabile per ospitare l’IDENTIFIER della matrice */ t_axe_variable *var = getVariable(program, ID); if(! var->isMatrix) notifyError(AXE_INVALID_TYPE); /* creo un’espressione che contiene la dimensione in righe della matrice */ t_axe_expression fact = create_expression(var->rowSize, IMMEDIATE); /* moltiplico le colonne per la dimensione delle righe /* per trovare la colonna di partenza t_axe_expression li = handle_bin_numeric_op(program, col, fact, MUL);

/* aggiungo le righe al valore ottenuto per trovare l'indice ricercato li = handle_bin_numeric_op(program, row, li, ADD); return li; } t_axe_declaration *alloc_declaration_matrix(char *ID, int row, int cols){ t_axe_declaration *result= alloc_declaration(ID, 1, row * cols, 0); if(result == NULL) return NULL; result->isMatrix = 1; result->colonSize = cols; result->rowSize = row; return result; } PUNTO 4

if (current_decl->isMatrix) createVariableMatrix(program, current_decl->ID, varType,

current_decl->rowSize, current_decl->colonSize); else

createVariable(program, current_decl->ID, varType, current_decl->isArray, current_decl->arraySize, current_decl->init_val);

void createVariableMatrix(t_program_infos *program, char *ID, int type, int rows, int cols){ if (program == NULL) notifyError(AXE_PROGRAM_NOT_INITIALIZED); t_axe_variable *var = alloc_variable_matrix(ID, type, rows, cols); if (var == NULL) notifyError(AXE_OUT_OF_MEMORY); var->labelID = newLabel(program); addVariable(program, var); } t_axe_declaration *alloc_declaration_matrix(char *ID, int row, int cols){ t_axe_declaration *result= alloc_declaration(ID, 1, row * cols, 0); if(result == NULL) return NULL; result->isMatrix = 1; result->colonSize = cols; result->rowSize = row; return result; }

Page 82: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni

28/06/2013

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . . . . .Corso: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Altro: . . .

Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’imple-mentazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengononecessarie delle modifiche in modo da estendere il compilatore Acse con la possibilitadi gestire il costrutto array comprehension per assegnare valore ad un vettore di interi.

int i, x[5], y[7];

x[0] = 1; x[1] = 2; x[2] = 3;

x[3] = 4; x[4] = 5;

// y = {-2, 1, 6, 13, 22, undef, undef}

y = [i * i - 3 for i in x];

write(y[3]);

Figura 1: Esempio

Ad ogni posizione del vettore destinazione (y) e assegnato il valore di una espressioneche dipende dal valore dell’elemento (i) nella medesima posizione del vettore sorgente(x). Si noti che:

• le variabili coinvolte devono essere dichiarate

• il costrutto non richiedere che le dimensioni dei vettori siano uguali.

s

1Tempo 60’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta. (3 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

2

Page 83: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3

4. Data il seguente snippet di codice Lance:

x * -7 > -y * (2 - x)

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definita inAcse.y iniziando dal non-terminale exp. (5 punti)

exp

exp

exp

IDENTIFIER

x

MUL OP

*

exp

MINUS

-

exp

NUMBER

7

GT

>

exp

MINUS

-

exp

exp

IDENTIFIER

y

MUL OP

*

exp

LPAR

(

exp

exp

NUMBER

2

MINUS exp

IDENTIFIER

x

RPAR

)

4

Page 84: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Si mostri un possibile modo di estendere il supporto al costrutto array

comprehension in modo da poter generare i valori da assegnare anche dalla specificadi un intervallo di valori discreti e ∈ [a, b).

int y[7], l, e;

read(l);

y = [2 * e - 7 for e in range(3, l)];

5

PUNTO 1

In Acse.lex:

"in" { return IN; } In Acse.y:

%token IN PUNTO 2

control_statement: ... | for_in_stmt SEMI ; PUNTO 3

struct{ t_axe_label *body_label; t_axe_label *control_label; int index_reg: }array_compr; for_in_stmt: IDENTIFIER ASSIGN { /* carico nel registro contenente l'indice dell'array il valore 0, /* ovvero il valore iniziale array_compr.index_reg = gen_load_immediate(program, 0); array_compr.control_label = newLabel(program); /* salto verso la fine del programma per trovare la i e la x */ gen_bt_instruction(program, array_compr.control_label, 0); /* assegno la label */ array_compr.body_label = assignNewLabel(program); } LSQUARE exp { /* assegno ad una variabile locale il valore della variabile /* globale e creo l'espressione */ int index_reg = array_compr.index_reg; t_axe_expression index_exp = create_expression(index_reg,REGISTER); storeArrayElement(program, $1, index_exp, $5); /* aggiorno l'indice aggiungendo 1 al contenuto di index_reg */ gen_addi_instruction(program, index_reg, index_reg, 1); } FOR IDENTIFIER IN IDENTIFIER RSQUARE { t_axe_variable *dest = getVariable(program, $1); t_axe_variable *iv = getVariable(program, $8); t_axe_variable *src = getVariable(program, $10);

Page 85: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

/* controllo che siano array tranne iv if(! dest->isArray || iv->isArray || ! src->isArray) exit(-1); /* calcolo quale array sia il più corto */ t_axe_expression min_size = create_expression(dest->size < src->size

? dest->size : src->size, IMMEDIATE); /* trovo il registro contenente i int iv_reg = get_symbol_location(program, $8, 0); int index_reg = array_compr.index_reg; t_axe_expression index_exp = create_expression(index_reg, REGISTER); t_axe_label *end_label = newLabel(program); /* assegno qui la label del bt precedente */ assignLabel(program, array_compr.control.label); /* controllo che l'indice sia inferiore della dimensione /* dell'array più corto */ t_axe_expression cmp = handle_bin_comparison(program, index_exp, min_size, _LT_); gen_beq_instruction(program, end_label, 0); /* carico il valore di i int elem = loadArrayElement(program, $10, index_expr); gen_addi_instruction(program, iv_reg, elem, REG_0); gen_bt_instruction(program, array_compr.body_label, 0); assignLabel(program, end_label); free($1); free($8); free($10); } ;

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni

06/09/2013

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . . . . .Corso: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Altro: . . .

Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’imple-mentazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengononecessarie delle modifiche in modo da estendere il compilatore Acse con la possibilitadi gestire il costrutto either-or-on.

int a, z, b, k;

// ...

either {

read(a);

a = a - 99;

} or {

z = 27;

a = z - b;

a = a * a;

} on a < 27 * k;

Figura 1: Esempio

Il costrutto either-or-on e simile al costrutto if-then-else: quando la condizione (spe-cificata dopo la keyword on) e verificata sara eseguito il blocco either, altrimenti saraeseguito il blocco or.

1Tempo 60’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 86: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta. (3 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

2 3

Page 87: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Data il seguente snippet di codice Lance:

x - (7 & k[j]) || 42 / i < y

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definita inAcse.y iniziando dal non-terminale exp. (5 punti)

exp

exp

exp

IDENTIFIER

x

MINUS OP

-

exp

LPAR

(

exp

exp

NUMBER

7

AND OP

&exp

IDENTIFIER

k

LSQUARE

[

exp

IDENTIFIER

j

RSQUARE

]

RPAR

)

OROR OP

||

exp

exp

exp

NUMBER

42

DIV OP

/

exp

IDENTIFIER

i

LT

<

exp

IDENTIFIER

y

4

5. (Bonus) Si indichi come estendere il costrutto either-or-on in modo da ripeterel’esecuzione dello stesso fino a quando non e verificata una condizione data:

either {

a[j] = h[j];

j = j + 1

} or {

b[j] = h[j];

j = j + 2;

} on h[j] - h[j]/2

until j >= 2*z;

5

Page 88: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 1+2

In Acse.lex

"either" { return EITHER; }

"or" { return OR; }

"on" { return ON; }

In Acse.y

- Semantic records

t_either_statement either_stmt;

- Token

%token OR ON

%token <either_stmt> EITHER

- Bison grammar

control_statement: …| either_statement SEMI

;

In axe_struct.h

typedef struct t_either_statement

{

t_axe_label *either_label;

t_axe_label *or_label;

t_axe_label *on_label;

t_axe_label *end_label;

} t_either_statement;

PUNTO 3

either_statement : EITHER

{

$1.or_label = newLabel(program);

$1.on_label = newLabel(program);

$1.end_label = newLabel(program);

gen_bt_instruction(program, $1.on_label, 0);

$1.either_label = assignNewLabel(program);

}

code_block OR

{

gen_bt_instruction(program, $1.end_label, 0);

assignLabel(program, $1.or_label);

}

code_block

{

gen_bt_instruction(program, $1.end_label, 0);

assignLabel(program, $1.on_label);

}

ON exp

{

if ($9.expression_type == IMMEDIATE) {

t_axe_label *dest = $9.value ? $1.either_label : $1.or_label;

gen_bt_instruction(program, dest, 0);

} else {

gen_andb_instruction(program, $9.value, $9.value, $9.value, CG_DIRECT_ALL);

gen_bne_instruction(program, $1.either_label, 0);

gen_bt_instruction(program, $1.or_label, 0);

}

assignLabel(program, $1.end_label);

}

;

Page 89: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

Linguaggi Formali e Compilatori

Proff. Breveglieri, Crespi Reghizzi, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni

25/09/2013

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . . . . .Corso: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Altro: . . .

Sezione: ◦ Prof. Breveglieri ◦ Prof. Crespi ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’imple-mentazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengononecessarie delle modifiche in modo da estendere il compilatore Acse con la possibilitadi gestire il costrutto loop-decreasing.

int x[100], input, c = 0, s = 100;

loop_decreasing s by c {

read(input);

c = c + 5;

write(c);

} while (input > 32 && c < 50);

write(input);

write(s);

Figura 1: Esempio

Questo tipo di ciclo ha come parametri un variabile contatore, un espressione di

decremento e una condizione di esecuzione. Il costrutto ha i seguenti vincoli:

• condizione necessaria per l’esecuzione del ciclo e che la variabile di conteggio siapositiva.

• l’esecuzione di tutte le iterazioni ad eccezione della prima e controllata anchedalla condizione di esecuzione: se la condizione e falsa il flusso di controllo escedal ciclo. In altre parole, la condizione di esecuzione e valutata alla fine del corpodel ciclo.

1Tempo 60’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta. (2 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (4 punti)

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (18 punti)

La soluzione e riportata nella patch allegata.

2

Page 90: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

3

4. Data il seguente snippet di codice Lance:

int v[100], i;

v[i / 8] = i & i * 42;

write(i);

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definita inAcse.y iniziando dal non-terminale statements. (6 punti)

statements

statements

statement

assign statement

IDENTIFIER

v

LSQUARE

[

exp

exp

IDENTIFIER

i

DIV OP

/

exp

NUMBER

8

RSQUARE

]

ASSIGN

=

exp

exp

IDENTIFIER

i

AND OP

&

exp

exp

IDENTIFIER

i

MUL OP

*

exp

NUMBER

42

SEMI

;

statement

read write statement

write statement

WRITE

write

LPAR

(

exp

IDENTIFIER

i

RPAR

)

SEMI

;

4

Page 91: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

5. (Bonus) Descrivere come estendere il costrutto loop-decreasing affinche usi unaespressione come valore del contatore anziche una variabile.Riportare la grammatica bison modifica che mostri entrambe le varianti del co-strutto loop-decreasing.Un’implementazione completa e opzionale.

int x,y,i;

read(x);

read(y);

loop_decreasing

from x + 100 by 14 - y {

i = i + 1;

write(i);

} while (y + i < 100);

5

PUNTO 1+2 In Acse.lex "read" { return READ; } "write" { return WRITE; } "loop_decreasing" { return LOOP_DECREASING; } "by" { return BY; } In Acse.y

- Semantic records

t_loop_decreasing_statement loop_decreasing_stmt; } - Token %token BY %token <loop_decreasing_stmt> LOOP_DECREASING - Bison grammar

control_statement: …| loop_decreasing_statement SEMI ; In axe_struct.h

typedef struct t_loop_decreasing_statement { t_axe_label *label_body; t_axe_label *label_end; t_axe_label *label_exp; } t_loop_decreasing_statement;

PUNTO 3

loop_decreasing_statement : LOOP_DECREASING IDENTIFIER { int iv_reg = get_symbol_location(program, $2, 0); gen_andb_instruction(program, iv_reg, iv_reg, iv_reg, CG_DIRECT_ALL); $1.label_end = newLabel(program); $1.label_body = newLabel(program); gen_bgt_instruction(program, $1.label_body,0); gen_bt_instruction(program,$1.label_end,0); $1.label_exp = assignNewLabel(program); } BY exp { int iv_reg = get_symbol_location(program, $2, 0); if ($5.expression_type == IMMEDIATE) gen_subi_instruction(program, iv_reg, iv_reg,

Page 92: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

$5.value); else gen_sub_instruction(program, iv_reg, iv_reg, $5.value, CG_DIRECT_ALL); gen_ble_instruction(program, $1.label_end, 0); assignLabel(program, $1.label_body); } code_block WHILE LPAR exp RPAR { if ($10.expression_type == REGISTER) { gen_andb_instruction(program, $10.value, $10.value, $10.value, CG_DIRECT_ALL); gen_bne_instruction(program, $1.label_exp, 0); } else if ($10.value) { gen_bt_instruction(program, $1.label_exp, 0); } assignLabel(program, $1.label_end); } ;

Linguaggi Formali e Compilatori

Proff. Breveglieri, Morzenti

Prova scritta 1: Domanda relativa alle esercitazioni

11/02/2014

COGNOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

NOME: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Matricola: . . . . . . . . . . . . . . . .Corso: ◦ Laurea Specialistica ◦ V. O. ◦ Laurea Triennale ◦ Altro: . . .

Sezione: ◦ Prof. Breveglieri ◦ Prof.Morzenti

Per la risoluzione della domanda relativa alle esercitazioni si deve utilizzare l’imple-mentazione del compilatore Acse che viene fornita insieme al compito.

Si richiede di modificare la specifica dell’analizzatore lessicale da fornire a flex,quella dell’analizzatore sintattico da fornire a bison ed i file sorgenti per cui si ritengononecessarie delle modifiche in modo da estendere il compilatore Acse con la possibilitadi gestire espressioni condizionali Python-like. Si consideri il seguente esempio:

int a;

int b;

read(a);

read(b);

b = a * 2 - b if a > 2 * b else 0;

write(b);

L’espressione condizionale qui presentata e sempre definita per ogni valore della con-dizione, indicata tra le keyword if ed else, e vale l’espressione che precede la keywordif nel caso la condizione sia vera, altrimenti l’espressione che segue la keyword else.Si specifichi inoltre la precedenza e associativita degli operatori in modo opportuno alfine di garantire la composizione di espressioni condizionali.

Sono preferibili implementazioni del costrutto che non mantengano il flusso di ese-cuzione lineare.

1Tempo 60’. Libri e appunti personali possono essere consultati.

E consentito scrivere a matita. Scrivere il proprio nome sugli eventuali fogli aggiuntivi.

1

Page 93: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

1. Definire i token (e le relative dichiarazioni in Acse.lex e Acse.y) necessari perottenere la funzionalita richiesta. (2 punti)

2. Definire le regole sintattiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (3 punti)

3. Definire le azioni semantiche (o le modifiche a quelle esistenti) necessarie perottenere la funzionalita richiesta. (20 punti)

La soluzione e riportata nella patch allegata.

2 3

Page 94: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

4. Data il seguente snippet di codice Lance:

a = -a * b;;

Scrivere l’albero sintattico relativo partendo dalla grammatica Bison definita inAcse.y iniziando dal non-terminale statements. (5 punti)

statements

statements

statement

assign statement

IDENTIFIER

a

ASSIGN

=

exp

MINUS

exp

exp

IDENTIFIER

a

MUL OP exp

IDENTIFIER

b

SEMI

;

statement

SEMI

;

4

5. (Bonus) Si descriva come estendere il costrutto dato in modo da poter specificareun valore alternativo per l’espressione qualora questa abbia valore zero.

x = a if c > 2 else b onzero 42;

5

Page 95: Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi ... · Linguaggi Formali e Compilatori Proff. Breveglieri, Crespi Reghizzi, Morzenti Prova scritta 1: Domanda relativa

PUNTO 1+2

In Acse.y

- Operator precedences

+%left IF ELSE

%left OROR

PUNTO 3

exp: …

| exp IF exp ELSE exp

{

if ($3.expression_type == IMMEDIATE) {

$$ = $3.value ? $1 : $5;

} else {

t_axe_expression zero = create_expression(0, IMMEDIATE);

t_axe_expression cmp = handle_binary_comparison(program, $3, zero, _EQ_);

t_axe_expression one = create_expression(1, IMMEDIATE);

t_axe_expression mask = handle_bin_numeric_op(program, cmp, one, SUB);

int r = getNewRegister(program);

gen_notb_instruction(program, r, mask.value);

t_axe_expression nmask = create_expression(r, REGISTER);

$$ = handle_bin_numeric_op(program,

handle_bin_numeric_op(program, $1, mask, ANDB),

handle_bin_numeric_op(program, $5, nmask, ANDB),

ORB);

}

}