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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2516 - (hide annotations) (download)
Thu Feb 6 21:11:23 2014 UTC (10 years, 1 month ago) by schoenebeck
File size: 96823 byte(s)
* WIP: LSCP Shell: implemented support for auto-correction of       
  obvious and trivial LSCP syntax mistakes, support for
  auto-completion by tab key and visual completion suggestion
  while typing.
* Bumped version (1.0.0.svn29).

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

  ViewVC Help
Powered by ViewVC