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