4 Ann Hell Ex Machina - Music Software
5 Copyright (C) 2003/2004 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
33 void yyerror(char * s);
34 int yy_input_for_flex(char * buf, int max);
37 static char * ascii_notes="ccddeffggaab";
39 /* redefinition of input function for GNU Flex */
41 #define YY_INPUT(b,r,m) (r=yy_input_for_flex(b,m))
43 #define MAX_INPUTS 256
47 char * code; /* code string */
48 int offset; /* current offset */
49 int times; /* times to be fed to lexer/parser */
50 int dyn; /* if set, free() after usage */
53 static struct code_stack _code_stack[MAX_INPUTS];
54 static int _code_stack_i=-1;
56 /* dynamic string manipulation macros */
58 struct ds { char * d; int p; int s; };
59 #define ds_init(x) do { x.d=(char *)0; x.p=x.s=0; } while(0)
60 #define ds_rewind(x) x.p=0;
61 #define ds_free(x) do { if(x.d) free(x.d); ds_init(x); } while(0)
62 #define ds_redim(x) do { if(x.p >= x.s) x.d=realloc(x.d, x.s += 32); } while(0)
63 #define ds_poke(x,c) do { ds_redim(x); x.d[x.p++]=c; } while(0)
64 #define ds_pokes(x,t) do { char *p=t; while(*p) ds_poke(x, *p++); } while(0)
68 static struct ds _blk;
70 /* 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_]+
99 /* integers without sign */
100 yylval.i=atoi(yytext);
104 /* signed integers */
105 yylval.i=atoi(yytext);
109 /* real numbers without sign */
110 yylval.d=atof(yytext);
114 /* signel real numbers */
115 yylval.d=atof(yytext);
121 yylval.i=strchr(ascii_notes, *yytext) - ascii_notes;
124 {NOTE_T3} { return(NOTE_T3); }
125 {NOTE_T5} { return(NOTE_T5); }
128 /* create new mark */
143 {WSPACE} { ; /* ignore blanks */ }
145 \/\* { BEGIN REM; /* C-like comments */ }
146 <REM>\*\/ { BEGIN 0; }
147 <REM>. { ; /* drop anything inside a comment */ }
149 \{ { BEGIN XC; /* start of extended commands */ }
151 /* double-quoted string */
152 yytext[yyleng - 1]='\0';
153 yylval.p=strdup(yytext + 1);
157 /* single-quoted string */
158 yytext[yyleng - 1]='\0';
159 yylval.p=strdup(yytext + 1);
163 yylval.i=atoi(yytext);
167 yylval.i=atoi(yytext);
171 yylval.d=atof(yytext);
175 yylval.d=atof(yytext);
179 /* frame count, in seconds */
180 yytext[yyleng - 1]='\0';
181 yylval.i=atof(yytext) * 1000;
185 /* frame count, in milliseconds */
186 yytext[yyleng - 2]='\0';
187 yylval.i=atoi(yytext);
190 <XC>{NOTE_P}[\#\&]?{P_INTEGER} {
194 yylval.i=strchr(ascii_notes, *ptr) - ascii_notes;
197 /* process optional sharps or flats */
211 yylval.i += atoi(ptr) * 12;
216 <XC>wav { return(SS_WAV); }
217 <XC>pat { return(SS_PAT); }
218 <XC>sustain { return(SS_SUSTAIN); }
220 <XC>delay { return(SS_EFF_DELAY); }
221 <XC>echo { return(SS_EFF_ECHO); }
222 <XC>comb { return(SS_EFF_COMB); }
223 <XC>allpass { return(SS_EFF_ALLPASS); }
224 <XC>flanger { return(SS_EFF_FLANGER); }
225 <XC>wobble { return(SS_EFF_WOBBLE); }
226 <XC>square_wobble { return(SS_EFF_SQWOBBLE); }
227 <XC>fader { return(SS_EFF_FADER); }
228 <XC>reverb { return(SS_EFF_REVERB); }
231 <XC>{WSPACE} { ; /* ignore blanks */ }
232 <XC>. { return(*yytext); }
240 <BLK>\( { _blk_i++; ds_poke(_blk, *yytext); }
242 /* one parentheses less */
257 <BLK>. { ds_poke(_blk, *yytext); }
259 =[ \t\n]*{BLOCKNAME} {
260 /* block assignation */
263 /* skip (possible) spaces between
264 the = and the blockname; this lex
265 rule is written this way to avoid
266 having a global match for {BLOCKNAME},
267 that could swallow notes and such,
268 being mismatched as blocknames */
269 while(*yylval.p == ' ' ||
277 /* block insertion */
283 yytext[yyleng - 1]='\0';
288 . { return(*yytext); }
292 int yywrap(void) { return(1); }
294 char * ds_load(char * file)
300 if((f=fopen(file, "r")) == NULL)
305 while((c=fgetc(f)) != EOF)
315 int push_code(char * code, int times, int dyn)
317 struct code_stack * cs;
319 if(_code_stack_i == MAX_INPUTS)
323 cs=&_code_stack[_code_stack_i];
334 int push_code_from_file(char * file)
338 if((c=ds_load(file)) == NULL)
346 int code_getchar(void)
348 struct code_stack * cs;
351 while(c == '\0' && _code_stack_i > -1)
353 /* get current char */
354 cs=&_code_stack[_code_stack_i];
355 c=cs->code[cs->offset++];
372 /* move to previous */
376 /* in any case, return a separator */
385 int yy_input_for_flex(char * buf, int max)
387 buf[0]=code_getchar();
389 return(buf[0] == '\0' ? 0 : 1);