Premier exercice
This commit is contained in:
		
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
exclude-executables.sh
 | 
			
		||||
lexical/example
 | 
			
		||||
lexical/flux
 | 
			
		||||
lexical/string
 | 
			
		||||
*.c
 | 
			
		||||
							
								
								
									
										3
									
								
								exclude-executables.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								exclude-executables.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
find . -perm /111 -type f | sed 's#^./##' | sort > .gitignore
 | 
			
		||||
echo "*.c" >> .gitignore
 | 
			
		||||
							
								
								
									
										29
									
								
								lexical/example.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lexical/example.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
%option noyywrap
 | 
			
		||||
 | 
			
		||||
%{
 | 
			
		||||
int lines = 1;  // On compte la première ligne
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
DIG	[0-9]
 | 
			
		||||
HEX 0x[0-9A-Fa-f]+
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
{HEX}	{ printf("hex(%d)", strtol(yytext, NULL, 16)); }
 | 
			
		||||
{DIG}+	{ printf("int(%d)", atoi(yytext)); }
 | 
			
		||||
"if"	{ printf("IF"); }
 | 
			
		||||
"then"	{ printf("THEN"); }
 | 
			
		||||
"else"	{ printf("ELSE"); }
 | 
			
		||||
\n		{ lines++; }
 | 
			
		||||
.		{ /* Pour tous les autres caractères, on ne fait rien */ }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
int main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	if (argc > 1) yyin = fopen(argv[1], "r");
 | 
			
		||||
	yylex();
 | 
			
		||||
	puts("");
 | 
			
		||||
	printf("%d lignes\n", lines);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								lexical/flux.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lexical/flux.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
%option noyywrap
 | 
			
		||||
 | 
			
		||||
%{
 | 
			
		||||
enum { T_INT = 1, T_CHAR = 2 };
 | 
			
		||||
union {
 | 
			
		||||
	int i;
 | 
			
		||||
	char c;
 | 
			
		||||
} data; 
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
DIG	[0-9]
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
{DIG}+	{ data.i = atoi(yytext); return T_INT; }
 | 
			
		||||
[+*()]	{ data.c = *yytext; return T_CHAR; }
 | 
			
		||||
[ \n]   { /* ignore */ }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
int main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int token;
 | 
			
		||||
	if (argc > 1) yyin = fopen(argv[1],"r");
 | 
			
		||||
	while (token = yylex())
 | 
			
		||||
	{
 | 
			
		||||
		switch(token)
 | 
			
		||||
		{
 | 
			
		||||
		  	case T_INT: printf("int(%d)  ",data.i); break;
 | 
			
		||||
		  	case T_CHAR: printf("'%c'  ",data.c); break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	puts("");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								lexical/string.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								lexical/string.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
%option noyywrap
 | 
			
		||||
 | 
			
		||||
DIG	[0-9]
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
{DIG}+	{ printf("int(%d)  ",atoi(yytext)); }
 | 
			
		||||
[+*()]	{ printf("'%c'  ",*yytext); }
 | 
			
		||||
[ \n]   { /* ignore */ }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
int main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	YY_BUFFER_STATE buffer;
 | 
			
		||||
 | 
			
		||||
	buffer = yy_scan_string("100+5*2");
 | 
			
		||||
	yylex();
 | 
			
		||||
	yy_delete_buffer(buffer);
 | 
			
		||||
 | 
			
		||||
	buffer = yy_scan_string("20+30");
 | 
			
		||||
	yylex();
 | 
			
		||||
	yy_delete_buffer(buffer);
 | 
			
		||||
 | 
			
		||||
	puts("");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								syntaxique/counter.my
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								syntaxique/counter.my
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
bool x,y,z;
 | 
			
		||||
 | 
			
		||||
while !(x && y && z) do
 | 
			
		||||
	print x,y,z;
 | 
			
		||||
	x := x ^ (y && z);
 | 
			
		||||
	y := y ^ z;
 | 
			
		||||
	z := !z
 | 
			
		||||
od
 | 
			
		||||
							
								
								
									
										39
									
								
								syntaxique/expr.y
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								syntaxique/expr.y
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
%{
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int yylex();
 | 
			
		||||
 | 
			
		||||
void yyerror(char *s)
 | 
			
		||||
{
 | 
			
		||||
        fflush(stdout);
 | 
			
		||||
        fprintf(stderr, "%s\n", s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
%union {
 | 
			
		||||
        int   i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
%token <i> INT
 | 
			
		||||
%type <i> E
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
S	: E		{ printf("result=%d\n",$1); }
 | 
			
		||||
 | 
			
		||||
E	: E '*' E	{ $$ = $1*$3; }
 | 
			
		||||
	| E '+' E	{ $$ = $1+$3; }
 | 
			
		||||
	| '(' E ')'	{ $$ = $2; }
 | 
			
		||||
	| INT
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
#include "exprlex.c"
 | 
			
		||||
 | 
			
		||||
int main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	if (argc > 1) yyin = fopen(argv[1],"r");
 | 
			
		||||
	yyparse();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								syntaxique/exprlex.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								syntaxique/exprlex.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
%option noyywrap
 | 
			
		||||
 | 
			
		||||
DIG	[0-9]
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
{DIG}+	{ yylval.i = atoi(yytext); return INT; }
 | 
			
		||||
[+*()]	{ return *yytext; }
 | 
			
		||||
[ \n]   { /* ignore */ }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										225
									
								
								syntaxique/lang.y
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								syntaxique/lang.y
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,225 @@
 | 
			
		||||
%{
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
int yylex();
 | 
			
		||||
 | 
			
		||||
void yyerror(char *s)
 | 
			
		||||
{
 | 
			
		||||
	fflush(stdout);
 | 
			
		||||
	fprintf(stderr, "%s\n", s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***************************************************************************/
 | 
			
		||||
/* Data structures for storing a programme.                                */
 | 
			
		||||
 | 
			
		||||
typedef struct var	// a variable
 | 
			
		||||
{
 | 
			
		||||
	char *name;
 | 
			
		||||
	int value;
 | 
			
		||||
	struct var *next;
 | 
			
		||||
} var;
 | 
			
		||||
 | 
			
		||||
typedef struct varlist	// variable reference (used for print statement)
 | 
			
		||||
{
 | 
			
		||||
	struct var *var;
 | 
			
		||||
	struct varlist *next;
 | 
			
		||||
} varlist;
 | 
			
		||||
 | 
			
		||||
typedef struct expr	// boolean expression
 | 
			
		||||
{
 | 
			
		||||
	int type;	// TRUE, FALSE, OR, AND, NOT, 0 (variable)
 | 
			
		||||
	var *var;
 | 
			
		||||
	struct expr *left, *right;
 | 
			
		||||
} expr;
 | 
			
		||||
 | 
			
		||||
typedef struct stmt	// command
 | 
			
		||||
{
 | 
			
		||||
	int type;	// ASSIGN, ';', WHILE, PRINT
 | 
			
		||||
	var *var;
 | 
			
		||||
	expr *expr;
 | 
			
		||||
	struct stmt *left, *right;
 | 
			
		||||
	varlist *list;
 | 
			
		||||
} stmt;
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
/* All data pertaining to the programme are accessible from these two vars. */
 | 
			
		||||
 | 
			
		||||
var *program_vars;
 | 
			
		||||
stmt *program_stmts;
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
/* Functions for settting up data structures at parse time.                 */
 | 
			
		||||
 | 
			
		||||
var* make_ident (char *s)
 | 
			
		||||
{
 | 
			
		||||
	var *v = malloc(sizeof(var));
 | 
			
		||||
	v->name = s;
 | 
			
		||||
	v->value = 0;	// make variable false initially
 | 
			
		||||
	v->next = NULL;
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var* find_ident (char *s)
 | 
			
		||||
{
 | 
			
		||||
	var *v = program_vars;
 | 
			
		||||
	while (v && strcmp(v->name,s)) v = v->next;
 | 
			
		||||
	if (!v) { yyerror("undeclared variable"); exit(1); }
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
varlist* make_varlist (char *s)
 | 
			
		||||
{
 | 
			
		||||
	var *v = find_ident(s);
 | 
			
		||||
	varlist *l = malloc(sizeof(varlist));
 | 
			
		||||
	l->var = v;
 | 
			
		||||
	l->next = NULL;
 | 
			
		||||
	return l;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr* make_expr (int type, var *var, expr *left, expr *right)
 | 
			
		||||
{
 | 
			
		||||
	expr *e = malloc(sizeof(expr));
 | 
			
		||||
	e->type = type;
 | 
			
		||||
	e->var = var;
 | 
			
		||||
	e->left = left;
 | 
			
		||||
	e->right = right;
 | 
			
		||||
	return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stmt* make_stmt (int type, var *var, expr *expr,
 | 
			
		||||
			stmt *left, stmt *right, varlist *list)
 | 
			
		||||
{
 | 
			
		||||
	stmt *s = malloc(sizeof(stmt));
 | 
			
		||||
	s->type = type;
 | 
			
		||||
	s->var = var;
 | 
			
		||||
	s->expr = expr;
 | 
			
		||||
	s->left = left;
 | 
			
		||||
	s->right = right;
 | 
			
		||||
	s->list = list;
 | 
			
		||||
	return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* types used by terminals and non-terminals */
 | 
			
		||||
 | 
			
		||||
%union {
 | 
			
		||||
	char *i;
 | 
			
		||||
	var *v;
 | 
			
		||||
	varlist *l;
 | 
			
		||||
	expr *e;
 | 
			
		||||
	stmt *s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
%type <v> declist
 | 
			
		||||
%type <l> varlist
 | 
			
		||||
%type <e> expr
 | 
			
		||||
%type <s> stmt assign
 | 
			
		||||
 | 
			
		||||
%token BOOL WHILE DO OD ASSIGN PRINT OR AND XOR NOT TRUE FALSE
 | 
			
		||||
%token <i> IDENT
 | 
			
		||||
 | 
			
		||||
%left ';'
 | 
			
		||||
 | 
			
		||||
%left OR XOR
 | 
			
		||||
%left AND
 | 
			
		||||
%right NOT
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
prog	: bools stmt	{ program_stmts = $2; }
 | 
			
		||||
 | 
			
		||||
bools	: BOOL declist ';'	{ program_vars = $2; }
 | 
			
		||||
 | 
			
		||||
declist	: IDENT			{ $$ = make_ident($1); }
 | 
			
		||||
	| declist ',' IDENT	{ ($$ = make_ident($3))->next = $1; }
 | 
			
		||||
 | 
			
		||||
stmt	: assign
 | 
			
		||||
	| stmt ';' stmt	
 | 
			
		||||
		{ $$ = make_stmt(';',NULL,NULL,$1,$3,NULL); }
 | 
			
		||||
	| WHILE expr DO stmt OD
 | 
			
		||||
		{ $$ = make_stmt(WHILE,NULL,$2,$4,NULL,NULL); }
 | 
			
		||||
	| PRINT varlist
 | 
			
		||||
		{ $$ = make_stmt(PRINT,NULL,NULL,NULL,NULL,$2); }
 | 
			
		||||
 | 
			
		||||
assign	: IDENT ASSIGN expr
 | 
			
		||||
		{ $$ = make_stmt(ASSIGN,find_ident($1),$3,NULL,NULL,NULL); }
 | 
			
		||||
 | 
			
		||||
varlist	: IDENT			{ $$ = make_varlist($1); }
 | 
			
		||||
	| varlist ',' IDENT	{ ($$ = make_varlist($3))->next = $1; }
 | 
			
		||||
 | 
			
		||||
expr	: IDENT		{ $$ = make_expr(0,find_ident($1),NULL,NULL); }
 | 
			
		||||
	| expr XOR expr	{ $$ = make_expr(XOR,NULL,$1,$3); }
 | 
			
		||||
	| expr OR expr	{ $$ = make_expr(OR,NULL,$1,$3); }
 | 
			
		||||
	| expr AND expr	{ $$ = make_expr(AND,NULL,$1,$3); }
 | 
			
		||||
	| NOT expr	{ $$ = make_expr(NOT,NULL,$2,NULL); }
 | 
			
		||||
	| TRUE		{ $$ = make_expr(TRUE,NULL,NULL,NULL); }
 | 
			
		||||
	| FALSE		{ $$ = make_expr(FALSE,NULL,NULL,NULL); }
 | 
			
		||||
	| '(' expr ')'	{ $$ = $2; }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
#include "langlex.c"
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
/* programme interpreter      :                                             */
 | 
			
		||||
 | 
			
		||||
int eval (expr *e)
 | 
			
		||||
{
 | 
			
		||||
	switch (e->type)
 | 
			
		||||
	{
 | 
			
		||||
		case TRUE: return 1;
 | 
			
		||||
		case FALSE: return 0;
 | 
			
		||||
		case XOR: return eval(e->left) ^ eval(e->right);
 | 
			
		||||
		case OR: return eval(e->left) || eval(e->right);
 | 
			
		||||
		case AND: return eval(e->left) && eval(e->right);
 | 
			
		||||
		case NOT: return !eval(e->left);
 | 
			
		||||
		case 0: return e->var->value;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_vars (varlist *l)
 | 
			
		||||
{
 | 
			
		||||
	// Attention, varlist is in reverse order (this was easier to set up
 | 
			
		||||
	// at parse time, see the code for varlist in the grammar).
 | 
			
		||||
 | 
			
		||||
	if (!l) return;
 | 
			
		||||
	print_vars(l->next);
 | 
			
		||||
	printf("%s = %c  ", l->var->name, l->var->value? 'T' : 'F');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void execute (stmt *s)
 | 
			
		||||
{
 | 
			
		||||
	switch(s->type)
 | 
			
		||||
	{
 | 
			
		||||
		case ASSIGN:
 | 
			
		||||
			s->var->value = eval(s->expr);
 | 
			
		||||
			break;
 | 
			
		||||
		case ';':
 | 
			
		||||
			execute(s->left);
 | 
			
		||||
			execute(s->right);
 | 
			
		||||
			break;
 | 
			
		||||
		case WHILE:
 | 
			
		||||
			while (eval(s->expr)) execute(s->left);
 | 
			
		||||
			break;
 | 
			
		||||
		case PRINT: 
 | 
			
		||||
			print_vars(s->list);
 | 
			
		||||
			puts("");
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
 | 
			
		||||
int main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	if (argc <= 1) { yyerror("no file specified"); exit(1); }
 | 
			
		||||
	yyin = fopen(argv[1],"r");
 | 
			
		||||
	if (!yyparse()) execute(program_stmts);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								syntaxique/langlex.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								syntaxique/langlex.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
%option noyywrap
 | 
			
		||||
 | 
			
		||||
DIG	[0-9]
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
"bool"	{ return BOOL; }
 | 
			
		||||
"while"	{ return WHILE; }
 | 
			
		||||
"do"	{ return DO; }
 | 
			
		||||
"od"	{ return OD; }
 | 
			
		||||
"print"	{ return PRINT; }
 | 
			
		||||
"true"	{ return TRUE; }
 | 
			
		||||
"false"	{ return FALSE; }
 | 
			
		||||
 | 
			
		||||
":="	{ return ASSIGN; }
 | 
			
		||||
"^"	{ return XOR; }
 | 
			
		||||
"||"	{ return OR; }
 | 
			
		||||
"&&"	{ return AND; }
 | 
			
		||||
"!"	{ return NOT; }
 | 
			
		||||
 | 
			
		||||
[a-z_][a-z0-9_]* { yylval.i = strdup(yytext); return IDENT; }
 | 
			
		||||
 | 
			
		||||
[	 \n]   { /* ignore */ }
 | 
			
		||||
 | 
			
		||||
.	{ return *yytext; }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user