/[svn]/linuxsampler/trunk/src/network/lscp.y
ViewVC logotype

Contents of /linuxsampler/trunk/src/network/lscp.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2515 - (show annotations) (download)
Wed Feb 5 20:45:18 2014 UTC (10 years, 2 months ago) by schoenebeck
File size: 86100 byte(s)
* WIP: Introducing the LSCP shell: for now, providing color
  highlighting while typing (indicating correct part bold white,
  incorrect part red, and turning green when the command is
  complete. The shell application is implemented as thin client,
  that is the parser work is performed on sampler side and the
  shell application is just providing output formatting.
* Bumped version (1.0.0.svn28).

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2014 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 /*
25 The parser's C++ source files should be automatically (re)generated if
26 this file was modified. If not, or in case you want explicitly
27 regenerate the parser C++ files, run 'make parser'. In both cases you
28 need to have bison or another yacc compatible parser generator
29 installed though.
30 */
31
32 %{
33
34 #include "lscpparser.h"
35 #include "lscpserver.h"
36 #include "lscpevent.h"
37 #include "lscpsymbols.h"
38 #include <algorithm>
39 #include "lscp.h"
40
41 namespace LinuxSampler {
42
43 // to save us typing work in the rules action definitions
44 #define LSCPSERVER ((yyparse_param_t*) yyparse_param)->pServer
45 #define SESSION_PARAM ((yyparse_param_t*) yyparse_param)
46 #define INCREMENT_LINE { SESSION_PARAM->iLine++; SESSION_PARAM->iColumn = 0; sParsed.clear(); }
47
48 // clears input buffer
49 void restart(yyparse_param_t* pparam, int& yychar);
50 #define RESTART restart((yyparse_param_t*) YYPARSE_PARAM, yychar)
51
52 static char buf[1024]; // input buffer to feed the parser with new characters
53 static int bytes = 0; // current number of characters in the input buffer
54 static int ptr = 0; // current position in the input buffer
55 static String sLastError; // error message of the last error occured
56 static String sParsed; ///< Characters of current line which have already been shifted (consumed/parsed) by the parser.
57
58 // external reference to the function which actually reads from the socket
59 extern int GetLSCPCommand( void *buf, int max_size);
60
61 // external reference to the function in lscpserver.cpp which returns the
62 // current session (only works because the server runs as singleton)
63 extern yyparse_param_t* GetCurrentYaccSession();
64
65 // returns true if supplied characters has an ASCII code of 128 or higher
66 inline bool isExtendedAsciiChar(const char c) {
67 return (c < 0);
68 }
69
70 // custom scanner function which reads from the socket
71 // (bison expects it to return the numerical ID of the next
72 // "recognized token" from the input stream)
73 int yylex(YYSTYPE* yylval) {
74 // check if we have to read new characters
75 if (ptr >= bytes) {
76 bytes = GetLSCPCommand(buf, 1023);
77 ptr = 0;
78 if (bytes < 0) {
79 bytes = 0;
80 return 0;
81 }
82 }
83 // this is the next character in the input stream
84 const char c = buf[ptr++];
85 // increment current reading position (just for verbosity / messages)
86 GetCurrentYaccSession()->iColumn++;
87 sParsed += c;
88 // we have to handle "normal" and "extended" ASCII characters separately
89 if (isExtendedAsciiChar(c)) {
90 // workaround for characters with ASCII code higher than 127
91 yylval->Char = c;
92 return EXT_ASCII_CHAR;
93 } else {
94 // simply return the ASCII code as terminal symbol ID
95 return (int) c;
96 }
97 }
98
99 // parser helper functions
100
101 int octalsToNumber(char oct_digit0, char oct_digit1 = '0', char oct_digit2 = '0') {
102 const char d0[] = { oct_digit0, '\0' };
103 const char d1[] = { oct_digit1, '\0' };
104 const char d2[] = { oct_digit2, '\0' };
105 return atoi(d2)*8*8 + atoi(d1)*8 + atoi(d0);
106 }
107
108 }
109
110 using namespace LinuxSampler;
111
112 static std::set<String> yyExpectedSymbols();
113
114 /**
115 * Will be called when an error occured (usually syntax error).
116 *
117 * We provide our own version of yyerror() so we a) don't have to link against
118 * the yacc library and b) can render more helpful syntax error messages.
119 */
120 void yyerror(void* x, const char* s) {
121 yyparse_param_t* param = GetCurrentYaccSession();
122
123 // get the text part already parsed (of current line)
124 const bool bContainsLineFeed =
125 sParsed.find('\r') != std::string::npos ||
126 sParsed.find('\n') != std::string::npos;
127 // remove potential line feed characters
128 if (bContainsLineFeed) {
129 for (size_t p = sParsed.find('\r'); p != std::string::npos;
130 p = sParsed.find('\r')) sParsed.erase(p);
131 for (size_t p = sParsed.find('\n'); p != std::string::npos;
132 p = sParsed.find('\n')) sParsed.erase(p);
133 }
134
135 // start assembling the error message with Bison's own message
136 String txt = s;
137
138 // append exact position info of syntax error
139 txt += (" (line:" + ToString(param->iLine+1)) +
140 (",column:" + ToString(param->iColumn)) + ")";
141
142 // append the part of the lined that has already been parsed
143 txt += ". Context: \"" + sParsed;
144 if (txt.empty() || bContainsLineFeed)
145 txt += "^";
146 else
147 txt.insert(txt.size() - 1, "^");
148 txt += "...\"";
149
150 // append the non-terminal symbols expected now/next
151 std::set<String> expectedSymbols = yyExpectedSymbols();
152 for (std::set<String>::const_iterator it = expectedSymbols.begin();
153 it != expectedSymbols.end(); ++it)
154 {
155 if (it == expectedSymbols.begin())
156 txt += " -> Should be: " + *it;
157 else
158 txt += " | " + *it;
159 }
160
161 dmsg(2,("LSCPParser: %s\n", txt.c_str()));
162 sLastError = txt;
163 }
164
165 %}
166
167 // reentrant parser
168 %pure-parser
169
170 %parse-param {void* yyparse_param}
171
172 // After entering the yyparse() function, store references to the parser's
173 // state stack, so that we can create more helpful syntax error messages than
174 // Bison (2.x) could do.
175 %initial-action {
176 yyparse_param_t* p = (yyparse_param_t*) yyparse_param;
177 p->ppStackBottom = &yyss;
178 p->ppStackTop = &yyssp;
179 }
180
181 // tell bison to spit out verbose syntax error messages
182 %error-verbose
183
184 %token <Char> EXT_ASCII_CHAR
185
186 %type <Char> char char_base alpha_char digit digit_oct digit_hex escape_seq escape_seq_octal escape_seq_hex
187 %type <Dotnum> real dotnum volume_value boolean control_value
188 %type <Number> number sampler_channel instrument_index fx_send_id audio_channel_index device_index effect_index effect_instance effect_chain chain_pos input_control midi_input_channel_index midi_input_port_index midi_map midi_bank midi_prog midi_ctrl
189 %type <String> string string_escaped text text_escaped text_escaped_base stringval stringval_escaped digits param_val_list param_val query_val filename module effect_system db_path map_name entry_name fx_send_name effect_name engine_name command add_instruction create_instruction destroy_instruction get_instruction list_instruction load_instruction send_instruction set_chan_instruction load_instr_args load_engine_args audio_output_type_name midi_input_type_name remove_instruction unmap_instruction set_instruction subscribe_event unsubscribe_event map_instruction reset_instruction clear_instruction find_instruction move_instruction copy_instruction scan_mode edit_instruction format_instruction append_instruction insert_instruction
190 %type <FillResponse> buffer_size_type
191 %type <KeyValList> key_val_list query_val_list
192 %type <LoadMode> instr_load_mode
193 %type <Bool> modal_arg
194 %type <UniversalPath> path path_base path_prefix path_body
195
196 %start input
197
198 %%
199
200 //TODO: return more meaningful error messages
201
202 /*
203 The LSCP specification document input file (Documentation/lscp.xml) is
204 automatically updated with this file using the scripts/update_grammar.pl
205 script. Do not modify or delete the GRAMMAR_BNF_BEGIN and GRAMMAR_BNF_END
206 lines !
207 */
208
209 // GRAMMAR_BNF_BEGIN - do NOT delete or modify this line !!!
210
211 input : line LF
212 | line CR LF
213 ;
214
215 line : /* epsilon (empty line ignored) */ { INCREMENT_LINE; return LSCP_DONE; }
216 | comment { INCREMENT_LINE; return LSCP_DONE; }
217 | command { INCREMENT_LINE; LSCPSERVER->AnswerClient($1); return LSCP_DONE; }
218 | error { INCREMENT_LINE; LSCPSERVER->AnswerClient("ERR:0:" + sLastError + "\r\n"); RESTART; return LSCP_SYNTAX_ERROR; }
219 ;
220
221 comment : '#'
222 | comment '#'
223 | comment SP
224 | comment number
225 | comment string
226 ;
227
228 command : ADD SP add_instruction { $$ = $3; }
229 | MAP SP map_instruction { $$ = $3; }
230 | UNMAP SP unmap_instruction { $$ = $3; }
231 | GET SP get_instruction { $$ = $3; }
232 | CREATE SP create_instruction { $$ = $3; }
233 | DESTROY SP destroy_instruction { $$ = $3; }
234 | LIST SP list_instruction { $$ = $3; }
235 | LOAD SP load_instruction { $$ = $3; }
236 | REMOVE SP remove_instruction { $$ = $3; }
237 | SET SP set_instruction { $$ = $3; }
238 | SUBSCRIBE SP subscribe_event { $$ = $3; }
239 | UNSUBSCRIBE SP unsubscribe_event { $$ = $3; }
240 | RESET SP reset_instruction { $$ = $3; }
241 | CLEAR SP clear_instruction { $$ = $3; }
242 | FIND SP find_instruction { $$ = $3; }
243 | MOVE SP move_instruction { $$ = $3; }
244 | COPY SP copy_instruction { $$ = $3; }
245 | EDIT SP edit_instruction { $$ = $3; }
246 | FORMAT SP format_instruction { $$ = $3; }
247 | SEND SP send_instruction { $$ = $3; }
248 | APPEND SP append_instruction { $$ = $3; }
249 | INSERT SP insert_instruction { $$ = $3; }
250 | RESET { $$ = LSCPSERVER->ResetSampler(); }
251 | QUIT { LSCPSERVER->AnswerClient("Bye!\r\n"); return LSCP_QUIT; }
252 ;
253
254 add_instruction : CHANNEL { $$ = LSCPSERVER->AddChannel(); }
255 | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index { $$ = LSCPSERVER->AddChannelMidiInput($5,$7); }
256 | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index { $$ = LSCPSERVER->AddChannelMidiInput($5,$7,$9); }
257 | DB_INSTRUMENT_DIRECTORY SP db_path { $$ = LSCPSERVER->AddDbInstrumentDirectory($3); }
258 | DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true); }
259 | DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP FILE_AS_DIR SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$9,$11, true, true); }
260 | DB_INSTRUMENTS SP scan_mode SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7); }
261 | DB_INSTRUMENTS SP scan_mode SP FILE_AS_DIR SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$7,$9, false, true); }
262 | DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$7, -1, true); }
263 | DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename SP instrument_index { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true); }
264 | DB_INSTRUMENTS SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$5); }
265 | DB_INSTRUMENTS SP db_path SP filename SP instrument_index { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7); }
266 | MIDI_INSTRUMENT_MAP { $$ = LSCPSERVER->AddMidiInstrumentMap(); }
267 | MIDI_INSTRUMENT_MAP SP map_name { $$ = LSCPSERVER->AddMidiInstrumentMap($3); }
268 | SEND_EFFECT_CHAIN SP device_index { $$ = LSCPSERVER->AddSendEffectChain($3); }
269 ;
270
271 subscribe_event : AUDIO_OUTPUT_DEVICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_count); }
272 | AUDIO_OUTPUT_DEVICE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_info); }
273 | MIDI_INPUT_DEVICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_count); }
274 | MIDI_INPUT_DEVICE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_info); }
275 | CHANNEL_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_count); }
276 | CHANNEL_MIDI { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_midi); }
277 | DEVICE_MIDI { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_device_midi); }
278 | VOICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_voice_count); }
279 | STREAM_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_stream_count); }
280 | BUFFER_FILL { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_buffer_fill); }
281 | CHANNEL_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_info); }
282 | FX_SEND_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_send_count); }
283 | FX_SEND_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_send_info); }
284 | MIDI_INSTRUMENT_MAP_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_map_count); }
285 | MIDI_INSTRUMENT_MAP_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_map_info); }
286 | MIDI_INSTRUMENT_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_count); }
287 | MIDI_INSTRUMENT_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_info); }
288 | DB_INSTRUMENT_DIRECTORY_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_dir_count); }
289 | DB_INSTRUMENT_DIRECTORY_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_dir_info); }
290 | DB_INSTRUMENT_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_count); }
291 | DB_INSTRUMENT_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_info); }
292 | DB_INSTRUMENTS_JOB_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instrs_job_info); }
293 | MISCELLANEOUS { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_misc); }
294 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_stream_count); }
295 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_voice_count); }
296 | GLOBAL_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_global_info); }
297 | EFFECT_INSTANCE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_count); }
298 | EFFECT_INSTANCE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_info); }
299 | SEND_EFFECT_CHAIN_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_count); }
300 | SEND_EFFECT_CHAIN_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_info); }
301 ;
302
303 unsubscribe_event : AUDIO_OUTPUT_DEVICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_count); }
304 | AUDIO_OUTPUT_DEVICE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_info); }
305 | MIDI_INPUT_DEVICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_count); }
306 | MIDI_INPUT_DEVICE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_info); }
307 | CHANNEL_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_count); }
308 | CHANNEL_MIDI { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_midi); }
309 | DEVICE_MIDI { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_device_midi); }
310 | VOICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_voice_count); }
311 | STREAM_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_stream_count); }
312 | BUFFER_FILL { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_buffer_fill); }
313 | CHANNEL_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_info); }
314 | FX_SEND_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_send_count); }
315 | FX_SEND_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_send_info); }
316 | MIDI_INSTRUMENT_MAP_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_map_count); }
317 | MIDI_INSTRUMENT_MAP_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_map_info); }
318 | MIDI_INSTRUMENT_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_count); }
319 | MIDI_INSTRUMENT_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_info); }
320 | DB_INSTRUMENT_DIRECTORY_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_dir_count); }
321 | DB_INSTRUMENT_DIRECTORY_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_dir_info); }
322 | DB_INSTRUMENT_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_count); }
323 | DB_INSTRUMENT_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_info); }
324 | DB_INSTRUMENTS_JOB_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instrs_job_info); }
325 | MISCELLANEOUS { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_misc); }
326 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_stream_count); }
327 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_voice_count); }
328 | GLOBAL_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_global_info); }
329 | EFFECT_INSTANCE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_count); }
330 | EFFECT_INSTANCE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_info); }
331 | SEND_EFFECT_CHAIN_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_count); }
332 | SEND_EFFECT_CHAIN_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_info); }
333 ;
334
335 map_instruction : MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,MidiInstrumentMapper::DONTCARE,"",$3); }
336 | MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,$18,"",$3); }
337 | MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP entry_name { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,MidiInstrumentMapper::DONTCARE,$18,$3); }
338 | MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode SP entry_name { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,$18,$20,$3); }
339 ;
340
341 unmap_instruction : MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog { $$ = LSCPSERVER->RemoveMIDIInstrumentMapping($3,$5,$7); }
342 ;
343
344 remove_instruction : CHANNEL SP sampler_channel { $$ = LSCPSERVER->RemoveChannel($3); }
345 | CHANNEL SP MIDI_INPUT SP sampler_channel { $$ = LSCPSERVER->RemoveChannelMidiInput($5); }
346 | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7); }
347 | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7,$9); }
348 | MIDI_INSTRUMENT_MAP SP midi_map { $$ = LSCPSERVER->RemoveMidiInstrumentMap($3); }
349 | MIDI_INSTRUMENT_MAP SP ALL { $$ = LSCPSERVER->RemoveAllMidiInstrumentMaps(); }
350 | SEND_EFFECT_CHAIN SP device_index SP effect_chain { $$ = LSCPSERVER->RemoveSendEffectChain($3,$5); }
351 | SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP chain_pos { $$ = LSCPSERVER->RemoveSendEffectChainEffect($5,$7,$9); }
352 | FX_SEND SP EFFECT SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->SetFxSendEffect($5,$7,-1,-1); }
353 | DB_INSTRUMENT_DIRECTORY SP FORCE SP db_path { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($5, true); }
354 | DB_INSTRUMENT_DIRECTORY SP db_path { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($3); }
355 | DB_INSTRUMENT SP db_path { $$ = LSCPSERVER->RemoveDbInstrument($3); }
356 ;
357
358 get_instruction : AVAILABLE_ENGINES { $$ = LSCPSERVER->GetAvailableEngines(); }
359 | AVAILABLE_EFFECTS { $$ = LSCPSERVER->GetAvailableEffects(); }
360 | EFFECT_INSTANCES { $$ = LSCPSERVER->GetEffectInstances(); }
361 | EFFECT SP INFO SP effect_index { $$ = LSCPSERVER->GetEffectInfo($5); }
362 | EFFECT_INSTANCE SP INFO SP effect_instance { $$ = LSCPSERVER->GetEffectInstanceInfo($5); }
363 | EFFECT_INSTANCE_INPUT_CONTROL SP INFO SP effect_instance SP input_control { $$ = LSCPSERVER->GetEffectInstanceInputControlInfo($5,$7); }
364 | SEND_EFFECT_CHAINS SP device_index { $$ = LSCPSERVER->GetSendEffectChains($3); }
365 | SEND_EFFECT_CHAIN SP INFO SP device_index SP effect_chain { $$ = LSCPSERVER->GetSendEffectChainInfo($5,$7); }
366 | AVAILABLE_MIDI_INPUT_DRIVERS { $$ = LSCPSERVER->GetAvailableMidiInputDrivers(); }
367 | MIDI_INPUT_DRIVER SP INFO SP string { $$ = LSCPSERVER->GetMidiInputDriverInfo($5); }
368 | MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7); }
369 | MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7, $9); }
370 | AVAILABLE_AUDIO_OUTPUT_DRIVERS { $$ = LSCPSERVER->GetAvailableAudioOutputDrivers(); }
371 | AUDIO_OUTPUT_DRIVER SP INFO SP string { $$ = LSCPSERVER->GetAudioOutputDriverInfo($5); }
372 | AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string { $$ = LSCPSERVER->GetAudioOutputDriverParameterInfo($5, $7); }
373 | AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list { $$ = LSCPSERVER->GetAudioOutputDriverParameterInfo($5, $7, $9); }
374 | AUDIO_OUTPUT_DEVICES { $$ = LSCPSERVER->GetAudioOutputDeviceCount(); }
375 | MIDI_INPUT_DEVICES { $$ = LSCPSERVER->GetMidiInputDeviceCount(); }
376 | AUDIO_OUTPUT_DEVICE SP INFO SP number { $$ = LSCPSERVER->GetAudioOutputDeviceInfo($5); }
377 | MIDI_INPUT_DEVICE SP INFO SP number { $$ = LSCPSERVER->GetMidiInputDeviceInfo($5); }
378 | MIDI_INPUT_PORT SP INFO SP number SP number { $$ = LSCPSERVER->GetMidiInputPortInfo($5, $7); }
379 | MIDI_INPUT_PORT_PARAMETER SP INFO SP number SP number SP string { $$ = LSCPSERVER->GetMidiInputPortParameterInfo($5, $7, $9); }
380 | AUDIO_OUTPUT_CHANNEL SP INFO SP number SP number { $$ = LSCPSERVER->GetAudioOutputChannelInfo($5, $7); }
381 | AUDIO_OUTPUT_CHANNEL_PARAMETER SP INFO SP number SP number SP string { $$ = LSCPSERVER->GetAudioOutputChannelParameterInfo($5, $7, $9); }
382 | CHANNELS { $$ = LSCPSERVER->GetChannels(); }
383 | CHANNEL SP INFO SP sampler_channel { $$ = LSCPSERVER->GetChannelInfo($5); }
384 | CHANNEL SP BUFFER_FILL SP buffer_size_type SP sampler_channel { $$ = LSCPSERVER->GetBufferFill($5, $7); }
385 | CHANNEL SP STREAM_COUNT SP sampler_channel { $$ = LSCPSERVER->GetStreamCount($5); }
386 | CHANNEL SP VOICE_COUNT SP sampler_channel { $$ = LSCPSERVER->GetVoiceCount($5); }
387 | ENGINE SP INFO SP engine_name { $$ = LSCPSERVER->GetEngineInfo($5); }
388 | SERVER SP INFO { $$ = LSCPSERVER->GetServerInfo(); }
389 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->GetTotalStreamCount(); }
390 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->GetTotalVoiceCount(); }
391 | TOTAL_VOICE_COUNT_MAX { $$ = LSCPSERVER->GetTotalVoiceCountMax(); }
392 | MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->GetMidiInstrumentMappings($3); }
393 | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->GetAllMidiInstrumentMappings(); }
394 | MIDI_INSTRUMENT SP INFO SP midi_map SP midi_bank SP midi_prog { $$ = LSCPSERVER->GetMidiInstrumentMapping($5,$7,$9); }
395 | MIDI_INSTRUMENT_MAPS { $$ = LSCPSERVER->GetMidiInstrumentMaps(); }
396 | MIDI_INSTRUMENT_MAP SP INFO SP midi_map { $$ = LSCPSERVER->GetMidiInstrumentMap($5); }
397 | FX_SENDS SP sampler_channel { $$ = LSCPSERVER->GetFxSends($3); }
398 | FX_SEND SP INFO SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->GetFxSendInfo($5,$7); }
399 | DB_INSTRUMENT_DIRECTORIES SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryCount($5, true); }
400 | DB_INSTRUMENT_DIRECTORIES SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryCount($3, false); }
401 | DB_INSTRUMENT_DIRECTORY SP INFO SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryInfo($5); }
402 | DB_INSTRUMENTS SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentCount($5, true); }
403 | DB_INSTRUMENTS SP db_path { $$ = LSCPSERVER->GetDbInstrumentCount($3, false); }
404 | DB_INSTRUMENT SP INFO SP db_path { $$ = LSCPSERVER->GetDbInstrumentInfo($5); }
405 | DB_INSTRUMENTS_JOB SP INFO SP number { $$ = LSCPSERVER->GetDbInstrumentsJobInfo($5); }
406 | VOLUME { $$ = LSCPSERVER->GetGlobalVolume(); }
407 | VOICES { $$ = LSCPSERVER->GetGlobalMaxVoices(); }
408 | STREAMS { $$ = LSCPSERVER->GetGlobalMaxStreams(); }
409 | FILE SP INSTRUMENTS SP filename { $$ = LSCPSERVER->GetFileInstruments($5); }
410 | FILE SP INSTRUMENT SP INFO SP filename SP instrument_index { $$ = LSCPSERVER->GetFileInstrumentInfo($7,$9); }
411 ;
412
413 set_instruction : AUDIO_OUTPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetAudioOutputDeviceParameter($3, $5, $7); }
414 | AUDIO_OUTPUT_CHANNEL_PARAMETER SP number SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetAudioOutputChannelParameter($3, $5, $7, $9); }
415 | MIDI_INPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetMidiInputDeviceParameter($3, $5, $7); }
416 | MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' NONE { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, ""); }
417 | MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, $9); }
418 | EFFECT_INSTANCE_INPUT_CONTROL SP VALUE SP effect_instance SP input_control SP control_value { $$ = LSCPSERVER->SetEffectInstanceInputControlValue($5, $7, $9); }
419 | CHANNEL SP set_chan_instruction { $$ = $3; }
420 | MIDI_INSTRUMENT_MAP SP NAME SP midi_map SP map_name { $$ = LSCPSERVER->SetMidiInstrumentMapName($5, $7); }
421 | FX_SEND SP NAME SP sampler_channel SP fx_send_id SP fx_send_name { $$ = LSCPSERVER->SetFxSendName($5,$7,$9); }
422 | FX_SEND SP AUDIO_OUTPUT_CHANNEL SP sampler_channel SP fx_send_id SP audio_channel_index SP audio_channel_index { $$ = LSCPSERVER->SetFxSendAudioOutputChannel($5,$7,$9,$11); }
423 | FX_SEND SP MIDI_CONTROLLER SP sampler_channel SP fx_send_id SP midi_ctrl { $$ = LSCPSERVER->SetFxSendMidiController($5,$7,$9); }
424 | FX_SEND SP LEVEL SP sampler_channel SP fx_send_id SP volume_value { $$ = LSCPSERVER->SetFxSendLevel($5,$7,$9); }
425 | FX_SEND SP EFFECT SP sampler_channel SP fx_send_id SP effect_chain SP chain_pos { $$ = LSCPSERVER->SetFxSendEffect($5,$7,$9,$11); }
426 | DB_INSTRUMENT_DIRECTORY SP NAME SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDirectoryName($5,$7); }
427 | DB_INSTRUMENT_DIRECTORY SP DESCRIPTION SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDirectoryDescription($5,$7); }
428 | DB_INSTRUMENT SP NAME SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentName($5,$7); }
429 | DB_INSTRUMENT SP DESCRIPTION SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDescription($5,$7); }
430 | DB_INSTRUMENT SP FILE_PATH SP filename SP filename { $$ = LSCPSERVER->SetDbInstrumentFilePath($5,$7); }
431 | ECHO SP boolean { $$ = LSCPSERVER->SetEcho((yyparse_param_t*) yyparse_param, $3); }
432 | SHELL SP INTERACT SP boolean { $$ = LSCPSERVER->SetShellInteract((yyparse_param_t*) yyparse_param, $5); }
433 | VOLUME SP volume_value { $$ = LSCPSERVER->SetGlobalVolume($3); }
434 | VOICES SP number { $$ = LSCPSERVER->SetGlobalMaxVoices($3); }
435 | STREAMS SP number { $$ = LSCPSERVER->SetGlobalMaxStreams($3); }
436 ;
437
438 create_instruction : AUDIO_OUTPUT_DEVICE SP string SP key_val_list { $$ = LSCPSERVER->CreateAudioOutputDevice($3,$5); }
439 | AUDIO_OUTPUT_DEVICE SP string { $$ = LSCPSERVER->CreateAudioOutputDevice($3); }
440 | MIDI_INPUT_DEVICE SP string SP key_val_list { $$ = LSCPSERVER->CreateMidiInputDevice($3,$5); }
441 | MIDI_INPUT_DEVICE SP string { $$ = LSCPSERVER->CreateMidiInputDevice($3); }
442 | FX_SEND SP sampler_channel SP midi_ctrl { $$ = LSCPSERVER->CreateFxSend($3,$5); }
443 | FX_SEND SP sampler_channel SP midi_ctrl SP fx_send_name { $$ = LSCPSERVER->CreateFxSend($3,$5,$7); }
444 | EFFECT_INSTANCE SP effect_index { $$ = LSCPSERVER->CreateEffectInstance($3); }
445 | EFFECT_INSTANCE SP effect_system SP module SP effect_name { $$ = LSCPSERVER->CreateEffectInstance($3,$5,$7); }
446 ;
447
448 reset_instruction : CHANNEL SP sampler_channel { $$ = LSCPSERVER->ResetChannel($3); }
449 ;
450
451 clear_instruction : MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->ClearMidiInstrumentMappings($3); }
452 | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->ClearAllMidiInstrumentMappings(); }
453 ;
454
455 find_instruction : DB_INSTRUMENTS SP NON_RECURSIVE SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstruments($5,$7, false); }
456 | DB_INSTRUMENTS SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstruments($3,$5, true); }
457 | DB_INSTRUMENT_DIRECTORIES SP NON_RECURSIVE SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstrumentDirectories($5,$7, false); }
458 | DB_INSTRUMENT_DIRECTORIES SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstrumentDirectories($3,$5, true); }
459 | LOST SP DB_INSTRUMENT_FILES { $$ = LSCPSERVER->FindLostDbInstrumentFiles(); }
460 ;
461
462 move_instruction : DB_INSTRUMENT_DIRECTORY SP db_path SP db_path { $$ = LSCPSERVER->MoveDbInstrumentDirectory($3,$5); }
463 | DB_INSTRUMENT SP db_path SP db_path { $$ = LSCPSERVER->MoveDbInstrument($3,$5); }
464 ;
465
466 copy_instruction : DB_INSTRUMENT_DIRECTORY SP db_path SP db_path { $$ = LSCPSERVER->CopyDbInstrumentDirectory($3,$5); }
467 | DB_INSTRUMENT SP db_path SP db_path { $$ = LSCPSERVER->CopyDbInstrument($3,$5); }
468 ;
469
470 destroy_instruction : AUDIO_OUTPUT_DEVICE SP number { $$ = LSCPSERVER->DestroyAudioOutputDevice($3); }
471 | MIDI_INPUT_DEVICE SP number { $$ = LSCPSERVER->DestroyMidiInputDevice($3); }
472 | FX_SEND SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->DestroyFxSend($3,$5); }
473 | EFFECT_INSTANCE SP number { $$ = LSCPSERVER->DestroyEffectInstance($3); }
474 ;
475
476 load_instruction : INSTRUMENT SP load_instr_args { $$ = $3; }
477 | ENGINE SP load_engine_args { $$ = $3; }
478 ;
479
480 append_instruction : SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP effect_instance { $$ = LSCPSERVER->AppendSendEffectChainEffect($5,$7,$9); }
481 ;
482
483 insert_instruction : SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP chain_pos SP effect_instance { $$ = LSCPSERVER->InsertSendEffectChainEffect($5,$7,$9,$11); }
484 ;
485
486 set_chan_instruction : AUDIO_OUTPUT_DEVICE SP sampler_channel SP device_index { $$ = LSCPSERVER->SetAudioOutputDevice($5, $3); }
487 | AUDIO_OUTPUT_CHANNEL SP sampler_channel SP audio_channel_index SP audio_channel_index { $$ = LSCPSERVER->SetAudioOutputChannel($5, $7, $3); }
488 | AUDIO_OUTPUT_TYPE SP sampler_channel SP audio_output_type_name { $$ = LSCPSERVER->SetAudioOutputType($5, $3); }
489 | MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index SP midi_input_channel_index { $$ = LSCPSERVER->SetMIDIInput($5, $7, $9, $3); }
490 | MIDI_INPUT_DEVICE SP sampler_channel SP device_index { $$ = LSCPSERVER->SetMIDIInputDevice($5, $3); }
491 | MIDI_INPUT_PORT SP sampler_channel SP midi_input_port_index { $$ = LSCPSERVER->SetMIDIInputPort($5, $3); }
492 | MIDI_INPUT_CHANNEL SP sampler_channel SP midi_input_channel_index { $$ = LSCPSERVER->SetMIDIInputChannel($5, $3); }
493 | MIDI_INPUT_TYPE SP sampler_channel SP midi_input_type_name { $$ = LSCPSERVER->SetMIDIInputType($5, $3); }
494 | VOLUME SP sampler_channel SP volume_value { $$ = LSCPSERVER->SetVolume($5, $3); }
495 | MUTE SP sampler_channel SP boolean { $$ = LSCPSERVER->SetChannelMute($5, $3); }
496 | SOLO SP sampler_channel SP boolean { $$ = LSCPSERVER->SetChannelSolo($5, $3); }
497 | MIDI_INSTRUMENT_MAP SP sampler_channel SP midi_map { $$ = LSCPSERVER->SetChannelMap($3, $5); }
498 | MIDI_INSTRUMENT_MAP SP sampler_channel SP NONE { $$ = LSCPSERVER->SetChannelMap($3, -1); }
499 | MIDI_INSTRUMENT_MAP SP sampler_channel SP DEFAULT { $$ = LSCPSERVER->SetChannelMap($3, -2); }
500 ;
501
502 edit_instruction : CHANNEL SP INSTRUMENT SP sampler_channel { $$ = LSCPSERVER->EditSamplerChannelInstrument($5); }
503 ;
504
505 format_instruction : INSTRUMENTS_DB { $$ = LSCPSERVER->FormatInstrumentsDb(); }
506 ;
507
508 modal_arg : /* epsilon (empty argument) */ { $$ = true; }
509 | NON_MODAL SP { $$ = false; }
510 ;
511
512 key_val_list : string '=' param_val_list { $$[$1] = $3; }
513 | key_val_list SP string '=' param_val_list { $$ = $1; $$[$3] = $5; }
514 ;
515
516 buffer_size_type : BYTES { $$ = fill_response_bytes; }
517 | PERCENTAGE { $$ = fill_response_percentage; }
518 ;
519
520 list_instruction : AUDIO_OUTPUT_DEVICES { $$ = LSCPSERVER->GetAudioOutputDevices(); }
521 | MIDI_INPUT_DEVICES { $$ = LSCPSERVER->GetMidiInputDevices(); }
522 | CHANNELS { $$ = LSCPSERVER->ListChannels(); }
523 | CHANNEL SP MIDI_INPUTS SP sampler_channel { $$ = LSCPSERVER->ListChannelMidiInputs($5); }
524 | AVAILABLE_ENGINES { $$ = LSCPSERVER->ListAvailableEngines(); }
525 | AVAILABLE_EFFECTS { $$ = LSCPSERVER->ListAvailableEffects(); }
526 | EFFECT_INSTANCES { $$ = LSCPSERVER->ListEffectInstances(); }
527 | SEND_EFFECT_CHAINS SP number { $$ = LSCPSERVER->ListSendEffectChains($3); }
528 | AVAILABLE_MIDI_INPUT_DRIVERS { $$ = LSCPSERVER->ListAvailableMidiInputDrivers(); }
529 | AVAILABLE_AUDIO_OUTPUT_DRIVERS { $$ = LSCPSERVER->ListAvailableAudioOutputDrivers(); }
530 | MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->ListMidiInstrumentMappings($3); }
531 | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->ListAllMidiInstrumentMappings(); }
532 | MIDI_INSTRUMENT_MAPS { $$ = LSCPSERVER->ListMidiInstrumentMaps(); }
533 | FX_SENDS SP sampler_channel { $$ = LSCPSERVER->ListFxSends($3); }
534 | DB_INSTRUMENT_DIRECTORIES SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectories($5, true); }
535 | DB_INSTRUMENT_DIRECTORIES SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectories($3); }
536 | DB_INSTRUMENTS SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstruments($5, true); }
537 | DB_INSTRUMENTS SP db_path { $$ = LSCPSERVER->GetDbInstruments($3); }
538 | FILE SP INSTRUMENTS SP filename { $$ = LSCPSERVER->ListFileInstruments($5); }
539 ;
540
541 send_instruction : CHANNEL SP MIDI_DATA SP string SP sampler_channel SP number SP number { $$ = LSCPSERVER->SendChannelMidiData($5, $7, $9, $11); }
542 ;
543
544 load_instr_args : filename SP instrument_index SP sampler_channel { $$ = LSCPSERVER->LoadInstrument($1, $3, $5); }
545 | NON_MODAL SP filename SP instrument_index SP sampler_channel { $$ = LSCPSERVER->LoadInstrument($3, $5, $7, true); }
546 ;
547
548 load_engine_args : engine_name SP sampler_channel { $$ = LSCPSERVER->SetEngineType($1, $3); }
549 ;
550
551 instr_load_mode : ON_DEMAND { $$ = MidiInstrumentMapper::ON_DEMAND; }
552 | ON_DEMAND_HOLD { $$ = MidiInstrumentMapper::ON_DEMAND_HOLD; }
553 | PERSISTENT { $$ = MidiInstrumentMapper::PERSISTENT; }
554 ;
555
556 effect_instance : number
557 ;
558
559 device_index : number
560 ;
561
562 audio_channel_index : number
563 ;
564
565 audio_output_type_name : string
566 ;
567
568 midi_input_port_index : number
569 ;
570
571 midi_input_channel_index : number
572 | ALL { $$ = 16; }
573 ;
574
575 midi_input_type_name : string
576 ;
577
578 midi_map : number
579 ;
580
581 midi_bank : number
582 ;
583
584 midi_prog : number
585 ;
586
587 midi_ctrl : number
588 ;
589
590 volume_value : dotnum
591 | number { $$ = $1; }
592 ;
593
594 control_value : real
595 ;
596
597 sampler_channel : number
598 ;
599
600 instrument_index : number
601 ;
602
603 fx_send_id : number
604 ;
605
606 engine_name : string
607 ;
608
609 filename : path {
610 #if WIN32
611 $$ = $1.toWindows();
612 #else
613 // assuming POSIX
614 $$ = $1.toPosix();
615 #endif
616 }
617 ;
618
619 db_path : path { $$ = $1.toDbPath(); }
620 ;
621
622 map_name : stringval_escaped
623 ;
624
625 entry_name : stringval_escaped
626 ;
627
628 fx_send_name : stringval_escaped
629 ;
630
631 effect_name : stringval_escaped
632 ;
633
634 effect_index : number
635 ;
636
637 effect_chain : number
638 ;
639
640 chain_pos : number
641 ;
642
643 input_control : number
644 ;
645
646 param_val_list : param_val
647 | param_val_list','param_val { $$ = $1 + "," + $3; }
648 ;
649
650 //TODO: the re-encapsulation into apostrophes for string and strinval here is a hack, since we need a way for __parse_strings() (DeviceParameters.cpp) to distinguish a comma separated list of strings and a string which contains commas. A clean solution would be to move those parser jobs over here to lscp.y
651 param_val : string { $$ = "\'" + $1 + "\'"; }
652 | stringval { $$ = "\'" + $1 + "\'"; }
653 | number { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); }
654 | dotnum { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); } //TODO: maybe better using 'real' instead of 'number' and 'dotnum' rules
655 ;
656
657 query_val_list : string '=' query_val { $$[$1] = $3; }
658 | query_val_list SP string '=' query_val { $$ = $1; $$[$3] = $5; }
659 ;
660
661 query_val : text_escaped
662 | stringval_escaped
663 ;
664
665 scan_mode : RECURSIVE { $$ = "RECURSIVE"; }
666 | NON_RECURSIVE { $$ = "NON_RECURSIVE"; }
667 | FLAT { $$ = "FLAT"; }
668 ;
669
670 effect_system : string
671 ;
672
673 module : filename
674 ;
675
676 // GRAMMAR_BNF_END - do NOT delete or modify this line !!!
677
678
679 // atomic variable symbol rules
680
681 boolean : number { $$ = $1; }
682 | string { $$ = -1; }
683 ;
684
685 dotnum : digits '.' digits { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
686 | '+' digits '.' digits { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
687 | '-' digits '.' digits { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
688 ;
689
690 real : digits '.' digits { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
691 | '+' digits '.' digits { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
692 | '-' digits '.' digits { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
693 | digits { std::stringstream ss($1); ss.imbue(std::locale::classic()); ss >> $$; }
694 | '+' digits { std::stringstream ss($2); ss.imbue(std::locale::classic()); ss >> $$; }
695 | '-' digits { std::stringstream ss("-" + $2); ss.imbue(std::locale::classic()); ss >> $$; }
696 ;
697
698
699 digits : digit { $$ = $1; }
700 | digits digit { $$ = $1 + $2; }
701 ;
702
703 digit : '0' { $$ = '0'; }
704 | '1' { $$ = '1'; }
705 | '2' { $$ = '2'; }
706 | '3' { $$ = '3'; }
707 | '4' { $$ = '4'; }
708 | '5' { $$ = '5'; }
709 | '6' { $$ = '6'; }
710 | '7' { $$ = '7'; }
711 | '8' { $$ = '8'; }
712 | '9' { $$ = '9'; }
713 ;
714
715 digit_oct : '0' { $$ = '0'; }
716 | '1' { $$ = '1'; }
717 | '2' { $$ = '2'; }
718 | '3' { $$ = '3'; }
719 | '4' { $$ = '4'; }
720 | '5' { $$ = '5'; }
721 | '6' { $$ = '6'; }
722 | '7' { $$ = '7'; }
723 ;
724
725 digit_hex : '0' { $$ = '0'; }
726 | '1' { $$ = '1'; }
727 | '2' { $$ = '2'; }
728 | '3' { $$ = '3'; }
729 | '4' { $$ = '4'; }
730 | '5' { $$ = '5'; }
731 | '6' { $$ = '6'; }
732 | '7' { $$ = '7'; }
733 | '8' { $$ = '8'; }
734 | '9' { $$ = '9'; }
735 | 'a' { $$ = 'a'; }
736 | 'b' { $$ = 'b'; }
737 | 'c' { $$ = 'c'; }
738 | 'd' { $$ = 'd'; }
739 | 'e' { $$ = 'e'; }
740 | 'f' { $$ = 'f'; }
741 | 'A' { $$ = 'a'; }
742 | 'B' { $$ = 'b'; }
743 | 'C' { $$ = 'c'; }
744 | 'D' { $$ = 'd'; }
745 | 'E' { $$ = 'e'; }
746 | 'F' { $$ = 'f'; }
747 ;
748
749 number : digit { $$ = atoi(String(1, $1).c_str()); }
750 | '1' digits { $$ = atoi(String(String("1") + $2).c_str()); }
751 | '2' digits { $$ = atoi(String(String("2") + $2).c_str()); }
752 | '3' digits { $$ = atoi(String(String("3") + $2).c_str()); }
753 | '4' digits { $$ = atoi(String(String("4") + $2).c_str()); }
754 | '5' digits { $$ = atoi(String(String("5") + $2).c_str()); }
755 | '6' digits { $$ = atoi(String(String("6") + $2).c_str()); }
756 | '7' digits { $$ = atoi(String(String("7") + $2).c_str()); }
757 | '8' digits { $$ = atoi(String(String("8") + $2).c_str()); }
758 | '9' digits { $$ = atoi(String(String("9") + $2).c_str()); }
759 ;
760
761 path : '\'' path_base '\'' { $$ = $2; }
762 | '\"' path_base '\"' { $$ = $2; }
763 ;
764
765 path_base : path_prefix path_body { $$ = $1 + $2; }
766 ;
767
768 path_prefix : '/' { $$ = Path(); }
769 | alpha_char ':' '/' { Path p; p.setDrive($1); $$ = p; }
770 ;
771
772 path_body : /* epsilon (empty argument) */ { $$ = Path(); }
773 | path_body '/' { $$ = $1; }
774 | path_body text_escaped_base { Path p; p.appendNode($2); $$ = $1 + p; }
775 ;
776
777 stringval : '\'' text '\'' { $$ = $2; }
778 | '\"' text '\"' { $$ = $2; }
779 ;
780
781 stringval_escaped : '\'' text_escaped '\'' { $$ = $2; }
782 | '\"' text_escaped '\"' { $$ = $2; }
783 ;
784
785 text : SP { $$ = " "; }
786 | string
787 | text SP { $$ = $1 + " "; }
788 | text string { $$ = $1 + $2; }
789 ;
790
791 // like text_escaped, but missing the slash ('/') character
792 text_escaped_base : SP { $$ = " "; }
793 | string_escaped
794 | text_escaped_base SP { $$ = $1 + " "; }
795 | text_escaped_base string_escaped { $$ = $1 + $2; }
796 ;
797
798 text_escaped : '/' { $$ = "/"; }
799 | text_escaped_base
800 | text_escaped '/' { $$ = $1 + "/"; }
801 | text_escaped text_escaped_base { $$ = $1 + $2; }
802 ;
803
804 string : char { std::string s; s = $1; $$ = s; }
805 | string char { $$ = $1 + $2; }
806 ;
807
808 string_escaped : char_base { std::string s; s = $1; $$ = s; }
809 | escape_seq { std::string s; s = $1; $$ = s; }
810 | string_escaped char_base { $$ = $1 + $2; }
811 | string_escaped escape_seq { $$ = $1 + $2; }
812 ;
813
814 // full ASCII character set except space, quotation mark and apostrophe
815 char : char_base
816 | '\\' { $$ = '\\'; }
817 | '/' { $$ = '/'; }
818 ;
819
820 // characters A..Z and a..z
821 alpha_char : 'A' { $$ = 'A'; } | 'B' { $$ = 'B'; } | 'C' { $$ = 'C'; } | 'D' { $$ = 'D'; } | 'E' { $$ = 'E'; } | 'F' { $$ = 'F'; } | 'G' { $$ = 'G'; } | 'H' { $$ = 'H'; } | 'I' { $$ = 'I'; } | 'J' { $$ = 'J'; } | 'K' { $$ = 'K'; } | 'L' { $$ = 'L'; } | 'M' { $$ = 'M'; } | 'N' { $$ = 'N'; } | 'O' { $$ = 'O'; } | 'P' { $$ = 'P'; } | 'Q' { $$ = 'Q'; } | 'R' { $$ = 'R'; } | 'S' { $$ = 'S'; } | 'T' { $$ = 'T'; } | 'U' { $$ = 'U'; } | 'V' { $$ = 'V'; } | 'W' { $$ = 'W'; } | 'X' { $$ = 'X'; } | 'Y' { $$ = 'Y'; } | 'Z' { $$ = 'Z'; }
822 | 'a' { $$ = 'a'; } | 'b' { $$ = 'b'; } | 'c' { $$ = 'c'; } | 'd' { $$ = 'd'; } | 'e' { $$ = 'e'; } | 'f' { $$ = 'f'; } | 'g' { $$ = 'g'; } | 'h' { $$ = 'h'; } | 'i' { $$ = 'i'; } | 'j' { $$ = 'j'; } | 'k' { $$ = 'k'; } | 'l' { $$ = 'l'; } | 'm' { $$ = 'm'; } | 'n' { $$ = 'n'; } | 'o' { $$ = 'o'; } | 'p' { $$ = 'p'; } | 'q' { $$ = 'q'; } | 'r' { $$ = 'r'; } | 's' { $$ = 's'; } | 't' { $$ = 't'; } | 'u' { $$ = 'u'; } | 'v' { $$ = 'v'; } | 'w' { $$ = 'w'; } | 'x' { $$ = 'x'; } | 'y' { $$ = 'y'; } | 'z' { $$ = 'z'; }
823 ;
824
825 // ASCII characters except space, quotation mark, apostrophe, backslash and slash
826 char_base : alpha_char
827 | '0' { $$ = '0'; } | '1' { $$ = '1'; } | '2' { $$ = '2'; } | '3' { $$ = '3'; } | '4' { $$ = '4'; } | '5' { $$ = '5'; } | '6' { $$ = '6'; } | '7' { $$ = '7'; } | '8' { $$ = '8'; } | '9' { $$ = '9'; }
828 | '!' { $$ = '!'; } | '#' { $$ = '#'; } | '$' { $$ = '$'; } | '%' { $$ = '%'; } | '&' { $$ = '&'; } | '(' { $$ = '('; } | ')' { $$ = ')'; } | '*' { $$ = '*'; } | '+' { $$ = '+'; } | '-' { $$ = '-'; } | '.' { $$ = '.'; } | ',' { $$ = ','; }
829 | ':' { $$ = ':'; } | ';' { $$ = ';'; } | '<' { $$ = '<'; } | '=' { $$ = '='; } | '>' { $$ = '>'; } | '?' { $$ = '?'; } | '@' { $$ = '@'; }
830 | '[' { $$ = '['; } | ']' { $$ = ']'; } | '^' { $$ = '^'; } | '_' { $$ = '_'; }
831 | '{' { $$ = '{'; } | '|' { $$ = '|'; } | '}' { $$ = '}'; } | '~' { $$ = '~'; }
832 | EXT_ASCII_CHAR
833 ;
834
835 escape_seq : '\\' '\'' { $$ = '\''; }
836 | '\\' '\"' { $$ = '\"'; }
837 | '\\' '\\' { $$ = '\\'; }
838 | '\\' '/' { $$ = '/'; }
839 | '\\' 'n' { $$ = '\n'; }
840 | '\\' 'r' { $$ = '\r'; }
841 | '\\' 'f' { $$ = '\f'; }
842 | '\\' 't' { $$ = '\t'; }
843 | '\\' 'v' { $$ = '\v'; }
844 | escape_seq_octal
845 | escape_seq_hex
846 ;
847
848 escape_seq_octal : '\\' digit_oct { $$ = (char) octalsToNumber($2); }
849 | '\\' digit_oct digit_oct { $$ = (char) octalsToNumber($3,$2); }
850 | '\\' digit_oct digit_oct digit_oct { $$ = (char) octalsToNumber($4,$3,$2); }
851 ;
852
853 escape_seq_hex : '\\' 'x' digit_hex { $$ = (char) hexsToNumber($3); }
854 | '\\' 'x' digit_hex digit_hex { $$ = (char) hexsToNumber($4,$3); }
855 ;
856
857 // rules which are more or less just terminal symbols
858
859 SP : ' '
860 ;
861
862 LF : '\n'
863 ;
864
865 CR : '\r'
866 ;
867
868 ADD : 'A''D''D'
869 ;
870
871 GET : 'G''E''T'
872 ;
873
874 MAP : 'M''A''P'
875 ;
876
877 UNMAP : 'U''N''M''A''P'
878 ;
879
880 CLEAR : 'C''L''E''A''R'
881 ;
882
883 FIND : 'F''I''N''D'
884 ;
885
886 FILE_AS_DIR : 'F''I''L''E''_''A''S''_''D''I''R'
887 ;
888
889 MOVE : 'M''O''V''E'
890 ;
891
892 COPY : 'C''O''P''Y'
893 ;
894
895 CREATE : 'C''R''E''A''T''E'
896 ;
897
898 DESTROY : 'D''E''S''T''R''O''Y'
899 ;
900
901 LIST : 'L''I''S''T'
902 ;
903
904 LOAD : 'L''O''A''D'
905 ;
906
907 ALL : 'A''L''L'
908 ;
909
910 NONE : 'N''O''N''E'
911 ;
912
913 DEFAULT : 'D''E''F''A''U''L''T'
914 ;
915
916 NON_MODAL : 'N''O''N''_''M''O''D''A''L'
917 ;
918
919 REMOVE : 'R''E''M''O''V''E'
920 ;
921
922 SET : 'S''E''T'
923 ;
924
925 SHELL : 'S''H''E''L''L'
926 ;
927
928 INTERACT : 'I''N''T''E''R''A''C''T'
929 ;
930
931 APPEND : 'A''P''P''E''N''D'
932 ;
933
934 INSERT : 'I''N''S''E''R''T'
935 ;
936
937 SUBSCRIBE : 'S''U''B''S''C''R''I''B''E'
938 ;
939
940 UNSUBSCRIBE : 'U''N''S''U''B''S''C''R''I''B''E'
941 ;
942
943 CHANNEL : 'C''H''A''N''N''E''L'
944 ;
945
946 AVAILABLE_ENGINES : 'A''V''A''I''L''A''B''L''E''_''E''N''G''I''N''E''S'
947 ;
948
949 AVAILABLE_AUDIO_OUTPUT_DRIVERS : 'A''V''A''I''L''A''B''L''E''_''A''U''D''I''O''_''O''U''T''P''U''T''_''D''R''I''V''E''R''S'
950 ;
951
952 CHANNELS : 'C''H''A''N''N''E''L''S'
953 ;
954
955 INFO : 'I''N''F''O'
956 ;
957
958 AUDIO_OUTPUT_DEVICE_COUNT : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E''_''C''O''U''N''T'
959 ;
960
961 AUDIO_OUTPUT_DEVICE_INFO : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E''_''I''N''F''O'
962 ;
963
964 MIDI_INPUT_DEVICE_COUNT : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''_''C''O''U''N''T'
965 ;
966
967 MIDI_INPUT_DEVICE_INFO : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''_''I''N''F''O'
968 ;
969
970 MIDI_INSTRUMENT_MAP_COUNT : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P''_''C''O''U''N''T'
971 ;
972
973 MIDI_INSTRUMENT_MAP_INFO : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P''_''I''N''F''O'
974 ;
975
976 MIDI_INSTRUMENT_COUNT : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''C''O''U''N''T'
977 ;
978
979 MIDI_INSTRUMENT_INFO : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'
980 ;
981
982 DB_INSTRUMENT_DIRECTORY_COUNT : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''D''I''R''E''C''T''O''R''Y''_''C''O''U''N''T'
983 ;
984
985 DB_INSTRUMENT_DIRECTORY_INFO : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''D''I''R''E''C''T''O''R''Y''_''I''N''F''O'
986 ;
987
988 DB_INSTRUMENT_COUNT : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''C''O''U''N''T'
989 ;
990
991 DB_INSTRUMENT_INFO : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'
992 ;
993
994 DB_INSTRUMENT_FILES : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''F''I''L''E''S'
995 ;
996
997 DB_INSTRUMENTS_JOB_INFO : 'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B''_''I''N''F''O'
998 ;
999
1000 CHANNEL_COUNT : 'C''H''A''N''N''E''L''_''C''O''U''N''T'
1001 ;
1002
1003 CHANNEL_MIDI : 'C''H''A''N''N''E''L''_''M''I''D''I'
1004 ;
1005
1006 DEVICE_MIDI : 'D''E''V''I''C''E''_''M''I''D''I'
1007 ;
1008
1009 CHANNEL_INFO : 'C''H''A''N''N''E''L''_''I''N''F''O'
1010 ;
1011
1012 FX_SEND_COUNT : 'F''X''_''S''E''N''D''_''C''O''U''N''T'
1013 ;
1014
1015 FX_SEND_INFO : 'F''X''_''S''E''N''D''_''I''N''F''O'
1016 ;
1017
1018 BUFFER_FILL : 'B''U''F''F''E''R''_''F''I''L''L'
1019 ;
1020
1021 STREAM_COUNT : 'S''T''R''E''A''M''_''C''O''U''N''T'
1022 ;
1023
1024 VOICE_COUNT : 'V''O''I''C''E''_''C''O''U''N''T'
1025 ;
1026
1027 TOTAL_STREAM_COUNT : 'T''O''T''A''L''_''S''T''R''E''A''M''_''C''O''U''N''T'
1028 ;
1029
1030 TOTAL_VOICE_COUNT : 'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T'
1031 ;
1032
1033 TOTAL_VOICE_COUNT_MAX: 'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T''_''M''A''X'
1034 ;
1035
1036 GLOBAL_INFO : 'G''L''O''B''A''L''_''I''N''F''O'
1037 ;
1038
1039 EFFECT_INSTANCE_COUNT : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''C''O''U''N''T'
1040 ;
1041
1042 EFFECT_INSTANCE_INFO : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''I''N''F''O'
1043 ;
1044
1045 SEND_EFFECT_CHAIN_COUNT : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''C''O''U''N''T'
1046 ;
1047
1048 SEND_EFFECT_CHAIN_INFO : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''I''N''F''O'
1049 ;
1050
1051 INSTRUMENT : 'I''N''S''T''R''U''M''E''N''T'
1052 ;
1053
1054 INSTRUMENTS : 'I''N''S''T''R''U''M''E''N''T''S'
1055 ;
1056
1057 ENGINE : 'E' 'N' 'G' 'I' 'N' 'E'
1058 ;
1059
1060 ON_DEMAND : 'O''N''_''D''E''M''A''N''D'
1061 ;
1062
1063 ON_DEMAND_HOLD : 'O''N''_''D''E''M''A''N''D''_''H''O''L''D'
1064 ;
1065
1066 PERSISTENT : 'P''E''R''S''I''S''T''E''N''T'
1067 ;
1068
1069 AUDIO_OUTPUT_DEVICE_PARAMETER : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E''_''P''A''R''A''M''E''T''E''R'
1070 ;
1071
1072 AUDIO_OUTPUT_DEVICES : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E''S'
1073 ;
1074
1075 AUDIO_OUTPUT_DEVICE : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E'
1076 ;
1077
1078 AUDIO_OUTPUT_DRIVER_PARAMETER : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''R''I''V''E''R''_''P''A''R''A''M''E''T''E''R'
1079 ;
1080
1081 AUDIO_OUTPUT_DRIVER : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''R''I''V''E''R'
1082 ;
1083
1084 AUDIO_OUTPUT_CHANNEL_PARAMETER : 'A''U''D''I''O''_''O''U''T''P''U''T''_''C''H''A''N''N''E''L''_''P''A''R''A''M''E''T''E''R'
1085 ;
1086
1087 AUDIO_OUTPUT_CHANNEL : 'A''U''D''I''O''_''O''U''T''P''U''T''_''C''H''A''N''N''E''L'
1088 ;
1089
1090 AUDIO_OUTPUT_TYPE : 'A''U''D''I''O''_''O''U''T''P''U''T''_''T''Y''P''E'
1091 ;
1092
1093 AVAILABLE_EFFECTS : 'A''V''A''I''L''A''B''L''E''_''E''F''F''E''C''T''S'
1094 ;
1095
1096 EFFECT : 'E''F''F''E''C''T'
1097 ;
1098
1099 EFFECT_INSTANCE : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E'
1100 ;
1101
1102 EFFECT_INSTANCES : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''S'
1103 ;
1104
1105 EFFECT_INSTANCE_INPUT_CONTROL : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''I''N''P''U''T''_''C''O''N''T''R''O''L'
1106 ;
1107
1108 SEND_EFFECT_CHAIN : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N'
1109 ;
1110
1111 SEND_EFFECT_CHAINS : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''S'
1112 ;
1113
1114 AVAILABLE_MIDI_INPUT_DRIVERS : 'A''V''A''I''L''A''B''L''E''_''M''I''D''I''_''I''N''P''U''T''_''D''R''I''V''E''R''S'
1115 ;
1116
1117 MIDI_INPUT_DEVICE_PARAMETER : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''_''P''A''R''A''M''E''T''E''R'
1118 ;
1119
1120 MIDI_INPUT_PORT_PARAMETER : 'M''I''D''I''_''I''N''P''U''T''_''P''O''R''T''_''P''A''R''A''M''E''T''E''R'
1121 ;
1122
1123 MIDI_INPUT_DEVICES : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''S'
1124 ;
1125
1126 MIDI_INPUT_DEVICE : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E'
1127 ;
1128
1129 MIDI_INPUT_DRIVER_PARAMETER : 'M''I''D''I''_''I''N''P''U''T''_''D''R''I''V''E''R''_''P''A''R''A''M''E''T''E''R'
1130 ;
1131
1132 MIDI_INSTRUMENT : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T'
1133 ;
1134
1135 MIDI_INSTRUMENTS : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''S'
1136 ;
1137
1138 MIDI_INSTRUMENT_MAP : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P'
1139 ;
1140
1141 MIDI_INSTRUMENT_MAPS : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P''S'
1142 ;
1143
1144 MIDI_INPUT_DRIVER : 'M''I''D''I''_''I''N''P''U''T''_''D''R''I''V''E''R'
1145 ;
1146
1147 MIDI_INPUT_PORT : 'M''I''D''I''_''I''N''P''U''T''_''P''O''R''T'
1148 ;
1149
1150 MIDI_INPUT_CHANNEL : 'M''I''D''I''_''I''N''P''U''T''_''C''H''A''N''N''E''L'
1151 ;
1152
1153 MIDI_INPUT_TYPE : 'M''I''D''I''_''I''N''P''U''T''_''T''Y''P''E'
1154 ;
1155
1156 MIDI_INPUT : 'M''I''D''I''_''I''N''P''U''T'
1157 ;
1158
1159 MIDI_INPUTS : 'M''I''D''I''_''I''N''P''U''T''S'
1160 ;
1161
1162 MIDI_CONTROLLER : 'M''I''D''I''_''C''O''N''T''R''O''L''L''E''R'
1163 ;
1164
1165 SEND : 'S''E''N''D'
1166 ;
1167
1168 FX_SEND : 'F''X''_''S''E''N''D'
1169 ;
1170
1171 FX_SENDS : 'F''X''_''S''E''N''D''S'
1172 ;
1173
1174 DB_INSTRUMENT_DIRECTORY : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''D''I''R''E''C''T''O''R''Y'
1175 ;
1176
1177 DB_INSTRUMENT_DIRECTORIES : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''D''I''R''E''C''T''O''R''I''E''S'
1178 ;
1179
1180 DB_INSTRUMENTS : 'D''B''_''I''N''S''T''R''U''M''E''N''T''S'
1181 ;
1182
1183 DB_INSTRUMENT : 'D''B''_''I''N''S''T''R''U''M''E''N''T'
1184 ;
1185
1186 DB_INSTRUMENTS_JOB : 'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B'
1187 ;
1188
1189 INSTRUMENTS_DB : 'I''N''S''T''R''U''M''E''N''T''S''_''D''B'
1190 ;
1191
1192 DESCRIPTION : 'D''E''S''C''R''I''P''T''I''O''N'
1193 ;
1194
1195 FORCE : 'F''O''R''C''E'
1196 ;
1197
1198 FLAT : 'F''L''A''T'
1199 ;
1200
1201 RECURSIVE : 'R''E''C''U''R''S''I''V''E'
1202 ;
1203
1204 NON_RECURSIVE : 'N''O''N''_''R''E''C''U''R''S''I''V''E'
1205 ;
1206
1207 LOST : 'L''O''S''T'
1208 ;
1209
1210 FILE_PATH : 'F''I''L''E''_''P''A''T''H'
1211 ;
1212
1213 SERVER : 'S''E''R''V''E''R'
1214 ;
1215
1216 VOLUME : 'V''O''L''U''M''E'
1217 ;
1218
1219 LEVEL : 'L''E''V''E''L'
1220 ;
1221
1222 VALUE : 'V''A''L''U''E'
1223 ;
1224
1225 MUTE : 'M''U''T''E'
1226 ;
1227
1228 SOLO : 'S''O''L''O'
1229 ;
1230
1231 VOICES : 'V''O''I''C''E''S'
1232 ;
1233
1234 STREAMS : 'S''T''R''E''A''M''S'
1235 ;
1236
1237 BYTES : 'B''Y''T''E''S'
1238 ;
1239
1240 PERCENTAGE : 'P''E''R''C''E''N''T''A''G''E'
1241 ;
1242
1243 FILE : 'F''I''L''E'
1244 ;
1245
1246 EDIT : 'E''D''I''T'
1247 ;
1248
1249 FORMAT : 'F''O''R''M''A''T'
1250 ;
1251
1252 MIDI_DATA : 'M''I''D''I''_''D''A''T''A'
1253 ;
1254
1255 RESET : 'R''E''S''E''T'
1256 ;
1257
1258 MISCELLANEOUS : 'M''I''S''C''E''L''L''A''N''E''O''U''S'
1259 ;
1260
1261 NAME : 'N''A''M''E'
1262 ;
1263
1264 ECHO : 'E''C''H''O'
1265 ;
1266
1267 QUIT : 'Q''U''I''T'
1268 ;
1269
1270 %%
1271
1272 #define DEBUG_BISON_SYNTAX_ERROR_WALKER 0
1273
1274 /**
1275 * Internal function, only called by yyExpectedSymbols(). It is given a Bison
1276 * parser state stack, reflecting the parser's entire state at a certain point,
1277 * i.e. when a syntax error occured. This function will then walk ahead the
1278 * potential parse tree starting from the current head of the given state
1279 * stack. This function will call itself recursively to scan the individual
1280 * parse tree branches. As soon as it hits on the next non-terminal grammar
1281 * symbol in one parse tree branch, it adds the found non-terminal symbol to
1282 * @a expectedSymbols and aborts scanning the respective tree branch further.
1283 * If any local parser state is reached a second time, the respective parse
1284 * tree is aborted to avoid any endless recursion.
1285 *
1286 * @param stack - Bison (yacc) state stack
1287 * @param expectedSymbols - will be filled with next expected grammar symbols
1288 * @param depth - just for internal debugging purposes
1289 */
1290 static void walkAndFillExpectedSymbols(std::vector<YYTYPE_INT16>& stack, std::set<String>& expectedSymbols, int depth = 0) {
1291 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1292 printf("\n");
1293 for (int i = 0; i < depth; ++i) printf("\t");
1294 printf("State stack:");
1295 for (int i = 0; i < stack.size(); ++i) {
1296 printf(" %d", stack[i]);
1297 }
1298 printf("\n");
1299 #endif
1300
1301 if (stack.empty()) return;
1302
1303 int state = stack[stack.size() - 1];
1304 int n = yypact[state];
1305 if (n == YYPACT_NINF) { // default reduction required ...
1306 // get default reduction rule for this state
1307 n = yydefact[state];
1308 if (n <= 0 || n >= YYNRULES) return; // no rule, something is wrong
1309 // return the new resolved expected symbol (left-hand symbol of grammar
1310 // rule), then we're done in this state
1311 expectedSymbols.insert(yytname[yyr1[n]]);
1312 return;
1313 }
1314 if (!(YYPACT_NINF < n && n <= YYLAST)) return;
1315
1316 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1317 for (int i = 0; i < depth; ++i) printf("\t");
1318 printf("Expected tokens:");
1319 #endif
1320 int begin = n < 0 ? -n : 0;
1321 int checklim = YYLAST - n + 1;
1322 int end = checklim < YYNTOKENS ? checklim : YYNTOKENS;
1323 int rule, action, stackSize;
1324 for (int token = begin; token < end; ++token) {
1325 if (token == YYTERROR || yycheck[n + token] != token) continue;
1326 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1327 printf(" %s", yytname[token]);
1328 #endif
1329
1330 //if (yycheck[n + token] != token) goto default_reduction;
1331
1332 action = yytable[n + token];
1333 if (action == 0 || action == YYTABLE_NINF) {
1334 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1335 printf(" (invalid action) "); fflush(stdout);
1336 #endif
1337 continue; // error, ignore
1338 }
1339 if (action < 0) { // reduction with rule -action required ...
1340 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1341 printf(" (reduction) "); fflush(stdout);
1342 #endif
1343 rule = -action;
1344 goto reduce;
1345 }
1346 if (action == YYFINAL) continue; // "accept" state, we don't care about it here
1347
1348 // "shift" required ...
1349
1350 if (std::find(stack.begin(), stack.end(), action) != stack.end())
1351 continue; // duplicate state, ignore it to avoid endless recursions
1352
1353 // "shift" / push the new state on the state stack and call this
1354 // function recursively, and restore the stack after the recurse return
1355 stackSize = stack.size();
1356 stack.push_back(action);
1357 walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1358 stack, expectedSymbols, depth + 1
1359 );
1360 stack.resize(stackSize); // restore stack
1361 continue;
1362
1363 //default_reduction: // resolve default reduction for this state
1364 // printf(" (default red.) "); fflush(stdout);
1365 // rule = yydefact[state];
1366
1367 reduce: // "reduce" required
1368 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1369 printf(" (reduce by %d) ", rule); fflush(stdout);
1370 #endif
1371 if (rule == 0 || rule >= YYNRULES) continue; // invalid rule, something is wrong
1372 // store the left-hand symbol of the grammar rule
1373 expectedSymbols.insert(yytname[yyr1[rule]]);
1374 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1375 printf(" (SYM %s) ", yytname[yyr1[rule]]); fflush(stdout);
1376 #endif
1377 }
1378 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1379 printf("\n");
1380 #endif
1381 }
1382
1383 inline static int _yyReduce(std::vector<YYTYPE_INT16>& stack, const int& rule) {
1384 if (stack.empty()) throw 1; // severe error
1385 const int len = yyr2[rule];
1386 stack.resize(stack.size() - len);
1387 YYTYPE_INT16 newState = yypgoto[yyr1[rule] - YYNTOKENS] + stack.back();
1388 if (0 <= newState && newState <= YYLAST && yycheck[newState] == stack.back())
1389 newState = yytable[newState];
1390 else
1391 newState = yydefgoto[yyr1[rule] - YYNTOKENS];
1392 stack.push_back(newState);
1393 return newState;
1394 }
1395
1396 inline static int _yyDefaultReduce(std::vector<YYTYPE_INT16>& stack) {
1397 if (stack.empty()) throw 2; // severe error
1398 int rule = yydefact[stack.back()];
1399 if (rule <= 0 || rule >= YYNRULES) throw 3; // no rule, something is wrong
1400 return _yyReduce(stack, rule);
1401 }
1402
1403 #define DEBUG_PUSH_PARSE 0
1404
1405 static bool yyPushParse(std::vector<YYTYPE_INT16>& stack, char ch) {
1406 startLabel:
1407
1408 #if DEBUG_PUSH_PARSE
1409 //printf("\n");
1410 //for (int i = 0; i < depth; ++i) printf("\t");
1411 printf("State stack:");
1412 for (int i = 0; i < stack.size(); ++i) {
1413 printf(" %d", stack[i]);
1414 }
1415 printf(" char='%c'(%d)\n", ch, (int)ch);
1416 #endif
1417
1418 if (stack.empty()) return false;
1419
1420 int state = stack.back();
1421 int n = yypact[state];
1422 if (n == YYPACT_NINF) { // default reduction required ...
1423 #if DEBUG_PUSH_PARSE
1424 printf("(def reduce 1)\n");
1425 #endif
1426 state = _yyDefaultReduce(stack);
1427 goto startLabel;
1428 }
1429 if (!(YYPACT_NINF < n && n <= YYLAST)) return false;
1430
1431 YYTYPE_INT16 token = (ch == YYEOF) ? YYEOF : yytranslate[ch];
1432 n += token;
1433 if (n < 0 || YYLAST < n || yycheck[n] != token) {
1434 #if DEBUG_PUSH_PARSE
1435 printf("(def reduce 2) n=%d token=%d\n", n, token);
1436 #endif
1437 state = _yyDefaultReduce(stack);
1438 goto startLabel;
1439 }
1440 int action = yytable[n]; // yytable[yypact[state] + token]
1441 if (action == 0 || action == YYTABLE_NINF) throw 4;
1442 if (action < 0) {
1443 #if DEBUG_PUSH_PARSE
1444 printf("(reduce)\n");
1445 #endif
1446 int rule = -action;
1447 state = _yyReduce(stack, rule);
1448 goto startLabel;
1449 }
1450 if (action == YYFINAL) return true; // final state reached
1451
1452 #if DEBUG_PUSH_PARSE
1453 printf("(push)\n");
1454 #endif
1455 // push new state
1456 state = action;
1457 stack.push_back(state);
1458 return true;
1459 }
1460
1461 static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch) {
1462 try {
1463 return yyPushParse(stack, ch);
1464 } catch (int i) {
1465 #if DEBUG_PUSH_PARSE
1466 printf("exception %d\n", i);
1467 #endif
1468 return false;
1469 } catch (...) {
1470 return false;
1471 }
1472 }
1473
1474 static int yyValidCharacters(std::vector<YYTYPE_INT16>& stack, const String& line) {
1475 int i;
1476 for (i = 0; i < line.size(); ++i) {
1477 if (!yyValid(stack, line[i])) return i;
1478 }
1479 return i;
1480 }
1481
1482 /**
1483 * Should only be called on syntax errors: returns a set of non-terminal
1484 * symbols expected to appear now/next, just at the point where the syntax
1485 * error appeared.
1486 */
1487 static std::set<String> yyExpectedSymbols() {
1488 std::set<String> result;
1489 yyparse_param_t* param = GetCurrentYaccSession();
1490 YYTYPE_INT16* ss = (*param->ppStackBottom);
1491 YYTYPE_INT16* sp = (*param->ppStackTop);
1492 int iStackSize = sp - ss + 1;
1493 // copy and wrap parser's state stack into a convenient STL container
1494 std::vector<YYTYPE_INT16> stack;
1495 for (int i = 0; i < iStackSize; ++i) {
1496 stack.push_back(ss[i]);
1497 }
1498 // do the actual parser work
1499 walkAndFillExpectedSymbols(stack, result);
1500 return result;
1501 }
1502
1503 namespace LinuxSampler {
1504
1505 String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param) {
1506 std::vector<YYTYPE_INT16> stack;
1507 stack.push_back(0); // every Bison symbol stack starts with zero
1508 String l = line + '\n';
1509 int n = yyValidCharacters(stack, l);
1510 String result = line;
1511 result.insert(n <= result.length() ? n : result.length(), LSCP_SHK_GOOD_FRONT);
1512 int code = (n > line.length()) ? LSCP_SHU_COMPLETE : (n < line.length()) ?
1513 LSCP_SHU_SYNTAX_ERR : LSCP_SHU_INCOMPLETE;
1514 result = "SHU:" + ToString(code) + ":" + result;
1515 //if (n > line.length()) result += " [OK]";
1516 #if DEBUG_PUSH_PARSE
1517 printf("%s\n", result.c_str());
1518 #endif
1519 return result;
1520 }
1521
1522 /**
1523 * Clears input buffer.
1524 */
1525 void restart(yyparse_param_t* pparam, int& yychar) {
1526 bytes = 0;
1527 ptr = 0;
1528 sLastError = "";
1529 sParsed = "";
1530 }
1531
1532 }

  ViewVC Help
Powered by ViewVC