-
Notifications
You must be signed in to change notification settings - Fork 0
/
scanner.l
167 lines (123 loc) · 4.42 KB
/
scanner.l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
%option yylineno
%x COMMENT
%x DQUOTE
%{
#include "token.h"
#include "symtab.h"
#include "global.h"
#include <string.h>
#include <stdarg.h>
char *line;
void copy_line();
%}
%%
^.* { copy_line(); }
/* commenti */
"/*" { BEGIN COMMENT; }
<COMMENT>[^*\n]* { }
<COMMENT>"*/" { BEGIN INITIAL; }
<COMMENT><<EOF>> { yyerror("unterminated comment"); BEGIN INITIAL; } /* begin initial -> evita loop */
("//".*) { }
/* stringhe */
\"\" { yylval.s = " "; return STRING; }
\" { BEGIN DQUOTE; }
<DQUOTE>([^"\\\n]|\\.)* { yylval.s = strdup(yytext); return STRING; }
<DQUOTE>\" { BEGIN INITIAL; }
<DQUOTE>\n |
<DQUOTE><<EOF>> { yyerror("missing terminating \" character"); BEGIN INITIAL; }
/* costanti numeriche */
[0]+ |
[1-9][0-9]* { yylval.s = strdup(yytext); return INT_NUM; }
[0]+[0-9]+ { yyerror("octal literal not allowed"); }
([0-9]+)?(\.[0-9]+) |
([0-9]+)\. |
([0-9]+)(e|E)(\+|-)?[0-9]+ |
([0-9]+)?(\.[0-9]+)(e|E)(\+|-)?[0-9]+ |
(([0-9]+)\.)(e|E)(\+|-)?[0-9]+ { yylval.s = strdup(yytext); return FLOAT_NUM; }
/* keyword */
"if" { return IF; }
"else" { return ELSE; }
"for" { return FOR; }
"scanf" { yylval.s = strdup(yytext); return SCANF; }
"printf" { yylval.s = strdup(yytext); return PRINTF; }
"return" { return RETURN; }
"int" { return INT; }
"float" { return FLOAT; }
"double" { return DOUBLE; }
"void" { return VOID; }
/* identificatori */
[_a-zA-Z][_a-zA-Z0-9]* { yylval.s = strdup(yytext); return ID; }
/* operatori aritmentici */
"+" |
"-" |
"*" |
"/" |
"=" { return yytext[0]; }
/* operatori logici */
"!" { return NOT; }
"&&" { return AND; }
"||" { return OR; }
/* operatori di confronto */
">" |
"<" { return yytext[0]; }
">=" { return GE; }
"<=" { return LE; }
"==" { return EQ; }
"!=" { return NE; }
/* altri simboli */
"{" { return yytext[0]; }
"}" { return yytext[0]; }
"(" |
")" |
"[" |
"]" |
";" |
"," |
"&" { return yytext[0]; }
/* spazi e tabulazioni */
[ \t\v\f\n] { }
/* fallback per gli errori */
. { yyerror(error_string_format("invalid character" BOLD " %s" RESET, yytext)); }
%%
/* Copia le righe dell'input */
void copy_line() {
if(line) {
free(line);
}
line = malloc(sizeof(char) * (yyleng + 1));
strcpy(line, yytext);
// restituisce la linea al buffer di input per matcharlo con le regole successive
yyless(0);
}
/* Printa gli errori sullo standard error e mantiene un contatore degli errori */
void yyerror(const char *s) {
fprintf(stderr, "%s:%d " RED "error:" RESET " %s\n", filename, yylineno, s);
fprintf(stderr, "%s\n", line);
error_num++;
}
/* Printa i warning sullo standard error */
void yywarning(char *s) {
/* per stamparlo su stderr */
fprintf(stderr, "%s:%d " YELLOW "warning:" RESET " %s\n", filename, yylineno, s);
fprintf(stderr, "%s\n", line);
}
/* Printa delle note sullo stantard error (tipicamente associate ad errori o warning) */
void yynote(char *s, int lineno, char *line){
fprintf(stderr, "%s:%d " BLUE "note:" RESET " %s\n", filename, lineno, s);
fprintf(stderr, " %s\n", line);
}
/* Funzione variadica di supporto alle funzioni per il print di errori, warning e note,
prende come parametro una format string e un numero variabile di argomenti
restituisce una nuova stringa dove sono inseriti i valori degli argomenti
*/
char* error_string_format(char *msg, ...) {
va_list args;
va_start(args, msg);
int size = vsnprintf(NULL, 0, msg, args) + 1; // serve per restituire la dimensione di msg + args
va_end(args);
char *buffer = malloc(size);
va_start(args, msg); //indica che il parametro msg precede la lista degli argomenti variabili
vsprintf(buffer, msg, args);
va_end(args);
return buffer;
}