/[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 2523 - (hide annotations) (download)
Sun Feb 23 19:10:36 2014 UTC (10 years, 1 month ago) by schoenebeck
File size: 108811 byte(s)
* LSCP Server: Fixed bug in LSCP grammar definition which caused a
  statement like "GET SERVER INFOasdf\n" to be accepted as valid
  statement (was so far practically irrelevant, however it caused
  problems with the following new LSCP shell's auto completion
  feature).
* LSCP shell: improvement of auto completion feature, which now
  not only resolves the next LSCP command token, but the longest,
  unique sequence of LSCP commands expected next. Accordingly it
  can now auto complete an entire line.
* Bumped version (1.0.0.svn33).

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

  ViewVC Help
Powered by ViewVC