commit 2f18fb4e70cc0ba1edf3e14755fdb631af4c7657 Author: Yohann D'ANELLO Date: Sat May 16 01:51:08 2020 +0200 Premier exercice diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd51575 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +exclude-executables.sh +lexical/example +lexical/flux +lexical/string +*.c diff --git a/exclude-executables.sh b/exclude-executables.sh new file mode 100755 index 0000000..9c4d224 --- /dev/null +++ b/exclude-executables.sh @@ -0,0 +1,3 @@ +#!/bin/sh +find . -perm /111 -type f | sed 's#^./##' | sort > .gitignore +echo "*.c" >> .gitignore diff --git a/lexical/example.l b/lexical/example.l new file mode 100644 index 0000000..2fc5e4e --- /dev/null +++ b/lexical/example.l @@ -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; +} diff --git a/lexical/flux.l b/lexical/flux.l new file mode 100644 index 0000000..ba959b4 --- /dev/null +++ b/lexical/flux.l @@ -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(""); +} diff --git a/lexical/string.l b/lexical/string.l new file mode 100644 index 0000000..31b3c1a --- /dev/null +++ b/lexical/string.l @@ -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(""); +} diff --git a/syntaxique/counter.my b/syntaxique/counter.my new file mode 100644 index 0000000..6132809 --- /dev/null +++ b/syntaxique/counter.my @@ -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 diff --git a/syntaxique/expr.y b/syntaxique/expr.y new file mode 100644 index 0000000..4a63ea1 --- /dev/null +++ b/syntaxique/expr.y @@ -0,0 +1,39 @@ +%{ +#include + +int yylex(); + +void yyerror(char *s) +{ + fflush(stdout); + fprintf(stderr, "%s\n", s); +} + +%} + +%union { + int i; +} + +%token INT +%type 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(); +} + diff --git a/syntaxique/exprlex.l b/syntaxique/exprlex.l new file mode 100644 index 0000000..b1b9658 --- /dev/null +++ b/syntaxique/exprlex.l @@ -0,0 +1,12 @@ +%option noyywrap + +DIG [0-9] + +%% + +{DIG}+ { yylval.i = atoi(yytext); return INT; } +[+*()] { return *yytext; } +[ \n] { /* ignore */ } + +%% + diff --git a/syntaxique/lang.y b/syntaxique/lang.y new file mode 100644 index 0000000..9cef9f8 --- /dev/null +++ b/syntaxique/lang.y @@ -0,0 +1,225 @@ +%{ + +#include +#include +#include + +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 declist +%type varlist +%type expr +%type stmt assign + +%token BOOL WHILE DO OD ASSIGN PRINT OR AND XOR NOT TRUE FALSE +%token 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); +} diff --git a/syntaxique/langlex.l b/syntaxique/langlex.l new file mode 100644 index 0000000..3ba90bd --- /dev/null +++ b/syntaxique/langlex.l @@ -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; } + +%% +