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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1345 by iliev, Thu Sep 13 21:46:25 2007 UTC revision 2516 by schoenebeck, Thu Feb 6 21:11:23 2014 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 - 2007 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2014 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 34  Line 34 
34  #include "lscpparser.h"  #include "lscpparser.h"
35  #include "lscpserver.h"  #include "lscpserver.h"
36  #include "lscpevent.h"  #include "lscpevent.h"
37    #include "lscpsymbols.h"
38    #include <algorithm>
39    #include "lscp.h"
40    
41    namespace LinuxSampler {
42    
43  // to save us typing work in the rules action definitions  // to save us typing work in the rules action definitions
44  #define LSCPSERVER ((yyparse_param_t*) yyparse_param)->pServer  #define LSCPSERVER ((yyparse_param_t*) yyparse_param)->pServer
45  #define SESSION_PARAM ((yyparse_param_t*) yyparse_param)  #define SESSION_PARAM ((yyparse_param_t*) yyparse_param)
46  #define INCREMENT_LINE { SESSION_PARAM->iLine++; SESSION_PARAM->iColumn = 0; }  #define INCREMENT_LINE { SESSION_PARAM->iLine++; SESSION_PARAM->iColumn = 0; sParsed.clear(); }
47    
48  // clears input buffer  // clears input buffer
49  void restart(yyparse_param_t* pparam, int& yychar);  void restart(yyparse_param_t* pparam, int& yychar);
50  #define RESTART restart((yyparse_param_t*) YYPARSE_PARAM, yychar)  #define RESTART restart((yyparse_param_t*) YYPARSE_PARAM, yychar)
51    
 // we provide our own version of yyerror() so we don't have to link against the yacc library  
 void yyerror(const char* s);  
   
52  static char buf[1024]; // input buffer to feed the parser with new characters  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  static int bytes = 0;  // current number of characters in the input buffer
54  static int ptr   = 0;  // current position in the input buffer  static int ptr   = 0;  // current position in the input buffer
55  static String sLastError; // error message of the last error occured  static String sLastError; // error message of the last error occured
56    static String sParsed; ///< Characters of current line which have already been shifted (consumed/parsed) by the parser.
57    
58  // external reference to the function which actually reads from the socket  // external reference to the function which actually reads from the socket
59  extern int GetLSCPCommand( void *buf, int max_size);  extern int GetLSCPCommand( void *buf, int max_size);
# Line 64  inline bool isExtendedAsciiChar(const ch Line 67  inline bool isExtendedAsciiChar(const ch
67      return (c < 0);      return (c < 0);
68  }  }
69    
70    // 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  // custom scanner function which reads from the socket  // custom scanner function which reads from the socket
81  // (bison expects it to return the numerical ID of the next  // (bison expects it to return the numerical ID of the next
82  // "recognized token" from the input stream)  // "recognized token" from the input stream)
# Line 81  int yylex(YYSTYPE* yylval) { Line 94  int yylex(YYSTYPE* yylval) {
94      const char c = buf[ptr++];      const char c = buf[ptr++];
95      // increment current reading position (just for verbosity / messages)      // increment current reading position (just for verbosity / messages)
96      GetCurrentYaccSession()->iColumn++;      GetCurrentYaccSession()->iColumn++;
97        sParsed += c;
98      // we have to handle "normal" and "extended" ASCII characters separately      // we have to handle "normal" and "extended" ASCII characters separately
99      if (isExtendedAsciiChar(c)) {      if (isExtendedAsciiChar(c)) {
100          // workaround for characters with ASCII code higher than 127          // workaround for characters with ASCII code higher than 127
# Line 101  int octalsToNumber(char oct_digit0, char Line 115  int octalsToNumber(char oct_digit0, char
115      return atoi(d2)*8*8 + atoi(d1)*8 + atoi(d0);      return atoi(d2)*8*8 + atoi(d1)*8 + atoi(d0);
116  }  }
117    
 int hexToNumber(char hex_digit) {  
     switch (hex_digit) {  
         case '0': return 0;  
         case '1': return 1;  
         case '2': return 2;  
         case '3': return 3;  
         case '4': return 4;  
         case '5': return 5;  
         case '6': return 6;  
         case '7': return 7;  
         case '8': return 8;  
         case '9': return 9;  
         // grammar rule 'digit_hex' already forced lower case  
         case 'a': return 10;  
         case 'b': return 11;  
         case 'c': return 12;  
         case 'd': return 13;  
         case 'e': return 14;  
         case 'f': return 15;  
         default:  return 0;  
     }  
118  }  }
119    
120  int hexsToNumber(char hex_digit0, char hex_digit1 = '0') {  using namespace LinuxSampler;
121      return hexToNumber(hex_digit1)*16 + hexToNumber(hex_digit0);  
122    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  %}  %}
176    
177  // reentrant parser  // reentrant parser
178  %pure_parser  %pure-parser
179    
180    %parse-param {void* yyparse_param}
181    
182    // 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  // tell bison to spit out verbose syntax error messages  // tell bison to spit out verbose syntax error messages
192  %error-verbose  %error-verbose
193    
194  %token <Char> EXT_ASCII_CHAR  %token <Char> EXT_ASCII_CHAR
195    
196  %type <Char> char char_base digit digit_oct digit_hex escape_seq escape_seq_octal escape_seq_hex  %type <Char> char char_base alpha_char digit digit_oct digit_hex escape_seq escape_seq_octal escape_seq_hex
197  %type <Dotnum> dotnum volume_value boolean  %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 midi_input_channel_index midi_input_port_index midi_map midi_bank midi_prog midi_ctrl  %type <Number> number sampler_channel instrument_index fx_send_id audio_channel_index device_index effect_index effect_instance effect_chain chain_pos input_control midi_input_channel_index midi_input_port_index midi_map midi_bank midi_prog midi_ctrl
199  %type <String> string string_escaped text text_escaped textval_escaped stringval stringval_escaped digits param_val_list param_val query_val filename db_path map_name entry_name fx_send_name engine_name command add_instruction create_instruction destroy_instruction get_instruction list_instruction load_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  %type <String> string string_escaped text text_escaped text_escaped_base stringval stringval_escaped digits param_val_list param_val query_val filename module effect_system db_path map_name entry_name fx_send_name effect_name engine_name command add_instruction create_instruction destroy_instruction get_instruction list_instruction load_instruction send_instruction set_chan_instruction load_instr_args load_engine_args audio_output_type_name midi_input_type_name remove_instruction unmap_instruction set_instruction subscribe_event unsubscribe_event map_instruction reset_instruction clear_instruction find_instruction move_instruction copy_instruction scan_mode edit_instruction format_instruction append_instruction insert_instruction
200  %type <FillResponse> buffer_size_type  %type <FillResponse> buffer_size_type
201  %type <KeyValList> key_val_list query_val_list  %type <KeyValList> key_val_list query_val_list
202  %type <LoadMode> instr_load_mode  %type <LoadMode> instr_load_mode
203  %type <Bool> modal_arg  %type <Bool> modal_arg
204  %type <UniversalPath> path path_base  %type <UniversalPath> path path_base path_prefix path_body
205    
206  %start input  %start input
207    
# Line 198  command               :  ADD SP add_inst Line 253  command               :  ADD SP add_inst
253                        |  MOVE SP move_instruction              { $$ = $3;                                                }                        |  MOVE SP move_instruction              { $$ = $3;                                                }
254                        |  COPY SP copy_instruction              { $$ = $3;                                                }                        |  COPY SP copy_instruction              { $$ = $3;                                                }
255                        |  EDIT SP edit_instruction              { $$ = $3;                                                }                        |  EDIT SP edit_instruction              { $$ = $3;                                                }
256                          |  FORMAT SP format_instruction          { $$ = $3;                                                }
257                          |  SEND SP send_instruction              { $$ = $3;                                                }
258                          |  APPEND SP append_instruction          { $$ = $3;                                                }
259                          |  INSERT SP insert_instruction          { $$ = $3;                                                }
260                        |  RESET                                 { $$ = LSCPSERVER->ResetSampler();                        }                        |  RESET                                 { $$ = LSCPSERVER->ResetSampler();                        }
261                        |  QUIT                                  { LSCPSERVER->AnswerClient("Bye!\r\n"); return LSCP_QUIT; }                        |  QUIT                                  { LSCPSERVER->AnswerClient("Bye!\r\n"); return LSCP_QUIT; }
262                        ;                        ;
263    
264  add_instruction       :  CHANNEL                               { $$ = LSCPSERVER->AddChannel();                  }  add_instruction       :  CHANNEL                               { $$ = LSCPSERVER->AddChannel();                  }
265                          |  CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index                           { $$ = LSCPSERVER->AddChannelMidiInput($5,$7);    }
266                          |  CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index  { $$ = LSCPSERVER->AddChannelMidiInput($5,$7,$9); }
267                        |  DB_INSTRUMENT_DIRECTORY SP db_path    { $$ = LSCPSERVER->AddDbInstrumentDirectory($3);  }                        |  DB_INSTRUMENT_DIRECTORY SP db_path    { $$ = LSCPSERVER->AddDbInstrumentDirectory($3);  }
268                        |  DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP db_path SP filename         { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true);  }                        |  DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP db_path SP filename                        { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true);        }
269                        |  DB_INSTRUMENTS SP scan_mode SP db_path SP filename                      { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7);        }                        |  DB_INSTRUMENTS SP NON_MODAL SP scan_mode SP FILE_AS_DIR SP db_path SP filename         { $$ = LSCPSERVER->AddDbInstruments($5,$9,$11, true, true); }
270                        |  DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename                      { $$ = LSCPSERVER->AddDbInstruments($5,$7, -1, true); }                        |  DB_INSTRUMENTS SP scan_mode SP db_path SP filename                                     { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7);              }
271                        |  DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename SP instrument_index  { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true);  }                        |  DB_INSTRUMENTS SP scan_mode SP FILE_AS_DIR SP db_path SP filename                      { $$ = LSCPSERVER->AddDbInstruments($3,$7,$9, false, true); }
272                        |  DB_INSTRUMENTS SP db_path SP filename                                   { $$ = LSCPSERVER->AddDbInstruments($3,$5);           }                        |  DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename                                     { $$ = LSCPSERVER->AddDbInstruments($5,$7, -1, true);       }
273                        |  DB_INSTRUMENTS SP db_path SP filename SP instrument_index               { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7);        }                        |  DB_INSTRUMENTS SP NON_MODAL SP db_path SP filename SP instrument_index                 { $$ = LSCPSERVER->AddDbInstruments($5,$7,$9, true);        }
274                          |  DB_INSTRUMENTS SP db_path SP filename                                                  { $$ = LSCPSERVER->AddDbInstruments($3,$5);                 }
275                          |  DB_INSTRUMENTS SP db_path SP filename SP instrument_index                              { $$ = LSCPSERVER->AddDbInstruments($3,$5,$7);              }
276                        |  MIDI_INSTRUMENT_MAP                   { $$ = LSCPSERVER->AddMidiInstrumentMap();                }                        |  MIDI_INSTRUMENT_MAP                   { $$ = LSCPSERVER->AddMidiInstrumentMap();                }
277                        |  MIDI_INSTRUMENT_MAP SP map_name       { $$ = LSCPSERVER->AddMidiInstrumentMap($3);              }                        |  MIDI_INSTRUMENT_MAP SP map_name       { $$ = LSCPSERVER->AddMidiInstrumentMap($3);              }
278                          |  SEND_EFFECT_CHAIN SP device_index     { $$ = LSCPSERVER->AddSendEffectChain($3);                }
279                        ;                        ;
280    
281  subscribe_event       :  AUDIO_OUTPUT_DEVICE_COUNT             { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_count);   }  subscribe_event       :  AUDIO_OUTPUT_DEVICE_COUNT             { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_audio_device_count);   }
# Line 219  subscribe_event       :  AUDIO_OUTPUT_DE Line 283  subscribe_event       :  AUDIO_OUTPUT_DE
283                        |  MIDI_INPUT_DEVICE_COUNT               { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_count);    }                        |  MIDI_INPUT_DEVICE_COUNT               { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_count);    }
284                        |  MIDI_INPUT_DEVICE_INFO                { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_info);     }                        |  MIDI_INPUT_DEVICE_INFO                { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_midi_device_info);     }
285                        |  CHANNEL_COUNT                         { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_count);        }                        |  CHANNEL_COUNT                         { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_count);        }
286                          |  CHANNEL_MIDI                          { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_channel_midi);         }
287                          |  DEVICE_MIDI                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_device_midi);          }
288                        |  VOICE_COUNT                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_voice_count);          }                        |  VOICE_COUNT                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_voice_count);          }
289                        |  STREAM_COUNT                          { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_stream_count);         }                        |  STREAM_COUNT                          { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_stream_count);         }
290                        |  BUFFER_FILL                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_buffer_fill);          }                        |  BUFFER_FILL                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_buffer_fill);          }
# Line 235  subscribe_event       :  AUDIO_OUTPUT_DE Line 301  subscribe_event       :  AUDIO_OUTPUT_DE
301                        |  DB_INSTRUMENT_INFO                    { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_info);        }                        |  DB_INSTRUMENT_INFO                    { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instr_info);        }
302                        |  DB_INSTRUMENTS_JOB_INFO               { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instrs_job_info);   }                        |  DB_INSTRUMENTS_JOB_INFO               { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_db_instrs_job_info);   }
303                        |  MISCELLANEOUS                         { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_misc);                 }                        |  MISCELLANEOUS                         { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_misc);                 }
304                          |  TOTAL_STREAM_COUNT                    { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_stream_count);   }
305                        |  TOTAL_VOICE_COUNT                     { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_voice_count);    }                        |  TOTAL_VOICE_COUNT                     { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_total_voice_count);    }
306                        |  GLOBAL_INFO                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_global_info);          }                        |  GLOBAL_INFO                           { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_global_info);          }
307                          |  EFFECT_INSTANCE_COUNT                 { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_count);    }
308                          |  EFFECT_INSTANCE_INFO                  { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_fx_instance_info);     }
309                          |  SEND_EFFECT_CHAIN_COUNT               { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_count);  }
310                          |  SEND_EFFECT_CHAIN_INFO                { $$ = LSCPSERVER->SubscribeNotification(LSCPEvent::event_send_fx_chain_info);   }
311                        ;                        ;
312    
313  unsubscribe_event     :  AUDIO_OUTPUT_DEVICE_COUNT             { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_count);   }  unsubscribe_event     :  AUDIO_OUTPUT_DEVICE_COUNT             { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_audio_device_count);   }
# Line 244  unsubscribe_event     :  AUDIO_OUTPUT_DE Line 315  unsubscribe_event     :  AUDIO_OUTPUT_DE
315                        |  MIDI_INPUT_DEVICE_COUNT               { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_count);    }                        |  MIDI_INPUT_DEVICE_COUNT               { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_count);    }
316                        |  MIDI_INPUT_DEVICE_INFO                { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_info);     }                        |  MIDI_INPUT_DEVICE_INFO                { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_midi_device_info);     }
317                        |  CHANNEL_COUNT                         { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_count);        }                        |  CHANNEL_COUNT                         { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_count);        }
318                          |  CHANNEL_MIDI                          { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_channel_midi);         }
319                          |  DEVICE_MIDI                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_device_midi);          }
320                        |  VOICE_COUNT                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_voice_count);          }                        |  VOICE_COUNT                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_voice_count);          }
321                        |  STREAM_COUNT                          { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_stream_count);         }                        |  STREAM_COUNT                          { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_stream_count);         }
322                        |  BUFFER_FILL                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_buffer_fill);          }                        |  BUFFER_FILL                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_buffer_fill);          }
# Line 260  unsubscribe_event     :  AUDIO_OUTPUT_DE Line 333  unsubscribe_event     :  AUDIO_OUTPUT_DE
333                        |  DB_INSTRUMENT_INFO                    { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_info);        }                        |  DB_INSTRUMENT_INFO                    { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instr_info);        }
334                        |  DB_INSTRUMENTS_JOB_INFO               { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instrs_job_info);   }                        |  DB_INSTRUMENTS_JOB_INFO               { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_db_instrs_job_info);   }
335                        |  MISCELLANEOUS                         { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_misc);                 }                        |  MISCELLANEOUS                         { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_misc);                 }
336                          |  TOTAL_STREAM_COUNT                    { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_stream_count);   }
337                        |  TOTAL_VOICE_COUNT                     { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_voice_count);    }                        |  TOTAL_VOICE_COUNT                     { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_total_voice_count);    }
338                        |  GLOBAL_INFO                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_global_info);          }                        |  GLOBAL_INFO                           { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_global_info);          }
339                          |  EFFECT_INSTANCE_COUNT                 { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_count);    }
340                          |  EFFECT_INSTANCE_INFO                  { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_fx_instance_info);     }
341                          |  SEND_EFFECT_CHAIN_COUNT               { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_count);  }
342                          |  SEND_EFFECT_CHAIN_INFO                { $$ = LSCPSERVER->UnsubscribeNotification(LSCPEvent::event_send_fx_chain_info);   }
343                        ;                        ;
344    
345  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::VOID,"",$3); }  map_instruction       :  MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,MidiInstrumentMapper::DONTCARE,"",$3); }
346                        |  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); }                        |  MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,$18,"",$3); }
347                        |  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::VOID,$18,$3); }                        |  MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP entry_name { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,MidiInstrumentMapper::DONTCARE,$18,$3); }
348                        |  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); }                        |  MIDI_INSTRUMENT SP modal_arg midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode SP entry_name { $$ = LSCPSERVER->AddOrReplaceMIDIInstrumentMapping($4,$6,$8,$10,$12,$14,$16,$18,$20,$3); }
349                        ;                        ;
350    
# Line 274  unmap_instruction     :  MIDI_INSTRUMENT Line 352  unmap_instruction     :  MIDI_INSTRUMENT
352                        ;                        ;
353    
354  remove_instruction    :  CHANNEL SP sampler_channel                   { $$ = LSCPSERVER->RemoveChannel($3);                      }  remove_instruction    :  CHANNEL SP sampler_channel                   { $$ = LSCPSERVER->RemoveChannel($3);                      }
355                          |  CHANNEL SP MIDI_INPUT SP sampler_channel                                           { $$ = LSCPSERVER->RemoveChannelMidiInput($5);       }
356                          |  CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index                           { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7);    }
357                          |  CHANNEL SP MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index  { $$ = LSCPSERVER->RemoveChannelMidiInput($5,$7,$9); }
358                        |  MIDI_INSTRUMENT_MAP SP midi_map              { $$ = LSCPSERVER->RemoveMidiInstrumentMap($3);            }                        |  MIDI_INSTRUMENT_MAP SP midi_map              { $$ = LSCPSERVER->RemoveMidiInstrumentMap($3);            }
359                        |  MIDI_INSTRUMENT_MAP SP ALL                   { $$ = LSCPSERVER->RemoveAllMidiInstrumentMaps();          }                        |  MIDI_INSTRUMENT_MAP SP ALL                   { $$ = LSCPSERVER->RemoveAllMidiInstrumentMaps();          }
360                          |  SEND_EFFECT_CHAIN SP device_index SP effect_chain  { $$ = LSCPSERVER->RemoveSendEffectChain($3,$5);     }
361                          |  SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP chain_pos  { $$ = LSCPSERVER->RemoveSendEffectChainEffect($5,$7,$9); }
362                          |  FX_SEND SP EFFECT SP sampler_channel SP fx_send_id  { $$ = LSCPSERVER->SetFxSendEffect($5,$7,-1,-1);    }
363                        |  DB_INSTRUMENT_DIRECTORY SP FORCE SP db_path  { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($5, true);  }                        |  DB_INSTRUMENT_DIRECTORY SP FORCE SP db_path  { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($5, true);  }
364                        |  DB_INSTRUMENT_DIRECTORY SP db_path           { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($3);        }                        |  DB_INSTRUMENT_DIRECTORY SP db_path           { $$ = LSCPSERVER->RemoveDbInstrumentDirectory($3);        }
365                        |  DB_INSTRUMENT SP db_path                     { $$ = LSCPSERVER->RemoveDbInstrument($3);                 }                        |  DB_INSTRUMENT SP db_path                     { $$ = LSCPSERVER->RemoveDbInstrument($3);                 }
366                        ;                        ;
367    
368  get_instruction       :  AVAILABLE_ENGINES                                                          { $$ = LSCPSERVER->GetAvailableEngines();                          }  get_instruction       :  AVAILABLE_ENGINES                                                          { $$ = LSCPSERVER->GetAvailableEngines();                          }
369                          |  AVAILABLE_EFFECTS                                                          { $$ = LSCPSERVER->GetAvailableEffects();                          }
370                          |  EFFECT_INSTANCES                                                           { $$ = LSCPSERVER->GetEffectInstances();                           }
371                          |  EFFECT SP INFO SP effect_index                                             { $$ = LSCPSERVER->GetEffectInfo($5);                              }
372                          |  EFFECT_INSTANCE SP INFO SP effect_instance                                 { $$ = LSCPSERVER->GetEffectInstanceInfo($5);                      }
373                          |  EFFECT_INSTANCE_INPUT_CONTROL SP INFO SP effect_instance SP input_control  { $$ = LSCPSERVER->GetEffectInstanceInputControlInfo($5,$7);       }
374                          |  SEND_EFFECT_CHAINS SP device_index                                         { $$ = LSCPSERVER->GetSendEffectChains($3);                        }
375                          |  SEND_EFFECT_CHAIN SP INFO SP device_index SP effect_chain                  { $$ = LSCPSERVER->GetSendEffectChainInfo($5,$7);                  }
376                        |  AVAILABLE_MIDI_INPUT_DRIVERS                                               { $$ = LSCPSERVER->GetAvailableMidiInputDrivers();                 }                        |  AVAILABLE_MIDI_INPUT_DRIVERS                                               { $$ = LSCPSERVER->GetAvailableMidiInputDrivers();                 }
377                        |  MIDI_INPUT_DRIVER SP INFO SP string                                        { $$ = LSCPSERVER->GetMidiInputDriverInfo($5);                     }                        |  MIDI_INPUT_DRIVER SP INFO SP string                                        { $$ = LSCPSERVER->GetMidiInputDriverInfo($5);                     }
378                        |  MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string                    { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7);        }                        |  MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string                    { $$ = LSCPSERVER->GetMidiInputDriverParameterInfo($5, $7);        }
# Line 305  get_instruction       :  AVAILABLE_ENGIN Line 396  get_instruction       :  AVAILABLE_ENGIN
396                        |  CHANNEL SP VOICE_COUNT SP sampler_channel                                  { $$ = LSCPSERVER->GetVoiceCount($5);                              }                        |  CHANNEL SP VOICE_COUNT SP sampler_channel                                  { $$ = LSCPSERVER->GetVoiceCount($5);                              }
397                        |  ENGINE SP INFO SP engine_name                                              { $$ = LSCPSERVER->GetEngineInfo($5);                              }                        |  ENGINE SP INFO SP engine_name                                              { $$ = LSCPSERVER->GetEngineInfo($5);                              }
398                        |  SERVER SP INFO                                                             { $$ = LSCPSERVER->GetServerInfo();                                }                        |  SERVER SP INFO                                                             { $$ = LSCPSERVER->GetServerInfo();                                }
399                          |  TOTAL_STREAM_COUNT                                                         { $$ = LSCPSERVER->GetTotalStreamCount();                           }
400                        |  TOTAL_VOICE_COUNT                                                          { $$ = LSCPSERVER->GetTotalVoiceCount();                           }                        |  TOTAL_VOICE_COUNT                                                          { $$ = LSCPSERVER->GetTotalVoiceCount();                           }
401                        |  TOTAL_VOICE_COUNT_MAX                                                      { $$ = LSCPSERVER->GetTotalVoiceCountMax();                        }                        |  TOTAL_VOICE_COUNT_MAX                                                      { $$ = LSCPSERVER->GetTotalVoiceCountMax();                        }
402                        |  MIDI_INSTRUMENTS SP midi_map                                               { $$ = LSCPSERVER->GetMidiInstrumentMappings($3);                  }                        |  MIDI_INSTRUMENTS SP midi_map                                               { $$ = LSCPSERVER->GetMidiInstrumentMappings($3);                  }
# Line 322  get_instruction       :  AVAILABLE_ENGIN Line 414  get_instruction       :  AVAILABLE_ENGIN
414                        |  DB_INSTRUMENT SP INFO SP db_path                                           { $$ = LSCPSERVER->GetDbInstrumentInfo($5);                        }                        |  DB_INSTRUMENT SP INFO SP db_path                                           { $$ = LSCPSERVER->GetDbInstrumentInfo($5);                        }
415                        |  DB_INSTRUMENTS_JOB SP INFO SP number                                       { $$ = LSCPSERVER->GetDbInstrumentsJobInfo($5);                    }                        |  DB_INSTRUMENTS_JOB SP INFO SP number                                       { $$ = LSCPSERVER->GetDbInstrumentsJobInfo($5);                    }
416                        |  VOLUME                                                                     { $$ = LSCPSERVER->GetGlobalVolume();                              }                        |  VOLUME                                                                     { $$ = LSCPSERVER->GetGlobalVolume();                              }
417                          |  VOICES                                                                     { $$ = LSCPSERVER->GetGlobalMaxVoices();                           }
418                          |  STREAMS                                                                    { $$ = LSCPSERVER->GetGlobalMaxStreams();                          }
419                          |  FILE SP INSTRUMENTS SP filename                                            { $$ = LSCPSERVER->GetFileInstruments($5);                         }
420                          |  FILE SP INSTRUMENT SP INFO SP filename SP instrument_index                 { $$ = LSCPSERVER->GetFileInstrumentInfo($7,$9);                   }
421                        ;                        ;
422    
423  set_instruction       :  AUDIO_OUTPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list             { $$ = LSCPSERVER->SetAudioOutputDeviceParameter($3, $5, $7);      }  set_instruction       :  AUDIO_OUTPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list             { $$ = LSCPSERVER->SetAudioOutputDeviceParameter($3, $5, $7);      }
# Line 329  set_instruction       :  AUDIO_OUTPUT_DE Line 425  set_instruction       :  AUDIO_OUTPUT_DE
425                        |  MIDI_INPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list               { $$ = LSCPSERVER->SetMidiInputDeviceParameter($3, $5, $7);        }                        |  MIDI_INPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list               { $$ = LSCPSERVER->SetMidiInputDeviceParameter($3, $5, $7);        }
426                        |  MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' NONE                 { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, "");      }                        |  MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' NONE                 { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, "");      }
427                        |  MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' param_val_list       { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, $9);      }                        |  MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' param_val_list       { $$ = LSCPSERVER->SetMidiInputPortParameter($3, $5, $7, $9);      }
428                          |  EFFECT_INSTANCE_INPUT_CONTROL SP VALUE SP effect_instance SP input_control SP control_value  { $$ = LSCPSERVER->SetEffectInstanceInputControlValue($5, $7, $9); }
429                        |  CHANNEL SP set_chan_instruction                                                  { $$ = $3;                                                         }                        |  CHANNEL SP set_chan_instruction                                                  { $$ = $3;                                                         }
430                        |  MIDI_INSTRUMENT_MAP SP NAME SP midi_map SP map_name                              { $$ = LSCPSERVER->SetMidiInstrumentMapName($5, $7);               }                        |  MIDI_INSTRUMENT_MAP SP NAME SP midi_map SP map_name                              { $$ = LSCPSERVER->SetMidiInstrumentMapName($5, $7);               }
431                        |  FX_SEND SP NAME SP sampler_channel SP fx_send_id SP fx_send_name                 { $$ = LSCPSERVER->SetFxSendName($5,$7,$9);                        }                        |  FX_SEND SP NAME SP sampler_channel SP fx_send_id SP fx_send_name                 { $$ = LSCPSERVER->SetFxSendName($5,$7,$9);                        }
432                        |  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); }                        |  FX_SEND SP AUDIO_OUTPUT_CHANNEL SP sampler_channel SP fx_send_id SP audio_channel_index SP audio_channel_index  { $$ = LSCPSERVER->SetFxSendAudioOutputChannel($5,$7,$9,$11); }
433                        |  FX_SEND SP MIDI_CONTROLLER SP sampler_channel SP fx_send_id SP midi_ctrl         { $$ = LSCPSERVER->SetFxSendMidiController($5,$7,$9);              }                        |  FX_SEND SP MIDI_CONTROLLER SP sampler_channel SP fx_send_id SP midi_ctrl         { $$ = LSCPSERVER->SetFxSendMidiController($5,$7,$9);              }
434                        |  FX_SEND SP LEVEL SP sampler_channel SP fx_send_id SP volume_value                { $$ = LSCPSERVER->SetFxSendLevel($5,$7,$9);                       }                        |  FX_SEND SP LEVEL SP sampler_channel SP fx_send_id SP volume_value                { $$ = LSCPSERVER->SetFxSendLevel($5,$7,$9);                       }
435                          |  FX_SEND SP EFFECT SP sampler_channel SP fx_send_id SP effect_chain SP chain_pos  { $$ = LSCPSERVER->SetFxSendEffect($5,$7,$9,$11);                  }
436                        |  DB_INSTRUMENT_DIRECTORY SP NAME SP db_path SP stringval_escaped                  { $$ = LSCPSERVER->SetDbInstrumentDirectoryName($5,$7);            }                        |  DB_INSTRUMENT_DIRECTORY SP NAME SP db_path SP stringval_escaped                  { $$ = LSCPSERVER->SetDbInstrumentDirectoryName($5,$7);            }
437                        |  DB_INSTRUMENT_DIRECTORY SP DESCRIPTION SP db_path SP stringval_escaped           { $$ = LSCPSERVER->SetDbInstrumentDirectoryDescription($5,$7);     }                        |  DB_INSTRUMENT_DIRECTORY SP DESCRIPTION SP db_path SP stringval_escaped           { $$ = LSCPSERVER->SetDbInstrumentDirectoryDescription($5,$7);     }
438                        |  DB_INSTRUMENT SP NAME SP db_path SP stringval_escaped                            { $$ = LSCPSERVER->SetDbInstrumentName($5,$7);                     }                        |  DB_INSTRUMENT SP NAME SP db_path SP stringval_escaped                            { $$ = LSCPSERVER->SetDbInstrumentName($5,$7);                     }
439                        |  DB_INSTRUMENT SP DESCRIPTION SP db_path SP stringval_escaped                     { $$ = LSCPSERVER->SetDbInstrumentDescription($5,$7);              }                        |  DB_INSTRUMENT SP DESCRIPTION SP db_path SP stringval_escaped                     { $$ = LSCPSERVER->SetDbInstrumentDescription($5,$7);              }
440                          |  DB_INSTRUMENT SP FILE_PATH SP filename SP filename                               { $$ = LSCPSERVER->SetDbInstrumentFilePath($5,$7);                 }
441                        |  ECHO SP boolean                                                                  { $$ = LSCPSERVER->SetEcho((yyparse_param_t*) yyparse_param, $3);  }                        |  ECHO SP boolean                                                                  { $$ = LSCPSERVER->SetEcho((yyparse_param_t*) yyparse_param, $3);  }
442                          |  SHELL SP INTERACT SP boolean                                                     { $$ = LSCPSERVER->SetShellInteract((yyparse_param_t*) yyparse_param, $5); }
443                          |  SHELL SP AUTO_CORRECT SP boolean                                                 { $$ = LSCPSERVER->SetShellAutoCorrect((yyparse_param_t*) yyparse_param, $5); }
444                        |  VOLUME SP volume_value                                                           { $$ = LSCPSERVER->SetGlobalVolume($3);                            }                        |  VOLUME SP volume_value                                                           { $$ = LSCPSERVER->SetGlobalVolume($3);                            }
445                          |  VOICES SP number                                                                 { $$ = LSCPSERVER->SetGlobalMaxVoices($3);                         }
446                          |  STREAMS SP number                                                                { $$ = LSCPSERVER->SetGlobalMaxStreams($3);                        }
447                        ;                        ;
448    
449  create_instruction    :  AUDIO_OUTPUT_DEVICE SP string SP key_val_list  { $$ = LSCPSERVER->CreateAudioOutputDevice($3,$5); }  create_instruction    :  AUDIO_OUTPUT_DEVICE SP string SP key_val_list  { $$ = LSCPSERVER->CreateAudioOutputDevice($3,$5); }
# Line 349  create_instruction    :  AUDIO_OUTPUT_DE Line 452  create_instruction    :  AUDIO_OUTPUT_DE
452                        |  MIDI_INPUT_DEVICE SP string                    { $$ = LSCPSERVER->CreateMidiInputDevice($3);      }                        |  MIDI_INPUT_DEVICE SP string                    { $$ = LSCPSERVER->CreateMidiInputDevice($3);      }
453                        |  FX_SEND SP sampler_channel SP midi_ctrl        { $$ = LSCPSERVER->CreateFxSend($3,$5);            }                        |  FX_SEND SP sampler_channel SP midi_ctrl        { $$ = LSCPSERVER->CreateFxSend($3,$5);            }
454                        |  FX_SEND SP sampler_channel SP midi_ctrl SP fx_send_name  { $$ = LSCPSERVER->CreateFxSend($3,$5,$7); }                        |  FX_SEND SP sampler_channel SP midi_ctrl SP fx_send_name  { $$ = LSCPSERVER->CreateFxSend($3,$5,$7); }
455                          |  EFFECT_INSTANCE SP effect_index                { $$ = LSCPSERVER->CreateEffectInstance($3);       }
456                          |  EFFECT_INSTANCE SP effect_system SP module SP effect_name  { $$ = LSCPSERVER->CreateEffectInstance($3,$5,$7); }
457                        ;                        ;
458    
459  reset_instruction     :  CHANNEL SP sampler_channel  { $$ = LSCPSERVER->ResetChannel($3); }  reset_instruction     :  CHANNEL SP sampler_channel  { $$ = LSCPSERVER->ResetChannel($3); }
# Line 362  find_instruction      :  DB_INSTRUMENTS Line 467  find_instruction      :  DB_INSTRUMENTS
467                        |  DB_INSTRUMENTS SP db_path SP query_val_list                               { $$ = LSCPSERVER->FindDbInstruments($3,$5, true);            }                        |  DB_INSTRUMENTS SP db_path SP query_val_list                               { $$ = LSCPSERVER->FindDbInstruments($3,$5, true);            }
468                        |  DB_INSTRUMENT_DIRECTORIES SP NON_RECURSIVE SP db_path SP query_val_list   { $$ = LSCPSERVER->FindDbInstrumentDirectories($5,$7, false); }                        |  DB_INSTRUMENT_DIRECTORIES SP NON_RECURSIVE SP db_path SP query_val_list   { $$ = LSCPSERVER->FindDbInstrumentDirectories($5,$7, false); }
469                        |  DB_INSTRUMENT_DIRECTORIES SP db_path SP query_val_list                    { $$ = LSCPSERVER->FindDbInstrumentDirectories($3,$5, true);  }                        |  DB_INSTRUMENT_DIRECTORIES SP db_path SP query_val_list                    { $$ = LSCPSERVER->FindDbInstrumentDirectories($3,$5, true);  }
470                          |  LOST SP DB_INSTRUMENT_FILES                                               { $$ = LSCPSERVER->FindLostDbInstrumentFiles();                 }
471                        ;                        ;
472    
473  move_instruction      :  DB_INSTRUMENT_DIRECTORY SP db_path SP db_path    { $$ = LSCPSERVER->MoveDbInstrumentDirectory($3,$5); }  move_instruction      :  DB_INSTRUMENT_DIRECTORY SP db_path SP db_path    { $$ = LSCPSERVER->MoveDbInstrumentDirectory($3,$5); }
# Line 375  copy_instruction      :  DB_INSTRUMENT_D Line 481  copy_instruction      :  DB_INSTRUMENT_D
481  destroy_instruction   :  AUDIO_OUTPUT_DEVICE SP number  { $$ = LSCPSERVER->DestroyAudioOutputDevice($3); }  destroy_instruction   :  AUDIO_OUTPUT_DEVICE SP number  { $$ = LSCPSERVER->DestroyAudioOutputDevice($3); }
482                        |  MIDI_INPUT_DEVICE SP number    { $$ = LSCPSERVER->DestroyMidiInputDevice($3);   }                        |  MIDI_INPUT_DEVICE SP number    { $$ = LSCPSERVER->DestroyMidiInputDevice($3);   }
483                        |  FX_SEND SP sampler_channel SP fx_send_id  { $$ = LSCPSERVER->DestroyFxSend($3,$5); }                        |  FX_SEND SP sampler_channel SP fx_send_id  { $$ = LSCPSERVER->DestroyFxSend($3,$5); }
484                          |  EFFECT_INSTANCE SP number      { $$ = LSCPSERVER->DestroyEffectInstance($3);    }
485                        ;                        ;
486    
487  load_instruction      :  INSTRUMENT SP load_instr_args  { $$ = $3; }  load_instruction      :  INSTRUMENT SP load_instr_args  { $$ = $3; }
488                        |  ENGINE SP load_engine_args     { $$ = $3; }                        |  ENGINE SP load_engine_args     { $$ = $3; }
489                        ;                        ;
490    
491    append_instruction    :  SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP effect_instance  { $$ = LSCPSERVER->AppendSendEffectChainEffect($5,$7,$9); }
492                          ;
493    
494    insert_instruction    :  SEND_EFFECT_CHAIN SP EFFECT SP device_index SP effect_chain SP chain_pos SP effect_instance  { $$ = LSCPSERVER->InsertSendEffectChainEffect($5,$7,$9,$11); }
495                          ;
496    
497  set_chan_instruction  :  AUDIO_OUTPUT_DEVICE SP sampler_channel SP device_index                                              { $$ = LSCPSERVER->SetAudioOutputDevice($5, $3);      }  set_chan_instruction  :  AUDIO_OUTPUT_DEVICE SP sampler_channel SP device_index                                              { $$ = LSCPSERVER->SetAudioOutputDevice($5, $3);      }
498                        |  AUDIO_OUTPUT_CHANNEL SP sampler_channel SP audio_channel_index SP audio_channel_index               { $$ = LSCPSERVER->SetAudioOutputChannel($5, $7, $3); }                        |  AUDIO_OUTPUT_CHANNEL SP sampler_channel SP audio_channel_index SP audio_channel_index               { $$ = LSCPSERVER->SetAudioOutputChannel($5, $7, $3); }
499                        |  AUDIO_OUTPUT_TYPE SP sampler_channel SP audio_output_type_name                                      { $$ = LSCPSERVER->SetAudioOutputType($5, $3);        }                        |  AUDIO_OUTPUT_TYPE SP sampler_channel SP audio_output_type_name                                      { $$ = LSCPSERVER->SetAudioOutputType($5, $3);        }
# Line 397  set_chan_instruction  :  AUDIO_OUTPUT_DE Line 510  set_chan_instruction  :  AUDIO_OUTPUT_DE
510                        |  MIDI_INSTRUMENT_MAP SP sampler_channel SP DEFAULT                                                   { $$ = LSCPSERVER->SetChannelMap($3, -2);             }                        |  MIDI_INSTRUMENT_MAP SP sampler_channel SP DEFAULT                                                   { $$ = LSCPSERVER->SetChannelMap($3, -2);             }
511                        ;                        ;
512    
513  edit_instruction      :  INSTRUMENT SP sampler_channel  { $$ = LSCPSERVER->EditSamplerChannelInstrument($3); }  edit_instruction      :  CHANNEL SP INSTRUMENT SP sampler_channel  { $$ = LSCPSERVER->EditSamplerChannelInstrument($5); }
514                          ;
515    
516    format_instruction    :  INSTRUMENTS_DB  { $$ = LSCPSERVER->FormatInstrumentsDb(); }
517                        ;                        ;
518    
519  modal_arg             :  /* epsilon (empty argument) */  { $$ = true;  }  modal_arg             :  /* epsilon (empty argument) */  { $$ = true;  }
# Line 415  buffer_size_type      :  BYTES       { $ Line 531  buffer_size_type      :  BYTES       { $
531  list_instruction      :  AUDIO_OUTPUT_DEVICES                               { $$ = LSCPSERVER->GetAudioOutputDevices();              }  list_instruction      :  AUDIO_OUTPUT_DEVICES                               { $$ = LSCPSERVER->GetAudioOutputDevices();              }
532                        |  MIDI_INPUT_DEVICES                                 { $$ = LSCPSERVER->GetMidiInputDevices();                }                        |  MIDI_INPUT_DEVICES                                 { $$ = LSCPSERVER->GetMidiInputDevices();                }
533                        |  CHANNELS                                           { $$ = LSCPSERVER->ListChannels();                       }                        |  CHANNELS                                           { $$ = LSCPSERVER->ListChannels();                       }
534                          |  CHANNEL SP MIDI_INPUTS SP sampler_channel          { $$ = LSCPSERVER->ListChannelMidiInputs($5);            }
535                        |  AVAILABLE_ENGINES                                  { $$ = LSCPSERVER->ListAvailableEngines();               }                        |  AVAILABLE_ENGINES                                  { $$ = LSCPSERVER->ListAvailableEngines();               }
536                          |  AVAILABLE_EFFECTS                                  { $$ = LSCPSERVER->ListAvailableEffects();               }
537                          |  EFFECT_INSTANCES                                   { $$ = LSCPSERVER->ListEffectInstances();                }
538                          |  SEND_EFFECT_CHAINS SP number                       { $$ = LSCPSERVER->ListSendEffectChains($3);             }
539                        |  AVAILABLE_MIDI_INPUT_DRIVERS                       { $$ = LSCPSERVER->ListAvailableMidiInputDrivers();      }                        |  AVAILABLE_MIDI_INPUT_DRIVERS                       { $$ = LSCPSERVER->ListAvailableMidiInputDrivers();      }
540                        |  AVAILABLE_AUDIO_OUTPUT_DRIVERS                     { $$ = LSCPSERVER->ListAvailableAudioOutputDrivers();    }                        |  AVAILABLE_AUDIO_OUTPUT_DRIVERS                     { $$ = LSCPSERVER->ListAvailableAudioOutputDrivers();    }
541                        |  MIDI_INSTRUMENTS SP midi_map                       { $$ = LSCPSERVER->ListMidiInstrumentMappings($3);       }                        |  MIDI_INSTRUMENTS SP midi_map                       { $$ = LSCPSERVER->ListMidiInstrumentMappings($3);       }
# Line 426  list_instruction      :  AUDIO_OUTPUT_DE Line 546  list_instruction      :  AUDIO_OUTPUT_DE
546                        |  DB_INSTRUMENT_DIRECTORIES SP db_path               { $$ = LSCPSERVER->GetDbInstrumentDirectories($3);       }                        |  DB_INSTRUMENT_DIRECTORIES SP db_path               { $$ = LSCPSERVER->GetDbInstrumentDirectories($3);       }
547                        |  DB_INSTRUMENTS SP RECURSIVE SP db_path             { $$ = LSCPSERVER->GetDbInstruments($5, true);           }                        |  DB_INSTRUMENTS SP RECURSIVE SP db_path             { $$ = LSCPSERVER->GetDbInstruments($5, true);           }
548                        |  DB_INSTRUMENTS SP db_path                          { $$ = LSCPSERVER->GetDbInstruments($3);                 }                        |  DB_INSTRUMENTS SP db_path                          { $$ = LSCPSERVER->GetDbInstruments($3);                 }
549                          |  FILE SP INSTRUMENTS SP filename                    { $$ = LSCPSERVER->ListFileInstruments($5);              }
550                          ;
551    
552    send_instruction      :  CHANNEL SP MIDI_DATA SP string SP sampler_channel SP number SP number  { $$ = LSCPSERVER->SendChannelMidiData($5, $7, $9, $11); }
553                        ;                        ;
554    
555  load_instr_args       :  filename SP instrument_index SP sampler_channel               { $$ = LSCPSERVER->LoadInstrument($1, $3, $5);       }  load_instr_args       :  filename SP instrument_index SP sampler_channel               { $$ = LSCPSERVER->LoadInstrument($1, $3, $5);       }
# Line 440  instr_load_mode       :  ON_DEMAND Line 564  instr_load_mode       :  ON_DEMAND
564                        |  PERSISTENT      { $$ = MidiInstrumentMapper::PERSISTENT;     }                        |  PERSISTENT      { $$ = MidiInstrumentMapper::PERSISTENT;     }
565                        ;                        ;
566    
567    effect_instance           : number
568                              ;
569    
570  device_index              :  number  device_index              :  number
571                            ;                            ;
572    
# Line 475  volume_value              :  dotnum Line 602  volume_value              :  dotnum
602                            |  number  { $$ = $1; }                            |  number  { $$ = $1; }
603                            ;                            ;
604    
605    control_value             :  real
606                              ;
607    
608  sampler_channel           :  number  sampler_channel           :  number
609                            ;                            ;
610    
# Line 487  fx_send_id                :  number Line 617  fx_send_id                :  number
617  engine_name               :  string  engine_name               :  string
618                            ;                            ;
619    
620  filename                  :  path  { $$ = $1.toPosix(); /*TODO: assuming POSIX*/ }  filename                  :  path  {
621                                     #if WIN32
622                                     $$ = $1.toWindows();
623                                     #else
624                                     // assuming POSIX
625                                     $$ = $1.toPosix();
626                                     #endif
627                                 }
628                            ;                            ;
629    
630  db_path                   :  path  { $$ = $1.toDbPath(); }  db_path                   :  path  { $$ = $1.toDbPath(); }
631                            ;                            ;
632    
633  map_name                  :  stringval  map_name                  :  stringval_escaped
634                              ;
635    
636    entry_name                :  stringval_escaped
637                              ;
638    
639    fx_send_name              :  stringval_escaped
640                            ;                            ;
641    
642  entry_name                :  stringval  effect_name               :  stringval_escaped
643                            ;                            ;
644    
645  fx_send_name              :  stringval  effect_index              :  number
646                              ;
647    
648    effect_chain              :  number
649                              ;
650    
651    chain_pos                 :  number
652                              ;
653    
654    input_control             :  number
655                            ;                            ;
656    
657  param_val_list            :  param_val  param_val_list            :  param_val
658                            |  param_val_list','param_val  { $$ = $1 + "," + $3; }                            |  param_val_list','param_val  { $$ = $1 + "," + $3; }
659                            ;                            ;
660    
661  param_val                 :  string  //TODO: the re-encapsulation into apostrophes for string and strinval here is a hack, since we need a way for __parse_strings() (DeviceParameters.cpp) to distinguish a comma separated list of strings and a string which contains commas. A clean solution would be to move those parser jobs over here to lscp.y
662                            |  stringval  param_val                 :  string            { $$ = "\'" + $1 + "\'"; }
663                              |  stringval         { $$ = "\'" + $1 + "\'"; }
664                            |  number            { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); }                            |  number            { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); }
665                            |  dotnum            { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); }                            |  dotnum            { std::stringstream ss; ss << "\'" << $1 << "\'"; $$ = ss.str(); } //TODO: maybe better using 'real' instead of 'number' and 'dotnum' rules
666                            ;                            ;
667    
668  query_val_list            :  string '=' query_val                    { $$[$1] = $3;          }  query_val_list            :  string '=' query_val                    { $$[$1] = $3;          }
669                            |  query_val_list SP string '=' query_val  { $$ = $1; $$[$3] = $5; }                            |  query_val_list SP string '=' query_val  { $$ = $1; $$[$3] = $5; }
670                            ;                            ;
671    
672  query_val                 :  textval_escaped  query_val                 :  text_escaped
673                            |  stringval_escaped                            |  stringval_escaped
674                            ;                            ;
675    
# Line 525  scan_mode                 :  RECURSIVE Line 678  scan_mode                 :  RECURSIVE
678                            |  FLAT           { $$ = "FLAT"; }                            |  FLAT           { $$ = "FLAT"; }
679                            ;                            ;
680    
681    effect_system             :  string
682                              ;
683    
684    module                    :  filename
685                              ;
686    
687  // GRAMMAR_BNF_END - do NOT delete or modify this line !!!  // GRAMMAR_BNF_END - do NOT delete or modify this line !!!
688    
689    
# Line 534  boolean               :  number  { $$ = Line 693  boolean               :  number  { $$ =
693                        |  string  { $$ = -1; }                        |  string  { $$ = -1; }
694                        ;                        ;
695    
696  dotnum                :      digits '.' digits  { $$ = atof(String($1 + "." + $3).c_str());                         }  dotnum                :      digits '.' digits  { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
697                        |  '+' digits '.' digits  { String s = "+"; s += $2; s += "."; s += $4; $$ = atof(s.c_str()); }                        |  '+' digits '.' digits  { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
698                        |  '-' digits '.' digits  { $$ = atof(String("-" + $2 + "." + $4).c_str());                   }                        |  '-' digits '.' digits  { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
699                          ;
700    
701    real                  :      digits '.' digits  { std::stringstream ss($1 + "." + $3); ss.imbue(std::locale::classic()); ss >> $$; }
702                          |  '+' digits '.' digits  { std::stringstream ss($2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
703                          |  '-' digits '.' digits  { std::stringstream ss("-" + $2 + "." + $4); ss.imbue(std::locale::classic()); ss >> $$; }
704                          |      digits             { std::stringstream ss($1); ss.imbue(std::locale::classic()); ss >> $$;                  }
705                          |  '+' digits             { std::stringstream ss($2); ss.imbue(std::locale::classic()); ss >> $$;                  }
706                          |  '-' digits             { std::stringstream ss("-" + $2); ss.imbue(std::locale::classic()); ss >> $$;            }
707                        ;                        ;
708    
709    
# Line 606  path                  :  '\'' path_base Line 773  path                  :  '\'' path_base
773                        |  '\"' path_base '\"'  { $$ = $2; }                        |  '\"' path_base '\"'  { $$ = $2; }
774                        ;                        ;
775    
776  path_base             :  '/'                     { $$ = Path();                           }  path_base             :  path_prefix path_body  { $$ = $1 + $2; }
777                        |  path_base '/'           { $$ = $1;                               }                        ;
778                        |  path_base text_escaped  { Path p; p.appendNode($2); $$ = $1 + p; }  
779    path_prefix           :  '/'                 { $$ = Path();                    }
780                          |  alpha_char ':' '/'  { Path p; p.setDrive($1); $$ = p; }
781                          ;
782    
783    path_body             :  /* epsilon (empty argument) */ { $$ = Path();                           }
784                          |  path_body '/'                  { $$ = $1;                               }
785                          |  path_body text_escaped_base    { Path p; p.appendNode($2); $$ = $1 + p; }
786                        ;                        ;
787    
788  stringval             :  '\'' text '\''  { $$ = $2; }  stringval             :  '\'' text '\''  { $$ = $2; }
789                        |  '\"' text '\"'  { $$ = $2; }                        |  '\"' text '\"'  { $$ = $2; }
790                        ;                        ;
791    
792  stringval_escaped     :  '\'' textval_escaped '\''  { $$ = $2; }  stringval_escaped     :  '\'' text_escaped '\''  { $$ = $2; }
793                        |  '\"' textval_escaped '\"'  { $$ = $2; }                        |  '\"' text_escaped '\"'  { $$ = $2; }
794                        ;                        ;
795    
796  text                  :  SP           { $$ = " ";      }  text                  :  SP           { $$ = " ";      }
# Line 625  text                  :  SP           { Line 799  text                  :  SP           {
799                        |  text string  { $$ = $1 + $2;  }                        |  text string  { $$ = $1 + $2;  }
800                        ;                        ;
801    
802  text_escaped          :  SP                           { $$ = " ";      }  // like text_escaped, but missing the slash ('/') character
803    text_escaped_base     :  SP                                { $$ = " ";      }
804                        |  string_escaped                        |  string_escaped
805                        |  text_escaped SP              { $$ = $1 + " "; }                        |  text_escaped_base SP              { $$ = $1 + " "; }
806                        |  text_escaped string_escaped  { $$ = $1 + $2;  }                        |  text_escaped_base string_escaped  { $$ = $1 + $2;  }
807                        ;                        ;
808    
809  textval_escaped       :  '/'                           { $$ = "/";      }  text_escaped          :  '/'                              { $$ = "/";      }
810                        |  text_escaped                        |  text_escaped_base
811                        |  textval_escaped '/'           { $$ = $1 + "/"; }                        |  text_escaped '/'                 { $$ = $1 + "/"; }
812                        |  textval_escaped text_escaped  { $$ = $1 + $2;  }                        |  text_escaped text_escaped_base   { $$ = $1 + $2;  }
813                        ;                        ;
814    
815  string                :  char          { std::string s; s = $1; $$ = s; }  string                :  char          { std::string s; s = $1; $$ = s; }
# Line 653  char                  :  char_base Line 828  char                  :  char_base
828                        |  '/'   { $$ = '/';  }                        |  '/'   { $$ = '/';  }
829                        ;                        ;
830    
831  // ASCII characters except space, quotation mark, apostrophe, backslash and slash  // characters A..Z and a..z
832  char_base             :  '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'; }  alpha_char            :  'A' { $$ = 'A'; } | 'B' { $$ = 'B'; } | 'C' { $$ = 'C'; } | 'D' { $$ = 'D'; } | 'E' { $$ = 'E'; } | 'F' { $$ = 'F'; } | 'G' { $$ = 'G'; } | 'H' { $$ = 'H'; } | 'I' { $$ = 'I'; } | 'J' { $$ = 'J'; } | 'K' { $$ = 'K'; } | 'L' { $$ = 'L'; } | 'M' { $$ = 'M'; } | 'N' { $$ = 'N'; } | 'O' { $$ = 'O'; } | 'P' { $$ = 'P'; } | 'Q' { $$ = 'Q'; } | 'R' { $$ = 'R'; } | 'S' { $$ = 'S'; } | 'T' { $$ = 'T'; } | 'U' { $$ = 'U'; } | 'V' { $$ = 'V'; } | 'W' { $$ = 'W'; } | 'X' { $$ = 'X'; } | 'Y' { $$ = 'Y'; } | 'Z' { $$ = 'Z'; }
833                        |  'a' { $$ = 'a'; } | 'b' { $$ = 'b'; } | 'c' { $$ = 'c'; } | 'd' { $$ = 'd'; } | 'e' { $$ = 'e'; } | 'f' { $$ = 'f'; } | 'g' { $$ = 'g'; } | 'h' { $$ = 'h'; } | 'i' { $$ = 'i'; } | 'j' { $$ = 'j'; } | 'k' { $$ = 'k'; } | 'l' { $$ = 'l'; } | 'm' { $$ = 'm'; } | 'n' { $$ = 'n'; } | 'o' { $$ = 'o'; } | 'p' { $$ = 'p'; } | 'q' { $$ = 'q'; } | 'r' { $$ = 'r'; } | 's' { $$ = 's'; } | 't' { $$ = 't'; } | 'u' { $$ = 'u'; } | 'v' { $$ = 'v'; } | 'w' { $$ = 'w'; } | 'x' { $$ = 'x'; } | 'y' { $$ = 'y'; } | 'z' { $$ = 'z'; }                        |  'a' { $$ = 'a'; } | 'b' { $$ = 'b'; } | 'c' { $$ = 'c'; } | 'd' { $$ = 'd'; } | 'e' { $$ = 'e'; } | 'f' { $$ = 'f'; } | 'g' { $$ = 'g'; } | 'h' { $$ = 'h'; } | 'i' { $$ = 'i'; } | 'j' { $$ = 'j'; } | 'k' { $$ = 'k'; } | 'l' { $$ = 'l'; } | 'm' { $$ = 'm'; } | 'n' { $$ = 'n'; } | 'o' { $$ = 'o'; } | 'p' { $$ = 'p'; } | 'q' { $$ = 'q'; } | 'r' { $$ = 'r'; } | 's' { $$ = 's'; } | 't' { $$ = 't'; } | 'u' { $$ = 'u'; } | 'v' { $$ = 'v'; } | 'w' { $$ = 'w'; } | 'x' { $$ = 'x'; } | 'y' { $$ = 'y'; } | 'z' { $$ = 'z'; }
834                          ;
835    
836    // ASCII characters except space, quotation mark, apostrophe, backslash and slash
837    char_base             :  alpha_char
838                        |  '0' { $$ = '0'; } | '1' { $$ = '1'; } | '2' { $$ = '2'; } | '3' { $$ = '3'; } | '4' { $$ = '4'; } | '5' { $$ = '5'; } | '6' { $$ = '6'; } | '7' { $$ = '7'; } | '8' { $$ = '8'; } | '9' { $$ = '9'; }                        |  '0' { $$ = '0'; } | '1' { $$ = '1'; } | '2' { $$ = '2'; } | '3' { $$ = '3'; } | '4' { $$ = '4'; } | '5' { $$ = '5'; } | '6' { $$ = '6'; } | '7' { $$ = '7'; } | '8' { $$ = '8'; } | '9' { $$ = '9'; }
839                        |  '!' { $$ = '!'; } | '#' { $$ = '#'; } | '$' { $$ = '$'; } | '%' { $$ = '%'; } | '&' { $$ = '&'; } | '(' { $$ = '('; } | ')' { $$ = ')'; } | '*' { $$ = '*'; } | '+' { $$ = '+'; } | '-' { $$ = '-'; } | '.' { $$ = '.'; } | ',' { $$ = ','; }                        |  '!' { $$ = '!'; } | '#' { $$ = '#'; } | '$' { $$ = '$'; } | '%' { $$ = '%'; } | '&' { $$ = '&'; } | '(' { $$ = '('; } | ')' { $$ = ')'; } | '*' { $$ = '*'; } | '+' { $$ = '+'; } | '-' { $$ = '-'; } | '.' { $$ = '.'; } | ',' { $$ = ','; }
840                        |  ':' { $$ = ':'; } | ';' { $$ = ';'; } | '<' { $$ = '<'; } | '=' { $$ = '='; } | '>' { $$ = '>'; } | '?' { $$ = '?'; } | '@' { $$ = '@'; }                        |  ':' { $$ = ':'; } | ';' { $$ = ';'; } | '<' { $$ = '<'; } | '=' { $$ = '='; } | '>' { $$ = '>'; } | '?' { $$ = '?'; } | '@' { $$ = '@'; }
# Line 715  CLEAR                 :  'C''L''E''A''R' Line 894  CLEAR                 :  'C''L''E''A''R'
894  FIND                  :  'F''I''N''D'  FIND                  :  'F''I''N''D'
895                        ;                        ;
896    
897    FILE_AS_DIR           :  'F''I''L''E''_''A''S''_''D''I''R'
898                          ;
899    
900  MOVE                  :  'M''O''V''E'  MOVE                  :  'M''O''V''E'
901                        ;                        ;
902    
# Line 751  REMOVE                :  'R''E''M''O''V' Line 933  REMOVE                :  'R''E''M''O''V'
933  SET                   :  'S''E''T'  SET                   :  'S''E''T'
934                        ;                        ;
935    
936    SHELL                 :  'S''H''E''L''L'
937                          ;
938    
939    INTERACT              :  'I''N''T''E''R''A''C''T'
940                          ;
941    
942    AUTO_CORRECT          :  'A''U''T''O''_''C''O''R''R''E''C''T'
943                          ;
944    
945    APPEND                :  'A''P''P''E''N''D'
946                          ;
947    
948    INSERT                :  'I''N''S''E''R''T'
949                          ;
950    
951  SUBSCRIBE             :  'S''U''B''S''C''R''I''B''E'  SUBSCRIBE             :  'S''U''B''S''C''R''I''B''E'
952                        ;                        ;
953    
# Line 808  DB_INSTRUMENT_COUNT           :  'D''B'' Line 1005  DB_INSTRUMENT_COUNT           :  'D''B''
1005  DB_INSTRUMENT_INFO            :  'D''B''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'  DB_INSTRUMENT_INFO            :  'D''B''_''I''N''S''T''R''U''M''E''N''T''_''I''N''F''O'
1006                                ;                                ;
1007    
1008    DB_INSTRUMENT_FILES           :  'D''B''_''I''N''S''T''R''U''M''E''N''T''_''F''I''L''E''S'
1009                                  ;
1010    
1011  DB_INSTRUMENTS_JOB_INFO       :  'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B''_''I''N''F''O'  DB_INSTRUMENTS_JOB_INFO       :  'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B''_''I''N''F''O'
1012                                ;                                ;
1013    
1014  CHANNEL_COUNT        :  'C''H''A''N''N''E''L''_''C''O''U''N''T'  CHANNEL_COUNT        :  'C''H''A''N''N''E''L''_''C''O''U''N''T'
1015                       ;                       ;
1016    
1017    CHANNEL_MIDI         :  'C''H''A''N''N''E''L''_''M''I''D''I'
1018                         ;
1019    
1020    DEVICE_MIDI          :  'D''E''V''I''C''E''_''M''I''D''I'
1021                         ;
1022    
1023  CHANNEL_INFO         :  'C''H''A''N''N''E''L''_''I''N''F''O'  CHANNEL_INFO         :  'C''H''A''N''N''E''L''_''I''N''F''O'
1024                       ;                       ;
1025    
# Line 832  STREAM_COUNT         :  'S''T''R''E''A'' Line 1038  STREAM_COUNT         :  'S''T''R''E''A''
1038  VOICE_COUNT          :  'V''O''I''C''E''_''C''O''U''N''T'  VOICE_COUNT          :  'V''O''I''C''E''_''C''O''U''N''T'
1039                       ;                       ;
1040    
1041    TOTAL_STREAM_COUNT   :  'T''O''T''A''L''_''S''T''R''E''A''M''_''C''O''U''N''T'
1042                         ;
1043    
1044  TOTAL_VOICE_COUNT    :  'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T'  TOTAL_VOICE_COUNT    :  'T''O''T''A''L''_''V''O''I''C''E''_''C''O''U''N''T'
1045                       ;                       ;
1046    
# Line 841  TOTAL_VOICE_COUNT_MAX:  'T''O''T''A''L'' Line 1050  TOTAL_VOICE_COUNT_MAX:  'T''O''T''A''L''
1050  GLOBAL_INFO          :  'G''L''O''B''A''L''_''I''N''F''O'  GLOBAL_INFO          :  'G''L''O''B''A''L''_''I''N''F''O'
1051                       ;                       ;
1052    
1053    EFFECT_INSTANCE_COUNT   :  'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''C''O''U''N''T'
1054                            ;
1055    
1056    EFFECT_INSTANCE_INFO    :  'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''I''N''F''O'
1057                            ;
1058    
1059    SEND_EFFECT_CHAIN_COUNT :  'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''C''O''U''N''T'
1060                            ;
1061    
1062    SEND_EFFECT_CHAIN_INFO  :  'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''_''I''N''F''O'
1063                            ;
1064    
1065  INSTRUMENT           :  'I''N''S''T''R''U''M''E''N''T'  INSTRUMENT           :  'I''N''S''T''R''U''M''E''N''T'
1066                       ;                       ;
1067    
1068    INSTRUMENTS          :  'I''N''S''T''R''U''M''E''N''T''S'
1069                         ;
1070    
1071  ENGINE               :  'E' 'N' 'G' 'I' 'N' 'E'  ENGINE               :  'E' 'N' 'G' 'I' 'N' 'E'
1072                       ;                       ;
1073    
# Line 880  AUDIO_OUTPUT_CHANNEL  :  'A''U''D''I''O' Line 1104  AUDIO_OUTPUT_CHANNEL  :  'A''U''D''I''O'
1104  AUDIO_OUTPUT_TYPE     :  'A''U''D''I''O''_''O''U''T''P''U''T''_''T''Y''P''E'  AUDIO_OUTPUT_TYPE     :  'A''U''D''I''O''_''O''U''T''P''U''T''_''T''Y''P''E'
1105                        ;                        ;
1106    
1107    AVAILABLE_EFFECTS :  'A''V''A''I''L''A''B''L''E''_''E''F''F''E''C''T''S'
1108                      ;
1109    
1110    EFFECT :  'E''F''F''E''C''T'
1111           ;
1112    
1113    EFFECT_INSTANCE :  'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E'
1114                    ;
1115    
1116    EFFECT_INSTANCES :  'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''S'
1117                     ;
1118    
1119    EFFECT_INSTANCE_INPUT_CONTROL :  'E''F''F''E''C''T''_''I''N''S''T''A''N''C''E''_''I''N''P''U''T''_''C''O''N''T''R''O''L'
1120                                  ;
1121    
1122    SEND_EFFECT_CHAIN :  'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N'
1123                      ;
1124    
1125    SEND_EFFECT_CHAINS :  'S''E''N''D''_''E''F''F''E''C''T''_''C''H''A''I''N''S'
1126                       ;
1127    
1128  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'  AVAILABLE_MIDI_INPUT_DRIVERS  :  'A''V''A''I''L''A''B''L''E''_''M''I''D''I''_''I''N''P''U''T''_''D''R''I''V''E''R''S'
1129                                ;                                ;
1130    
# Line 925  MIDI_INPUT_TYPE       :  'M''I''D''I''_' Line 1170  MIDI_INPUT_TYPE       :  'M''I''D''I''_'
1170  MIDI_INPUT            :  'M''I''D''I''_''I''N''P''U''T'  MIDI_INPUT            :  'M''I''D''I''_''I''N''P''U''T'
1171                        ;                        ;
1172    
1173    MIDI_INPUTS           :  'M''I''D''I''_''I''N''P''U''T''S'
1174                          ;
1175    
1176  MIDI_CONTROLLER       :  'M''I''D''I''_''C''O''N''T''R''O''L''L''E''R'  MIDI_CONTROLLER       :  'M''I''D''I''_''C''O''N''T''R''O''L''L''E''R'
1177                        ;                        ;
1178    
1179    SEND                  :  'S''E''N''D'
1180                          ;
1181    
1182  FX_SEND               :  'F''X''_''S''E''N''D'  FX_SEND               :  'F''X''_''S''E''N''D'
1183                        ;                        ;
1184    
# Line 949  DB_INSTRUMENT              :  'D''B''_'' Line 1200  DB_INSTRUMENT              :  'D''B''_''
1200  DB_INSTRUMENTS_JOB         :  'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B'  DB_INSTRUMENTS_JOB         :  'D''B''_''I''N''S''T''R''U''M''E''N''T''S''_''J''O''B'
1201                             ;                             ;
1202    
1203    INSTRUMENTS_DB             :  'I''N''S''T''R''U''M''E''N''T''S''_''D''B'
1204                               ;
1205    
1206  DESCRIPTION                :  'D''E''S''C''R''I''P''T''I''O''N'  DESCRIPTION                :  'D''E''S''C''R''I''P''T''I''O''N'
1207                             ;                             ;
1208    
# Line 964  RECURSIVE                  :  'R''E''C'' Line 1218  RECURSIVE                  :  'R''E''C''
1218  NON_RECURSIVE              :  'N''O''N''_''R''E''C''U''R''S''I''V''E'  NON_RECURSIVE              :  'N''O''N''_''R''E''C''U''R''S''I''V''E'
1219                             ;                             ;
1220    
1221    LOST                       :  'L''O''S''T'
1222                               ;
1223    
1224    FILE_PATH                  :  'F''I''L''E''_''P''A''T''H'
1225                               ;
1226    
1227  SERVER                :  'S''E''R''V''E''R'  SERVER                :  'S''E''R''V''E''R'
1228                        ;                        ;
1229    
# Line 973  VOLUME                :  'V''O''L''U''M' Line 1233  VOLUME                :  'V''O''L''U''M'
1233  LEVEL                 :  'L''E''V''E''L'  LEVEL                 :  'L''E''V''E''L'
1234                        ;                        ;
1235    
1236    VALUE                 :  'V''A''L''U''E'
1237                          ;
1238    
1239  MUTE                  :  'M''U''T''E'  MUTE                  :  'M''U''T''E'
1240                        ;                        ;
1241    
1242  SOLO                  :  'S''O''L''O'  SOLO                  :  'S''O''L''O'
1243                        ;                        ;
1244    
1245    VOICES                :  'V''O''I''C''E''S'
1246                          ;
1247    
1248    STREAMS               :  'S''T''R''E''A''M''S'
1249                          ;
1250    
1251  BYTES                 :  'B''Y''T''E''S'  BYTES                 :  'B''Y''T''E''S'
1252                        ;                        ;
1253    
1254  PERCENTAGE            :  'P''E''R''C''E''N''T''A''G''E'  PERCENTAGE            :  'P''E''R''C''E''N''T''A''G''E'
1255                        ;                        ;
1256    
1257    FILE                  :  'F''I''L''E'
1258                          ;
1259    
1260  EDIT                  :  'E''D''I''T'  EDIT                  :  'E''D''I''T'
1261                        ;                        ;
1262    
1263    FORMAT                :  'F''O''R''M''A''T'
1264                          ;
1265    
1266    MIDI_DATA             :  'M''I''D''I''_''D''A''T''A'
1267                          ;
1268    
1269  RESET                 :  'R''E''S''E''T'  RESET                 :  'R''E''S''E''T'
1270                        ;                        ;
1271    
# Line 1005  QUIT                  :  'Q''U''I''T' Line 1283  QUIT                  :  'Q''U''I''T'
1283    
1284  %%  %%
1285    
1286    // TODO: actually would be fine to have the following bunch of source code in a separate file, however those functions are a) accessing private Bison tables like yytable and b) including the functions from another file here would make the line numbers incorrect on compile errors in auto generated lscpparser.cpp
1287    
1288  /**  /**
1289   * Will be called when an error occured (usually syntax error).   * Additional informations of a grammar symbol.
1290     */
1291    struct BisonSymbolInfo {
1292        bool isTerminalSymbol; ///< Whether the symbol is a terminal or non-termianl symbol. NOTE: Read comment regarding this in _isRuleTerminalSymbol() !!
1293        String nextExpectedChars; ///< According to current parser position: sequence of characters expected next for satisfying this grammar symbol.
1294    };
1295    
1296    /**
1297     * Returns true if the given grammar @a rule is a terminal symbol (in *our*
1298     * terms).
1299     *
1300     * Please note that the term "terminal symbol" is a bit confusingly used in
1301     * this source code here around. In Bison's terms, "terminal symbols" are (more
1302     * or less) just the numbers returned by the YYLEX function. Since we decided
1303     * though to use a convenient solution without a separate lexer, and all its
1304     * caveats, all numbers by the yylex() function here are just the ASCII
1305     * numbers of the individual characters received. Based on that however, one
1306     * single character is not what one would intuitively expect of being a
1307     * "terminal symbol", because it is simply too primitive.
1308     *
1309     * So in this LSCP parser source code a "terminal symbol" rather means a
1310     * keyword like "CREATE" or "GET". In the grammal definition above, those are
1311     * however defined as grammar rules (non-terminals in Bison's terms). So this
1312     * function decides like this: if the given grammar rule just contains
1313     * individual characters on the right side of its grammar rule, then it is a
1314     * "terminal symbol" in *our* terms.
1315     *
1316     * @param rule - Bison grammar rule number
1317     */
1318    inline static bool _isRuleTerminalSymbol(int rule) {
1319        for (int i = yyprhs[rule]; yyrhs[i] != -1; ++i)
1320            if (yyrhs[i] >= YYNTOKENS) return false;
1321        return true;
1322    }
1323    
1324    /**
1325     * Returns additional informations to the given grammar @a rule.
1326     */
1327    inline static BisonSymbolInfo _symbolInfoForRule(int rule, const String& nextExpectedChars) {
1328        BisonSymbolInfo info;
1329        info.isTerminalSymbol = _isRuleTerminalSymbol(rule);
1330        if (info.isTerminalSymbol) info.nextExpectedChars  = nextExpectedChars;
1331        return info;
1332    }
1333    
1334    /**
1335     * Returns the human readable name of the given @a token.
1336     */
1337    inline static String _tokenName(int token) {
1338        String s = yytname[token];
1339        // remove leading and trailing apostrophes that Bison usually adds to
1340        // ASCII characters used directly in grammar rules
1341        if (s.empty()) return s;
1342        if (s[0] == '\'') s.erase(0, 1);
1343        if (s.empty()) return s;
1344        if (s[s.size() - 1] == '\'') s.erase(s.size() - 1);
1345        return s;
1346    }
1347    
1348    #define DEBUG_BISON_SYNTAX_ERROR_WALKER 0
1349    
1350    /**
1351     * Tries to find the next expected grammar symbols according to the given
1352     * precise parse position & state represented by @a stack, according to Bison's
1353     * LALR(1) parser algorithm.
1354     *
1355     * This function is given a Bison parser state stack, reflecting the parser's
1356     * entire state at a certain point, i.e. when a syntax error occured. This
1357     * function will then walk ahead the potential parse tree starting from the
1358     * current head of the given state stack. This function will call itself
1359     * recursively to scan the individual parse tree branches. As soon as it hits
1360     * on the next non-terminal grammar symbol in one parse tree branch, it adds the
1361     * found non-terminal symbol to @a expectedSymbols and aborts scanning the
1362     * respective tree branch further. If any local parser state is reached a second
1363     * time, the respective parse tree is aborted to avoid any endless recursion.
1364     *
1365     * @param stack - current Bison (yacc) state stack to be examined
1366     * @param expectedSymbols - will be filled with next expected grammar symbols
1367     * @param nextExpectedChars - just for internal purpose, due to the recursive
1368     *                            implementation of this function, do supply an
1369     *                            empty character for this argument
1370     * @param depth - just for internal debugging purposes
1371     */
1372    static void walkAndFillExpectedSymbols(
1373        std::vector<YYTYPE_INT16>& stack,
1374        std::map<String,BisonSymbolInfo>& expectedSymbols,
1375        String& nextExpectedChars, int depth = 0)
1376    {
1377    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1378        printf("\n");
1379        for (int i = 0; i < depth; ++i) printf("\t");
1380        printf("State stack:");
1381        for (int i = 0; i < stack.size(); ++i) {
1382            printf(" %d", stack[i]);
1383        }
1384        printf("\n");
1385    #endif
1386    
1387        if (stack.empty()) return;
1388    
1389        int state = stack[stack.size() - 1];
1390        int n = yypact[state];
1391        if (n == YYPACT_NINF) { // default reduction required ...
1392            // get default reduction rule for this state
1393            n = yydefact[state];
1394            if (n <= 0 || n >= YYNRULES) return; // no rule, something is wrong
1395            // return the new resolved expected symbol (left-hand symbol of grammar
1396            // rule), then we're done in this state
1397            expectedSymbols[yytname[yyr1[n]]] = _symbolInfoForRule(n, nextExpectedChars);
1398            return;
1399        }
1400        if (!(YYPACT_NINF < n && n <= YYLAST)) return;
1401    
1402    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1403        for (int i = 0; i < depth; ++i) printf("\t");
1404        printf("Expected tokens:");
1405    #endif
1406        int begin = n < 0 ? -n : 0;
1407        int checklim = YYLAST - n + 1;
1408        int end = checklim < YYNTOKENS ? checklim : YYNTOKENS;
1409        int rule, action, stackSize, nextExpectedCharsLen;
1410        for (int token = begin; token < end; ++token) {
1411            if (token == YYTERROR || yycheck[n + token] != token) continue;
1412    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1413            printf(" %s", yytname[token]);
1414    #endif
1415    
1416            //if (yycheck[n + token] != token) goto default_reduction;
1417    
1418            action = yytable[n + token];
1419            if (action == 0 || action == YYTABLE_NINF) {
1420    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1421                printf(" (invalid action) "); fflush(stdout);
1422    #endif
1423                continue; // error, ignore
1424            }
1425            if (action < 0) { // reduction with rule -action required ...
1426    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1427                printf(" (reduction) "); fflush(stdout);
1428    #endif
1429                rule = -action;
1430                goto reduce;
1431            }
1432            if (action == YYFINAL) continue; // "accept" state, we don't care about it here
1433    
1434            // "shift" required ...
1435    
1436            if (std::find(stack.begin(), stack.end(), action) != stack.end())
1437                continue; // duplicate state, ignore it to avoid endless recursions
1438    
1439            // "shift" / push the new state on the state stack and call this
1440            // function recursively, and restore the stack after the recurse return
1441            stackSize = stack.size();
1442            nextExpectedCharsLen = nextExpectedChars.size();
1443            stack.push_back(action);
1444            nextExpectedChars += _tokenName(token);
1445            walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1446                stack, expectedSymbols, nextExpectedChars, depth + 1
1447            );
1448            stack.resize(stackSize); // restore stack
1449            nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'
1450            continue;
1451    
1452        //default_reduction: // resolve default reduction for this state
1453        //    printf(" (default red.) "); fflush(stdout);
1454        //    rule = yydefact[state];
1455    
1456        reduce: // "reduce" required
1457    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1458            printf(" (reduce by %d) ", rule); fflush(stdout);
1459    #endif
1460            if (rule == 0 || rule >= YYNRULES) continue; // invalid rule, something is wrong
1461            // store the left-hand symbol of the grammar rule
1462            expectedSymbols[yytname[yyr1[rule]]] = _symbolInfoForRule(rule, nextExpectedChars);
1463    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1464            printf(" (SYM %s) ", yytname[yyr1[rule]]); fflush(stdout);
1465    #endif
1466        }
1467    #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1468        printf("\n");
1469    #endif
1470    }
1471    
1472    /**
1473     * Implements Bison's so called "reduce" action, according to Bison's LALR(1)
1474     * parser algorithm.
1475   */   */
1476  void yyerror(const char* s) {  inline static int _yyReduce(std::vector<YYTYPE_INT16>& stack, const int& rule) {
1477        if (stack.empty()) throw 1; // severe error
1478        const int len = yyr2[rule];
1479        stack.resize(stack.size() - len);
1480        YYTYPE_INT16 newState = yypgoto[yyr1[rule] - YYNTOKENS] + stack.back();
1481        if (0 <= newState && newState <= YYLAST && yycheck[newState] == stack.back())
1482            newState = yytable[newState];
1483        else
1484            newState = yydefgoto[yyr1[rule] - YYNTOKENS];
1485        stack.push_back(newState);
1486        return newState;
1487    }
1488    
1489    /**
1490     * Implements Bison's so called "default reduce" action, according to Bison's
1491     * LALR(1) parser algorithm.
1492     */
1493    inline static int _yyDefaultReduce(std::vector<YYTYPE_INT16>& stack) {
1494        if (stack.empty()) throw 2; // severe error
1495        int rule = yydefact[stack.back()];
1496        if (rule <= 0 || rule >= YYNRULES) throw 3; // no rule, something is wrong
1497        return _yyReduce(stack, rule);
1498    }
1499    
1500    #define DEBUG_PUSH_PARSE 0
1501    
1502    /**
1503     * Implements parsing exactly one character (given by @a c), continueing at the
1504     * parser position reflected by @a stack. The @a stack will hold the new parser
1505     * state after this call.
1506     *
1507     * This function is implemented according to Bison's LALR(1) parser algorithm.
1508     */
1509    static bool yyPushParse(std::vector<YYTYPE_INT16>& stack, char ch) {
1510        startLabel:
1511    
1512    #if DEBUG_PUSH_PARSE
1513        //printf("\n");
1514        //for (int i = 0; i < depth; ++i) printf("\t");
1515        printf("State stack:");
1516        for (int i = 0; i < stack.size(); ++i) {
1517            printf(" %d", stack[i]);
1518        }
1519        printf(" char='%c'(%d)\n", ch, (int)ch);
1520    #endif
1521    
1522        if (stack.empty()) return false;
1523    
1524        int state = stack.back();
1525        int n = yypact[state];
1526        if (n == YYPACT_NINF) { // default reduction required ...
1527    #if DEBUG_PUSH_PARSE
1528            printf("(def reduce 1)\n");
1529    #endif
1530            state = _yyDefaultReduce(stack);
1531            goto startLabel;
1532        }
1533        if (!(YYPACT_NINF < n && n <= YYLAST)) return false;
1534    
1535        YYTYPE_INT16 token = (ch == YYEOF) ? YYEOF : yytranslate[ch];
1536        n += token;
1537        if (n < 0 || YYLAST < n || yycheck[n] != token) {
1538    #if DEBUG_PUSH_PARSE
1539            printf("(def reduce 2) n=%d token=%d\n", n, token);
1540    #endif
1541            state = _yyDefaultReduce(stack);
1542            goto startLabel;
1543        }
1544        int action = yytable[n]; // yytable[yypact[state] + token]
1545        if (action == 0 || action == YYTABLE_NINF) throw 4;
1546        if (action < 0) {
1547    #if DEBUG_PUSH_PARSE
1548            printf("(reduce)\n");
1549    #endif
1550            int rule = -action;
1551            state = _yyReduce(stack, rule);
1552            goto startLabel;
1553        }
1554        if (action == YYFINAL) return true; // final state reached
1555    
1556    #if DEBUG_PUSH_PARSE
1557        printf("(push)\n");
1558    #endif
1559        // push new state
1560        state = action;
1561        stack.push_back(state);
1562        return true;
1563    }
1564    
1565    /**
1566     * Returns true if parsing ahead with given character @a ch is syntactially
1567     * valid according to the LSCP grammar, it returns false if it would create a
1568     * parse error.
1569     *
1570     * This is just a wrapper ontop of yyPushParse() which converts parser
1571     * exceptions thrown by yyPushParse() into negative return value.
1572     */
1573    static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch) {
1574        try {
1575            return yyPushParse(stack, ch);
1576        } catch (int i) {
1577    #if DEBUG_PUSH_PARSE
1578            printf("exception %d\n", i);
1579    #endif
1580            return false;
1581        } catch (...) {
1582            return false;
1583        }
1584    }
1585    
1586    /**
1587     * Returns the amount of correct characters of given @a line from the left,
1588     * according to the LSCP grammar.
1589     *
1590     * @param stack - a Bison symbol state stack to work with
1591     * @param line  - the input line to check
1592     * @param bAutoCorrect - if true: try to correct obvious, trivial syntax errors
1593     */
1594    static int yyValidCharacters(std::vector<YYTYPE_INT16>& stack, String& line, bool bAutoCorrect) {
1595        int i;
1596        for (i = 0; i < line.size(); ++i) {
1597            // since we might check the same parser state twice against the current
1598            // char here below, and since the state stack might be altered
1599            // (i.e. shifted or reduced) on syntax errors, we have to backup the
1600            // current state stack and restore it on syntax errors below
1601            std::vector<YYTYPE_INT16> stackBackup = stack;
1602            if (yyValid(stackBackup, line[i])) {
1603                stack = stackBackup;
1604                continue;
1605            }
1606            if (bAutoCorrect) {
1607                // try trivial corrections, i.e. upper case character instead of
1608                // lower case, subline instead of space and vice versa
1609                char c;
1610                if      (line[i] == ' ') c = '_';
1611                else if (line[i] == '_') c = ' ';
1612                else if (isLowerCaseAlphaChar(line[i]))
1613                    c = alphaCharToUpperCase(line[i]);
1614                else return i;
1615                if (yyValid(stack, c)) {
1616                    line[i] = c;
1617                    continue;
1618                }
1619            }
1620            return i;
1621        }
1622        return i;
1623    }
1624    
1625    /**
1626     * Should only be called on syntax errors: returns a set of non-terminal
1627     * symbols expected to appear now/next, just at the point where the syntax
1628     * error appeared.
1629     */
1630    static std::set<String> yyExpectedSymbols() {
1631        std::map<String,BisonSymbolInfo> expectedSymbols;
1632      yyparse_param_t* param = GetCurrentYaccSession();      yyparse_param_t* param = GetCurrentYaccSession();
1633      String msg = s      YYTYPE_INT16* ss = (*param->ppStackBottom);
1634          + (" (line:"   + ToString(param->iLine+1))      YYTYPE_INT16* sp = (*param->ppStackTop);
1635          + ( ",column:" + ToString(param->iColumn))      int iStackSize   = sp - ss + 1;
1636          + ")";      // copy and wrap parser's state stack into a convenient STL container
1637      dmsg(2,("LSCPParser: %s\n", msg.c_str()));      std::vector<YYTYPE_INT16> stack;
1638      sLastError = msg;      for (int i = 0; i < iStackSize; ++i) {
1639            stack.push_back(ss[i]);
1640        }
1641        String notUsedHere;
1642        // do the actual parser work
1643        walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere);
1644    
1645        // convert expectedSymbols to the result set
1646        std::set<String> result;
1647        for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1648             it != expectedSymbols.end(); ++it) result.insert(it->first);
1649        return result;
1650    }
1651    
1652    namespace LinuxSampler {
1653    
1654    #define DEBUG_SHELL_INTERACTION 0
1655    
1656    /**
1657     * If LSP shell mode is enabled, then this function is called on every new
1658     * received from client. It will check the current total input line and reply
1659     * to the LSCP shell for providing colored syntax highlighting and potential
1660     * auto completion in the shell.
1661     *
1662     * It also performs auto correction of obvious & trivial syntax mistakes if
1663     * requested.
1664     */
1665    String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param) {
1666        // first, determine how many characters (starting from the left) of the
1667        // given input line are already syntactially correct
1668        std::vector<YYTYPE_INT16> stack;
1669        stack.push_back(0); // every Bison symbol stack starts with state zero
1670        String l = line + '\n'; // '\n' to pretend ENTER as if the line was now complete
1671        int n = yyValidCharacters(stack, l, param->bShellAutoCorrect);
1672    
1673        // if auto correction is enabled, apply the auto corrected string to
1674        // intput/output string 'line'
1675        if (param->bShellAutoCorrect) {
1676            int nMin = (n < line.length()) ? n : line.length();
1677            line.replace(0, nMin, l.substr(0, nMin));
1678        }
1679    
1680        // generate an info string that will be sent to the LSCP shell for letting
1681        // it know which part is correct, which one is wrong, where is the cursor, etc.
1682        String result = line;
1683        result.insert(n <= result.length() ? n : result.length(), LSCP_SHK_GOOD_FRONT);
1684        int code = (n > line.length()) ? LSCP_SHU_COMPLETE : (n < line.length()) ?
1685                   LSCP_SHU_SYNTAX_ERR : LSCP_SHU_INCOMPLETE;
1686        result = "SHU:" + ToString(code) + ":" + result + LSCP_SHK_CURSOR;
1687        //if (n > line.length()) result += " [OK]";
1688    
1689        // get a clean parser stack to the last valid parse position
1690        // (due to the appended '\n' character above, and on syntax errors, the
1691        // state stack might be in undesired, i.e. reduced state)
1692        stack.clear();
1693        stack.push_back(0); // every Bison symbol stack starts with state zero
1694        l = line.substr(0, n);
1695        if (!l.empty()) yyValidCharacters(stack, l, param->bShellAutoCorrect);
1696    
1697        // generate auto completion suggestion (based on the current parser stack)
1698        std::map<String,BisonSymbolInfo> expectedSymbols;
1699        String notUsedHere;
1700        walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere);
1701        if (expectedSymbols.size() == 1) {
1702            String name          = expectedSymbols.begin()->first;
1703            BisonSymbolInfo info = expectedSymbols.begin()->second;
1704    #if DEBUG_SHELL_INTERACTION
1705            printf("Suggested Completion (%d): %s '%s'\n", expectedSymbols.size(), (info.isTerminalSymbol) ? "T:" : "NT:", (name + " (" + info.nextExpectedChars + ")").c_str());
1706    #endif
1707            result += LSCP_SHK_SUGGEST_BACK + info.nextExpectedChars;
1708        } else if (expectedSymbols.size() == 0) {
1709    #if DEBUG_SHELL_INTERACTION
1710            printf("No suggestion.\n");
1711    #endif
1712        } else if (expectedSymbols.size() > 1) {
1713    #if DEBUG_SHELL_INTERACTION
1714            printf("Multiple possibilities:");
1715            for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1716                 it != expectedSymbols.end(); ++it)
1717            {
1718                printf(" %s (..%s)", it->first.c_str(), it->second.nextExpectedChars.c_str());
1719            }
1720            printf("\n");
1721    #endif
1722            // check if any of the possibilites is a non-terminal symbol, if so, we
1723            // have no way for auto completion at this point
1724            bool bNonTerminalExists = false;
1725            for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1726                 it != expectedSymbols.end(); ++it) if (!it->second.isTerminalSymbol) { bNonTerminalExists = true; break; };
1727            if (!bNonTerminalExists) {
1728                // all possibilites are terminal symbaols, so try to find the least
1729                // common string all possibilites start with from the left
1730                String sCommon;
1731                for (int i = 0; true; ++i) {
1732                    char c;
1733                    for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin();
1734                         it != expectedSymbols.end(); ++it)
1735                    {
1736                        if (i >= it->second.nextExpectedChars.size())
1737                            goto commonSearchEndLabel;
1738                        if (it == expectedSymbols.begin())
1739                            c = it->second.nextExpectedChars[i];
1740                        if (c != it->second.nextExpectedChars[i])
1741                            goto commonSearchEndLabel;
1742                        if (it == --expectedSymbols.end())
1743                            sCommon += c;
1744                    }
1745                }
1746                commonSearchEndLabel:
1747                if (!sCommon.empty()) result += LSCP_SHK_SUGGEST_BACK + sCommon;
1748    #if DEBUG_SHELL_INTERACTION
1749                printf("Common possibility: '%s'\n", sCommon.c_str());
1750    #endif
1751            }
1752        }
1753    
1754    #if DEBUG_SHELL_INTERACTION
1755        printf("%s\n", result.c_str());
1756    #endif
1757    
1758        return result;
1759  }  }
1760    
1761  /**  /**
# Line 1025  void restart(yyparse_param_t* pparam, in Line 1765  void restart(yyparse_param_t* pparam, in
1765      bytes = 0;      bytes = 0;
1766      ptr   = 0;      ptr   = 0;
1767      sLastError = "";      sLastError = "";
1768        sParsed = "";
1769    }
1770    
1771  }  }

Legend:
Removed from v.1345  
changed lines
  Added in v.2516

  ViewVC Help
Powered by ViewVC