/[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 2534 - (hide annotations) (download)
Sun Mar 9 21:34:03 2014 UTC (10 years, 1 month ago) by schoenebeck
File size: 113878 byte(s)
* LSCP shell (WIP): Added initial support for built-in LSCP reference
  documentation, which will automatically show the relevant LSCP reference
  section on screen as soon as one specific LSCP command was detected while
  typing on the command line.
* Bumped version (1.0.0.svn37).

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 2531 #define INCREMENT_LINE { SESSION_PARAM->onNextLine(); 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 schoenebeck 2525 // symbol stack, so that we can create more helpful syntax error messages than
184 schoenebeck 2510 // 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 schoenebeck 2523 %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 line statement 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 schoenebeck 2523 input : line { INCREMENT_LINE; if (!$1.empty()) LSCPSERVER->AnswerClient($1); return LSCP_DONE; }
222     | error { INCREMENT_LINE; LSCPSERVER->AnswerClient("ERR:0:" + sLastError + "\r\n"); RESTART; return LSCP_SYNTAX_ERROR; }
223 schoenebeck 219 ;
224 schoenebeck 35
225 schoenebeck 2523 line : statement LF { $$ = $1; }
226     | statement CR LF { $$ = $1; }
227 schoenebeck 35 ;
228    
229 schoenebeck 2523 statement : /* epsilon (empty statement/line ignored) */ { $$ = ""; }
230     | comment { $$ = ""; }
231     | command
232     ;
233    
234 schoenebeck 219 comment : '#'
235     | comment '#'
236 schoenebeck 111 | comment SP
237 schoenebeck 219 | comment number
238 schoenebeck 111 | comment string
239     ;
240    
241 schoenebeck 973 command : ADD SP add_instruction { $$ = $3; }
242 schoenebeck 947 | MAP SP map_instruction { $$ = $3; }
243     | UNMAP SP unmap_instruction { $$ = $3; }
244 schoenebeck 219 | GET SP get_instruction { $$ = $3; }
245     | CREATE SP create_instruction { $$ = $3; }
246     | DESTROY SP destroy_instruction { $$ = $3; }
247     | LIST SP list_instruction { $$ = $3; }
248     | LOAD SP load_instruction { $$ = $3; }
249 schoenebeck 947 | REMOVE SP remove_instruction { $$ = $3; }
250 schoenebeck 219 | SET SP set_instruction { $$ = $3; }
251     | SUBSCRIBE SP subscribe_event { $$ = $3; }
252     | UNSUBSCRIBE SP unsubscribe_event { $$ = $3; }
253 schoenebeck 947 | RESET SP reset_instruction { $$ = $3; }
254     | CLEAR SP clear_instruction { $$ = $3; }
255 iliev 1187 | FIND SP find_instruction { $$ = $3; }
256 iliev 1161 | MOVE SP move_instruction { $$ = $3; }
257 iliev 1187 | COPY SP copy_instruction { $$ = $3; }
258 schoenebeck 1212 | EDIT SP edit_instruction { $$ = $3; }
259 iliev 1353 | FORMAT SP format_instruction { $$ = $3; }
260 schoenebeck 1800 | SEND SP send_instruction { $$ = $3; }
261 schoenebeck 2135 | APPEND SP append_instruction { $$ = $3; }
262     | INSERT SP insert_instruction { $$ = $3; }
263 schoenebeck 219 | RESET { $$ = LSCPSERVER->ResetSampler(); }
264     | QUIT { LSCPSERVER->AnswerClient("Bye!\r\n"); return LSCP_QUIT; }
265 schoenebeck 35 ;
266    
267 iliev 1345 add_instruction : CHANNEL { $$ = LSCPSERVER->AddChannel(); }
268 schoenebeck 2500 | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index { $$ = LSCPSERVER->AddChannelMidiInput($5,$7); }
269     | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index { $$ = LSCPSERVER->AddChannelMidiInput($5,$7,$9); }
270 iliev 1345 | DB_INSTRUMENT_DIRECTORY SP db_path { $$ = LSCPSERVER->AddDbInstrumentDirectory($3); }
271 iliev 1781 | DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true); }
272     | DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP FILE_AS_DIR SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$9,$11, true, true); }
273     | DB_INSTRUMENTS SP scan_mode SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7); }
274     | DB_INSTRUMENTS SP scan_mode SP FILE_AS_DIR SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$7,$9, false, true); }
275     | DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($5,$7, -1, true); }
276     | DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename SP instrument_index { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true); }
277     | DB_INSTRUMENTS SP db_path SP filename { $$ = LSCPSERVER->AddDbInstruments($3,$5); }
278     | DB_INSTRUMENTS SP db_path SP filename SP instrument_index { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7); }
279 schoenebeck 973 | MIDI_INSTRUMENT_MAP { $$ = LSCPSERVER->AddMidiInstrumentMap(); }
280     | MIDI_INSTRUMENT_MAP SP map_name { $$ = LSCPSERVER->AddMidiInstrumentMap($3); }
281 schoenebeck 2137 | SEND_EFFECT_CHAIN SP device_index { $$ = LSCPSERVER->AddSendEffectChain($3); }
282 schoenebeck 973 ;
283    
284 iliev 981 subscribe_event : AUDIO_OUTPUT_DEVICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_count); }
285     | AUDIO_OUTPUT_DEVICE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_info); }
286     | MIDI_INPUT_DEVICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_count); }
287     | MIDI_INPUT_DEVICE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_info); }
288     | CHANNEL_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_count); }
289 schoenebeck 1686 | CHANNEL_MIDI { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_midi); }
290 schoenebeck 1695 | DEVICE_MIDI { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_device_midi); }
291 iliev 981 | VOICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_voice_count); }
292     | STREAM_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_stream_count); }
293     | BUFFER_FILL { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_buffer_fill); }
294     | CHANNEL_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_info); }
295 iliev 1108 | FX_SEND_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_send_count); }
296     | FX_SEND_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_send_info); }
297 iliev 981 | MIDI_INSTRUMENT_MAP_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_map_count); }
298     | MIDI_INSTRUMENT_MAP_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_map_info); }
299     | MIDI_INSTRUMENT_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_count); }
300     | MIDI_INSTRUMENT_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_instr_info); }
301 iliev 1161 | DB_INSTRUMENT_DIRECTORY_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_dir_count); }
302     | DB_INSTRUMENT_DIRECTORY_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_dir_info); }
303     | DB_INSTRUMENT_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_count); }
304     | DB_INSTRUMENT_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_info); }
305 iliev 1200 | DB_INSTRUMENTS_JOB_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instrs_job_info); }
306 iliev 981 | MISCELLANEOUS { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_misc); }
307 iliev 1541 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_stream_count); }
308 iliev 981 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_voice_count); }
309 iliev 1108 | GLOBAL_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_global_info); }
310 iliev 2188 | EFFECT_INSTANCE_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_count); }
311     | EFFECT_INSTANCE_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_info); }
312     | SEND_EFFECT_CHAIN_COUNT { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_count); }
313     | SEND_EFFECT_CHAIN_INFO { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_info); }
314 senkov 135 ;
315    
316 iliev 981 unsubscribe_event : AUDIO_OUTPUT_DEVICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_count); }
317     | AUDIO_OUTPUT_DEVICE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_info); }
318     | MIDI_INPUT_DEVICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_count); }
319     | MIDI_INPUT_DEVICE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_info); }
320     | CHANNEL_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_count); }
321 schoenebeck 1686 | CHANNEL_MIDI { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_midi); }
322 schoenebeck 1695 | DEVICE_MIDI { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_device_midi); }
323 iliev 981 | VOICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_voice_count); }
324     | STREAM_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_stream_count); }
325     | BUFFER_FILL { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_buffer_fill); }
326     | CHANNEL_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_info); }
327 iliev 1108 | FX_SEND_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_send_count); }
328     | FX_SEND_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_send_info); }
329 iliev 981 | MIDI_INSTRUMENT_MAP_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_map_count); }
330     | MIDI_INSTRUMENT_MAP_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_map_info); }
331     | MIDI_INSTRUMENT_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_count); }
332     | MIDI_INSTRUMENT_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_instr_info); }
333 iliev 1161 | DB_INSTRUMENT_DIRECTORY_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_dir_count); }
334     | DB_INSTRUMENT_DIRECTORY_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_dir_info); }
335     | DB_INSTRUMENT_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_count); }
336     | DB_INSTRUMENT_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_info); }
337 iliev 1200 | DB_INSTRUMENTS_JOB_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instrs_job_info); }
338 iliev 981 | MISCELLANEOUS { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_misc); }
339 iliev 1541 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_stream_count); }
340 iliev 981 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_voice_count); }
341 iliev 1108 | GLOBAL_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_global_info); }
342 iliev 2188 | EFFECT_INSTANCE_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_count); }
343     | EFFECT_INSTANCE_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_info); }
344     | SEND_EFFECT_CHAIN_COUNT { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_count); }
345     | SEND_EFFECT_CHAIN_INFO { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_info); }
346 senkov 135 ;
347    
348 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); }
349 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); }
350 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); }
351 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); }
352 schoenebeck 947 ;
353    
354 schoenebeck 973 unmap_instruction : MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog { $$ = LSCPSERVER->RemoveMIDIInstrumentMapping($3,$5,$7); }
355 schoenebeck 947 ;
356    
357 iliev 1345 remove_instruction : CHANNEL SP sampler_channel { $$ = LSCPSERVER->RemoveChannel($3); }
358 schoenebeck 2500 | CHANNEL SP MIDI_INPUT SP sampler_channel { $$ = LSCPSERVER->RemoveChannelMidiInput($5); }
359     | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7); }
360     | CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7,$9); }
361 iliev 1345 | MIDI_INSTRUMENT_MAP SP midi_map { $$ = LSCPSERVER->RemoveMidiInstrumentMap($3); }
362     | MIDI_INSTRUMENT_MAP SP ALL { $$ = LSCPSERVER->RemoveAllMidiInstrumentMaps(); }
363 schoenebeck 2137 | SEND_EFFECT_CHAIN SP device_index SP effect_chain { $$ = LSCPSERVER->RemoveSendEffectChain($3,$5); }
364     | SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP chain_pos { $$ = LSCPSERVER->RemoveSendEffectChainEffect($5,$7,$9); }
365 schoenebeck 2140 | FX_SEND SP EFFECT SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->SetFxSendEffect($5,$7,-1,-1); }
366 iliev 1345 | DB_INSTRUMENT_DIRECTORY SP FORCE SP db_path { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($5, true); }
367     | DB_INSTRUMENT_DIRECTORY SP db_path { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($3); }
368     | DB_INSTRUMENT SP db_path { $$ = LSCPSERVER->RemoveDbInstrument($3); }
369 schoenebeck 947 ;
370    
371 schoenebeck 219 get_instruction : AVAILABLE_ENGINES { $$ = LSCPSERVER->GetAvailableEngines(); }
372 schoenebeck 2135 | AVAILABLE_EFFECTS { $$ = LSCPSERVER->GetAvailableEffects(); }
373     | EFFECT_INSTANCES { $$ = LSCPSERVER->GetEffectInstances(); }
374 schoenebeck 2137 | EFFECT SP INFO SP effect_index { $$ = LSCPSERVER->GetEffectInfo($5); }
375     | EFFECT_INSTANCE SP INFO SP effect_instance { $$ = LSCPSERVER->GetEffectInstanceInfo($5); }
376     | EFFECT_INSTANCE_INPUT_CONTROL SP INFO SP effect_instance SP input_control { $$ = LSCPSERVER->GetEffectInstanceInputControlInfo($5,$7); }
377     | SEND_EFFECT_CHAINS SP device_index { $$ = LSCPSERVER->GetSendEffectChains($3); }
378     | SEND_EFFECT_CHAIN SP INFO SP device_index SP effect_chain { $$ = LSCPSERVER->GetSendEffectChainInfo($5,$7); }
379 schoenebeck 219 | AVAILABLE_MIDI_INPUT_DRIVERS { $$ = LSCPSERVER->GetAvailableMidiInputDrivers(); }
380     | MIDI_INPUT_DRIVER SP INFO SP string { $$ = LSCPSERVER->GetMidiInputDriverInfo($5); }
381     | MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7); }
382     | MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7, $9); }
383     | AVAILABLE_AUDIO_OUTPUT_DRIVERS { $$ = LSCPSERVER->GetAvailableAudioOutputDrivers(); }
384     | AUDIO_OUTPUT_DRIVER SP INFO SP string { $$ = LSCPSERVER->GetAudioOutputDriverInfo($5); }
385     | AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string { $$ = LSCPSERVER->GetAudioOutputDriverParameterInfo($5, $7); }
386     | AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list { $$ = LSCPSERVER->GetAudioOutputDriverParameterInfo($5, $7, $9); }
387     | AUDIO_OUTPUT_DEVICES { $$ = LSCPSERVER->GetAudioOutputDeviceCount(); }
388     | MIDI_INPUT_DEVICES { $$ = LSCPSERVER->GetMidiInputDeviceCount(); }
389     | AUDIO_OUTPUT_DEVICE SP INFO SP number { $$ = LSCPSERVER->GetAudioOutputDeviceInfo($5); }
390     | MIDI_INPUT_DEVICE SP INFO SP number { $$ = LSCPSERVER->GetMidiInputDeviceInfo($5); }
391     | MIDI_INPUT_PORT SP INFO SP number SP number { $$ = LSCPSERVER->GetMidiInputPortInfo($5, $7); }
392     | MIDI_INPUT_PORT_PARAMETER SP INFO SP number SP number SP string { $$ = LSCPSERVER->GetMidiInputPortParameterInfo($5, $7, $9); }
393     | AUDIO_OUTPUT_CHANNEL SP INFO SP number SP number { $$ = LSCPSERVER->GetAudioOutputChannelInfo($5, $7); }
394     | AUDIO_OUTPUT_CHANNEL_PARAMETER SP INFO SP number SP number SP string { $$ = LSCPSERVER->GetAudioOutputChannelParameterInfo($5, $7, $9); }
395     | CHANNELS { $$ = LSCPSERVER->GetChannels(); }
396     | CHANNEL SP INFO SP sampler_channel { $$ = LSCPSERVER->GetChannelInfo($5); }
397     | CHANNEL SP BUFFER_FILL SP buffer_size_type SP sampler_channel { $$ = LSCPSERVER->GetBufferFill($5, $7); }
398     | CHANNEL SP STREAM_COUNT SP sampler_channel { $$ = LSCPSERVER->GetStreamCount($5); }
399     | CHANNEL SP VOICE_COUNT SP sampler_channel { $$ = LSCPSERVER->GetVoiceCount($5); }
400     | ENGINE SP INFO SP engine_name { $$ = LSCPSERVER->GetEngineInfo($5); }
401 schoenebeck 563 | SERVER SP INFO { $$ = LSCPSERVER->GetServerInfo(); }
402 iliev 1541 | TOTAL_STREAM_COUNT { $$ = LSCPSERVER->GetTotalStreamCount(); }
403 iliev 1161 | TOTAL_VOICE_COUNT { $$ = LSCPSERVER->GetTotalVoiceCount(); }
404 iliev 778 | TOTAL_VOICE_COUNT_MAX { $$ = LSCPSERVER->GetTotalVoiceCountMax(); }
405 schoenebeck 973 | MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->GetMidiInstrumentMappings($3); }
406     | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->GetAllMidiInstrumentMappings(); }
407     | MIDI_INSTRUMENT SP INFO SP midi_map SP midi_bank SP midi_prog { $$ = LSCPSERVER->GetMidiInstrumentMapping($5,$7,$9); }
408     | MIDI_INSTRUMENT_MAPS { $$ = LSCPSERVER->GetMidiInstrumentMaps(); }
409     | MIDI_INSTRUMENT_MAP SP INFO SP midi_map { $$ = LSCPSERVER->GetMidiInstrumentMap($5); }
410 schoenebeck 1001 | FX_SENDS SP sampler_channel { $$ = LSCPSERVER->GetFxSends($3); }
411     | FX_SEND SP INFO SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->GetFxSendInfo($5,$7); }
412 iliev 1345 | DB_INSTRUMENT_DIRECTORIES SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryCount($5, true); }
413     | DB_INSTRUMENT_DIRECTORIES SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryCount($3, false); }
414     | DB_INSTRUMENT_DIRECTORY SP INFO SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectoryInfo($5); }
415     | DB_INSTRUMENTS SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentCount($5, true); }
416     | DB_INSTRUMENTS SP db_path { $$ = LSCPSERVER->GetDbInstrumentCount($3, false); }
417     | DB_INSTRUMENT SP INFO SP db_path { $$ = LSCPSERVER->GetDbInstrumentInfo($5); }
418 iliev 1200 | DB_INSTRUMENTS_JOB SP INFO SP number { $$ = LSCPSERVER->GetDbInstrumentsJobInfo($5); }
419 schoenebeck 1005 | VOLUME { $$ = LSCPSERVER->GetGlobalVolume(); }
420 schoenebeck 1800 | VOICES { $$ = LSCPSERVER->GetGlobalMaxVoices(); }
421     | STREAMS { $$ = LSCPSERVER->GetGlobalMaxStreams(); }
422 schoenebeck 1525 | FILE SP INSTRUMENTS SP filename { $$ = LSCPSERVER->GetFileInstruments($5); }
423     | FILE SP INSTRUMENT SP INFO SP filename SP instrument_index { $$ = LSCPSERVER->GetFileInstrumentInfo($7,$9); }
424 schoenebeck 35 ;
425    
426 schoenebeck 483 set_instruction : AUDIO_OUTPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetAudioOutputDeviceParameter($3, $5, $7); }
427     | AUDIO_OUTPUT_CHANNEL_PARAMETER SP number SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetAudioOutputChannelParameter($3, $5, $7, $9); }
428     | MIDI_INPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetMidiInputDeviceParameter($3, $5, $7); }
429 iliev 1296 | MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' NONE { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, ""); }
430 schoenebeck 483 | MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' param_val_list { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, $9); }
431 schoenebeck 2137 | EFFECT_INSTANCE_INPUT_CONTROL SP VALUE SP effect_instance SP input_control SP control_value { $$ = LSCPSERVER->SetEffectInstanceInputControlValue($5, $7, $9); }
432 schoenebeck 483 | CHANNEL SP set_chan_instruction { $$ = $3; }
433 schoenebeck 973 | MIDI_INSTRUMENT_MAP SP NAME SP midi_map SP map_name { $$ = LSCPSERVER->SetMidiInstrumentMapName($5, $7); }
434 iliev 1135 | FX_SEND SP NAME SP sampler_channel SP fx_send_id SP fx_send_name { $$ = LSCPSERVER->SetFxSendName($5,$7,$9); }
435 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); }
436 schoenebeck 1026 | FX_SEND SP MIDI_CONTROLLER SP sampler_channel SP fx_send_id SP midi_ctrl { $$ = LSCPSERVER->SetFxSendMidiController($5,$7,$9); }
437     | FX_SEND SP LEVEL SP sampler_channel SP fx_send_id SP volume_value { $$ = LSCPSERVER->SetFxSendLevel($5,$7,$9); }
438 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); }
439 schoenebeck 1389 | DB_INSTRUMENT_DIRECTORY SP NAME SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDirectoryName($5,$7); }
440     | DB_INSTRUMENT_DIRECTORY SP DESCRIPTION SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDirectoryDescription($5,$7); }
441     | DB_INSTRUMENT SP NAME SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentName($5,$7); }
442     | DB_INSTRUMENT SP DESCRIPTION SP db_path SP stringval_escaped { $$ = LSCPSERVER->SetDbInstrumentDescription($5,$7); }
443 iliev 1727 | DB_INSTRUMENT SP FILE_PATH SP filename SP filename { $$ = LSCPSERVER->SetDbInstrumentFilePath($5,$7); }
444 schoenebeck 483 | ECHO SP boolean { $$ = LSCPSERVER->SetEcho((yyparse_param_t*) yyparse_param, $3); }
445 schoenebeck 2515 | SHELL SP INTERACT SP boolean { $$ = LSCPSERVER->SetShellInteract((yyparse_param_t*) yyparse_param, $5); }
446 schoenebeck 2516 | SHELL SP AUTO_CORRECT SP boolean { $$ = LSCPSERVER->SetShellAutoCorrect((yyparse_param_t*) yyparse_param, $5); }
447 schoenebeck 2534 | SHELL SP DOC SP boolean { $$ = LSCPSERVER->SetShellDoc((yyparse_param_t*) yyparse_param, $5); }
448 schoenebeck 1005 | VOLUME SP volume_value { $$ = LSCPSERVER->SetGlobalVolume($3); }
449 schoenebeck 1800 | VOICES SP number { $$ = LSCPSERVER->SetGlobalMaxVoices($3); }
450     | STREAMS SP number { $$ = LSCPSERVER->SetGlobalMaxStreams($3); }
451 schoenebeck 123 ;
452    
453 schoenebeck 219 create_instruction : AUDIO_OUTPUT_DEVICE SP string SP key_val_list { $$ = LSCPSERVER->CreateAudioOutputDevice($3,$5); }
454     | AUDIO_OUTPUT_DEVICE SP string { $$ = LSCPSERVER->CreateAudioOutputDevice($3); }
455     | MIDI_INPUT_DEVICE SP string SP key_val_list { $$ = LSCPSERVER->CreateMidiInputDevice($3,$5); }
456     | MIDI_INPUT_DEVICE SP string { $$ = LSCPSERVER->CreateMidiInputDevice($3); }
457 schoenebeck 1001 | FX_SEND SP sampler_channel SP midi_ctrl { $$ = LSCPSERVER->CreateFxSend($3,$5); }
458     | FX_SEND SP sampler_channel SP midi_ctrl SP fx_send_name { $$ = LSCPSERVER->CreateFxSend($3,$5,$7); }
459 schoenebeck 2137 | EFFECT_INSTANCE SP effect_index { $$ = LSCPSERVER->CreateEffectInstance($3); }
460     | EFFECT_INSTANCE SP effect_system SP module SP effect_name { $$ = LSCPSERVER->CreateEffectInstance($3,$5,$7); }
461 schoenebeck 123 ;
462    
463 schoenebeck 947 reset_instruction : CHANNEL SP sampler_channel { $$ = LSCPSERVER->ResetChannel($3); }
464     ;
465    
466 schoenebeck 973 clear_instruction : MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->ClearMidiInstrumentMappings($3); }
467     | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->ClearAllMidiInstrumentMappings(); }
468 schoenebeck 947 ;
469    
470 iliev 1345 find_instruction : DB_INSTRUMENTS SP NON_RECURSIVE SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstruments($5,$7, false); }
471     | DB_INSTRUMENTS SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstruments($3,$5, true); }
472     | DB_INSTRUMENT_DIRECTORIES SP NON_RECURSIVE SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstrumentDirectories($5,$7, false); }
473     | DB_INSTRUMENT_DIRECTORIES SP db_path SP query_val_list { $$ = LSCPSERVER->FindDbInstrumentDirectories($3,$5, true); }
474 iliev 1727 | LOST SP DB_INSTRUMENT_FILES { $$ = LSCPSERVER->FindLostDbInstrumentFiles(); }
475 iliev 1187 ;
476    
477 iliev 1345 move_instruction : DB_INSTRUMENT_DIRECTORY SP db_path SP db_path { $$ = LSCPSERVER->MoveDbInstrumentDirectory($3,$5); }
478     | DB_INSTRUMENT SP db_path SP db_path { $$ = LSCPSERVER->MoveDbInstrument($3,$5); }
479 iliev 1161 ;
480    
481 iliev 1345 copy_instruction : DB_INSTRUMENT_DIRECTORY SP db_path SP db_path { $$ = LSCPSERVER->CopyDbInstrumentDirectory($3,$5); }
482     | DB_INSTRUMENT SP db_path SP db_path { $$ = LSCPSERVER->CopyDbInstrument($3,$5); }
483 iliev 1187 ;
484    
485 schoenebeck 219 destroy_instruction : AUDIO_OUTPUT_DEVICE SP number { $$ = LSCPSERVER->DestroyAudioOutputDevice($3); }
486     | MIDI_INPUT_DEVICE SP number { $$ = LSCPSERVER->DestroyMidiInputDevice($3); }
487 schoenebeck 1001 | FX_SEND SP sampler_channel SP fx_send_id { $$ = LSCPSERVER->DestroyFxSend($3,$5); }
488 schoenebeck 2135 | EFFECT_INSTANCE SP number { $$ = LSCPSERVER->DestroyEffectInstance($3); }
489 schoenebeck 123 ;
490    
491 schoenebeck 35 load_instruction : INSTRUMENT SP load_instr_args { $$ = $3; }
492     | ENGINE SP load_engine_args { $$ = $3; }
493     ;
494    
495 schoenebeck 2137 append_instruction : SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP effect_instance { $$ = LSCPSERVER->AppendSendEffectChainEffect($5,$7,$9); }
496 schoenebeck 2135 ;
497    
498 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); }
499 schoenebeck 2135 ;
500    
501 schoenebeck 219 set_chan_instruction : AUDIO_OUTPUT_DEVICE SP sampler_channel SP device_index { $$ = LSCPSERVER->SetAudioOutputDevice($5, $3); }
502     | AUDIO_OUTPUT_CHANNEL SP sampler_channel SP audio_channel_index SP audio_channel_index { $$ = LSCPSERVER->SetAudioOutputChannel($5, $7, $3); }
503     | AUDIO_OUTPUT_TYPE SP sampler_channel SP audio_output_type_name { $$ = LSCPSERVER->SetAudioOutputType($5, $3); }
504     | MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index SP midi_input_channel_index { $$ = LSCPSERVER->SetMIDIInput($5, $7, $9, $3); }
505     | MIDI_INPUT_DEVICE SP sampler_channel SP device_index { $$ = LSCPSERVER->SetMIDIInputDevice($5, $3); }
506     | MIDI_INPUT_PORT SP sampler_channel SP midi_input_port_index { $$ = LSCPSERVER->SetMIDIInputPort($5, $3); }
507     | MIDI_INPUT_CHANNEL SP sampler_channel SP midi_input_channel_index { $$ = LSCPSERVER->SetMIDIInputChannel($5, $3); }
508     | MIDI_INPUT_TYPE SP sampler_channel SP midi_input_type_name { $$ = LSCPSERVER->SetMIDIInputType($5, $3); }
509     | VOLUME SP sampler_channel SP volume_value { $$ = LSCPSERVER->SetVolume($5, $3); }
510 schoenebeck 705 | MUTE SP sampler_channel SP boolean { $$ = LSCPSERVER->SetChannelMute($5, $3); }
511     | SOLO SP sampler_channel SP boolean { $$ = LSCPSERVER->SetChannelSolo($5, $3); }
512 schoenebeck 973 | MIDI_INSTRUMENT_MAP SP sampler_channel SP midi_map { $$ = LSCPSERVER->SetChannelMap($3, $5); }
513     | MIDI_INSTRUMENT_MAP SP sampler_channel SP NONE { $$ = LSCPSERVER->SetChannelMap($3, -1); }
514     | MIDI_INSTRUMENT_MAP SP sampler_channel SP DEFAULT { $$ = LSCPSERVER->SetChannelMap($3, -2); }
515 schoenebeck 35 ;
516    
517 schoenebeck 1407 edit_instruction : CHANNEL SP INSTRUMENT SP sampler_channel { $$ = LSCPSERVER->EditSamplerChannelInstrument($5); }
518 schoenebeck 1212 ;
519    
520 iliev 1353 format_instruction : INSTRUMENTS_DB { $$ = LSCPSERVER->FormatInstrumentsDb(); }
521     ;
522    
523 schoenebeck 1047 modal_arg : /* epsilon (empty argument) */ { $$ = true; }
524     | NON_MODAL SP { $$ = false; }
525     ;
526    
527 schoenebeck 483 key_val_list : string '=' param_val_list { $$[$1] = $3; }
528     | key_val_list SP string '=' param_val_list { $$ = $1; $$[$3] = $5; }
529 senkov 135 ;
530 schoenebeck 123
531 schoenebeck 35 buffer_size_type : BYTES { $$ = fill_response_bytes; }
532     | PERCENTAGE { $$ = fill_response_percentage; }
533     ;
534    
535 iliev 1187 list_instruction : AUDIO_OUTPUT_DEVICES { $$ = LSCPSERVER->GetAudioOutputDevices(); }
536     | MIDI_INPUT_DEVICES { $$ = LSCPSERVER->GetMidiInputDevices(); }
537     | CHANNELS { $$ = LSCPSERVER->ListChannels(); }
538 schoenebeck 2500 | CHANNEL SP MIDI_INPUTS SP sampler_channel { $$ = LSCPSERVER->ListChannelMidiInputs($5); }
539 iliev 1187 | AVAILABLE_ENGINES { $$ = LSCPSERVER->ListAvailableEngines(); }
540 schoenebeck 2135 | AVAILABLE_EFFECTS { $$ = LSCPSERVER->ListAvailableEffects(); }
541     | EFFECT_INSTANCES { $$ = LSCPSERVER->ListEffectInstances(); }
542 schoenebeck 2137 | SEND_EFFECT_CHAINS SP number { $$ = LSCPSERVER->ListSendEffectChains($3); }
543 iliev 1187 | AVAILABLE_MIDI_INPUT_DRIVERS { $$ = LSCPSERVER->ListAvailableMidiInputDrivers(); }
544     | AVAILABLE_AUDIO_OUTPUT_DRIVERS { $$ = LSCPSERVER->ListAvailableAudioOutputDrivers(); }
545     | MIDI_INSTRUMENTS SP midi_map { $$ = LSCPSERVER->ListMidiInstrumentMappings($3); }
546     | MIDI_INSTRUMENTS SP ALL { $$ = LSCPSERVER->ListAllMidiInstrumentMappings(); }
547     | MIDI_INSTRUMENT_MAPS { $$ = LSCPSERVER->ListMidiInstrumentMaps(); }
548     | FX_SENDS SP sampler_channel { $$ = LSCPSERVER->ListFxSends($3); }
549 iliev 1345 | DB_INSTRUMENT_DIRECTORIES SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectories($5, true); }
550     | DB_INSTRUMENT_DIRECTORIES SP db_path { $$ = LSCPSERVER->GetDbInstrumentDirectories($3); }
551     | DB_INSTRUMENTS SP RECURSIVE SP db_path { $$ = LSCPSERVER->GetDbInstruments($5, true); }
552     | DB_INSTRUMENTS SP db_path { $$ = LSCPSERVER->GetDbInstruments($3); }
553 schoenebeck 1525 | FILE SP INSTRUMENTS SP filename { $$ = LSCPSERVER->ListFileInstruments($5); }
554 schoenebeck 123 ;
555    
556 iliev 1771 send_instruction : CHANNEL SP MIDI_DATA SP string SP sampler_channel SP number SP number { $$ = LSCPSERVER->SendChannelMidiData($5, $7, $9, $11); }
557     ;
558    
559 schoenebeck 219 load_instr_args : filename SP instrument_index SP sampler_channel { $$ = LSCPSERVER->LoadInstrument($1, $3, $5); }
560     | NON_MODAL SP filename SP instrument_index SP sampler_channel { $$ = LSCPSERVER->LoadInstrument($3, $5, $7, true); }
561 schoenebeck 35 ;
562    
563 schoenebeck 411 load_engine_args : engine_name SP sampler_channel { $$ = LSCPSERVER->SetEngineType($1, $3); }
564 schoenebeck 35 ;
565    
566 schoenebeck 947 instr_load_mode : ON_DEMAND { $$ = MidiInstrumentMapper::ON_DEMAND; }
567     | ON_DEMAND_HOLD { $$ = MidiInstrumentMapper::ON_DEMAND_HOLD; }
568     | PERSISTENT { $$ = MidiInstrumentMapper::PERSISTENT; }
569     ;
570    
571 schoenebeck 2137 effect_instance : number
572     ;
573    
574 schoenebeck 219 device_index : number
575     ;
576    
577     audio_channel_index : number
578     ;
579    
580     audio_output_type_name : string
581     ;
582    
583     midi_input_port_index : number
584     ;
585    
586     midi_input_channel_index : number
587 schoenebeck 274 | ALL { $$ = 16; }
588 schoenebeck 219 ;
589    
590     midi_input_type_name : string
591     ;
592    
593 schoenebeck 973 midi_map : number
594 schoenebeck 947 ;
595    
596 schoenebeck 973 midi_bank : number
597 schoenebeck 947 ;
598    
599     midi_prog : number
600     ;
601    
602 schoenebeck 1001 midi_ctrl : number
603     ;
604    
605 schoenebeck 219 volume_value : dotnum
606     | number { $$ = $1; }
607     ;
608    
609 schoenebeck 2137 control_value : real
610 schoenebeck 2135 ;
611    
612 schoenebeck 219 sampler_channel : number
613     ;
614    
615     instrument_index : number
616     ;
617    
618 schoenebeck 1001 fx_send_id : number
619     ;
620    
621 schoenebeck 219 engine_name : string
622     ;
623    
624 schoenebeck 1471 filename : path {
625     #if WIN32
626     $$ = $1.toWindows();
627     #else
628     // assuming POSIX
629     $$ = $1.toPosix();
630     #endif
631     }
632 iliev 1161 ;
633    
634 iliev 1345 db_path : path { $$ = $1.toDbPath(); }
635 iliev 1161 ;
636    
637 schoenebeck 1389 map_name : stringval_escaped
638 schoenebeck 973 ;
639    
640 schoenebeck 1389 entry_name : stringval_escaped
641 schoenebeck 947 ;
642    
643 schoenebeck 1389 fx_send_name : stringval_escaped
644 schoenebeck 1001 ;
645    
646 schoenebeck 2135 effect_name : stringval_escaped
647     ;
648    
649 schoenebeck 2137 effect_index : number
650     ;
651    
652     effect_chain : number
653     ;
654    
655     chain_pos : number
656     ;
657    
658     input_control : number
659     ;
660    
661 schoenebeck 483 param_val_list : param_val
662     | param_val_list','param_val { $$ = $1 + "," + $3; }
663     ;
664    
665 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
666     param_val : string { $$ = "\'" + $1 + "\'"; }
667     | stringval { $$ = "\'" + $1 + "\'"; }
668 schoenebeck 483 | number { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); }
669 schoenebeck 2135 | dotnum { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); } //TODO: maybe better using 'real' instead of 'number' and 'dotnum' rules
670 schoenebeck 219 ;
671    
672 iliev 1187 query_val_list : string '=' query_val { $$[$1] = $3; }
673     | query_val_list SP string '=' query_val { $$ = $1; $$[$3] = $5; }
674     ;
675    
676 schoenebeck 1389 query_val : text_escaped
677     | stringval_escaped
678 iliev 1187 ;
679    
680 iliev 1200 scan_mode : RECURSIVE { $$ = "RECURSIVE"; }
681     | NON_RECURSIVE { $$ = "NON_RECURSIVE"; }
682     | FLAT { $$ = "FLAT"; }
683     ;
684    
685 schoenebeck 2137 effect_system : string
686     ;
687    
688     module : filename
689     ;
690    
691 schoenebeck 573 // GRAMMAR_BNF_END - do NOT delete or modify this line !!!
692 schoenebeck 219
693 schoenebeck 573
694 schoenebeck 219 // atomic variable symbol rules
695    
696     boolean : number { $$ = $1; }
697     | string { $$ = -1; }
698 capela 159 ;
699    
700 persson 1349 dotnum : digits '.' digits { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
701     | '+' digits '.' digits { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
702     | '-' digits '.' digits { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
703 capela 143 ;
704    
705 schoenebeck 2135 real : digits '.' digits { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
706     | '+' digits '.' digits { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
707     | '-' digits '.' digits { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
708     | digits { std::stringstream ss($1); ss.imbue(std::locale::classic()); ss >> $$; }
709     | '+' digits { std::stringstream ss($2); ss.imbue(std::locale::classic()); ss >> $$; }
710     | '-' digits { std::stringstream ss("-" + $2); ss.imbue(std::locale::classic()); ss >> $$; }
711     ;
712 schoenebeck 219
713 schoenebeck 2135
714 schoenebeck 219 digits : digit { $$ = $1; }
715     | digits digit { $$ = $1 + $2; }
716 senkov 155 ;
717    
718 schoenebeck 219 digit : '0' { $$ = '0'; }
719     | '1' { $$ = '1'; }
720     | '2' { $$ = '2'; }
721     | '3' { $$ = '3'; }
722     | '4' { $$ = '4'; }
723     | '5' { $$ = '5'; }
724     | '6' { $$ = '6'; }
725     | '7' { $$ = '7'; }
726     | '8' { $$ = '8'; }
727     | '9' { $$ = '9'; }
728 senkov 155 ;
729    
730 schoenebeck 1245 digit_oct : '0' { $$ = '0'; }
731     | '1' { $$ = '1'; }
732     | '2' { $$ = '2'; }
733     | '3' { $$ = '3'; }
734     | '4' { $$ = '4'; }
735     | '5' { $$ = '5'; }
736     | '6' { $$ = '6'; }
737     | '7' { $$ = '7'; }
738     ;
739    
740     digit_hex : '0' { $$ = '0'; }
741     | '1' { $$ = '1'; }
742     | '2' { $$ = '2'; }
743     | '3' { $$ = '3'; }
744     | '4' { $$ = '4'; }
745     | '5' { $$ = '5'; }
746     | '6' { $$ = '6'; }
747     | '7' { $$ = '7'; }
748     | '8' { $$ = '8'; }
749     | '9' { $$ = '9'; }
750     | 'a' { $$ = 'a'; }
751     | 'b' { $$ = 'b'; }
752     | 'c' { $$ = 'c'; }
753     | 'd' { $$ = 'd'; }
754     | 'e' { $$ = 'e'; }
755     | 'f' { $$ = 'f'; }
756     | 'A' { $$ = 'a'; }
757     | 'B' { $$ = 'b'; }
758     | 'C' { $$ = 'c'; }
759     | 'D' { $$ = 'd'; }
760     | 'E' { $$ = 'e'; }
761     | 'F' { $$ = 'f'; }
762     ;
763    
764 schoenebeck 219 number : digit { $$ = atoi(String(1, $1).c_str()); }
765     | '1' digits { $$ = atoi(String(String("1") + $2).c_str()); }
766     | '2' digits { $$ = atoi(String(String("2") + $2).c_str()); }
767     | '3' digits { $$ = atoi(String(String("3") + $2).c_str()); }
768     | '4' digits { $$ = atoi(String(String("4") + $2).c_str()); }
769     | '5' digits { $$ = atoi(String(String("5") + $2).c_str()); }
770     | '6' digits { $$ = atoi(String(String("6") + $2).c_str()); }
771     | '7' digits { $$ = atoi(String(String("7") + $2).c_str()); }
772     | '8' digits { $$ = atoi(String(String("8") + $2).c_str()); }
773     | '9' digits { $$ = atoi(String(String("9") + $2).c_str()); }
774 schoenebeck 1332 ;
775 schoenebeck 219
776 schoenebeck 1332 path : '\'' path_base '\'' { $$ = $2; }
777     | '\"' path_base '\"' { $$ = $2; }
778 senkov 155 ;
779    
780 schoenebeck 1471 path_base : path_prefix path_body { $$ = $1 + $2; }
781 schoenebeck 1332 ;
782    
783 schoenebeck 1471 path_prefix : '/' { $$ = Path(); }
784     | alpha_char ':' '/' { Path p; p.setDrive($1); $$ = p; }
785     ;
786    
787     path_body : /* epsilon (empty argument) */ { $$ = Path(); }
788     | path_body '/' { $$ = $1; }
789     | path_body text_escaped_base { Path p; p.appendNode($2); $$ = $1 + p; }
790     ;
791    
792 schoenebeck 1332 stringval : '\'' text '\'' { $$ = $2; }
793     | '\"' text '\"' { $$ = $2; }
794     ;
795    
796 schoenebeck 1389 stringval_escaped : '\'' text_escaped '\'' { $$ = $2; }
797     | '\"' text_escaped '\"' { $$ = $2; }
798 iliev 1345 ;
799    
800 schoenebeck 221 text : SP { $$ = " "; }
801     | string
802     | text SP { $$ = $1 + " "; }
803     | text string { $$ = $1 + $2; }
804 schoenebeck 35 ;
805    
806 schoenebeck 1389 // like text_escaped, but missing the slash ('/') character
807     text_escaped_base : SP { $$ = " "; }
808 schoenebeck 1245 | string_escaped
809 schoenebeck 1389 | text_escaped_base SP { $$ = $1 + " "; }
810     | text_escaped_base string_escaped { $$ = $1 + $2; }
811 schoenebeck 1245 ;
812    
813 schoenebeck 1389 text_escaped : '/' { $$ = "/"; }
814     | text_escaped_base
815     | text_escaped '/' { $$ = $1 + "/"; }
816     | text_escaped text_escaped_base { $$ = $1 + $2; }
817 iliev 1345 ;
818    
819 schoenebeck 1332 string : char { std::string s; s = $1; $$ = s; }
820     | string char { $$ = $1 + $2; }
821 schoenebeck 221 ;
822 schoenebeck 219
823 schoenebeck 1332 string_escaped : char_base { std::string s; s = $1; $$ = s; }
824     | escape_seq { std::string s; s = $1; $$ = s; }
825     | string_escaped char_base { $$ = $1 + $2; }
826     | string_escaped escape_seq { $$ = $1 + $2; }
827 schoenebeck 1245 ;
828 schoenebeck 221
829 schoenebeck 1332 // full ASCII character set except space, quotation mark and apostrophe
830     char : char_base
831     | '\\' { $$ = '\\'; }
832     | '/' { $$ = '/'; }
833     ;
834    
835 schoenebeck 1471 // characters A..Z and a..z
836     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'; }
837     | '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'; }
838     ;
839    
840 schoenebeck 1332 // ASCII characters except space, quotation mark, apostrophe, backslash and slash
841 schoenebeck 1471 char_base : alpha_char
842 schoenebeck 1332 | '0' { $$ = '0'; } | '1' { $$ = '1'; } | '2' { $$ = '2'; } | '3' { $$ = '3'; } | '4' { $$ = '4'; } | '5' { $$ = '5'; } | '6' { $$ = '6'; } | '7' { $$ = '7'; } | '8' { $$ = '8'; } | '9' { $$ = '9'; }
843     | '!' { $$ = '!'; } | '#' { $$ = '#'; } | '$' { $$ = '$'; } | '%' { $$ = '%'; } | '&' { $$ = '&'; } | '(' { $$ = '('; } | ')' { $$ = ')'; } | '*' { $$ = '*'; } | '+' { $$ = '+'; } | '-' { $$ = '-'; } | '.' { $$ = '.'; } | ',' { $$ = ','; }
844     | ':' { $$ = ':'; } | ';' { $$ = ';'; } | '<' { $$ = '<'; } | '=' { $$ = '='; } | '>' { $$ = '>'; } | '?' { $$ = '?'; } | '@' { $$ = '@'; }
845     | '[' { $$ = '['; } | ']' { $$ = ']'; } | '^' { $$ = '^'; } | '_' { $$ = '_'; }
846     | '{' { $$ = '{'; } | '|' { $$ = '|'; } | '}' { $$ = '}'; } | '~' { $$ = '~'; }
847     | EXT_ASCII_CHAR
848     ;
849    
850 schoenebeck 1245 escape_seq : '\\' '\'' { $$ = '\''; }
851     | '\\' '\"' { $$ = '\"'; }
852     | '\\' '\\' { $$ = '\\'; }
853 schoenebeck 1332 | '\\' '/' { $$ = '/'; }
854 schoenebeck 1245 | '\\' 'n' { $$ = '\n'; }
855     | '\\' 'r' { $$ = '\r'; }
856     | '\\' 'f' { $$ = '\f'; }
857     | '\\' 't' { $$ = '\t'; }
858     | '\\' 'v' { $$ = '\v'; }
859     | escape_seq_octal
860     | escape_seq_hex
861     ;
862    
863     escape_seq_octal : '\\' digit_oct { $$ = (char) octalsToNumber($2); }
864     | '\\' digit_oct digit_oct { $$ = (char) octalsToNumber($3,$2); }
865     | '\\' digit_oct digit_oct digit_oct { $$ = (char) octalsToNumber($4,$3,$2); }
866     ;
867    
868     escape_seq_hex : '\\' 'x' digit_hex { $$ = (char) hexsToNumber($3); }
869     | '\\' 'x' digit_hex digit_hex { $$ = (char) hexsToNumber($4,$3); }
870     ;
871    
872 schoenebeck 219 // rules which are more or less just terminal symbols
873    
874     SP : ' '
875 schoenebeck 35 ;
876    
877 schoenebeck 219 LF : '\n'
878 schoenebeck 35 ;
879    
880 schoenebeck 219 CR : '\r'
881 schoenebeck 35 ;
882    
883 schoenebeck 219 ADD : 'A''D''D'
884 schoenebeck 35 ;
885    
886 schoenebeck 219 GET : 'G''E''T'
887 schoenebeck 35 ;
888    
889 schoenebeck 947 MAP : 'M''A''P'
890     ;
891    
892     UNMAP : 'U''N''M''A''P'
893     ;
894    
895     CLEAR : 'C''L''E''A''R'
896     ;
897    
898 iliev 1187 FIND : 'F''I''N''D'
899     ;
900    
901 iliev 1781 FILE_AS_DIR : 'F''I''L''E''_''A''S''_''D''I''R'
902     ;
903    
904 iliev 1161 MOVE : 'M''O''V''E'
905     ;
906    
907 iliev 1187 COPY : 'C''O''P''Y'
908     ;
909    
910 schoenebeck 219 CREATE : 'C''R''E''A''T''E'
911 schoenebeck 35 ;
912    
913 schoenebeck 219 DESTROY : 'D''E''S''T''R''O''Y'
914 schoenebeck 210 ;
915    
916 schoenebeck 219 LIST : 'L''I''S''T'
917 schoenebeck 35 ;
918    
919 schoenebeck 219 LOAD : 'L''O''A''D'
920     ;
921    
922 schoenebeck 228 ALL : 'A''L''L'
923     ;
924    
925 schoenebeck 973 NONE : 'N''O''N''E'
926     ;
927    
928     DEFAULT : 'D''E''F''A''U''L''T'
929     ;
930    
931 schoenebeck 219 NON_MODAL : 'N''O''N''_''M''O''D''A''L'
932     ;
933    
934     REMOVE : 'R''E''M''O''V''E'
935     ;
936    
937     SET : 'S''E''T'
938     ;
939    
940 schoenebeck 2515 SHELL : 'S''H''E''L''L'
941     ;
942    
943     INTERACT : 'I''N''T''E''R''A''C''T'
944     ;
945    
946 schoenebeck 2516 AUTO_CORRECT : 'A''U''T''O''_''C''O''R''R''E''C''T'
947     ;
948    
949 schoenebeck 2135 APPEND : 'A''P''P''E''N''D'
950     ;
951    
952     INSERT : 'I''N''S''E''R''T'
953     ;
954    
955 schoenebeck 219 SUBSCRIBE : 'S''U''B''S''C''R''I''B''E'
956     ;
957    
958     UNSUBSCRIBE : 'U''N''S''U''B''S''C''R''I''B''E'
959     ;
960    
961     CHANNEL : 'C''H''A''N''N''E''L'
962     ;
963    
964     AVAILABLE_ENGINES : 'A''V''A''I''L''A''B''L''E''_''E''N''G''I''N''E''S'
965     ;
966    
967     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'
968     ;
969    
970     CHANNELS : 'C''H''A''N''N''E''L''S'
971     ;
972    
973     INFO : 'I''N''F''O'
974     ;
975    
976 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'
977 iliev 1161 ;
978 iliev 981
979     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'
980 iliev 1161 ;
981 iliev 981
982     MIDI_INPUT_DEVICE_COUNT : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''_''C''O''U''N''T'
983 iliev 1161 ;
984 iliev 981
985     MIDI_INPUT_DEVICE_INFO : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''_''I''N''F''O'
986 iliev 1161 ;
987 iliev 981
988     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'
989 iliev 1161 ;
990 iliev 981
991     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'
992 iliev 1161 ;
993 iliev 981
994     MIDI_INSTRUMENT_COUNT : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''C''O''U''N''T'
995 iliev 1161 ;
996 iliev 981
997     MIDI_INSTRUMENT_INFO : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'
998 iliev 1161 ;
999 iliev 981
1000 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'
1001     ;
1002    
1003     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'
1004     ;
1005    
1006     DB_INSTRUMENT_COUNT : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''C''O''U''N''T'
1007     ;
1008    
1009     DB_INSTRUMENT_INFO : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'
1010     ;
1011    
1012 iliev 1727 DB_INSTRUMENT_FILES : 'D''B''_''I''N''S''T''R''U''M''E''N''T''_''F''I''L''E''S'
1013     ;
1014    
1015 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'
1016     ;
1017    
1018 schoenebeck 556 CHANNEL_COUNT : 'C''H''A''N''N''E''L''_''C''O''U''N''T'
1019     ;
1020    
1021 schoenebeck 1686 CHANNEL_MIDI : 'C''H''A''N''N''E''L''_''M''I''D''I'
1022     ;
1023    
1024 schoenebeck 1695 DEVICE_MIDI : 'D''E''V''I''C''E''_''M''I''D''I'
1025     ;
1026    
1027 schoenebeck 556 CHANNEL_INFO : 'C''H''A''N''N''E''L''_''I''N''F''O'
1028     ;
1029    
1030 iliev 1108 FX_SEND_COUNT : 'F''X''_''S''E''N''D''_''C''O''U''N''T'
1031     ;
1032    
1033     FX_SEND_INFO : 'F''X''_''S''E''N''D''_''I''N''F''O'
1034     ;
1035    
1036 schoenebeck 219 BUFFER_FILL : 'B''U''F''F''E''R''_''F''I''L''L'
1037     ;
1038    
1039     STREAM_COUNT : 'S''T''R''E''A''M''_''C''O''U''N''T'
1040     ;
1041    
1042     VOICE_COUNT : 'V''O''I''C''E''_''C''O''U''N''T'
1043     ;
1044    
1045 iliev 1541 TOTAL_STREAM_COUNT : 'T''O''T''A''L''_''S''T''R''E''A''M''_''C''O''U''N''T'
1046     ;
1047    
1048 iliev 778 TOTAL_VOICE_COUNT : 'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T'
1049     ;
1050    
1051     TOTAL_VOICE_COUNT_MAX: 'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T''_''M''A''X'
1052     ;
1053    
1054 iliev 1108 GLOBAL_INFO : 'G''L''O''B''A''L''_''I''N''F''O'
1055     ;
1056    
1057 iliev 2188 EFFECT_INSTANCE_COUNT : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''C''O''U''N''T'
1058     ;
1059    
1060     EFFECT_INSTANCE_INFO : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''I''N''F''O'
1061     ;
1062    
1063     SEND_EFFECT_CHAIN_COUNT : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''C''O''U''N''T'
1064     ;
1065    
1066     SEND_EFFECT_CHAIN_INFO : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''I''N''F''O'
1067     ;
1068    
1069 schoenebeck 219 INSTRUMENT : 'I''N''S''T''R''U''M''E''N''T'
1070     ;
1071    
1072 schoenebeck 1525 INSTRUMENTS : 'I''N''S''T''R''U''M''E''N''T''S'
1073     ;
1074    
1075 schoenebeck 219 ENGINE : 'E' 'N' 'G' 'I' 'N' 'E'
1076     ;
1077    
1078 schoenebeck 947 ON_DEMAND : 'O''N''_''D''E''M''A''N''D'
1079     ;
1080    
1081     ON_DEMAND_HOLD : 'O''N''_''D''E''M''A''N''D''_''H''O''L''D'
1082     ;
1083    
1084     PERSISTENT : 'P''E''R''S''I''S''T''E''N''T'
1085     ;
1086    
1087 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'
1088     ;
1089    
1090     AUDIO_OUTPUT_DEVICES : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E''S'
1091     ;
1092    
1093     AUDIO_OUTPUT_DEVICE : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''E''V''I''C''E'
1094     ;
1095    
1096     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'
1097     ;
1098    
1099     AUDIO_OUTPUT_DRIVER : 'A''U''D''I''O''_''O''U''T''P''U''T''_''D''R''I''V''E''R'
1100     ;
1101    
1102     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'
1103     ;
1104    
1105     AUDIO_OUTPUT_CHANNEL : 'A''U''D''I''O''_''O''U''T''P''U''T''_''C''H''A''N''N''E''L'
1106     ;
1107    
1108     AUDIO_OUTPUT_TYPE : 'A''U''D''I''O''_''O''U''T''P''U''T''_''T''Y''P''E'
1109     ;
1110    
1111 schoenebeck 2135 AVAILABLE_EFFECTS : 'A''V''A''I''L''A''B''L''E''_''E''F''F''E''C''T''S'
1112     ;
1113    
1114     EFFECT : 'E''F''F''E''C''T'
1115     ;
1116    
1117     EFFECT_INSTANCE : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E'
1118     ;
1119    
1120     EFFECT_INSTANCES : 'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''S'
1121     ;
1122    
1123     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'
1124     ;
1125    
1126 schoenebeck 2137 SEND_EFFECT_CHAIN : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N'
1127     ;
1128 schoenebeck 2135
1129 schoenebeck 2137 SEND_EFFECT_CHAINS : 'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''S'
1130     ;
1131    
1132 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'
1133     ;
1134    
1135     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'
1136     ;
1137    
1138     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'
1139     ;
1140    
1141     MIDI_INPUT_DEVICES : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E''S'
1142     ;
1143    
1144     MIDI_INPUT_DEVICE : 'M''I''D''I''_''I''N''P''U''T''_''D''E''V''I''C''E'
1145     ;
1146    
1147     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'
1148     ;
1149    
1150 schoenebeck 947 MIDI_INSTRUMENT : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T'
1151     ;
1152    
1153     MIDI_INSTRUMENTS : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''S'
1154     ;
1155    
1156 schoenebeck 973 MIDI_INSTRUMENT_MAP : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P'
1157     ;
1158    
1159     MIDI_INSTRUMENT_MAPS : 'M''I''D''I''_''I''N''S''T''R''U''M''E''N''T''_''M''A''P''S'
1160     ;
1161    
1162 schoenebeck 219 MIDI_INPUT_DRIVER : 'M''I''D''I''_''I''N''P''U''T''_''D''R''I''V''E''R'
1163     ;
1164    
1165     MIDI_INPUT_PORT : 'M''I''D''I''_''I''N''P''U''T''_''P''O''R''T'
1166     ;
1167    
1168     MIDI_INPUT_CHANNEL : 'M''I''D''I''_''I''N''P''U''T''_''C''H''A''N''N''E''L'
1169     ;
1170    
1171     MIDI_INPUT_TYPE : 'M''I''D''I''_''I''N''P''U''T''_''T''Y''P''E'
1172     ;
1173    
1174     MIDI_INPUT : 'M''I''D''I''_''I''N''P''U''T'
1175     ;
1176    
1177 schoenebeck 2500 MIDI_INPUTS : 'M''I''D''I''_''I''N''P''U''T''S'
1178     ;
1179    
1180 schoenebeck 1026 MIDI_CONTROLLER : 'M''I''D''I''_''C''O''N''T''R''O''L''L''E''R'
1181     ;
1182    
1183 iliev 1771 SEND : 'S''E''N''D'
1184     ;
1185    
1186 schoenebeck 1001 FX_SEND : 'F''X''_''S''E''N''D'
1187     ;
1188    
1189     FX_SENDS : 'F''X''_''S''E''N''D''S'
1190     ;
1191    
1192 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'
1193     ;
1194    
1195     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'
1196     ;
1197    
1198     DB_INSTRUMENTS : 'D''B''_''I''N''S''T''R''U''M''E''N''T''S'
1199     ;
1200    
1201     DB_INSTRUMENT : 'D''B''_''I''N''S''T''R''U''M''E''N''T'
1202     ;
1203    
1204 iliev 1200 DB_INSTRUMENTS_JOB : 'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B'
1205     ;
1206    
1207 iliev 1353 INSTRUMENTS_DB : 'I''N''S''T''R''U''M''E''N''T''S''_''D''B'
1208     ;
1209    
1210 iliev 1161 DESCRIPTION : 'D''E''S''C''R''I''P''T''I''O''N'
1211     ;
1212    
1213     FORCE : 'F''O''R''C''E'
1214     ;
1215    
1216     FLAT : 'F''L''A''T'
1217     ;
1218    
1219 iliev 1187 RECURSIVE : 'R''E''C''U''R''S''I''V''E'
1220     ;
1221    
1222 iliev 1161 NON_RECURSIVE : 'N''O''N''_''R''E''C''U''R''S''I''V''E'
1223     ;
1224    
1225 iliev 1727 LOST : 'L''O''S''T'
1226     ;
1227    
1228     FILE_PATH : 'F''I''L''E''_''P''A''T''H'
1229     ;
1230    
1231 schoenebeck 563 SERVER : 'S''E''R''V''E''R'
1232     ;
1233    
1234 schoenebeck 219 VOLUME : 'V''O''L''U''M''E'
1235     ;
1236    
1237 schoenebeck 1026 LEVEL : 'L''E''V''E''L'
1238     ;
1239    
1240 schoenebeck 2137 VALUE : 'V''A''L''U''E'
1241     ;
1242    
1243 schoenebeck 705 MUTE : 'M''U''T''E'
1244     ;
1245    
1246     SOLO : 'S''O''L''O'
1247     ;
1248    
1249 schoenebeck 1800 VOICES : 'V''O''I''C''E''S'
1250     ;
1251    
1252     STREAMS : 'S''T''R''E''A''M''S'
1253     ;
1254    
1255 schoenebeck 219 BYTES : 'B''Y''T''E''S'
1256     ;
1257    
1258     PERCENTAGE : 'P''E''R''C''E''N''T''A''G''E'
1259     ;
1260    
1261 schoenebeck 1525 FILE : 'F''I''L''E'
1262     ;
1263    
1264 schoenebeck 1212 EDIT : 'E''D''I''T'
1265     ;
1266    
1267 iliev 1353 FORMAT : 'F''O''R''M''A''T'
1268     ;
1269    
1270 iliev 1771 MIDI_DATA : 'M''I''D''I''_''D''A''T''A'
1271     ;
1272    
1273 schoenebeck 219 RESET : 'R''E''S''E''T'
1274     ;
1275    
1276     MISCELLANEOUS : 'M''I''S''C''E''L''L''A''N''E''O''U''S'
1277     ;
1278    
1279 schoenebeck 973 NAME : 'N''A''M''E'
1280     ;
1281    
1282 schoenebeck 219 ECHO : 'E''C''H''O'
1283     ;
1284    
1285 schoenebeck 2534 DOC : 'D''O''C'
1286     ;
1287    
1288 schoenebeck 219 QUIT : 'Q''U''I''T'
1289     ;
1290    
1291 schoenebeck 35 %%
1292    
1293 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
1294    
1295     /**
1296     * Additional informations of a grammar symbol.
1297     */
1298     struct BisonSymbolInfo {
1299     bool isTerminalSymbol; ///< Whether the symbol is a terminal or non-termianl symbol. NOTE: Read comment regarding this in _isRuleTerminalSymbol() !!
1300     String nextExpectedChars; ///< According to current parser position: sequence of characters expected next for satisfying this grammar symbol.
1301     };
1302    
1303 schoenebeck 2518 #if HAVE_BISON_MAJ >= 3 // Bison 3.x or younger ...
1304    
1305 schoenebeck 2516 /**
1306 schoenebeck 2518 * Must ONLY be called just before a so called "reduce" parser action:
1307     * Returns true if the grammar rule, which is just about to be "reduced", is a
1308     * terminal symbol (in *our* terms).
1309     *
1310     * Please note that the term "terminal symbol" is a bit confusingly used in
1311     * this source code here around. In Bison's terms, "terminal symbols" are (more
1312     * or less) just the numbers returned by the YYLEX function. Since we decided
1313     * though to use a convenient solution without a separate lexer, and all its
1314     * caveats, all numbers by the yylex() function here are just the ASCII
1315     * numbers of the individual characters received. Based on that however, one
1316     * single character is not what one would intuitively expect of being a
1317     * "terminal symbol", because it is simply too primitive.
1318     *
1319     * So in this LSCP parser source code a "terminal symbol" rather means a
1320     * keyword like "CREATE" or "GET". In the grammal definition above, those are
1321     * however defined as grammar rules (non-terminals in Bison's terms). So this
1322     * function decides like this: if the given grammar rule just contains
1323     * individual characters on the right side of its grammar rule, then it is a
1324     * "terminal symbol" in *our* terms.
1325     *
1326     * @param rule - Bison grammar rule number
1327     * @param stack - reflecting current Bison parser state
1328     */
1329     inline static bool _isRuleTerminalSymbol(int rule, const std::vector<YYTYPE_INT16>& stack) {
1330     int nrhs = yyr2[rule];
1331     for (int i = 0; i < nrhs; ++i)
1332     if (yystos[*(stack.end() - nrhs + i)] >= YYNTOKENS) return false;
1333     return true;
1334     }
1335    
1336     /**
1337     * Must ONLY be called just before a so called "reduce" parser action: Returns
1338     * additional informations to the given grammar rule that is about to be
1339     * "reduced".
1340     *
1341     * @param rule - Bison grammar rule number
1342     * @param stack - reflecting current Bison parser state
1343     * @param nextExpectedChars - must already be filled with the characters
1344     * expected to be coming next
1345     */
1346     inline static BisonSymbolInfo _symbolInfoForRule(int rule, const std::vector<YYTYPE_INT16>& stack, const String& nextExpectedChars) {
1347     BisonSymbolInfo info;
1348     info.isTerminalSymbol = _isRuleTerminalSymbol(rule, stack);
1349     if (info.isTerminalSymbol) info.nextExpectedChars = nextExpectedChars;
1350     return info;
1351     }
1352    
1353     #else // Bison 2.x or older ...
1354    
1355 schoenebeck 2524 //TODO: The Bison 2.x code below can probably soon just be deleted. Most Bisonx 2.x versions should be able to compile successfully with the Bison 3.x code above as well (just requires the existence of table yystos[] in the auto generated lscpparser.cpp).
1356    
1357 schoenebeck 2518 /**
1358 schoenebeck 2516 * Returns true if the given grammar @a rule is a terminal symbol (in *our*
1359     * terms).
1360     *
1361     * Please note that the term "terminal symbol" is a bit confusingly used in
1362     * this source code here around. In Bison's terms, "terminal symbols" are (more
1363     * or less) just the numbers returned by the YYLEX function. Since we decided
1364     * though to use a convenient solution without a separate lexer, and all its
1365     * caveats, all numbers by the yylex() function here are just the ASCII
1366     * numbers of the individual characters received. Based on that however, one
1367     * single character is not what one would intuitively expect of being a
1368     * "terminal symbol", because it is simply too primitive.
1369     *
1370     * So in this LSCP parser source code a "terminal symbol" rather means a
1371     * keyword like "CREATE" or "GET". In the grammal definition above, those are
1372     * however defined as grammar rules (non-terminals in Bison's terms). So this
1373     * function decides like this: if the given grammar rule just contains
1374     * individual characters on the right side of its grammar rule, then it is a
1375     * "terminal symbol" in *our* terms.
1376     *
1377     * @param rule - Bison grammar rule number
1378     */
1379     inline static bool _isRuleTerminalSymbol(int rule) {
1380     for (int i = yyprhs[rule]; yyrhs[i] != -1; ++i)
1381     if (yyrhs[i] >= YYNTOKENS) return false;
1382     return true;
1383     }
1384    
1385     /**
1386     * Returns additional informations to the given grammar @a rule.
1387 schoenebeck 2518 *
1388     * @param rule - grammar rule index to retrieve informations about
1389     * @param nextExpectedChars - must already be filled with the characters
1390     * expected to be coming next
1391 schoenebeck 2516 */
1392     inline static BisonSymbolInfo _symbolInfoForRule(int rule, const String& nextExpectedChars) {
1393     BisonSymbolInfo info;
1394     info.isTerminalSymbol = _isRuleTerminalSymbol(rule);
1395     if (info.isTerminalSymbol) info.nextExpectedChars = nextExpectedChars;
1396     return info;
1397     }
1398    
1399 schoenebeck 2518 #endif // HAVE_BISON_MAJ >= 3
1400    
1401 schoenebeck 2516 /**
1402     * Returns the human readable name of the given @a token.
1403     */
1404     inline static String _tokenName(int token) {
1405     String s = yytname[token];
1406     // remove leading and trailing apostrophes that Bison usually adds to
1407     // ASCII characters used directly in grammar rules
1408     if (s.empty()) return s;
1409     if (s[0] == '\'') s.erase(0, 1);
1410     if (s.empty()) return s;
1411     if (s[s.size() - 1] == '\'') s.erase(s.size() - 1);
1412     return s;
1413     }
1414    
1415 schoenebeck 2523 /**
1416     * Assumes the given @a token is exactly one character and returns that
1417     * character. This must be changed in future, i.e. in case Unicode characters
1418     * will be introduced in the LSCP grammar one day.
1419     */
1420     inline static char _tokenChar(int token) {
1421     String s = _tokenName(token);
1422     if (s == "\\n") return '\n';
1423     if (s == "\\r") return '\r';
1424     return _tokenName(token)[0];
1425     }
1426    
1427     /**
1428     * Implements Bison's so called "reduce" action, according to Bison's LALR(1)
1429     * parser algorithm.
1430     */
1431     inline static int _yyReduce(std::vector<YYTYPE_INT16>& stack, const int& rule) {
1432     if (stack.empty()) throw 1; // severe error
1433     const int len = yyr2[rule];
1434     stack.resize(stack.size() - len);
1435     YYTYPE_INT16 newState = yypgoto[yyr1[rule] - YYNTOKENS] + stack.back();
1436     if (0 <= newState && newState <= YYLAST && yycheck[newState] == stack.back())
1437     newState = yytable[newState];
1438     else
1439     newState = yydefgoto[yyr1[rule] - YYNTOKENS];
1440     stack.push_back(newState);
1441     return newState;
1442     }
1443    
1444     /**
1445     * Implements Bison's so called "default reduce" action, according to Bison's
1446     * LALR(1) parser algorithm.
1447     */
1448     inline static int _yyDefaultReduce(std::vector<YYTYPE_INT16>& stack) {
1449     if (stack.empty()) throw 2; // severe error
1450     int rule = yydefact[stack.back()];
1451     if (rule <= 0 || rule >= YYNRULES) throw 3; // no rule, something is wrong
1452     return _yyReduce(stack, rule);
1453     }
1454    
1455     static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch);
1456    
1457 schoenebeck 2532 /**
1458     * A set of parser symbol stacks. This type is used for the recursive algorithms
1459     * in a) yyAutoComplete() and b) walkAndFillExpectedSymbols() for detecting
1460     * endless recursions.
1461     *
1462     * This unique container is used to keep track of all previous parser states
1463     * (stacks), for detecting a parser symbol stack that has already been
1464     * encountered before. Because if yyAutoComplete() or
1465     * walkAndFillExpectedSymbols() reach the exactly same parser symbol stack
1466     * again, that means there is an endless recursion in that part of the grammar
1467     * tree branch and shall not be evaluated any further, since it would end up in
1468     * an endless loop of the algorithm otherwise.
1469     *
1470     * This solution consumes a lot of memory, but unfortunately there is no other
1471     * easy way to solve it. With our grammar and today's usual memory heap size &
1472     * memory stack size in modern devices, it should be fine though.
1473     */
1474     typedef std::set< std::vector<YYTYPE_INT16> > YYStackHistory;
1475    
1476 schoenebeck 2510 #define DEBUG_BISON_SYNTAX_ERROR_WALKER 0
1477    
1478 schoenebeck 35 /**
1479 schoenebeck 2516 * Tries to find the next expected grammar symbols according to the given
1480     * precise parse position & state represented by @a stack, according to Bison's
1481     * LALR(1) parser algorithm.
1482 schoenebeck 2510 *
1483 schoenebeck 2525 * This function is given a Bison parser symbol stack, reflecting the parser's
1484 schoenebeck 2516 * entire state at a certain point, i.e. when a syntax error occured. This
1485     * function will then walk ahead the potential parse tree starting from the
1486 schoenebeck 2525 * current head of the given symbol stack. This function will call itself
1487 schoenebeck 2516 * recursively to scan the individual parse tree branches. As soon as it hits
1488     * on the next non-terminal grammar symbol in one parse tree branch, it adds the
1489     * found non-terminal symbol to @a expectedSymbols and aborts scanning the
1490     * respective tree branch further. If any local parser state is reached a second
1491     * time, the respective parse tree is aborted to avoid any endless recursion.
1492     *
1493 schoenebeck 2525 * @param stack - current Bison (yacc) symbol stack to be examined
1494 schoenebeck 2510 * @param expectedSymbols - will be filled with next expected grammar symbols
1495 schoenebeck 2516 * @param nextExpectedChars - just for internal purpose, due to the recursive
1496     * implementation of this function, do supply an
1497 schoenebeck 2534 * empty string for this argument
1498 schoenebeck 2532 * @param history - only for internal purpose, keeps a history of all previous
1499     * parser symbol stacks (just for avoiding endless recursion in
1500 schoenebeck 2534 * this recursive algorithm), do supply an empty history
1501     * @param depth - just for internal debugging purposes, do not supply it
1502 schoenebeck 35 */
1503 schoenebeck 2516 static void walkAndFillExpectedSymbols(
1504     std::vector<YYTYPE_INT16>& stack,
1505     std::map<String,BisonSymbolInfo>& expectedSymbols,
1506 schoenebeck 2532 String& nextExpectedChars, YYStackHistory& history, int depth = 0)
1507 schoenebeck 2516 {
1508 schoenebeck 2510 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1509     printf("\n");
1510     for (int i = 0; i < depth; ++i) printf("\t");
1511 schoenebeck 2525 printf("Symbol stack:");
1512 schoenebeck 2510 for (int i = 0; i < stack.size(); ++i) {
1513     printf(" %d", stack[i]);
1514     }
1515     printf("\n");
1516     #endif
1517 schoenebeck 2523 startLabel:
1518 schoenebeck 2510
1519 schoenebeck 2532 // detect endless recursion
1520     if (history.count(stack)) return;
1521     history.insert(stack);
1522    
1523 schoenebeck 2523 if (stack.empty()) {
1524     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1525     for (int i = 0; i < depth; ++i) printf("\t");
1526     printf("(EMPTY STACK)\n");
1527     #endif
1528     return;
1529     }
1530 schoenebeck 2510
1531     int state = stack[stack.size() - 1];
1532     int n = yypact[state];
1533     if (n == YYPACT_NINF) { // default reduction required ...
1534     // get default reduction rule for this state
1535     n = yydefact[state];
1536 schoenebeck 2523 if (n <= 0 || n >= YYNRULES) {
1537     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1538     for (int i = 0; i < depth; ++i) printf("\t");
1539     printf("(EMPTY RULE)\n");
1540     #endif
1541     return; // no rule, something is wrong
1542     }
1543     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1544     for (int i = 0; i < depth; ++i) printf("\t");
1545     printf("(default reduction)\n");
1546     #endif
1547 schoenebeck 2524 #if HAVE_BISON_MAJ >= 3
1548 schoenebeck 2523 if (!nextExpectedChars.empty() || !_isRuleTerminalSymbol(n, stack)) {
1549 schoenebeck 2524 #else
1550     if (!nextExpectedChars.empty() || !_isRuleTerminalSymbol(n)) {
1551     #endif
1552 schoenebeck 2523 // Return the new resolved expected symbol (left-hand symbol of grammar
1553     // rule), then we're done in this state. (If the same symbol can be
1554     // matched on different ways, then it is non-terminal symbol.)
1555     bool ambigious =
1556     expectedSymbols.count(yytname[yyr1[n]]) &&
1557     expectedSymbols[yytname[yyr1[n]]].nextExpectedChars != nextExpectedChars;
1558     #if HAVE_BISON_MAJ >= 3
1559     expectedSymbols[yytname[yyr1[n]]] = _symbolInfoForRule(n, stack, nextExpectedChars);
1560     #else
1561     expectedSymbols[yytname[yyr1[n]]] = _symbolInfoForRule(n, nextExpectedChars);
1562     #endif
1563     if (ambigious)
1564     expectedSymbols[yytname[yyr1[n]]].isTerminalSymbol = false;
1565     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1566     for (int i = 0; i < depth; ++i) printf("\t");
1567     printf("(empty expectedChars. sym = %s)\n", yytname[yyr1[n]]);
1568     #endif
1569     return;
1570     }
1571     _yyReduce(stack, n);
1572     goto startLabel;
1573     }
1574     if (!(YYPACT_NINF < n && n <= YYLAST)) {
1575     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1576     for (int i = 0; i < depth; ++i) printf("\t");
1577     printf("(invalid action B)\n");
1578     #endif
1579 schoenebeck 2510 return;
1580     }
1581    
1582 schoenebeck 2523 // Check for duplicate states, if duplicates exist return
1583     // (this check is necessary since the introduction of the yyValid() call
1584     // below, which does not care about duplicates).
1585     for (int i = 0; i < stack.size(); ++i)
1586     for (int k = i + 1; k < stack.size(); ++k)
1587     if (stack[i] == stack[k])
1588     return;
1589    
1590 schoenebeck 2510 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1591     for (int i = 0; i < depth; ++i) printf("\t");
1592     printf("Expected tokens:");
1593     #endif
1594     int begin = n < 0 ? -n : 0;
1595 schoenebeck 2523 //int checklim = YYLAST - n + 1;
1596     int end = YYNTOKENS;//checklim < YYNTOKENS ? checklim : YYNTOKENS;
1597 schoenebeck 2516 int rule, action, stackSize, nextExpectedCharsLen;
1598 schoenebeck 2510 for (int token = begin; token < end; ++token) {
1599 schoenebeck 2523 if (token <= YYTERROR) continue;
1600     if (yytname[token] == String("$undefined")) continue;
1601     if (yytname[token] == String("EXT_ASCII_CHAR")) continue;
1602     //if (yycheck[n + token] != token) goto default_reduction;
1603     if (yycheck[n + token] != token) { // default reduction suggested ...
1604     // If we are here, it means the current token in the loop would not
1605     // cause a "shift", however we don't already know whether this token
1606     // is valid or not. Because there might be several reductions
1607     // involved until one can determine whether the token causes an
1608     // error or is valid. So we use this heavy check instead:
1609     std::vector<YYTYPE_INT16> stackCopy = stack; // copy required, since reduction will take place
1610     if (!yyValid(stackCopy, _tokenChar(token))) continue; // invalid token
1611 schoenebeck 2510 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1612 schoenebeck 2523 printf(" ETdr(%s)", yytname[token]);
1613 schoenebeck 2510 #endif
1614 schoenebeck 2523 // the token is valid, "stackCopy" has been reduced accordingly
1615     // and now do recurse ...
1616     nextExpectedChars += _tokenName(token);
1617     nextExpectedCharsLen = nextExpectedChars.size();
1618     walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1619 schoenebeck 2532 stackCopy, expectedSymbols, nextExpectedChars, history, depth + 1
1620 schoenebeck 2523 );
1621     nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'
1622     continue;
1623     }
1624     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1625     printf(" ET(%s)", yytname[token]);
1626     #endif
1627 schoenebeck 2510
1628     action = yytable[n + token];
1629     if (action == 0 || action == YYTABLE_NINF) {
1630     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1631 schoenebeck 2523 printf(" (invalid action A) "); fflush(stdout);
1632 schoenebeck 2510 #endif
1633     continue; // error, ignore
1634     }
1635     if (action < 0) { // reduction with rule -action required ...
1636     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1637     printf(" (reduction) "); fflush(stdout);
1638     #endif
1639     rule = -action;
1640     goto reduce;
1641     }
1642 schoenebeck 2523 if (action == YYFINAL) {
1643     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1644     printf(" (ACCEPT) "); fflush(stdout);
1645     #endif
1646     continue; // "accept" state, we don't care about it here
1647     }
1648 schoenebeck 2510
1649     // "shift" required ...
1650    
1651 schoenebeck 2523 if (std::find(stack.begin(), stack.end(), action) != stack.end()) {
1652     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1653     printf(" (duplicate state %d) ", action); fflush(stdout);
1654     #endif
1655 schoenebeck 2510 continue; // duplicate state, ignore it to avoid endless recursions
1656 schoenebeck 2523 }
1657 schoenebeck 2510
1658 schoenebeck 2525 // "shift" / push the new state on the symbol stack and call this
1659 schoenebeck 2510 // function recursively, and restore the stack after the recurse return
1660     stackSize = stack.size();
1661 schoenebeck 2516 nextExpectedCharsLen = nextExpectedChars.size();
1662 schoenebeck 2510 stack.push_back(action);
1663 schoenebeck 2516 nextExpectedChars += _tokenName(token);
1664 schoenebeck 2510 walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1665 schoenebeck 2532 stack, expectedSymbols, nextExpectedChars, history, depth + 1
1666 schoenebeck 2510 );
1667     stack.resize(stackSize); // restore stack
1668 schoenebeck 2516 nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'
1669 schoenebeck 2510 continue;
1670    
1671     //default_reduction: // resolve default reduction for this state
1672     // printf(" (default red.) "); fflush(stdout);
1673     // rule = yydefact[state];
1674    
1675     reduce: // "reduce" required
1676     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1677     printf(" (reduce by %d) ", rule); fflush(stdout);
1678     #endif
1679 schoenebeck 2523 if (rule == 0 || rule >= YYNRULES) {
1680     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1681     printf(" (invalid rule) "); fflush(stdout);
1682     #endif
1683     continue; // invalid rule, something is wrong
1684     }
1685     // Store the left-hand symbol of the grammar rule. (If the same symbol
1686     // can be matched on different ways, then it is non-terminal symbol.)
1687     bool ambigious =
1688     expectedSymbols.count(yytname[yyr1[rule]]) &&
1689     expectedSymbols[yytname[yyr1[rule]]].nextExpectedChars != nextExpectedChars;
1690 schoenebeck 2518 #if HAVE_BISON_MAJ >= 3
1691     expectedSymbols[yytname[yyr1[rule]]] = _symbolInfoForRule(rule, stack, nextExpectedChars);
1692     #else
1693 schoenebeck 2516 expectedSymbols[yytname[yyr1[rule]]] = _symbolInfoForRule(rule, nextExpectedChars);
1694 schoenebeck 2518 #endif
1695 schoenebeck 2523 if (ambigious)
1696     expectedSymbols[yytname[yyr1[n]]].isTerminalSymbol = false;
1697 schoenebeck 2510 #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1698     printf(" (SYM %s) ", yytname[yyr1[rule]]); fflush(stdout);
1699     #endif
1700     }
1701     #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1702     printf("\n");
1703     #endif
1704     }
1705    
1706 schoenebeck 2532 /**
1707     * Just a convenience wrapper on top of the actual walkAndFillExpectedSymbols()
1708     * implementation above, which can be called with less parameters than the
1709     * implementing function above actually requires.
1710     */
1711     static void walkAndFillExpectedSymbols(
1712     std::vector<YYTYPE_INT16>& stack,
1713     std::map<String,BisonSymbolInfo>& expectedSymbols)
1714     {
1715     String nextExpectedChars;
1716     YYStackHistory history;
1717    
1718     walkAndFillExpectedSymbols(
1719     stack, expectedSymbols, nextExpectedChars, history
1720     );
1721     }
1722    
1723 schoenebeck 2515 #define DEBUG_PUSH_PARSE 0
1724    
1725 schoenebeck 2516 /**
1726 schoenebeck 2534 * Implements parsing exactly one character (given by @a ch), continueing at the
1727 schoenebeck 2516 * parser position reflected by @a stack. The @a stack will hold the new parser
1728     * state after this call.
1729     *
1730     * This function is implemented according to Bison's LALR(1) parser algorithm.
1731     */
1732 schoenebeck 2515 static bool yyPushParse(std::vector<YYTYPE_INT16>& stack, char ch) {
1733     startLabel:
1734    
1735     #if DEBUG_PUSH_PARSE
1736     //printf("\n");
1737     //for (int i = 0; i < depth; ++i) printf("\t");
1738 schoenebeck 2525 printf("Symbol stack:");
1739 schoenebeck 2515 for (int i = 0; i < stack.size(); ++i) {
1740     printf(" %d", stack[i]);
1741     }
1742     printf(" char='%c'(%d)\n", ch, (int)ch);
1743     #endif
1744    
1745     if (stack.empty()) return false;
1746    
1747     int state = stack.back();
1748     int n = yypact[state];
1749     if (n == YYPACT_NINF) { // default reduction required ...
1750     #if DEBUG_PUSH_PARSE
1751     printf("(def reduce 1)\n");
1752     #endif
1753     state = _yyDefaultReduce(stack);
1754     goto startLabel;
1755     }
1756     if (!(YYPACT_NINF < n && n <= YYLAST)) return false;
1757    
1758     YYTYPE_INT16 token = (ch == YYEOF) ? YYEOF : yytranslate[ch];
1759     n += token;
1760     if (n < 0 || YYLAST < n || yycheck[n] != token) {
1761     #if DEBUG_PUSH_PARSE
1762     printf("(def reduce 2) n=%d token=%d\n", n, token);
1763     #endif
1764     state = _yyDefaultReduce(stack);
1765     goto startLabel;
1766     }
1767     int action = yytable[n]; // yytable[yypact[state] + token]
1768     if (action == 0 || action == YYTABLE_NINF) throw 4;
1769     if (action < 0) {
1770     #if DEBUG_PUSH_PARSE
1771     printf("(reduce)\n");
1772     #endif
1773     int rule = -action;
1774     state = _yyReduce(stack, rule);
1775     goto startLabel;
1776     }
1777     if (action == YYFINAL) return true; // final state reached
1778    
1779     #if DEBUG_PUSH_PARSE
1780     printf("(push)\n");
1781     #endif
1782     // push new state
1783     state = action;
1784     stack.push_back(state);
1785     return true;
1786     }
1787    
1788 schoenebeck 2516 /**
1789 schoenebeck 2523 * Returns true if parsing ahead with given character @a ch is syntactically
1790 schoenebeck 2516 * valid according to the LSCP grammar, it returns false if it would create a
1791     * parse error.
1792     *
1793 schoenebeck 2523 * The @a stack will reflect the new parser state after this call.
1794     *
1795 schoenebeck 2516 * This is just a wrapper ontop of yyPushParse() which converts parser
1796 schoenebeck 2534 * exceptions thrown by yyPushParse() into @c false return value.
1797 schoenebeck 2516 */
1798 schoenebeck 2515 static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch) {
1799     try {
1800     return yyPushParse(stack, ch);
1801     } catch (int i) {
1802     #if DEBUG_PUSH_PARSE
1803     printf("exception %d\n", i);
1804     #endif
1805     return false;
1806     } catch (...) {
1807     return false;
1808     }
1809     }
1810    
1811 schoenebeck 2516 /**
1812     * Returns the amount of correct characters of given @a line from the left,
1813     * according to the LSCP grammar.
1814     *
1815 schoenebeck 2525 * @param stack - a Bison symbol stack to work with
1816 schoenebeck 2516 * @param line - the input line to check
1817     * @param bAutoCorrect - if true: try to correct obvious, trivial syntax errors
1818     */
1819     static int yyValidCharacters(std::vector<YYTYPE_INT16>& stack, String& line, bool bAutoCorrect) {
1820 schoenebeck 2515 int i;
1821     for (i = 0; i < line.size(); ++i) {
1822 schoenebeck 2516 // since we might check the same parser state twice against the current
1823 schoenebeck 2525 // char here below, and since the symbol stack might be altered
1824 schoenebeck 2516 // (i.e. shifted or reduced) on syntax errors, we have to backup the
1825 schoenebeck 2525 // current symbol stack and restore it on syntax errors below
1826 schoenebeck 2523 std::vector<YYTYPE_INT16> stackCopy = stack;
1827     if (yyValid(stackCopy, line[i])) {
1828     stack = stackCopy;
1829 schoenebeck 2516 continue;
1830     }
1831     if (bAutoCorrect) {
1832     // try trivial corrections, i.e. upper case character instead of
1833     // lower case, subline instead of space and vice versa
1834     char c;
1835     if (line[i] == ' ') c = '_';
1836     else if (line[i] == '_') c = ' ';
1837     else if (isLowerCaseAlphaChar(line[i]))
1838     c = alphaCharToUpperCase(line[i]);
1839     else return i;
1840     if (yyValid(stack, c)) {
1841     line[i] = c;
1842     continue;
1843     }
1844     }
1845     return i;
1846 schoenebeck 2515 }
1847     return i;
1848     }
1849    
1850 schoenebeck 2510 /**
1851     * Should only be called on syntax errors: returns a set of non-terminal
1852     * symbols expected to appear now/next, just at the point where the syntax
1853     * error appeared.
1854 schoenebeck 2523 *
1855     * @returns names of the non-terminal symbols expected at this parse position
1856 schoenebeck 2510 */
1857     static std::set<String> yyExpectedSymbols() {
1858 schoenebeck 2516 std::map<String,BisonSymbolInfo> expectedSymbols;
1859 schoenebeck 1252 yyparse_param_t* param = GetCurrentYaccSession();
1860 schoenebeck 2510 YYTYPE_INT16* ss = (*param->ppStackBottom);
1861     YYTYPE_INT16* sp = (*param->ppStackTop);
1862     int iStackSize = sp - ss + 1;
1863 schoenebeck 2525 // copy and wrap parser's symbol stack into a convenient STL container
1864 schoenebeck 2510 std::vector<YYTYPE_INT16> stack;
1865     for (int i = 0; i < iStackSize; ++i) {
1866     stack.push_back(ss[i]);
1867     }
1868     // do the actual parser work
1869 schoenebeck 2532 walkAndFillExpectedSymbols(stack, expectedSymbols);
1870 schoenebeck 2516
1871     // convert expectedSymbols to the result set
1872     std::set<String> result;
1873     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1874     it != expectedSymbols.end(); ++it) result.insert(it->first);
1875 schoenebeck 2510 return result;
1876 schoenebeck 35 }
1877    
1878 schoenebeck 2523 #define DEBUG_YY_AUTO_COMPLETE 0
1879    
1880     /**
1881     * Generates and returns an auto completion string for the current parser
1882 schoenebeck 2525 * state given by @a stack. That means, this function will return the longest
1883     * sequence of characters that is uniqueley expected to be sent next by the LSCP
1884     * client. Or in other words, if the LSCP client would send any other
1885     * character(s) than returned here, it would result in a syntax error.
1886 schoenebeck 2523 *
1887 schoenebeck 2525 * This function takes a Bison symbol @a stack as argument, reflecting the
1888     * current Bison parser state, and evaluates the individual grammar tree
1889     * branches starting from that particular position. It walks along the grammar
1890     * tree as long as there is only one possible tree branch and assembles a string
1891     * of input characters that would lead to that walk through the grammar tree. As
1892     * soon as a position in the grammar tree is reached where there are multiple
1893     * possible tree branches, this algorithm will stop, since the user could have
1894     * multiple possible valid characters he could type at that point, thus auto
1895     * completion would no longer be unique at that point.
1896     *
1897 schoenebeck 2523 * Regarding @a history argument: read the description on YYStackHistory for the
1898     * purpose behind this argument.
1899     *
1900 schoenebeck 2525 * @param stack - current Bison (yacc) symbol stack to create auto completion for
1901     * @param history - only for internal purpose, keeps a history of all previous
1902     * parser symbol stacks (just for avoiding endless recursion in
1903 schoenebeck 2534 * this auto completion algorithm), do supply an empty history
1904     * @param depth - just for internal debugging purposes, do not supply anything
1905 schoenebeck 2523 * @returns auto completion for current, given parser state
1906     */
1907     static String yyAutoComplete(std::vector<YYTYPE_INT16>& stack, YYStackHistory& history, int depth = 0) {
1908     std::map<String,BisonSymbolInfo> expectedSymbols;
1909 schoenebeck 2532 walkAndFillExpectedSymbols(stack, expectedSymbols);
1910 schoenebeck 2523 if (expectedSymbols.size() == 1) {
1911     String name = expectedSymbols.begin()->first;
1912     BisonSymbolInfo info = expectedSymbols.begin()->second;
1913     #if DEBUG_YY_AUTO_COMPLETE
1914     for (int q = 0; q < depth; ++q) printf(" ");
1915     printf("(%d) Suggested Sub Completion (sz=%d): type=%s %s -> '%s'\n", depth, expectedSymbols.size(), (info.isTerminalSymbol) ? "T" : "NT", name.c_str(), info.nextExpectedChars.c_str());
1916     #endif
1917     if (info.nextExpectedChars.empty() || !info.isTerminalSymbol) return "";
1918     // parse forward with the suggested auto completion
1919     std::vector<YYTYPE_INT16> stackCopy = stack;
1920     yyValidCharacters(stackCopy, info.nextExpectedChars, false);
1921     // detect endless recursion
1922     if (history.count(stackCopy)) return "";
1923     history.insert(stackCopy);
1924     // recurse and return the expanded auto completion with maximum length
1925     return info.nextExpectedChars + yyAutoComplete(stackCopy, history, depth + 1);
1926     } else if (expectedSymbols.size() == 0) {
1927     #if DEBUG_YY_AUTO_COMPLETE
1928     for (int q = 0; q < depth; ++q) printf(" ");
1929     printf("(%d) No sub suggestion.\n", depth);
1930     #endif
1931     return "";
1932     } else if (expectedSymbols.size() > 1) {
1933     #if DEBUG_YY_AUTO_COMPLETE
1934     for (int q = 0; q < depth; ++q) printf(" ");
1935     printf("(%d) Multiple sub possibilities (before expansion):", depth);
1936     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1937     it != expectedSymbols.end(); ++it)
1938     {
1939     printf(" %s (..%s)", it->first.c_str(), it->second.nextExpectedChars.c_str());
1940     }
1941     printf("\n");
1942     #endif
1943     // check if any of the possibilites is a non-terminal symbol, if so, we
1944     // have no way for auto completion at this point
1945     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1946     it != expectedSymbols.end(); ++it)
1947     {
1948     if (!it->second.isTerminalSymbol) {
1949     #if DEBUG_YY_AUTO_COMPLETE
1950     for (int q = 0; q < depth; ++q) printf(" ");
1951     printf("(%d) Non-terminal exists. Stop.", depth);
1952     #endif
1953     return "";
1954     }
1955     }
1956     #if 0 // commented out for now, since practically irrelevant and VERY slow ...
1957     // all possibilities are terminal symbols, so expand all possiblities to
1958     // maximum length with a recursive call for each possibility
1959     for (std::map<String,BisonSymbolInfo>::iterator it = expectedSymbols.begin();
1960     it != expectedSymbols.end(); ++it)
1961     {
1962     if (it->second.nextExpectedChars.empty() || !it->second.isTerminalSymbol) continue;
1963     // parse forward with this particular suggested auto completion
1964     std::vector<YYTYPE_INT16> stackCopy = stack;
1965     yyValidCharacters(stackCopy, it->second.nextExpectedChars, false);
1966     // detect endless recursion
1967     if (history.count(stackCopy)) continue;
1968     history.insert(stackCopy);
1969     // recurse and return the total possible auto completion for this
1970     // grammar tree branch
1971     it->second.nextExpectedChars += yyAutoComplete(stackCopy, history, depth + 1);
1972     }
1973     #endif
1974     // try to find the longest common string all possibilities start with
1975     // (from the left)
1976     String sCommon;
1977     for (int i = 0; true; ++i) {
1978     char c;
1979     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1980     it != expectedSymbols.end(); ++it)
1981     {
1982     if (i >= it->second.nextExpectedChars.size())
1983     goto commonSearchEndLabel;
1984     if (it == expectedSymbols.begin())
1985     c = it->second.nextExpectedChars[i];
1986     if (c != it->second.nextExpectedChars[i])
1987     goto commonSearchEndLabel;
1988     if (it == --expectedSymbols.end())
1989     sCommon += c;
1990     }
1991     }
1992     commonSearchEndLabel:
1993     #if DEBUG_YY_AUTO_COMPLETE
1994     for (int q = 0; q < depth; ++q) printf(" ");
1995     printf("(%d) Multiple sub possibilities (after expansion):", depth);
1996     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1997     it != expectedSymbols.end(); ++it)
1998     {
1999     printf(" %s (..%s)", it->first.c_str(), it->second.nextExpectedChars.c_str());
2000     }
2001     printf("\n");
2002     for (int q = 0; q < depth; ++q) printf(" ");
2003     printf("(%d) Common sub possibility: '%s'\n", depth, sCommon.c_str());
2004     #endif
2005     return sCommon;
2006     }
2007     return ""; // just pro forma, should never happen though
2008     }
2009    
2010     /**
2011     * Just a convenience wrapper on top of the actual yyAutoComplete()
2012 schoenebeck 2534 * implementation. See its description above for details.
2013 schoenebeck 2523 */
2014     static String yyAutoComplete(std::vector<YYTYPE_INT16>& stack) {
2015     YYStackHistory history;
2016     return yyAutoComplete(stack, history);
2017     }
2018    
2019 persson 1765 namespace LinuxSampler {
2020    
2021 schoenebeck 2516 #define DEBUG_SHELL_INTERACTION 0
2022    
2023     /**
2024 schoenebeck 2524 * If LSCP shell mode is enabled for the respective LSCP client connection, then
2025 schoenebeck 2523 * this function is called on every new byte received from that client. It will
2026 schoenebeck 2525 * check the current total input line and reply to the LSCP shell with a
2027     * specially crafted string, which allows the shell to provide colored syntax
2028     * highlighting and potential auto completion in the shell.
2029 schoenebeck 2516 *
2030     * It also performs auto correction of obvious & trivial syntax mistakes if
2031     * requested.
2032 schoenebeck 2523 *
2033     * The return value of this function will be sent to the client. It contains one
2034 schoenebeck 2525 * line specially formatted for the LSCP shell application, which can easily be
2035     * processed by the client/shell for extracting its necessary informations like
2036     * which part of the current command line is syntactically correct, which part
2037     * is incorrect, what could be auto completed right now, etc. So all the heavy
2038     * grammar evaluation tasks are peformed by the LSCP server for the LSCP shell
2039     * application (which is desgined as a thin client), so the LSCP shell
2040     * application will only have to show the results of the LSCP server's
2041     * evaluation to the user on the screen.
2042 schoenebeck 2523 *
2043 schoenebeck 2528 * @param line - the current command line to be evaluated by LSCP parser
2044     * @param param = reentrant parser session parameters
2045     * @param possibilities - whether all possibilities shall be shown
2046 schoenebeck 2523 * @returns LSCP shell response line to be returned to the client
2047 schoenebeck 2516 */
2048 schoenebeck 2528 String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param, bool possibilities) {
2049 schoenebeck 2516 // first, determine how many characters (starting from the left) of the
2050 schoenebeck 2523 // given input line are already syntactically correct
2051 schoenebeck 2515 std::vector<YYTYPE_INT16> stack;
2052 schoenebeck 2516 stack.push_back(0); // every Bison symbol stack starts with state zero
2053     String l = line + '\n'; // '\n' to pretend ENTER as if the line was now complete
2054     int n = yyValidCharacters(stack, l, param->bShellAutoCorrect);
2055    
2056     // if auto correction is enabled, apply the auto corrected string to
2057     // intput/output string 'line'
2058     if (param->bShellAutoCorrect) {
2059     int nMin = (n < line.length()) ? n : line.length();
2060     line.replace(0, nMin, l.substr(0, nMin));
2061     }
2062    
2063 schoenebeck 2531 size_t cursorPos = line.size() + param->iCursorOffset;
2064     if (cursorPos < 0) cursorPos = 0;
2065    
2066 schoenebeck 2516 // generate an info string that will be sent to the LSCP shell for letting
2067     // it know which part is correct, which one is wrong, where is the cursor, etc.
2068 schoenebeck 2515 String result = line;
2069     result.insert(n <= result.length() ? n : result.length(), LSCP_SHK_GOOD_FRONT);
2070 schoenebeck 2531 result.insert(cursorPos <= n ? cursorPos : cursorPos + String(LSCP_SHK_GOOD_FRONT).length(), LSCP_SHK_CURSOR);
2071 schoenebeck 2515 int code = (n > line.length()) ? LSCP_SHU_COMPLETE : (n < line.length()) ?
2072     LSCP_SHU_SYNTAX_ERR : LSCP_SHU_INCOMPLETE;
2073 schoenebeck 2531 result = "SHU:" + ToString(code) + ":" + result;
2074 schoenebeck 2515 //if (n > line.length()) result += " [OK]";
2075 schoenebeck 2516
2076     // get a clean parser stack to the last valid parse position
2077     // (due to the appended '\n' character above, and on syntax errors, the
2078 schoenebeck 2525 // symbol stack might be in undesired, i.e. reduced state)
2079 schoenebeck 2516 stack.clear();
2080     stack.push_back(0); // every Bison symbol stack starts with state zero
2081     l = line.substr(0, n);
2082     if (!l.empty()) yyValidCharacters(stack, l, param->bShellAutoCorrect);
2083    
2084     // generate auto completion suggestion (based on the current parser stack)
2085 schoenebeck 2528 std::vector<YYTYPE_INT16> stackCopy = stack; // make a copy, since yyAutoComplete() might alter the stack
2086     String sSuggestion = yyAutoComplete(stackCopy);
2087 schoenebeck 2523 if (!sSuggestion.empty()) result += LSCP_SHK_SUGGEST_BACK + sSuggestion;
2088 schoenebeck 2516
2089 schoenebeck 2534 if (possibilities) {
2090     // append all possible terminals and non-terminals according to
2091     // current parser state
2092     std::map<String,BisonSymbolInfo> expectedSymbols;
2093     walkAndFillExpectedSymbols(stack, expectedSymbols);
2094 schoenebeck 2528
2095     // pretend to LSCP shell that the following terminal symbols were
2096     // non-terminal symbols (since they are not human visible for auto
2097     // completion on the shell's screen)
2098     std::set<String> specialNonTerminals;
2099     specialNonTerminals.insert("SP");
2100     specialNonTerminals.insert("CR");
2101     specialNonTerminals.insert("LF");
2102    
2103     String sPossibilities;
2104     int iNonTerminals = 0;
2105     int iTerminals = 0;
2106     for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
2107     it != expectedSymbols.end(); ++it)
2108     {
2109     if (!sPossibilities.empty()) sPossibilities += " | ";
2110     if (it->second.isTerminalSymbol && !specialNonTerminals.count(it->first)) {
2111     sPossibilities += it->first;
2112     iTerminals++;
2113     } else {
2114     sPossibilities += "<" + it->first + ">";
2115     iNonTerminals++;
2116     }
2117     }
2118     if (!sPossibilities.empty() && (iNonTerminals || iTerminals > 1)) {
2119     result += LSCP_SHK_POSSIBILITIES_BACK + sPossibilities;
2120     }
2121     }
2122    
2123 schoenebeck 2516 #if DEBUG_SHELL_INTERACTION
2124 schoenebeck 2515 printf("%s\n", result.c_str());
2125     #endif
2126 schoenebeck 2516
2127 schoenebeck 2515 return result;
2128     }
2129    
2130 schoenebeck 35 /**
2131 schoenebeck 219 * Clears input buffer.
2132 schoenebeck 35 */
2133     void restart(yyparse_param_t* pparam, int& yychar) {
2134 schoenebeck 219 bytes = 0;
2135     ptr = 0;
2136 schoenebeck 1252 sLastError = "";
2137 schoenebeck 2510 sParsed = "";
2138 schoenebeck 35 }
2139 persson 1765
2140     }

  ViewVC Help
Powered by ViewVC