CFugue
Parser.h
1 /*
2  This is part of CFugue, a C++ Runtime for MIDI Score Programming
3  Copyright (C) 2009 Gopalakrishna Palem
4 
5  For links to further information, or to contact the author,
6  see <http://cfugue.sourceforge.net/>.
7 
8  $LastChangedDate: 2014-05-10 10:56:34 +0530 (Sat, 10 May 2014) $
9  $Rev: 203 $
10  $LastChangedBy: krishnapg $
11 */
12 
13 #ifndef PARESER_H__B6901FE6_6B09_486c_87AB_E584C1DBE30F__
14 #define PARESER_H__B6901FE6_6B09_486c_87AB_E584C1DBE30F__
15 
16 /// <Summary>
17 /// You can enable or disable tracing events in the CParser derived classes by
18 /// defining ENABLE_TRACING to be 1 or 0 before including this header file.
19 /// By default, ENABLE_TRACING is defined to be 1 in DEBUG builds, and 0 in
20 /// RELEASE builds.
21 /// </Summary>
22 #ifndef ENABLE_TRACING
23 #if defined(DEBUG) || defined (_DEBUG)
24 #define ENABLE_TRACING 1
25 #endif // if defined(DEBUG)
26 #endif // ifndef ENABLE_TRACING
27 
28 #include "Common/EventHandler.h"
29 #include "Common/_TChar.h" // On Non win32 platforms we use a local TChar.h
30 
31 namespace CFugue
32 {
33  // Forward Declarations
34  class ChannelPressure;
35  class ControllerEvent;
36  class Instrument;
37  class KeySignature;
38  class Layer;
39  class PitchBend;
40  class PolyphonicPressure;
41  class Tempo;
42  class Time;
43  class Voice;
44  struct Note;
45  class CParserListener;
46 
47  /// <Summary>
48  /// \brief Base class that represents a Parser Object.
49  ///
50  /// Parsers are implemented using an event subscription model. For each token encountered
51  /// during the parsing, Parsers raise the appropriate event, which will be handled by the listeners.
52  /// This event model allows any CParser based object to be connected with any CParserListener based object.
53  /// For example, a MIDIParser can be connected to a Sheet Music generator, or a MusicString
54  /// parser can be connected to a MIDI Renderer.
55  ///
56  /// A listener interested in the Parse events can subscribe to all events at once using the CParser::AddListener method,
57  /// or subscribe to only few selected events using the event's Subscribe method.
58  ///
59  /// Multiple listeners can be connected to a single Parser object. However, the order in which the listeners are
60  /// notified about the events is not guaranteed to be sequential.
61  ///
62  /// </Summary>
63  class CParser : public OIL::CEventSource
64  {
65  public:
66 
67  OIL::CEventT<const CParser, const ControllerEvent> evController; ///< Event Raised when Parser encounters a MIDI Controller Event
68  OIL::CEventT<const CParser, const Instrument> evInstrument; ///< Event Raised when Parser encounters an Instrument command
69  OIL::CEventT<const CParser, const KeySignature> evKeySignature; ///< Event Raised when Parser encounters a Key Signature command
70  OIL::CEventT<const CParser, const Layer> evLayer; ///< Event Raised when Parser encounters a Layer command
71  OIL::CEventT<const CParser> evMeasure; ///< Event Raised when Parser encounters a Measure bar
72  OIL::CEventT<const CParser, const ChannelPressure> evChannelPressure; ///< Event Raised when Parser encounters a Channel Pressure command
73  OIL::CEventT<const CParser, const PolyphonicPressure> evPolyphonicPressure; ///< Event Raised when Parser encounters a Key Pressure command
74  OIL::CEventT<const CParser, const PitchBend> evPitchBend; ///< Event Raised when Parser encounters a PitchBend command
75  OIL::CEventT<const CParser, const Tempo> evTempo; ///< Event Raised when Parser encounters a Tempo command
76  OIL::CEventT<const CParser, const Time> evTime; ///< Event Raised when Parser encounters a Time command
77  OIL::CEventT<const CParser, const Voice> evVoice; ///< Event Raised when Parser encounters a Voice command
78  OIL::CEventT<const CParser, const Note> evNote; ///< Event Raised when Parser encounters a Note
79  OIL::CEventT<const CParser> evSequentialNote; ///< Encountered a Sequential note after a first note
80  OIL::CEventT<const CParser> evParalleNote; ///< Encountered a Parallel note after a first note
81 
82  inline CParser(void) { }
83 
84  inline virtual ~CParser(void) { }
85 
86  /// <Summary> Subscribes a Listener object for all events </Summary>
87  void AddListener(CParserListener* pListener);
88 
89  /// <Summary> UnSubscribes the Listener Object from the events </Summary>
90  void RemoveListener(CParserListener* pListener);
91 
92  void* m_pUserData;
93 
94  void SetUserData(void* pData) { m_pUserData = pData; }
95 
96  const void* GetUserData() const { return m_pUserData; }
97  public:
98  /// <Summary>Error code values used by ErrorEventHandlerArgs</Summary>
99  enum ErrorCode
100  {
101  CRITICAL_ERROR_MEMORY_ALLOCATION, ///< Memory allocation failed
102  PARSE_ERROR_MISSING_ASSIGNMENT, ///< No Assignment symbol found
103  PARSE_ERROR_CPRESSURE_MACRO_END, ///< MACRO_END missing while parsing a Controller Index Macro.
104  PARSE_ERROR_CPRESSURE_VALUE, ///< Failure while converting/retrieving a Controller Value number.
105  PARSE_ERROR_CONTROLLER_MACRO_END, ///< MACRO_END missing while parsing a Controller Index Macro.
106  PARSE_ERROR_CONTROLLER_VALUE, ///< Failure while converting/retrieving a Controller Value number.
107  PARSE_ERROR_INSTRUMENT_MACRO_END, ///< MACRO_END missing while parsing a Instrument Macro.
108  PARSE_ERROR_INSTRUMENT_VALUE, ///< Failure while converting/retrieving a Instrument number.
109  PARSE_ERROR_KEYPRESSURE_MACRO_END, ///< MACRO_END missing while parsing a Polyphonic Pressure Macro.
110  PARSE_ERROR_KEYPRESSURE_VALUE, ///< Failure while converting/retrieving a Polyphonic Pressure number.
111  PARSE_ERROR_KEYSIGNATURE_MACRO_END, ///< MACRO_END missing while parsing a Key Signature Macro.
112  PARSE_ERROR_KEYSIGNATURE_VALUE, ///< Failure while converting/retrieving a Key Signature number.
113  PARSE_ERROR_KEYSIGNATURE_MAXLIMIT, ///< Specified a KeySignature beyond permitted range [0, 14] , [64, 78], [129, 200]
114  PARSE_ERROR_PITCHBEND_MACRO_END, ///< MACRO_END missing while parsing a PitchBend Macro.
115  PARSE_ERROR_PITCHBEND_VALUE, ///< Failure while converting/retrieving a PitchBend number.
116  PARSE_ERROR_TALAM_MACRO_END, ///< MACRO_END missing while parsing a Talam Macro.
117  PARSE_ERROR_TALAM_VALUE, ///< Failure while converting/retrieving a Talam number.
118  PARSE_ERROR_TALAM_MAXLIMIT, ///< Specified a Talam beyond permitted range [0, 35]
119  PARSE_ERROR_SPEED_MACRO_END, ///< MACRO_END missing while parsing a Speed Macro.
120  PARSE_ERROR_SPEED_VALUE, ///< Failure while converting/retrieving a Speed number.
121  PARSE_ERROR_SPEED_MAXLIMIT, ///< Specified a Speed beyond permitted range [1, 6]
122  PARSE_ERROR_LAYER_MACRO_END, ///< MACRO_END missing while parsing a Layer Macro.
123  PARSE_ERROR_LAYER_VALUE, ///< Failure while converting/retrieving a Layer number.
124  PARSE_ERROR_TEMPO_MACRO_END, ///< MACRO_END missing while parsing a Tempo Macro.
125  PARSE_ERROR_TEMPO_VALUE, ///< Failure while converting/retrieving a Tempo number.
126  PARSE_ERROR_TIME_MACRO_END, ///< MACRO_END missing while parsing a Time Macro.
127  PARSE_ERROR_TIME_VALUE, ///< Failure while converting/retrieving a Time number.
128  PARSE_ERROR_VOICE_MACRO_END, ///< MACRO_END missing while parsing a Voice Macro.
129  PARSE_ERROR_VOICE_VALUE, ///< Failure while converting/retrieving a Voice number.
130  PARSE_ERROR_VOICE_MAXLIMIT, ///< Specified a voice that is beyond the permitted range [0, 15]
131  PARSE_ERROR_NUMERIC_NOTE_END, ///< MACRO_END missing while parsing a numeric note.
132  PARSE_ERROR_NUMERIC_NOTE_VALUE, ///< Failure while converting/retrieving a numeric note number.
133  PARSE_ERROR_LETTER_NOTE, ///< Invalid Alphabet encountering while trying to read a Note Symbol
134  PARSE_ERROR_CHORDINV_MACRO_END, ///< MACRO_END missing while parsing a Chord Inversion.
135  PARSE_ERROR_CHORDINV_VALUE, ///< Failure while converting/retrieving a Chord Inversion Root Note number.
136  PARSE_ERROR_CHORDINV_MAXLIMIT, ///< Specified an inversion root note that is not with in acceptable range of values
137  PARSE_ERROR_OCTAVE_MACRO_END, ///< MACRO_END missing while parsing an Octave Macro
138  PARSE_ERROR_OCTAVE_VALUE, ///< Failure while conveting/retrieving an Octave macro number
139  PARSE_ERROR_OCTAVE_MAXLIMIT, ///< Specified an octave that is beyond the permitted range [0, 10]
140  PARSE_ERROR_DURATION_MACRO_END, ///< MACRO_END missing while parsing an Duration Macro
141  PARSE_ERROR_DURATION_VALUE, ///< Failure while conveting/retrieving a Duration number
142  PARSE_ERROR_TUPLET_NUMERATOR, ///< Failure while conveting/retrieving the Numerator of Tuplet fraction
143  PARSE_ERROR_TUPLET_DENOMINATOR, ///< Failure while conveting/retrieving the Denominator of Tuplet fraction
144  PARSE_ERROR_VELOCITY_MACRO_END, ///< MACRO_END missing while parsing a Velocity Macro
145  PARSE_ERROR_VELOCITY_VALUE, ///< Failure while conveting/retrieving a Velocity number
146  PARSE_ERROR_NOTEVALUE_MAXLIMIT, ///< Computed Note Value is going beyond the permitted range [0, 127]
147  };
148  /// <Summary>
149  /// The structure that is passed as argument to the Error Event Handler procedure.
150  /// Listeners who want to know about the error events can subscribe to the evError
151  /// event and handle the trace events raised by MusicStringParser as the parsing progresses.
152  ///
153  /// Unlike the other programming paradigms that teach greedy methods asking you to exit
154  /// the moment any error occurs, CFugue library fights to live its best before it gives up.
155  /// So, usually if there is any error in parsing a token, parser does not abort and tries to continue
156  /// parsing the rest of the tokens.
157  /// In case this behavior is not suitable for your application and if you would like to stop the processing
158  /// immediately when there is an error, you can indicate your preference to stop the processing
159  /// by using the <code>bShouldStopParsing</code> variable. Set it to true in the error handler
160  /// procedure, to halt the processing immediately. By default it would be False (meaning the parser
161  /// should continue its best to resolve the token ignoring the error).
162  ///
163  /// %Note that, when there are multiple listeners for the event, options set by one listener might be
164  /// overriden by the next listener. Parser only respects the last value it sees. So, use care while
165  /// dealing with multiple listeners, and ensure that they do not use conflicting settings.
166  ///
167  /// Ofcourse, in case of critical errors such as memory allocation failure etc.. there is nothing
168  /// that could be done, so the listener preferences are ignored and processing would be stopped.
169  /// </Summary>
171  {
172  const ErrorCode errCode; ///< Error Code
173  const TCHAR* szErrMsg; ///< The Error message sent by Parser
174  const TCHAR* szToken; ///< Token the error is applicable for
175  bool bShouldStopParsing; ///< Should Parser continue to parse or should stop now? (only for PARSE_ERRORS)
176 
177  inline ErrorEventHandlerArgs(ErrorCode argErrCode, const TCHAR* argErrMsg, const TCHAR* argSzToken)
178  : errCode(argErrCode), szErrMsg(argErrMsg), szToken(argSzToken), bShouldStopParsing(false) { }
179  };
180 
181  OIL::CEventT<const CParser, ErrorEventHandlerArgs> evError; ///< Raised when a parse error happens
182  protected:
183  /// <Summary>
184  /// Error method is called whenever there is a parse error.
185  /// This method will raise events through the CParser::evError event
186  /// variable. Listeners can subscribe to it to get to know about the parse errors.
187  ///
188  /// You can override this method in derived classes if you wish to modify this error
189  /// reporting implementation.
190  ///
191  /// @param argErrCode the Error code
192  /// @param szTraceMsg Error message details
193  /// @param szToken The token that is being parsed when the error happened
194  /// @return Boolean value indicating if the parsing should stop now or should continue
195  /// </Summary>
196  inline virtual bool Error(ErrorCode argErrCode, const TCHAR* szTraceMsg, const TCHAR* szToken)
197  {
198  ErrorEventHandlerArgs evArgs(argErrCode, szTraceMsg, szToken);
200  return evArgs.bShouldStopParsing;
201  }
202 
203  public:
204  /// <Summary>
205  /// The structure that is passed as argument to the Trace Event Handler procedure.
206  /// Listeners who want to know about the trace events can subscribe to the CParser::evTrace
207  /// event and handle the trace events raised by the Parser as the parsing progresses.
208  /// </Summary>
210  {
211  const TCHAR* szTraceMsg; ///< The Error message sent by Parser
212  inline TraceEventHandlerArgs(const TCHAR* sz) : szTraceMsg(sz) { }
213  };
214 
215  OIL::CEventT<const CParser, TraceEventHandlerArgs> evTrace; ///< Raised by Parser during the Parsing
216 
217 #if ENABLE_TRACING
218  protected:
219  /// <Summary>
220  /// Trace method is called through out the parsing process. However, the functionality
221  /// is enabled only if ENABLE_TRACING directive is defined to be 1 (which is default for
222  /// DEBUG builds, but not for RELEASE builds).
223  /// When enabled, Trace will raise events through the CParser::evTrace event
224  /// variable. Listeners can subscribe to this event to get to know the trace messages.
225  ///
226  /// @param szTraceMsg the Trace message generated by the Parser
227  /// </Summary>
228  inline virtual void Trace(const TCHAR* szTraceMsg)
229  {
230  TraceEventHandlerArgs args(szTraceMsg);
232  }
233 #else
234 
235 #define Trace(x)
236 
237 #endif // #if ENABLE_TRACING
238  };
239 
240 } // namespace CFugue
241 
242 
243 
244 #endif // PARESER_H__B6901FE6_6B09_486c_87AB_E584C1DBE30F__
MACRO_END missing while parsing a Voice Macro.
Definition: Parser.h:128
MACRO_END missing while parsing a Velocity Macro.
Definition: Parser.h:144
Failure while converting/retrieving a Controller Value number.
Definition: Parser.h:106
Computed Note Value is going beyond the permitted range [0, 127].
Definition: Parser.h:146
Failure while converting/retrieving a PitchBend number.
Definition: Parser.h:115
OIL::CEventT< const CParser, const Voice > evVoice
Event Raised when Parser encounters a Voice command.
Definition: Parser.h:77
Failure while converting/retrieving a numeric note number.
Definition: Parser.h:132
Failure while conveting/retrieving the Numerator of Tuplet fraction.
Definition: Parser.h:142
void AddListener(CParserListener *pListener)
Subscribes a Listener object for all events
Definition: Parser.cpp:16
OIL::CEventT< const CParser, const PitchBend > evPitchBend
Event Raised when Parser encounters a PitchBend command.
Definition: Parser.h:74
void RemoveListener(CParserListener *pListener)
UnSubscribes the Listener Object from the events
Definition: Parser.cpp:35
Failure while conveting/retrieving a Duration number.
Definition: Parser.h:141
MACRO_END missing while parsing a Speed Macro.
Definition: Parser.h:119
Failure while converting/retrieving a Instrument number.
Definition: Parser.h:108
OIL::CEventT< const CParser, const Tempo > evTempo
Event Raised when Parser encounters a Tempo command.
Definition: Parser.h:75
MACRO_END missing while parsing a Key Signature Macro.
Definition: Parser.h:111
No Assignment symbol found.
Definition: Parser.h:102
Specified a KeySignature beyond permitted range [0, 14] , [64, 78], [129, 200].
Definition: Parser.h:113
Failure while converting/retrieving a Speed number.
Definition: Parser.h:120
Specified a Talam beyond permitted range [0, 35].
Definition: Parser.h:118
Failure while conveting/retrieving the Denominator of Tuplet fraction.
Definition: Parser.h:143
OIL::CEventT< const CParser, const ControllerEvent > evController
Event Raised when Parser encounters a MIDI Controller Event.
Definition: Parser.h:67
MACRO_END missing while parsing a Controller Index Macro.
Definition: Parser.h:103
Failure while conveting/retrieving an Octave macro number.
Definition: Parser.h:138
Invalid Alphabet encountering while trying to read a Note Symbol.
Definition: Parser.h:133
MACRO_END missing while parsing an Duration Macro.
Definition: Parser.h:140
Specified a voice that is beyond the permitted range [0, 15].
Definition: Parser.h:130
OIL::CEventT< const CParser > evMeasure
Event Raised when Parser encounters a Measure bar.
Definition: Parser.h:71
OIL::CEventT< const CParser, const KeySignature > evKeySignature
Event Raised when Parser encounters a Key Signature command.
Definition: Parser.h:69
OIL::CEventT< const CParser, TraceEventHandlerArgs > evTrace
Raised by Parser during the Parsing.
Definition: Parser.h:215
Specified a Speed beyond permitted range [1, 6].
Definition: Parser.h:121
MACRO_END missing while parsing a Polyphonic Pressure Macro.
Definition: Parser.h:109
OIL::CEventT< const CParser, ErrorEventHandlerArgs > evError
Raised when a parse error happens.
Definition: Parser.h:181
MACRO_END missing while parsing a numeric note.
Definition: Parser.h:131
OIL::CEventT< const CParser, const Note > evNote
Event Raised when Parser encounters a Note.
Definition: Parser.h:78
MACRO_END missing while parsing a PitchBend Macro.
Definition: Parser.h:114
const TCHAR * szToken
Token the error is applicable for.
Definition: Parser.h:174
MACRO_END missing while parsing an Octave Macro.
Definition: Parser.h:137
Failure while converting/retrieving a Polyphonic Pressure number.
Definition: Parser.h:110
MACRO_END missing while parsing a Tempo Macro.
Definition: Parser.h:124
ErrorCode
Error code values used by ErrorEventHandlerArgs
Definition: Parser.h:99
OIL::CEventT< const CParser, const ChannelPressure > evChannelPressure
Event Raised when Parser encounters a Channel Pressure command.
Definition: Parser.h:72
const ErrorCode errCode
Error Code.
Definition: Parser.h:172
const TCHAR * szTraceMsg
The Error message sent by Parser.
Definition: Parser.h:211
Specified an inversion root note that is not with in acceptable range of values.
Definition: Parser.h:136
Failure while converting/retrieving a Time number.
Definition: Parser.h:127
MACRO_END missing while parsing a Layer Macro.
Definition: Parser.h:122
OIL::CEventT< const CParser, const PolyphonicPressure > evPolyphonicPressure
Event Raised when Parser encounters a Key Pressure command.
Definition: Parser.h:73
OIL::CEventT< const CParser, const Time > evTime
Event Raised when Parser encounters a Time command.
Definition: Parser.h:76
Base class that represents a Parser Object.
Definition: Parser.h:63
Failure while converting/retrieving a Controller Value number.
Definition: Parser.h:104
OIL::CEventT< const CParser > evParalleNote
Encountered a Parallel note after a first note.
Definition: Parser.h:80
Failure while conveting/retrieving a Velocity number.
Definition: Parser.h:145
Failure while converting/retrieving a Voice number.
Definition: Parser.h:129
Failure while converting/retrieving a Chord Inversion Root Note number.
Definition: Parser.h:135
OIL::CEventT< const CParser > evSequentialNote
Encountered a Sequential note after a first note.
Definition: Parser.h:79
Specified an octave that is beyond the permitted range [0, 10].
Definition: Parser.h:139
MACRO_END missing while parsing a Chord Inversion.
Definition: Parser.h:134
OIL::CEventT< const CParser, const Instrument > evInstrument
Event Raised when Parser encounters an Instrument command.
Definition: Parser.h:68
const TCHAR * szErrMsg
The Error message sent by Parser.
Definition: Parser.h:173
Failure while converting/retrieving a Layer number.
Definition: Parser.h:123
OIL::CEventT< const CParser, const Layer > evLayer
Event Raised when Parser encounters a Layer command.
Definition: Parser.h:70
Failure while converting/retrieving a Key Signature number.
Definition: Parser.h:112
Failure while converting/retrieving a Talam number.
Definition: Parser.h:117
MACRO_END missing while parsing a Talam Macro.
Definition: Parser.h:116
bool bShouldStopParsing
Should Parser continue to parse or should stop now? (only for PARSE_ERRORS)
Definition: Parser.h:175
void RaiseEvent(CEventT< TEventSource, TEventHandlerArgs > *pEvent, TEventHandlerArgs *pArgs)
Definition: EventHandler.h:320
MACRO_END missing while parsing a Time Macro.
Definition: Parser.h:126
virtual bool Error(ErrorCode argErrCode, const TCHAR *szTraceMsg, const TCHAR *szToken)
Definition: Parser.h:196
MACRO_END missing while parsing a Controller Index Macro.
Definition: Parser.h:105
MACRO_END missing while parsing a Instrument Macro.
Definition: Parser.h:107
Failure while converting/retrieving a Tempo number.
Definition: Parser.h:125

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem