]> mj.ucw.cz Git - umpf.git/blob - lex.c
part of conditions, printing variables
[umpf.git] / lex.c
1 #include <stdio.h>
2 #include <ctype.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6
7 #include "cond.tab.h"
8 #include "brum.h"
9 #define BUFSIZE 4096
10 #define KLEN 10 
11
12 struct keys {
13         char* keywords;
14         enum yytokentype keytoks;
15 };
16
17 static struct keys kwds[] = 
18         {       {"copy", KW_COPY},
19                 {"else", KW_ELSE},
20                 {"if", KW_IF}, 
21                 {"mail", KW_MAIL}, 
22                 {"pipe", KW_PIPE}
23         };
24
25 void __attribute__ ((noreturn)) 
26 die(char* msg, ...)
27 {
28         va_list args;
29
30         va_start(args, msg);
31         vfprintf(stderr, msg, args);
32         fputc('\n', stderr);
33         va_end(args);
34         exit(1);
35 }
36
37 void*
38 xmalloc(size_t size)
39 {
40         void* ret;
41
42         if (!(ret = malloc(size)))
43                 die("Low memory");
44
45         return ret;
46 }
47
48 static void __attribute__ ((noreturn)) 
49 parse_err(char* msg, ...)
50 {
51         va_list args;
52
53         va_start(args, msg);
54         fprintf(stderr, "Line %d: ", line);
55         vfprintf(stderr, msg, args);
56         fputc('\n', stderr);
57         va_end(args);
58         exit(1);
59 }
60
61 char*
62 xstrdup(char* s)
63 {
64         void* ret;
65
66         if (!(ret = strdup(s)))
67                 die("Low memory");
68
69         return ret;
70 }
71
72 static char*
73 get_string_out(int delim)
74 {
75         int last = delim; 
76         int i = 0;
77         int c;
78         char buf[BUFSIZE];
79
80         while ((c = getchar()) != delim || last == '\\'){
81                 if (last=='\\' && c != delim)
82                         buf[i-1] = c;
83                 else {          
84                         buf[i] = c;
85                         i++;
86                 }
87                 last = c;
88                 if (i >= BUFSIZE-1)
89                         parse_err("Too long string, max allowed length is %d",BUFSIZE-1);       
90         }       
91         buf[i] = '\0';
92
93         return xstrdup(buf);
94 }
95
96 static int
97 is_var_id(int c)
98 {
99         return  (c >= '0' && c <= '9' ) ||
100                 (c >= 'a' && c <= 'z') ||
101                 (c >= 'A' && c <= 'Z') ||
102                 c == '_' ||
103                 c == '-'; 
104 }
105
106 static int
107 is_alpha(int c)
108 {
109         return (c >= 'a' && c <= 'z') ||
110                 (c >= 'A' && c <= 'Z');
111 }
112
113 int
114 yylex(void)
115 {
116         int c;
117         
118         while ((c = getchar ()) == ' ' || c == '\t' || c =='\n'){
119                 if (c == '\n')
120                         line++;
121         }
122         
123         if (c == EOF)
124                 return 0;
125         
126         int d = getchar();
127         if (d >= 0) {
128                 switch (CC(c,d)) {
129                 case CC('!','='): yylval.n = CC('!','='); return NEQ;
130                 case CC('!','~'): yylval.n = CC('!','='); return NRE;
131                 case CC('<','='): yylval.n = CC('<','='); return LE;
132                 case CC('>','='): yylval.n = CC('>','='); return GE;
133                 case CC('=','='): yylval.n = CC('=','='); return EQ;
134                 case CC('~','~'): yylval.n = CC('~','~'); return RE;
135                 case CC('-','>'): yylval.n = CC('-','>'); return ARROW;
136                 }
137                 ungetc(d,stdin);
138         }
139
140         switch (c) {
141                 case '!':
142                 case '(':
143                 case ')':
144                 case '-':
145                 case '+':
146                 case '*':
147                 case '/':
148                 case '{':
149                 case '}':
150                 case '<':
151                 case '>':
152                 case '=':
153                 case ';':
154                 case '.':
155                 case '|':
156                 case '&':
157                 case '^':
158                         yylval.n = c;
159                         return c;
160                 
161                 case '"':
162                 case '\'':
163                         yylval.str = get_string_out(c);
164                         return CONST;   
165         }
166
167         if (c >= '0' && c <= '9'){
168                 ungetc(c,stdin);
169                 int i = 0;
170                 char buf[BUFSIZE];
171         
172                 while ((c = getchar())>= '0' && c<= '9'){
173                         buf[i] = c;
174                         i++;
175                         if (i >= BUFSIZE-1)
176                                 parse_err("Too long number");   
177                 }
178                 ungetc(c,stdin);
179                 buf[i] = 0;
180                 yylval.str = xstrdup(buf);
181
182                 return CONST;
183         }
184
185         if (c == '$'){
186                 int i = 0;
187                 char buf[BUFSIZE];
188         
189                 while (is_var_id(c = getchar())){
190                         buf[i]=c;
191                         i++;
192                         if (i >= BUFSIZE-1)
193                                 parse_err("Too long identifier, max allowed length is %d",BUFSIZE-1);   
194                 }
195                 ungetc(c,stdin);
196                 buf[i] = 0;
197                 yylval.str = xstrdup(buf);
198
199                 return VAR;
200         }
201
202         if (is_alpha(c)){
203                 char buf[KLEN]; 
204                 int n, i = 0;
205
206                 ungetc(c,stdin);
207                 while (is_alpha(c = getchar())){
208                         buf[i++] = c;
209                         if (i >= KLEN)
210                                 parse_err("Keyword too long");
211                 }
212                 buf[i] = 0;
213                 ungetc(c,stdin);
214
215                 n = (sizeof(kwds)/sizeof(struct keys));
216                 for (i = 0; i < n; i++){
217                         if (!strcmp(buf,kwds[i].keywords))
218                                 return kwds[i].keytoks;
219                 }
220
221                 parse_err("Unknown keyword %s", buf);
222         }
223
224         parse_err("Unknown character %c", c);
225 }