1 %{
2 
3 #include <string>
4 #include <iostream>
5 #include <vector>
6 #include <assert.h>
7 
8 #include "guidoelement.h"
9 #include "gmnreader.h"
10 #include "guidorational.h"
11 
12 #include "guidoparse.h++"
13 #include "guidolex.c++"
14 
15 int guidoarerror(const char*s);
guidoarwrap()16 int	guidoarwrap()		{ return(1); }
17 
18 extern guido::gmnreader* gReader;
19 
vadd(std::vector<guido::Sguidoelement> * v1,std::vector<guido::Sguidoelement> * v2)20 static void vadd (std::vector<guido::Sguidoelement>* v1, std::vector<guido::Sguidoelement>* v2)
21 {
22 	for (std::vector<guido::Sguidoelement>::iterator i = v2->begin(); i != v2->end(); i++)
23 		v1->push_back(*i);
24 }
25 
26 //#define parseDebug
27 
28 #ifdef parseDebug
29 #define debug(msg)		cout << msg << endl;
30 #define vdebug(msg,v)	cout << msg << " " << v << endl;
31 #else
32 #define debug(msg)
33 #define vdebug(msg, v)
34 #endif
35 
36 #define addElt(to,elt)	(to)->push(*elt); delete elt
37 
38 using namespace std;
39 
40 namespace guido
41 {
42 
43 %}
44 
45 
46 //%pure_parser
47 
48 %union {
49 	long int		num;
50 	float			real;
51 	const char*		token;
52 	std::string*	str;
53 	char			c;
54 	guido::Sguidoelement *		elt;
55 	guido::Sguidoattribute*		attr;
56 	std::vector<guido::Sguidoelement>*	 velt;
57 	std::vector<guido::Sguidoattribute>* vattr;
58 	guido::rational *		r;
59 }
60 
61 /*------------------------------ numbers ------------------------------*/
62 %token NUMBER
63 %token PNUMBER
64 %token NNUMBER
65 %token FLOAT
66 
67 /*------------------------------ markers ------------------------------*/
68 %token STARTCHORD
69 %token ENDCHORD
70 %token STARTSEQ
71 %token ENDSEQ
72 %token STARTPARAM
73 %token ENDPARAM
74 %token STARTRANGE
75 %token ENDRANGE
76 %token SEP
77 %token IDSEP
78 
79 /*------------------------------   tags  ------------------------------*/
80 %token BAR
81 %token TAGNAME
82 %token ID
83 
84 /*------------------------------   notes ------------------------------*/
85 %token DIATONIC
86 %token CHROMATIC
87 %token SOLFEGE
88 %token EMPTY
89 %token REST
90 %token DOT
91 %token DDOT
92 %token SHARP
93 %token FLAT
94 
95 /*------------------------------   misc  ------------------------------*/
96 %token MLS
97 %token SEC
98 %token UNIT
99 %token MULT
100 %token DIV
101 %token EQUAL
102 %token STRING
103 %token EXTRA
104 
105 %type <num> 	NUMBER PNUMBER NNUMBER
106 %type <real> 	FLOAT floatn
107 %type <token>	TAGNAME ID MLS SEC STRING UNIT DIATONIC CHROMATIC SOLFEGE REST
108 %type <token>	EMPTY DOT DDOT EXTRA
109 %type <c>		STARTCHORD ENDCHORD STARTSEQ ENDSEQ STARTPARAM ENDPARAM STARTRANGE ENDRANGE SEP IDSEP BAR
110 %type <c>		SHARP FLAT MULT DIV EQUAL
111 
112 %type <str>		notename noteid tagname id
113 %type <num>		dots accidentals accidental octave number pnumber nnumber signednumber
114 %type <r>		duration
115 %type <elt>		score voice note rest music chord  tag tagid positiontag rangetag rangechordtag
116 %type <attr>	tagarg tagparam
117 %type <velt>	symbols voicelist chordsymbol chordsymbols taglist tagchordsymbol
118 %type <vattr>	tagparams
119 
120 %%
121 
122 start		: score				{delete $1;}
123 		;
124 
125 //_______________________________________________
126 score		: STARTCHORD ENDCHORD							{ debug("new score"); $$ = gReader->newScore(); }
127 			| STARTCHORD voicelist ENDCHORD					{ debug("score voicelist"); $$ = gReader->newScore(); addElt(*$$, $2); }
128 			| voice											{ debug("score voice"); $$ = gReader->newScore(); addElt(*$$, $1); }
129 			;
130 
131 voicelist	: voice											{ debug("new voicelist"); $$ = new vector<Sguidoelement>; $$->push_back (*$1); delete $1; }
132 			| voicelist SEP voice							{ debug("add voicelist"); $$ = $1; $$->push_back (*$3); delete $3; }
133 			;
134 
135 voice		: STARTSEQ symbols ENDSEQ						{ debug("new voice"); $$ = gReader->newVoice(); addElt(*$$, $2); }
136 			;
137 
138 symbols		:												{ debug("new symbols"); $$ = new vector<Sguidoelement>; }
139 			| symbols music									{ debug("add music"); $$ = $1; $$->push_back(*$2); delete $2; }
140 			| symbols tag									{ debug("add tag"); $$ = $1; $$->push_back(*$2); delete $2; }
141 			| symbols chord									{ debug("add chord"); $$ = $1; $$->push_back(*$2); delete $2; }
142 			;
143 
144 //_______________________________________________
145 // tags description
146 tag			: positiontag									{ debug("position tag "); $$ = $1; }
147 			| rangetag										{ debug("range tag "); $$ = $1; }
148 			;
149 
150 positiontag	: tagid											{ debug("new position tag "); $$ = $1; }
151 			| tagid STARTPARAM tagparams ENDPARAM			{ debug("new tag + params"); $$ = $1; (*$1)->add (*$3); delete $3; }
152 			;
153 
154 rangetag	: positiontag  STARTRANGE symbols ENDRANGE		{ debug("new range tag "); $$ = $1; (*$1)->push (*$3); delete $3; }
155 			;
156 
157 tagname		: TAGNAME										{ debug("tag name "); $$ = new string(guidoartext); }
158 			;
159 
160 tagid		: tagname										{ vdebug("new tag", *$1); $$ = gReader->newTag(*$1, 0); delete $1; if (!$$) { guidoarerror("unknown tag"); YYERROR;} }
161 			| tagname IDSEP NUMBER							{ debug("new tag::id"); $$ = gReader->newTag(*$1, $2); delete $1; if (!$$) { guidoarerror("unknown tag"); YYERROR;} }
162 			| BAR											{ debug("new bar"); $$ = gReader->newTag("bar", 0); }
163 			;
164 
165 tagarg		: signednumber									{ debug("new signednumber arg"); $$ = gReader->newAttribute($1); }
166 			| floatn										{ debug("new FLOAT arg"); $$ = gReader->newAttribute($1); }
167 			| signednumber UNIT								{ debug("new signednumber UNIT arg"); $$ = gReader->newAttribute($1); (*$$)->setUnit(guidoartext); }
168 			| floatn UNIT									{ debug("new FLOAT UNIT arg"); $$ = gReader->newAttribute($1); (*$$)->setUnit(guidoartext); }
169 			| STRING										{ debug("new STRING arg"); $$ = gReader->newAttribute(guidoartext, true); }
170 			| id											{ debug("new ID arg"); $$ = gReader->newAttribute(*$1, false); delete $1; }
171 			;
172 
173 tagparam	: tagarg										{ $$ = $1; }
174 			| id EQUAL tagarg								{ $$ = $3; (*$3)->setName(*$1); delete $1; }
175 			;
176 
177 tagparams	: tagparam										{ $$ = new vector<Sguidoattribute>; $$->push_back(*$1); delete $1; }
178 			| tagparams SEP tagparam						{ $$ = $1; $$->push_back(*$3); delete $3; }
179 			;
180 
181 
182 //_______________________________________________
183 // chord description
184 
185 chord		: STARTCHORD chordsymbols ENDCHORD				{ debug("new chord"); $$ = gReader->newChord(); (*$$)->push(*$2); delete $2; }
186 			;
187 
188 chordsymbols: tagchordsymbol								{ $$ = new vector<Sguidoelement>; vadd($$, $1); delete $1; }
189 			| chordsymbols SEP tagchordsymbol				{ $$ = $1; vadd($$, $3); delete $3; }
190 			;
191 
192 tagchordsymbol: chordsymbol									{ $$ = $1;}
193 			| taglist chordsymbol							{ $$ = $1; vadd($$, $2); delete $2; }
194 			| chordsymbol taglist							{ $$ = $1; vadd($$, $2); delete $2; }
195 			| taglist chordsymbol taglist					{ $$ = $1; vadd($$, $2); delete $2; vadd($$, $3); delete $3; }
196 			;
197 
198 chordsymbol	: music											{ $$ = new vector<Sguidoelement>; $$->push_back(*$1); delete $1; }
199 			| rangechordtag									{ $$ = new vector<Sguidoelement>; $$->push_back(*$1); delete $1; }
200 			;
201 
202 rangechordtag : positiontag  STARTRANGE tagchordsymbol ENDRANGE	{ debug("range chord tag"); $$ = $1; (*$$)->push(*$3); delete $3; }
203 			;
204 
205 taglist		: positiontag									{ debug("new taglist 1"); $$ = new vector<Sguidoelement>; $$->push_back(*$1); delete $1; }
206 			| taglist positiontag							{ debug("new taglist 2"); $$ = $1; $$->push_back(*$2); delete $2; }
207 			;
208 
209 //_______________________________________________
210 // notes description
211 
212 music		: note											{ $$ = $1; }
213 			| rest											{ $$ = $1; }
214 			;
215 
216 rest		: REST duration	dots							{ debug("new rest 1"); $$ = gReader->newRest($2, $3); delete $2; }
217 			| REST STARTPARAM NUMBER ENDPARAM duration dots	{ debug("new rest 2"); $$ = gReader->newRest($5, $6); delete $5; }
218 			;
219 
220 note		: noteid octave duration dots				{ debug("new note v1"); $$ = gReader->newNote(*$1, 0, $2, $3, $4); delete $1; delete $3; }
221 			| noteid accidentals octave duration dots	{ debug("new note v2"); $$ = gReader->newNote(*$1, $2, $3, $4, $5); delete $1; delete $4; }
222 			;
223 
224 noteid		: notename									{ vdebug("notename", *$1); $$ = $1; }
225 			| notename STARTPARAM NUMBER ENDPARAM		{ $$ = $1; }
226 			;
227 
228 notename	: DIATONIC								{ debug("new diatonic note"); $$ = new string(guidoartext); }
229 			| CHROMATIC								{ debug("new chromatic note"); $$ = new string(guidoartext); }
230 			| SOLFEGE								{ debug("new solfege note"); $$ = new string(guidoartext); }
231 			| EMPTY									{ debug("new empty note"); $$ = new string(guidoartext); }
232 			;
233 
234 accidentals	: accidental							{ debug("accidental"); $$ = $1; }
235 			| accidentals accidental				{ debug("accidentals"); $$ = $1 + $2; }
236 			;
237 
238 accidental	: SHARP									{ debug("sharp"); $$ = 1; }
239 			| FLAT									{ debug("flat"); $$ = -1; }
240 			;
241 
242 octave		:										{ debug("no octave"); $$ = -1000; }					// implicit duration
243 			| signednumber							{ debug("octave"); $$ = $1; }
244 			;
245 
246 duration	:										{ debug("implicit duration"); $$ = new rational(-1, 1); }	// implicit duration
247 			| MULT number DIV number				{ debug("duration ./."); $$ = new rational($2, $4); }
248 			| MULT number							{ debug("duration *"); $$ = new rational($2, 1); }
249 			| DIV number							{ debug("duration /"); $$ = new rational(1, $2); }
250 			;
251 
252 dots		:										{ debug("dots 0"); $$ = 0; }
253 			| DOT									{ debug("dots 1"); $$ = 1; }
254 			| DDOT									{ debug("dots 2"); $$ = 2; }
255 			;
256 
257 //_______________________________________________
258 // misc
259 
260 id			: ID									{ $$ = new string(guidoartext); }
261 			;
262 number		: NUMBER								{ vdebug("NUMBER", guidoartext); $$ = atol(guidoartext); }
263 			;
264 pnumber		: PNUMBER								{ vdebug("NUMBER", guidoartext); $$ = atol(guidoartext); }
265 			;
266 nnumber		: NNUMBER								{ vdebug("NUMBER", guidoartext); $$ = atol(guidoartext); }
267 			;
268 floatn		: FLOAT									{ $$ = atof(guidoartext); }
269 			;
270 signednumber: number								{ $$ = $1; }
271 			| pnumber								{ $$ = $1; }
272 			| nnumber								{ $$ = $1; }
273 			;
274 %%
275 
276 } // namespace
277 
guidoarerror(const char * s)278 int guidoarerror(const char*s) {
279 	YY_FLUSH_BUFFER;
280 	return gReader->error(s, guidoarlineno);
281 }
282