]> mj.ucw.cz Git - umpf.git/blob - lex.c
add arrow and .
[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 "lex.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 static 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 #define CC(a,b) ((a<<8)|b)
127         int d = getchar();
128         if (d >= 0) {
129                 switch (CC(c,d)) {
130                 case CC('!','='): yylval.n = CC('!','='); return NEQ;
131                 case CC('!','~'): yylval.n = CC('!','='); return NRE;
132                 case CC('<','='): yylval.n = CC('<','='); return LE;
133                 case CC('>','='): yylval.n = CC('>','='); return GE;
134                 case CC('=','='): yylval.n = CC('=','='); return EQ;
135                 case CC('~','~'): yylval.n = CC('~','~'); return RE;
136                 case CC('-','>'): yylval.n = CC('-','>'); return ARROW;
137                 }
138                 ungetc(d,stdin);
139         }
140
141         switch (c) {
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                         yylval.n = c;
157                         return c;
158                 
159                 case '"':
160                 case '\'':
161                         yylval.str = get_string_out(c);
162                         return CONST;   
163         }
164
165         if (c >= '0' && c <= '9'){
166                 ungetc(c,stdin);
167                 scanf("%d",&yylval.n);
168                 return NUM;
169         }
170
171         if (c == '$'){
172                 int i = 0;
173                 char buf[BUFSIZE];
174         
175                 while (is_var_id(c = getchar())){
176                         buf[i]=c;
177                         i++;
178                         if (i >= BUFSIZE-1)
179                                 parse_err("Too long identifier, max allowed length is %d",BUFSIZE-1);   
180                 }
181                 ungetc(c,stdin);
182                 buf[i] = 0;
183                 yylval.str = xstrdup(buf);
184
185                 return VAR;
186         }
187
188         if (is_alpha(c)){
189                 char buf[KLEN]; 
190                 int n, i = 0;
191
192                 ungetc(c,stdin);
193                 while (is_alpha(c = getchar())){
194                         buf[i++] = c;
195                         if (i >= KLEN)
196                                 parse_err("Keyword too long");
197                 }
198                 buf[i] = 0;
199                 ungetc(c,stdin);
200
201                 n = (sizeof(kwds)/sizeof(struct keys));
202                 for (i = 0; i < n; i++){
203                         if (!strcmp(buf,kwds[i].keywords))
204                                 return kwds[i].keytoks;
205                 }
206
207                 parse_err("Unknown keyword %s", buf);
208         }
209
210         parse_err("Unknown character %c", c);
211 }