-
Notifications
You must be signed in to change notification settings - Fork 1
/
token.c
151 lines (139 loc) · 2.46 KB
/
token.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "token.h"
static int tokcap = 8;
static const char *in;
const char *tok_string[] = {
"NOT AN OPERATOR",
"NOT AN OPERATOR",
"'*'",
"'/'",
"'+'",
"'-'",
"'^'",
"NOT AN OPERATOR",
"'('",
"')'",
"'{'",
"'}'",
"'['",
"']'",
"a number",
"a variable",
"end of line"
};
void tok_add(struct Token token) {
if(tokcount >= tokcap) {
tokcap = tokcap*1.5;
toklist = realloc(toklist, tokcap * sizeof *toklist);
}
toklist[tokcount] = token;
tokcount++;
}
bool tokisop(struct Token tok) {
switch(tok.type) {
case START_OP ... END_OP:
return true;
break;
default:
return false;
break;
}
}
static enum TokenType tok_type(const char *c) {
switch(*c) {
case '+': return ADD;
case '-': return SUB;
case '*': return PROD;
case '/': return DIV;
case '^': return EXP;
case '(': return OPAREN;
case ')': return CLOPAREN;
case '{': return OBRACE;
case '}': return CLOBRACE;
case '[': return OBRACKET;
case ']': return CLOBRACKET;
case '0' ... '9': return NUM;
case ' ': return NONE;
default: return VAR;
}
}
static struct Token tok_var() {
int n = 0;
const char *start = in;
while (*in && (tok_type(in) == VAR)) {
in++;
n++;
}
struct Token tok = {.type = VAR, .name=strndup(start, n)};
return tok;
}
// Number format {'0'..'9'}['.'{'0'..'9'}][('e'|'E')['+'|'-']{'0'..'9'}['.'{'0'..'9'}]]
// e.g. 1.25e23
static struct Token tok_num() {
int n = 0;
const char *start = in;
while(isdigit(*in)) {
in++;
n++;
}
if(*in == '.') {
in++;
n++;
while(isdigit(*in)) {
in++;
n++;
}
}
if(*in == 'e') {
while(isdigit(*in)) {
in++;
n++;
}
if(*in == '.') {
in++;
n++;
while(isdigit(*in)) {
in++;
n++;
}
}
}
struct Token tok;
tok.type = NUM;
tok.name = strndup(start, n);
tok.val = strtod(start, NULL);
return tok;
}
void tokenize(const char * input) {
tokcount = 0;
in = input;
struct Token tok;
// init toklist
toklist = malloc(tokcap * sizeof *toklist);
while(*in) {
tok.type = tok_type(in);
if(tok.type == NUM) {
//char *end = NULL;
//errno = 0;
//tok.val = strtod(in, &end);
//if(errno) {
// perror("string-number conversion");
//}
//if(in == end) {
// printf("Invalid Number %s\n", in);
// in++;
//} else {
// in = (const char *)end;
//}
tok = tok_num();
} else if(tok.type == VAR){
tok = tok_var();
} else {
in++;
}
if(tok.type != NONE) {
tok_add(tok);
}
}
tok.type = EOL;
tok_add(tok);
}