-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.c
135 lines (114 loc) · 2.74 KB
/
lexer.c
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
/* Implementation of "lexer.h" */
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "lexer.h"
/* NB: allocation below requires that END is the last token
TAKE CARE to synchronize token_name with token type of lexer.h
*/
static const char* token_name[END+1] = {
"<INT>",
"#",
"?",
"+",
"-",
"*",
"/",
"(",
")",
"<END>"
};
void display(token t, int v) {
printf("%s", token_name[t]);
switch (t) {
case INT:case VAR:
if (v >= 0) {
printf("%d",v);
} else {
printf("...\n");
}
default:
break;
}
}
void unexpected(token t, int v, const char *mesg) {
printf("ERROR: unexpected token ");
display(t, v);
if (mesg[0] != 0) {
printf(" in %s", mesg);
}
printf("\n");
exit(1);
}
static int isDigit(char c) {
return '0' <= c && c <= '9';
}
static int digit(char c) {
assert(isDigit(c));
return c - '0';
}
static char current;
static void update_current() {
current = fgetc(stdin);
}
static void parse_int(int *v) {
int res=0;
if (! isDigit(current)) {
printf("LEXICAL ERROR: unexpected character '%c'\n", current);
exit(1);
}
do{
res = res *(10) + digit(current) ;
update_current();
}while(isDigit(current));
*v = res;
}
/* Boolean variable indicating whether "current" has been initialized or not.
NB: this variable is only used in "next".
*/
static int init = 0;
token next(int *v) {
if (! init) {
// phase d'initialisation
update_current();
init = 1;
}
for ( ; ; ) {
switch (current) {
case ' ': case '\t': case '\n':
update_current();
break;
case '+':
update_current();
return PLUS;
case '-':
update_current();
return MINUS;
case '*':
update_current();
return MULT;
case '/':
update_current();
return DIV;
case EOF:
return END;
case '?':
update_current();
return QUEST;
//on traite en dernier les deux cas de INT et VAR
case '#':
update_current();
parse_int(v);
return VAR;
//cas des parenthèses: rajoutées pour le TP2
case '(':
update_current();
return OPAR;
case ')':
update_current();
return CPAR;
default:
parse_int(v);
return INT;
};}
}