Updated RELEASE_NOTES.
[mpsl.git] / mpsl.l
blob9d3f4d50d617c5d3dfc08f6869daf913b4104743
1 %{
2 /*
4     MPSL - Minimum Profit Scripting Language
5     Copyright (C) 2003/2007 Angel Ortega <angel@triptico.com>
7     mpsl.l - Minimum Profit Scripting Language [F]lexer
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License
11     as published by the Free Software Foundation; either version 2
12     of the License, or (at your option) any later version.
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23     http://www.triptico.com
27 #include <stdio.h>
28 #include <wchar.h>
29 #include "mpdm.h"
31 #include <stdlib.h>
32 #include "y.tab.h"
34 void yyerror(char * s);
35 int yy_input_for_flex(char * buf, int max);
37 /* redefinition of input function for GNU Flex */
38 #undef YY_INPUT
39 #define YY_INPUT(b,r,m) (r = yy_input_for_flex(b,m))
41 /* internal pointer to next character in code */
42 wchar_t * mpsl_next_char = NULL;
44 /* file stream for compiling from file */
45 FILE * mpsl_file = NULL;
47 /* line number */
48 int mpsl_line = 0;
50 /* cached value MPSL.LC */
51 mpdm_t mpsl_lc = NULL;
53 /* dynamic string manipulation macros */
54 #ifndef ds_init
55 struct ds { wchar_t * d; int p; int s; };
56 #define ds_init(x) do { x.d = (wchar_t *)0; x.p = x.s = 0; } while(0)
57 #define ds_rewind(x) x.p = 0;
58 #define ds_free(x) do { if(x.d) free(x.d); ds_init(x); } while(0)
59 #define ds_redim(x) do { if(x.p >= x.s) x.d = realloc(x.d, ++x.s * sizeof(wchar_t)); } while(0)
60 #define ds_poke(x,c) do { ds_redim(x); x.d[x.p++] = c; } while(0)
61 #define ds_pokes(x,t) do { wchar_t *p = t; while(*p) ds_poke(x, *p++); } while(0)
62 #endif /* ds_init */
64 /* a dynamic string */
65 struct ds ds_v;
67 static wchar_t * s_mbstowcs(char * str)
68 /* converts from mbs to wcs, using a static buffer */
70         static wchar_t * wc = NULL;
71         static int wc_s = 0;
72         int n;
74         /* allocs wchar_t space, if needed */
75         if ((n = mbstowcs(NULL, str, 0)) > wc_s) {
76                 wc_s = n;
77                 wc = realloc(wc, (wc_s + 1) * sizeof(wchar_t));
78         }
80         /* really converts */
81         mbstowcs(wc, str, n);
82         wc[n] = L'\0';
84         return wc;
88 static mpdm_t literal_cache(char * ptr, wchar_t * wptr)
89 /* the cache of literal values */
91         mpdm_t v;
93         /* convert to wchar_t */
94         if (ptr != NULL)
95                 wptr = s_mbstowcs(ptr);
97         /* search in cache */
98         if ((v = mpdm_hget_s(mpsl_lc, wptr)) == NULL) {
99                 v = MPDM_S(wptr);
100                 mpdm_hset(mpsl_lc, v, v);
101         }
103         return v;
109 DIGIT           [0-9]
110 LETTER          [a-zA-Z_]
111 WSPACE          [ \t\r]+
112 OCTDIGIT        [0-7]
113 HEXDIGIT        [0-9a-fA-F]
114 HEXQUAD         {HEXDIGIT}{1,4}
116 DECINTEGER      {DIGIT}+
117 OCTINTEGER      0{OCTDIGIT}+
118 HEXINTEGER      0[xX]{HEXDIGIT}+
120 REAL            {DIGIT}*[\.]?{DIGIT}+
121 SYMBOL          {LETTER}({LETTER}|{DIGIT})*
122 INTEGER         ({DECINTEGER}|{OCTINTEGER}|{HEXINTEGER})
124 %x REM
125 %x STR
129 {INTEGER}       {
130                         /* integers */
131                         yylval.v = literal_cache(yytext, NULL);
132                         return INTEGER;
133                 }
135 {REAL}          {
136                         /* real numbers */
137                         yylval.v = literal_cache(yytext, NULL);
138                         return REAL;
139                 }
141 \'[^']*\'       {
142                         /* single quoted string; return as is */
143                         yytext[yyleng - 1] = '\0';
144                         yylval.v = literal_cache(yytext + 1, NULL);
145                         return STRING;
146                 }
148 "NULL"          return NULLV;
149 "while"         return WHILE;
150 "if"            return IF;
151 "else"          return ELSE;
152 "sub"           return SUB;
153 "foreach"       return FOREACH;
154 "local"         return LOCAL;
155 "break"         return BREAK;
156 "return"        return RETURN;
158 "=="            return NUMEQ;
159 "!="            return NUMNE;
160 ">="            return NUMGE;
161 "<="            return NUMLE;
162 "&&"            return BOOLAND;
163 "||"            return BOOLOR;
164 "=>"            return HASHPAIR;
165 ".."            return RANGE;
166 "&"             return BITAND;
167 "|"             return BITOR;
168 "^"             return BITXOR;
170 "eq"            return STREQ;
171 "ne"            return STRNE;
172 "~"             return STRCAT;
174 "++"            return INC;
175 "--"            return DEC;
176 "+="            return IADD;
177 "-="            return ISUB;
178 "*="            return IMUL;
179 "/="            return IDIV;
180 "%"             return MOD;
181 "%="            return IMOD;
183 {SYMBOL}        {
184                         /* symbol name */
185                         yylval.v = literal_cache(yytext, NULL);
186                         return SYMBOL;
187                 }
189 {WSPACE}        ;       /* ignore spaces */
191 \n              { mpsl_line++; }
193 \/\*            { BEGIN REM; /* C-like comments */ }
194 <REM>\*\/       { BEGIN 0; }
195 <REM>\n         { mpsl_line++; }
196 <REM>.          ;
198 \"              { BEGIN STR; ds_rewind(ds_v); }
199 <STR>\n         { ds_poke(ds_v, L'\n'); mpsl_line++; }
200 <STR>\\n        { ds_poke(ds_v, L'\n'); }
201 <STR>\\t        { ds_poke(ds_v, L'\t'); }
202 <STR>\\r        { ds_poke(ds_v, L'\r'); }
203 <STR>\\e        { ds_poke(ds_v, 27); }
204 <STR>\\\"       { ds_poke(ds_v, L'\"'); }
205 <STR>\\\\       { ds_poke(ds_v, L'\\'); }
206 <STR>\"\\\n[ \t]+\"     ;
207 <STR>\"         {
208                         ds_poke(ds_v, L'\0');
209                         yylval.v = literal_cache(NULL, ds_v.d);
210                         BEGIN 0;
211                         return STRING;
212                 }
213 <STR>\\x\{{HEXQUAD}\} {
214                         int c;
216                         sscanf(yytext, "\\x{%x}", &c);
217                         ds_poke(ds_v, (wchar_t) c);
218                 }
219 <STR>.          { wchar_t wc; if (mbtowc(&wc, yytext, 1) > 0) ds_poke(ds_v, wc); }
221 .               { return *yytext; }
225 int yywrap(void) { return 1; }
227 int yy_input_for_flex(char * buf, int max)
229         int n = 0;
231         if (mpsl_file != NULL) {
232                 while (n < max) {
233                         int c;
235                         if ((c = fgetc(mpsl_file)) == EOF) {
236                                 mpsl_file = NULL;
237                                 break;
238                         }
240                         buf[n++] = c;
241                 }
242         }
243         else
244         if (mpsl_next_char != NULL) {
245                 for (;;) {
246                         char tmp[64];   /* really MB_CUR_MAX + 1 */
247                         int c, i;
249                         if (*mpsl_next_char == L'\0' ||
250                            (c = wctomb(tmp, *mpsl_next_char)) < 0) {
251                                 mpsl_next_char = NULL;
252                                 break;
253                         }
255                         /* no room? try next time */
256                         if (n + c >= max)
257                                 break;
259                         mpsl_next_char++;
261                         /* transfer */
262                         for (i = 0; i < c; i++)
263                                 buf[n++] = tmp[i];
264                 }
265         }
267         return n;