/[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 4002 - (hide annotations) (download)
Mon Nov 22 20:06:26 2021 UTC (2 years, 4 months ago) by schoenebeck
File size: 114236 byte(s)
* Fix compiler error with release tarball if no Bison installed
  (SVN version still requires Flex and Bison being installed).

* Bumped version (2.2.0.svn7).

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

  ViewVC Help
Powered by ViewVC