Revert bs-a and bs-b patch.
[mpsl.git] / mpsl.l
blob86e1e9615d7cd079462c7be4f8e6f927f5d8e49f
1 %{
2 /*
4     MPSL - Minimum Profit Scripting Language
5     Copyright (C) 2003/2010 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 {
56     wchar_t *d;
57     int p;
58     int s;
60 #define ds_init(x) do { x.d = (wchar_t *)0; x.p = x.s = 0; } while(0)
61 #define ds_rewind(x) x.p = 0;
62 #define ds_free(x) do { if(x.d) free(x.d); ds_init(x); } while(0)
63 #define ds_redim(x) do { if(x.p >= x.s) x.d = realloc(x.d, ++x.s * sizeof(wchar_t)); } while(0)
64 #define ds_poke(x,c) do { ds_redim(x); x.d[x.p++] = c; } while(0)
65 #define ds_pokes(x,t) do { wchar_t *p = t; while(*p) ds_poke(x, *p++); } while(0)
66 #endif                          /* ds_init */
68 /* a dynamic string */
69 struct ds ds_v;
71 static wchar_t *s_mbstowcs(char *str)
72 /* converts from mbs to wcs, using a static buffer */
74     static wchar_t *wc = NULL;
75     int n;
77     /* get needed space */
78     n = mbstowcs(NULL, str, 0);
79     wc = realloc(wc, (n + 1) * sizeof(wchar_t));
81     /* really convert */
82     mbstowcs(wc, str, n);
83     wc[n] = L'\0';
85     return wc;
89 static mpdm_t literal_cache(char *ptr, wchar_t * wptr)
90 /* the cache of literal values */
92     mpdm_t v;
94     /* convert to wchar_t */
95     if (ptr != NULL)
96         wptr = s_mbstowcs(ptr);
98     /* search in cache */
99     if ((v = mpdm_hget_s(mpsl_lc, wptr)) == NULL) {
100         v = MPDM_S(wptr);
101         mpdm_hset(mpsl_lc, v, v);
102     }
104     return v;
110 DIGIT           [0-9]
111 LETTER          [a-zA-Z_]
112 WSPACE          [ \t\r]+
113 OCTDIGIT        [0-7]
114 HEXDIGIT        [0-9a-fA-F]
115 BINDIGIT        [0-1]
116 HEXQUAD         {HEXDIGIT}{1,4}
118 DECINTEGER      {DIGIT}+
119 OCTINTEGER      0{OCTDIGIT}+
120 HEXINTEGER      0[xX]{HEXDIGIT}+
121 BININTEGER      0[bB]{BINDIGIT}+
123 REAL            {DIGIT}*[\.]?{DIGIT}+
124 SCIENT          {DIGIT}+(\.{DIGIT}+)?[eE][-+]?{DIGIT}+
125 SYMBOL          {LETTER}({LETTER}|{DIGIT})*
126 INTEGER         ({DECINTEGER}|{OCTINTEGER}|{HEXINTEGER}|{BININTEGER})
128 %x REM
129 %x STR
133 {INTEGER}       {
134                         /* integers */
135                         yylval.v = literal_cache(yytext, NULL);
136                         return INTEGER;
137                 }
139 ({REAL}|{SCIENT})       {
140                         /* real numbers */
141                         yylval.v = literal_cache(yytext, NULL);
142                         return REAL;
143                 }
145 \'[^']*\'       {
146                         /* single quoted string; return as is */
147                         yytext[yyleng - 1] = '\0';
148                         yylval.v = literal_cache(yytext + 1, NULL);
149                         return STRING;
150                 }
152 "NULL"          return NULLV;
153 "while"         return WHILE;
154 "for"       return FOR;
155 "if"            return IF;
156 "else"          return ELSE;
157 "sub"           return SUB;
158 "foreach"       return FOREACH;
159 "local"         return LOCAL;
160 "break"         return BREAK;
161 "return"        return RETURN;
163 "=="            return NUMEQ;
164 "!="            return NUMNE;
165 ">="            return NUMGE;
166 "<="            return NUMLE;
167 "&&"            return BOOLAND;
168 "||"            return BOOLOR;
169 "=>"            return ARROW;
170 ".."            return RANGE;
171 "&"             return AMPERSAND;
172 "|"             return BITOR;
173 "^"             return BITXOR;
174 "<<"    return SHL;
175 ">>"    return SHR;
176 "->"            return INVCALL;
178 "eq"            return STREQ;
179 "ne"            return STRNE;
180 "~"             return STRCAT;
182 "++"            return INC;
183 "--"            return DEC;
184 "+="            return IADD;
185 "-="            return ISUB;
186 "*="            return IMUL;
187 "/="            return IDIV;
188 "%"             return MOD;
189 "%="            return IMOD;
190 "&="            return IBITAND;
191 "|="            return IBITOR;
192 "^="            return IBITXOR;
193 "<<="           return ISHL;
194 ">>="           return ISHR;
195 "**"            return POW;
197 {SYMBOL}        {
198                         /* symbol name */
199                         yylval.v = literal_cache(yytext, NULL);
200                         return SYMBOL;
201                 }
203 {WSPACE}        ;       /* ignore spaces */
205 \n              { mpsl_line++; }
207 \/\*            { BEGIN REM; /* C-like comments */ }
208 <REM>\*\/       { BEGIN 0; }
209 <REM>\n         { mpsl_line++; }
210 <REM>.          ;
212 \"              { BEGIN STR; ds_rewind(ds_v); }
213 <STR>\n         { ds_poke(ds_v, L'\n'); mpsl_line++; }
214 <STR>\\n        { ds_poke(ds_v, L'\n'); }
215 <STR>\\t        { ds_poke(ds_v, L'\t'); }
216 <STR>\\r        { ds_poke(ds_v, L'\r'); }
217 <STR>\\e        { ds_poke(ds_v, 27); }
218 <STR>\\\"       { ds_poke(ds_v, L'\"'); }
219 <STR>\\\\       { ds_poke(ds_v, L'\\'); }
220 <STR>\"\\\n[ \t]+\"     ;
221 <STR>\"         {
222                         ds_poke(ds_v, L'\0');
223                         yylval.v = literal_cache(NULL, ds_v.d);
224                         BEGIN 0;
225                         return STRING;
226                 }
227 <STR>\\x\{{HEXQUAD}\} {
228                         int c;
230                         sscanf(yytext, "\\x{%x}", &c);
231                         ds_poke(ds_v, (wchar_t) c);
232                 }
233 <STR>.          { wchar_t wc; if (mbtowc(&wc, yytext, 1) > 0) ds_poke(ds_v, wc); }
235 .               { return *yytext; }
239 int yywrap(void)
241     return 1;
244 int yy_input_for_flex(char *buf, int max)
246     int n = 0;
248     if (mpsl_file != NULL) {
249         while (n < max) {
250             int c;
252             if ((c = fgetc(mpsl_file)) == EOF) {
253                 mpsl_file = NULL;
254                 break;
255             }
257             buf[n++] = c;
258         }
259     }
260     else if (mpsl_next_char != NULL) {
261         for (;;) {
262             char tmp[64];       /* really MB_CUR_MAX + 1 */
263             int c, i;
265             if (*mpsl_next_char == L'\0' ||
266                 (c = wctomb(tmp, *mpsl_next_char)) < 0) {
267                 mpsl_next_char = NULL;
268                 break;
269             }
271             /* no room? try next time */
272             if (n + c >= max)
273                 break;
275             mpsl_next_char++;
277             /* transfer */
278             for (i = 0; i < c; i++)
279                 buf[n++] = tmp[i];
280         }
281     }
283     return n;