4 Ann Hell Ex Machina - Music Software
5 Copyright (C) 2003/2008 Angel Ortega <angel@triptico.com>
7 compiler.l - Scripting language [F]lex 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
35 void yyerror(const char *s);
36 int yy_input_for_flex(char * buf, int max);
39 static const char *ascii_notes = "ccddeffggaab";
41 /* redefinition of input function for GNU Flex */
43 #define YY_INPUT(b,r,m) (r = yy_input_for_flex(b,m))
46 const char *code; /* code string */
47 int offset; /* current offset */
50 static struct code_stack *code_stack = NULL;
51 static int code_stack_i = -1;
53 /* dynamic string manipulation macros */
55 struct ds { char *d; int p; int s; };
56 #define ds_init(x) do { x.d = (char *)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 += 32); } 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 { char *p = t; while (*p) ds_poke(x, *p++); } while(0)
65 static struct ds ds_blk;
67 /* count of parentheses */
77 S_INTEGER [-+]{P_INTEGER}
78 P_REAL {DIGIT}*[\.]?{DIGIT}+
85 MARKNAME [-a-zA-Z0-9_]+
88 ASSERT_MARK !{MARKNAME}
90 BLOCKNAME [-a-zA-Z0-9_#&]+
101 /* integers without sign */
102 yylval.i = atoi(yytext);
106 /* signed integers */
107 yylval.i = atoi(yytext);
111 /* real numbers without sign */
112 yylval.d = atof(yytext);
116 /* signel real numbers */
117 yylval.d = atof(yytext);
123 yylval.i = strchr(ascii_notes, *yytext) - ascii_notes;
126 {NOTE_T3} { return NOTE_T3; }
127 {NOTE_T5} { return NOTE_T5; }
130 /* create new mark */
131 yylval.p = yytext + 1;
136 yylval.p = yytext + 1;
141 yylval.p = yytext + 1;
146 /* alteration string */
147 yylval.p = yytext + 1;
151 {WSPACE} { ; /* ignore blanks */ }
155 \/\* { BEGIN REM; /* C-like comments */ }
156 <REM>\*\/ { BEGIN 0; }
157 <REM>\n { yyline++; }
158 <REM>. { ; /* drop anything inside a comment */ }
160 \{ { BEGIN XC; /* start of extended commands */ }
162 /* double-quoted string */
163 yytext[yyleng - 1] = '\0';
164 yylval.p = strdup(yytext + 1);
168 /* single-quoted string */
169 yytext[yyleng - 1] = '\0';
170 yylval.p = strdup(yytext + 1);
174 yylval.i = atoi(yytext);
178 yylval.i = atoi(yytext);
182 yylval.d = atof(yytext);
186 yylval.d = atof(yytext);
190 /* frame count, in seconds */
191 yytext[yyleng - 1] = '\0';
192 yylval.d = atof(yytext) * 1000;
196 /* frame count, in milliseconds */
197 yytext[yyleng - 2] = '\0';
198 yylval.d = atof(yytext);
201 <XC>{NOTE_P}[\#\&]?{P_INTEGER} {
205 yylval.i = strchr(ascii_notes, *ptr) - ascii_notes;
208 /* process optional sharps or flats */
220 yylval.i += atoi(ptr) * 12;
225 <XC>wav { return SS_WAV; }
226 <XC>pat { return SS_PAT; }
227 <XC>sf2 { return SS_SF2; }
228 <XC>sustain { return SS_SUSTAIN; }
229 <XC>attack { return SS_ATTACK; }
230 <XC>vibrato { return SS_VIBRATO; }
231 <XC>portamento { return SS_PORTAMENTO; }
232 <XC>channel { return SS_CHANNEL; }
233 <XC>vol { return SS_VOL; }
234 <XC>master_volume { return SS_MASTER_VOL; }
236 <XC>delay { return SS_EFF_DELAY; }
237 <XC>echo { return SS_EFF_ECHO; }
238 <XC>comb { return SS_EFF_COMB; }
239 <XC>allpass { return SS_EFF_ALLPASS; }
240 <XC>flanger { return SS_EFF_FLANGER; }
241 <XC>wobble { return SS_EFF_WOBBLE; }
242 <XC>square_wobble { return SS_EFF_SQWOBBLE; }
243 <XC>half_wobble { return SS_EFF_HFWOBBLE; }
244 <XC>fader { return SS_EFF_FADER; }
245 <XC>reverb { return SS_EFF_REVERB; }
246 <XC>foldback { return SS_EFF_FOLDBACK; }
247 <XC>atan { return SS_EFF_ATAN; }
248 <XC>distort { return SS_EFF_DISTORT; }
249 <XC>overdrive { return SS_EFF_OVERDRIVE; }
250 <XC>off { return SS_EFF_OFF; }
252 <XC>pitch_stretch { return SS_PITCH_STRETCH; }
253 <XC>time_stretch { return SS_TIME_STRETCH; }
254 <XC>print_wave_tempo { return SS_PRINT_WAVE_TEMPO; }
256 <XC>song_info { return SONG_INFO; }
258 <XC>midi_channel { return MIDI_CHANNEL; }
259 <XC>midi_program { return MIDI_PROGRAM; }
260 <XC>midi_generic { return MIDI_GENERIC; }
262 <XC>\/\* { BEGIN REMXC; /* C-like comments inside XC */ }
263 <REMXC>\*\/ { BEGIN XC; /* jump back to XC processing */ }
264 <REMXC>\n { yyline++; }
268 <XC>{WSPACE} { ; /* ignore blanks */ }
270 <XC>. { return *yytext; }
278 <BLK>\( { ds_blk_i++; ds_poke(ds_blk, *yytext); }
280 /* one parentheses less */
285 ds_poke(ds_blk, '\0');
292 ds_poke(ds_blk, ')');
294 <BLK>\n { ds_poke(ds_blk, ' '); yyline++; }
295 <BLK>. { ds_poke(ds_blk, *yytext); }
297 =[ \t\n]*{BLOCKNAME} {
298 /* block assignation */
299 yylval.p = yytext + 1;
301 /* skip (possible) spaces between
302 the = and the blockname; this lex
303 rule is written this way to avoid
304 having a global match for {BLOCKNAME},
305 that could swallow notes and such,
306 being mismatched as blocknames */
307 while (*yylval.p == ' ' ||
315 /* block insertion */
316 yylval.p = yytext + 1;
321 yytext[yyleng - 1] = '\0';
322 yylval.p = yytext + 1;
327 yylval.p = yytext + 1;
331 . { return *yytext; }
335 int yywrap(void) { return(1); }
337 char * ds_load(const char * file)
343 if ((f = libpath_fopen(file, "rb")) == NULL)
348 while ((c = fgetc(f)) != EOF)
358 int push_code(const char * code)
360 struct code_stack * cs;
363 GROW(code_stack, code_stack_i, struct code_stack);
365 cs = &code_stack[code_stack_i];
374 int push_code_from_file(const char * file)
378 if ((c = ds_load(file)) == NULL)
386 int code_getchar(void)
388 struct code_stack * cs;
391 while (c == '\0' && code_stack_i > -1) {
392 /* get current char */
393 cs = &code_stack[code_stack_i];
394 c = cs->code[cs->offset++];
399 free((char *) cs->code);
401 /* move to previous */
404 /* in any case, return a separator */
413 int yy_input_for_flex(char * buf, int max)
415 buf[0] = code_getchar();
417 return buf[0] == '\0' ? 0 : 1;