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
32 void yyerror(char * s);
34 /* redefinition of input function for GNU Flex */
36 #define YY_INPUT(b,r,m) (r=yy_input_for_flex(b,m))
38 #define MAX_INPUTS 256
42 char * code; /* code string */
43 int offset; /* current offset */
44 int times; /* times to be fed to lexer/parser */
45 int dyn; /* if set, free() after usage */
48 static struct code_stack _code_stack[MAX_INPUTS];
49 static int _code_stack_i=-1;
51 /* dynamic string manipulation macros */
53 struct ds { char * d; int p; int s; };
54 #define ds_init(x) do { x.d=(char *)0; x.p=x.s=0; } while(0)
55 #define ds_rewind(x) x.p=0;
56 #define ds_free(x) do { if(x.d) free(x.d); ds_init(x); } while(0)
57 #define ds_redim(x) do { if(x.p >= x.s) x.d=realloc(x.d, x.s += 32); } while(0)
58 #define ds_poke(x,c) do { ds_redim(x); x.d[x.p++]=c; } while(0)
59 #define ds_pokes(x,t) do { char *p=t; while(*p) ds_poke(x, *p++); } while(0)
63 static struct ds _blk;
65 /* count of parentheses */
72 REAL {DIGIT}*[\.]?{DIGIT}+
73 OPERATOR [~\*\./,@+#-]
81 MARKNAME [-a-zA-Z0-9_]+
84 ASSERT_MARK !{MARKNAME}
86 BLOCKNAME [-a-zA-Z0-9_]+
89 COMMAND [zrost\\$?<;>l:xTM|]
97 yylval.i=atoi(yytext);
102 yylval.d=atof(yytext);
106 {COMMAND} { return(*yytext); }
107 {OPERATOR} { return(*yytext); }
110 yylval.i=*yytext - 'a';
114 /* immediate octave changes */
117 for(n=0;yytext[n];n++)
119 (yytext[n] == ',' ? -1 : 1);
123 {NOTE_T3} { return(NOTE_T3); }
124 {NOTE_T5} { return(NOTE_T5); }
127 /* create new mark */
143 /* sequence of + and - */
146 for(n=0;yytext[n];n++)
148 (yytext[n] == '+' ? 1 : -1);
152 {WSPACE} { ; /* ignore blanks */ }
154 \/\* { BEGIN REM; /* C-like comments */ }
155 <REM>\*\/ { BEGIN 0; }
156 <REM>. { ; /* drop anything inside a comment */ }
158 \{ { BEGIN SS; /* start of software synth commands */ }
160 /* double-quoted string */
161 yytext[yyleng - 1]='\0';
167 yylval.i=atoi(yytext);
172 yylval.d=atof(yytext);
176 /* frame count, in seconds */
177 yytext[yyleng - 1]='\0';
178 yylval.i=atoi(yytext) * 44100;
182 /* frame count, in milliseconds */
183 yytext[yyleng - 2]='\0';
184 yylval.i=(atoi(yytext) * 44100) / 1000;
187 <SS>wav { return(SS_WAV); }
188 <SS>pat { return(SS_PAT); }
189 <SS>sustain { return(SS_SUSTAIN); }
191 <SS>delay { return(SS_EFF_DELAY); }
192 <SS>echo { return(SS_EFF_ECHO); }
193 <SS>comb { return(SS_EFF_COMB); }
194 <SS>allpass { return(SS_EFF_ALLPASS); }
195 <SS>flanger { return(SS_EFF_FLANGER); }
196 <SS>wobble { return(SS_EFF_WOBBLE); }
197 <SS>square_wobble { return(SS_EFF_SQWOBBLE); }
198 <SS>fader { return(SS_EFF_FADER); }
201 <SS>{WSPACE} { ; /* ignore blanks */ }
202 <SS>. yyerror("<SS>LEX unknown character");
210 <BLK>\( { _blk_i++; ds_poke(_blk, *yytext); }
212 /* one parentheses less */
227 <BLK>. { ds_poke(_blk, *yytext); }
228 =[ \t\n]*{BLOCKNAME} {
229 /* block assignation */
232 /* skip (possible) spaces between
233 the = and the blockname; this lex
234 rule is written this way to avoid
235 having a global match for {BLOCKNAME},
236 that could swallow notes and such,
237 being mismatched as blocknames */
238 while(*yylval.p == ' ' ||
246 /* block insertion */
256 . yyerror("LEX Unknown character");
260 int yywrap(void) { return(1); }
262 int push_code(char * code, int times, int dyn)
264 struct code_stack * cs;
266 if(_code_stack_i == MAX_INPUTS)
270 cs=&_code_stack[_code_stack_i];
281 int code_getchar(void)
283 struct code_stack * cs;
286 while(c == '\0' && _code_stack_i > -1)
288 /* get current char */
289 cs=&_code_stack[_code_stack_i];
290 c=cs->code[cs->offset++];
307 /* move to previous */
311 /* in any case, return a separator */
320 int yy_input_for_flex(char * buf, int max)
322 buf[0]=code_getchar();
324 return(buf[0] == '\0' ? 0 : 1);