Next: About this document ...
Up: Compiler Theory: Assignment 3
Previous: A starting point for the
To make things simple, one could avoid linked lists
and use only records and arrays instatead.
For instance let us consider the following
types in mool-3.h
#define INT "int"
// Maximum effective size of strings
#define MAX_STRING_LENGTH 255
// Maximum effective number of classes
#define MAX_CLASS_NUMBER 16
// Maximum effective number of attributes per class
#define MAX_ATTRIBUTE_NUMBER 16
// Maximum effective number of methods per class
#define MAX_METHOD_NUMBER 64
// Maximum effective number of parameters per method
#define MAX_PARAMETER_NUMBER 16
// Maximum effective number of variables per body
#define MAX_VARIABLE_NUMBER 64
// A parsed variable will be known by its name and type
// By convention the type field will refer to the class
// rank in the class table. Negative values will be used
// for primitive types. Currently we have only one such
// type which is int and we will use -1 for it.
typedef struct {
char name[MAX_STRING_LENGTH+1];
int type;
} Variable;
// This structure is meant to store information
// local to the body of a method or the main body
// of a program. In our case, this information
// consists of local Variables together with
// the number of them.
typedef struct {
Variable varTab[MAX_VARIABLE_NUMBER];
int varNumb;
} Locals;
// This structure is meant to store the information
// related to a method.
typedef struct {
char name[MAX_STRING_LENGTH+1];
Variable paramTab[MAX_PARAMETER_NUMBER];
int paramNumb;
Locals body;
int class;
} Method;
// This structure is meant to store the information
// related to a class.
typedef struct {
char name[MAX_STRING_LENGTH+1];
Variable attribTab[MAX_ATTRIBUTE_NUMBER];
int attribNumb;
Method methTab[MAX_METHOD_NUMBER];
int methNumb;
} Class;
Here's the version mool-3.y
of the mool.y YACC program.
- The symbol table for the whole program
consists of
- the table classTab for the classes
- and the table mainBody for the
variables declared in the MainBody.
- The global variables classNumber
pc, pa, pm keep track
of where we are in the parsing:
how many classes yet, which class now,
which attribute and which method
respectively.
Observe that
- we report errors on the error canal
- when a construct (like an attribute declaration)
is invalid, we just skip it and continue parsing
- types are encoded by integers:
- -1 for int
- ranks in classTab for classes.
- Certain actions should become function calls:
- we should put the definitions of these
functions in a separate C file
- we should declare these functions together
with the global variables in the header file mool.h
%{
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mool.h"
// The symbol table for classes
Class classTab[MAX_CLASS_NUMBER];
// The current number of known classes
int classNumber=0;
// The index in classTab of the class
// currently being parsed
int pc =-1;
// The index in classTab[pc] of the attribute
// currently being parsed
int pa =-1;
// The index in classTab[pc] of the method
// currently being parsed
int pm =-1;
// The symbol table of the main body
Locals mainBody;
int i;
int j;
int c;
int na;
int yywrap()
{
return 1;
}
%}
%union{
int ival;
char sval[MAX_STRING_LENGTH+1];
};
%token <ival> TOK_NUM
%token <sval> TOK_CLASS TOK_INT TOK_iD TOK_ID TOK_LP TOK_LB TOK_RP TOK_RB TOK_SM TOK_ERROR
%type <sval> kind
%%
program : {printf("Parsing program ... \n"); }
classDecs
{printf("Program parsed.\n");
// Reporting on the symbol tables:
for(i=0;i<classNumber;i++) {
printf("Class[%d] is %s\n", i, classTab[i].name);
na = classTab[i].attribNumb;
for (j=0;j<na;j++) {
printf(" Attribute %d : %s of type %d\n",
j,
(classTab[i].attribTab)[j].name,
(classTab[i].attribTab)[j].type);
}
}
}
;
classDecs : classDec classDecs
| /* empty word */
;
classDec : TOK_CLASS
TOK_ID
{
if (classNumber < MAX_CLASS_NUMBER)
{
pc++;
pa = -1;
pm =-1;
strcpy(classTab[pc].name, $2);
printf(" Parsing class %s ...\n",
classTab[pc].name);
classNumber++;
}
}
TOK_LB
attributes
TOK_RB
{
if (classNumber < MAX_CLASS_NUMBER)
{
printf(" Class parsed.\n");
}
}
;
attributes : attribute
attributes
| /* empty word */
;
attribute :
kind
TOK_iD
{
if (classTab[pc].attribNumb < MAX_ATTRIBUTE_NUMBER)
{
// Determining the type of the attribute
c = -2;
if (strcmp($1,INT) == 0) {
c = - 1;
} else {
for (i=0;i<classNumber;i++) {
if (strcmp($1,classTab[i].name) == 0) {
c = i;
break;
}
}
}
// Feeding the symbol table if type ok
if (c > -2) {
pa++;
strcpy((classTab[pc].attribTab)[pa].name, $2);
(classTab[pc].attribTab)[pa].type = c;
(classTab[pc].attribNumb)++;
} else {
fprintf(stderr,"\nUnknown type:\n%s\n", $1);
}
// One could also check if the attribute
// was not already defined ...
}
}
TOK_SM
;
kind : TOK_ID { strcpy($$, $1);}
| TOK_INT { strcpy($$, $1); }
;
%%
Consider the MOOL program:
class Pair {
int left;
int right;
}
class ThreeByTwo {
Pair left;
Pair middle;
Pair right;
}
class MeliMelo {
int a;
Pair b;
int c;
ThreeByTwo d;
}
The parsing of this file with mool-3.y:
[moreno@iguanodon yacc]$ ./bin/mool < test/p3.mool
Parsing program ...
Parsing class Pair ...
Class parsed.
Parsing class ThreeByTwo ...
Class parsed.
Parsing class MeliMelo ...
Class parsed.
Program parsed.
Class[0] is Pair
Attribute 0 : left of type -1
Attribute 1 : right of type -1
Class[1] is ThreeByTwo
Attribute 0 : left of type 0
Attribute 1 : middle of type 0
Attribute 2 : right of type 0
Class[2] is MeliMelo
Attribute 0 : a of type -1
Attribute 1 : b of type 0
Attribute 2 : c of type -1
Attribute 3 : d of type 1
Next: About this document ...
Up: Compiler Theory: Assignment 3
Previous: A starting point for the
Marc Moreno Maza
2004-12-01