}
-
+@Book{banter,
+ author = {Harald Banter},
+ title = {Akkord Lexikon},
+ publisher = {Schott's S\"ohne},
+ year = {1987},
+ isbn = {ISBN 3-7957-2095-8},
+ note = {Comprehensive overview of commonly used
+ chords. Suggests (and uses) a unification for all different kinds
+ of chord names.},
+ address = {Mainz, Germany},
+}
@Book {read78,
* who is trying to print too (small/big) piano braces all the time?
warning: piano brace too small (16.000pt)
-
* latex bla.tex broken (titles / \lilyfooter stuff?)
* msgfmt -o check?
* space after bars?
- * [/3 c8 c16 c c c]/1
+ * \type Voice \times 2/3 { [c8 c16 c16 c16 c16] }
* fix singleStaffBracket
* The time signature warnings still remain, will be fixed later.
-ii Summary of minor spelling irregularities:
+ Summary of minor spelling irregularities:
- capitalization/use of underscores in property names
* fix SkipBars -> skipBars
* typo checks on property names?
- * make engraver hacking robust.
-
- * --safe: disallow backslashes, disallow \include.
+ * --safe: disallow backslashes
* use streambufs and iostream
to provide IO handling for TeX stream, mudela stream, data-file.
3RD PARTY BUGS:
+ * make GCC warn about ctor that leaves member vars uninitialised.
+
* redhat (v?) graphical install bomb-out?
* GNU diff 2.7: diff -rN does not see a new directory with empty file
--- /dev/null
+%{
+ chord modifiers
+%}
+
+\chordmodifiers {
+ m = \musicalpitch { 0 2 -1 }
+ min = \musicalpitch { 0 2 -1 }
+ aug = \musicalpitch { 0 4 1 }
+ dim = \musicalpitch { 0 4 -1 }
+ % urg, not actually a chord-modifier, but it works
+ % c7 -> <c bes>, c 7+ -> c b
+ maj = \musicalpitch { 0 6 1 }
+ % sus4 should delete 2 too...
+ sus = \musicalpitch { 0 3 0 }
+}
\include "dynamic.ly"
\include "nederlands.ly" % dutch
+\include "chord-modifiers.ly"
\include "script.ly"
--- /dev/null
+\version "1.0.12";
+
+%{
+Would this be acceptable/good enough/convenient for entry?
+
+ Convention/Standard Lily
+
+ C# cis
+ Cb ces
+ Cm; Cmin c3-; c m; c min
+ Caug c5+; c aug;
+ Cdim c5-; c dim
+ Cmaj7 c7+; c maj
+ C7 c7
+ Csus; Csus4 c4; c sus
+%}
+
+scales = \notes\transpose c''\chords{
+ <c1 e g>
+ @1c m @c min @4c dim @c aug @c sus @c maj
+ @1c6 @4c7 @c9 @c11 @c13
+ @1c @g @d @a @e @b @fis
+ @1c @f @bes @es @as @des @ges
+ }
+
+keys = \notes{
+ s1
+ s1 s1 s1
+ s1 s1
+ s1
+ \key g; s1
+ \key d; s1
+ \key a; s1
+ \key e; s1
+ \key b; s1
+ \key fis; s1
+ \key c; s1
+ \key f; s1
+ \key bes; s1
+ \key es; s1
+ \key as; s1
+ \key des; s1
+ \key ges; s1
+ }
+
+\score{
+ <
+ \type ChordNames \scales
+ \type Staff < \scales \keys >
+ >
+}
--- /dev/null
+\version "1.0.12";
+
+%{
+Would this be acceptable/good enough/convenient for entry?
+
+ Convention/Standard Logical/Lily(?)
+
+ C# cis
+ Cb ces
+ Cm/Cmin c3-
+ Caug c5+
+ Cdim c5-
+ Cmaj7 c7
+ C7 c7-
+ Csus/Csus4 c4^3
+%}
+
+scales = \notes\transpose c''\chords{
+ *c *g *d *a *e *b *fis
+ *c *f *bes *es *as *des *ges
+ *c6 *c7 *c9 *c11 *c13
+ }
+
+\score{
+ <
+ \type ChordNames \scales
+ \type Staff \scales
+ >
+}
\header{
-filename = "twinkle.ly";
+filename = "twinkle-pop.ly";
title = "Ah, vous dirais-je, maman ";
description = "twinkle twinkle in pop-song-settings";
composer = "traditional";
-
enteredby = "HWN, chords by Johan Vromans";
copyright = "public domain";
}
\version "1.0.10";
-melodie = \notes\relative c {
- \clef"violin";
+melodie = \notes\relative c'' {
+ \clef "violin";
\time 2/4 ;
- c''4^"C" c | g' g | a^"F" a | g2^"C" |
- f4^"F" f | e^"C" e | d^"G7" d | c2^"C" |
- g'4^"G" g | f^"F" f | e^"C" e | d^"G7" d |
- g^"G" g | f^"F" f | e^"C" e | d^"G7" d |
- c4^"C" c | g' g | a^"F" a | g2^"C" |
- f4^"F" f | e^"C" e | d^"G7" d | c2^"C" |
+ c4 c | g' g | a a | g2 |
+ f4 f | e e | d d | c2 |
+ g'4 g | f f | e e | d d |
+ g g | f f | e e | d d |
+ % copy 1-8
+ c4 c | g' g | a a | g2 |
+ f4 f | e e | d d | c2 |
+}
+
+acc = \chords {
+ % why don't \skip, s4 work?
+ @2c @c @f @c
+ @f @c @g7 @c
+ @g @f @c @g7 % urg, bug!
+ @g @f @c @g7
+ % copy 1-8
+ @2c @c @f @c
+ @f @c @g7 @c
}
text = \lyrics{
}
\score {
- < \notes \type Staff \melodie
- \lyrics \type Lyrics \text
+ <
+ \chords \type ChordNames \acc
+% \notes \type Staff=chords \acc
+ \notes \type Staff=melody \melodie
+ \lyrics \type Lyrics \text
>
\paper { }
}
--- /dev/null
+/*
+ chord-name-engraver.cc -- implement Chord_name_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "chord-name-engraver.hh"
+#include "musical-request.hh"
+#include "text-item.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "main.hh"
+#include "dimensions.hh"
+
+ADD_THIS_TRANSLATOR (Chord_name_engraver);
+
+Chord_name_engraver::Chord_name_engraver ()
+{
+}
+
+void
+Chord_name_engraver::acknowledge_element (Score_element_info i)
+{
+ if (Note_req* n = dynamic_cast<Note_req*> (i.req_l_))
+ pitch_arr_.push (n->pitch_);
+}
+
+bool
+Chord_name_engraver::do_try_music (Music* m)
+{
+ if (Note_req* n = dynamic_cast<Note_req*> (m))
+ {
+ pitch_arr_.push (n->pitch_);
+ return true;
+ }
+ return false;
+}
+
+void
+Chord_name_engraver::do_process_requests ()
+{
+ if (text_p_arr_.size ())
+ return;
+ if (!pitch_arr_.size ())
+ return;
+
+ /*
+ Banter style chord names (almost).
+ TODO:
+ - don't print inclusive scale (i.e. no "9" in c 9/11)
+ - handle c7 / cmaj7
+ - use #,b iso -es -is on tonica
+ - switch on property, add american (?) chordNameStyle
+
+ Scalar chordNameStyle = get_property ("chordNameStyle");
+ if (chordNameStyle == "Banner")
+ chord = pitches_to_banner (pitch_arr_.size ());
+
+ */
+
+ Scalar style = get_property ("textstyle");
+ Scalar alignment = get_property ("textalignment");
+ Text_def* text_p = new Text_def;
+ text_p->align_dir_ = LEFT;
+ if (style.length_i ())
+ text_p->style_str_ = style;
+ if (alignment.isnum_b())
+ text_p->align_dir_= (Direction)(int)alignment;
+
+ Musical_pitch tonic = pitch_arr_[0];
+
+ Array<Musical_pitch> scale;
+ scale.push (Musical_pitch (0)); // c
+ scale.push (Musical_pitch (1)); // d
+ scale.push (Musical_pitch (2)); // e
+ scale.push (Musical_pitch (3)); // f
+ scale.push (Musical_pitch (4)); // g
+ scale.push (Musical_pitch (5)); // a
+ // 7 always means 7-...
+ scale.push (Musical_pitch (6, -1)); // b
+
+ for (int i = 0; i < scale.size (); i++)
+ scale[i].transpose (tonic);
+
+ //urg, should do translation in scheme.
+ char const *acc[] = {"\\textflat\\textflat", "\\textflat", "", "\\textsharp" , "\\textsharp\\textsharp"};
+ String tonic_str = tonic.str ();
+ tonic_str = tonic_str.left_str (1).upper_str ()
+ + acc[tonic.accidental_i_ + 2];
+
+ String add_str;
+ String sep_str;
+ for (int i=1; i < pitch_arr_.size (); i++)
+ {
+ Musical_pitch p = pitch_arr_[i];
+ int trap = p.notename_i_ - tonic.notename_i_
+ + (p.octave_i_ - tonic.octave_i_) * 7 + 1;
+ int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
+ if ((trap == 3) && (accidental == -1))
+ tonic_str += "m"; // hmm
+ else if (accidental || (!(trap % 2) || ((i + 1 == pitch_arr_.size ()) && (trap > 5))))
+ {
+ add_str += sep_str;
+ if ((trap == 7) && (accidental == 1))
+ add_str += "maj7";
+ else
+ {
+ add_str += to_str (trap);
+ if (accidental)
+ add_str += accidental < 0 ? "-" : "+";
+ }
+ sep_str = "/";
+ }
+ }
+
+ text_p->text_str_ = tonic_str + "$^{" + add_str + "}$";
+ Text_item* item_p = new Text_item (text_p);
+ item_p->dir_ = DOWN;
+ item_p->fat_b_ = true;
+ text_p_arr_.push (item_p);
+ announce_element (Score_element_info (item_p, 0));
+}
+
+void
+Chord_name_engraver::do_pre_move_processing ()
+{
+ for (int i=0; i < text_p_arr_.size (); i++)
+ {
+ typeset_element (text_p_arr_[i]);
+ }
+ text_p_arr_.clear ();
+ pitch_arr_.clear ();
+}
+
*/
struct Musical_pitch : public Input
{
- Musical_pitch ();
+ Musical_pitch (int notename=0, int accidental=0, int octave=0, bool cautionary=false);
/// 0 is c, 6 is b
int notename_i_;
- /// 0 is central c
- int octave_i_;
/// 0 natural, 1 sharp, etc
int accidental_i_;
+ /// 0 is central c
+ int octave_i_;
/// Used for cautionary accidentals
bool cautionary_b_;
- void init () ;
Musical_pitch to_relative_octave (Musical_pitch);
void transpose (Musical_pitch);
static int compare (Musical_pitch const&,Musical_pitch const&);
String main_input_str_;
void * lexval_l;
Scope * toplevel_scope_p_;
+ bool main_input_b_;
Notename_table *note_tab_p_;
Array<Scope*> scope_l_arr_;
Keyword_table * keytable_p_;
int errorlevel_i_;
-
-
+ Notename_table *chordmodifier_tab_p_;
+ Musical_pitch lookup_notename (String s);
void start_main_input ();
void set_notename_table(Notename_table*tab_p);
+ bool chordmodifier_b (String) const;
+ void set_chordmodifier_table (Notename_table*tab_p);
+ Musical_pitch lookup_chordmodifier (String s);
+
bool notename_b(String) const;
Identifier*lookup_identifier (String s);
Musical_pitch lookup_pitch (String s);
void push_note_state();
+ void push_chord_state();
void push_lyric_state();
void pop_state();
void LexerError (char const *);
void print_declarations (bool init_b) const;
void add_notename (String, Musical_pitch);
bool note_state_b() const;
+ bool chord_state_b() const;
bool lyric_state_b() const;
};
#include "array.hh"
#include "input.hh"
-class My_lily_parser {
- char const* here_ch_C() const;
- Array<Input> define_spot_array_;
- String init_str_;
-
- void add_requests (Simultaneous_music*v);
+class My_lily_parser
+{
+public:
+ My_lily_parser (Sources * sources_l);
+ ~My_lily_parser();
- Simultaneous_music * get_note_element (Note_req * ,Duration *);
- Simultaneous_music* get_rest_element (String, Duration *);
- Simultaneous_music* get_word_element (String, Duration*);
- Melodic_req* get_melodic_req (Melodic_req* melodic, int quotes);
- String notename_str (Melodic_req* melodic);
- void set_last_duration (Duration const *);
- void set_abbrev_beam (int type_i);
- friend int yyparse (void*);
+ void do_init_file();
+ void parse_file ( String init_str, String file_str);
+ void set_version_check (bool ignore);
public:
int abbrev_beam_type_i_;
My_lily_lexer * lexer_p_;
Moment plet_mom();
- void add_notename (String, Musical_pitch req_p);
Input here_input() const;
void remember_spot();
Input pop_spot();
void set_debug();
void set_yydebug (bool);
bool ignore_version_b_;
-public:
- void do_init_file();
- void parse_file ( String init_str, String file_str);
- My_lily_parser (Sources * sources_l);
- ~My_lily_parser();
- void set_version_check (bool ignore);
+
+private:
+ char const* here_ch_C() const;
+ Array<Input> define_spot_array_;
+ String init_str_;
+
+ void add_requests (Simultaneous_music*v);
+
+ Simultaneous_music * get_note_element (Note_req * ,Duration *);
+ Simultaneous_music * get_chord (Musical_pitch, Array<Musical_pitch>*, Array<Musical_pitch>*, Duration);
+ Simultaneous_music* get_rest_element (String, Duration *);
+ Simultaneous_music* get_word_element (String, Duration*);
+ Melodic_req* get_melodic_req (Melodic_req* melodic, int quotes);
+ String notename_str (Melodic_req* melodic);
+ void set_last_duration (Duration const *);
+ void set_abbrev_beam (int type_i);
+ friend int yyparse (void*);
};
#endif // MY_LILY_PARSER_HH
%option never-interactive
%option warn
+%x chords
%x incl
%x lyrics
%x notes
// windows-suck-suck-suck
}
-<notes,incl,INITIAL,lyrics>{
+<INITIAL,chords,incl,lyrics,notes>{
"%{" {
yy_push_state (longcomment);
}
}
-<notes,INITIAL,lyrics>\\maininput {
- start_main_input ();
+<INITIAL,chords,lyrics,notes>\\maininput {
+ if (!main_input_b_)
+ {
+ start_main_input ();
+ main_input_b_ = true;
+ }
+ else
+ error ("\\maininput disallowed outside init files.");
}
-<notes,INITIAL,lyrics>\\include {
+<INITIAL,chords,lyrics,notes>\\include {
yy_push_state (incl);
}
<incl>\"[^"]*\";? { /* got the include file name */
<notes>R {
return MEASURES;
}
-<INITIAL,lyrics,notes>\\\${BLACK}*{WHITE} {
+<INITIAL,chords,lyrics,notes>\\\${BLACK}*{WHITE} {
String s=YYText () + 2;
s=s.left_str (s.length_i () - 1);
return scan_escaped_word (s);
}
-<INITIAL,lyrics,notes>\${BLACK}*{WHITE} {
+<INITIAL,chords,lyrics,notes>\${BLACK}*{WHITE} {
String s=YYText () + 1;
s=s.left_str (s.length_i () - 1);
return scan_bare_word (s);
}
-<INITIAL,lyrics,notes>\\\${BLACK}* { // backup rule
+<INITIAL,chords,lyrics,notes>\\\${BLACK}* { // backup rule
cerr << _ ("white expected") << endl;
exit (1);
}
-<INITIAL,lyrics,notes>\${BLACK}* { // backup rule
+<INITIAL,chords,lyrics,notes>\${BLACK}* { // backup rule
cerr << _ ("white expected") << endl;
exit (1);
}
<notes>{
-
{ALPHAWORD} {
return scan_bare_word (YYText ());
-
}
{NOTECOMMAND} {
}
<lyrics>{
-
\" {
start_quote ();
}
return yylval.c = YYText ()[0];
}
}
+<chords>{
+ {ALPHAWORD} {
+ return scan_bare_word (YYText ());
+ }
+ {NOTECOMMAND} {
+ return scan_escaped_word (YYText () + 1);
+ }
+ {UNSIGNED} {
+ yylval.i = String_convert::dec2_i (String (YYText ()));
+ return UNSIGNED;
+ }
+ . {
+ return yylval.c = YYText ()[0];
+ }
+}
<<EOF>> {
DOUT << "<<eof>>";
yy_push_state (notes);
}
+void
+My_lily_lexer::push_chord_state ()
+{
+ yy_push_state (chords);
+}
+
void
My_lily_lexer::push_lyric_state ()
{
yy_push_state (lyrics);
}
+
void
My_lily_lexer::pop_state ()
{
yylval.id = id;
return id->token_code_i_;
}
- if (YYSTATE != notes) {
- if (notename_b (str))
- {
- yylval.pitch = new Musical_pitch (lookup_pitch (str));
+ if ((YYSTATE != notes) && (YYSTATE != chords)) {
+ if (notename_b (str)) {
+ yylval.pitch = new Musical_pitch (lookup_notename (str));
yylval.pitch->set_spot (Input (source_file_l (),
here_ch_C ()));
return NOTENAME_PITCH;
- }
+ }
}
if (check_debug)
print_declarations (true);
My_lily_lexer::scan_bare_word (String str)
{
DOUT << "word: `" << str<< "'\n";
- if (YYSTATE == notes){
+ if ((YYSTATE == notes) || (YYSTATE == chords)) {
if (notename_b (str)) {
DOUT << "(notename)\n";
- yylval.pitch = new Musical_pitch (lookup_pitch (str));
+ yylval.pitch = new Musical_pitch (lookup_notename (str));
yylval.pitch->set_spot (Input (source_file_l (),
here_ch_C ()));
return NOTENAME_PITCH;
+ } else if (chordmodifier_b (str)) {
+ DOUT << "(chordmodifier)\n";
+ yylval.pitch = new Musical_pitch (lookup_chordmodifier (str));
+ yylval.pitch->set_spot (Input (source_file_l (),
+ here_ch_C ()));
+ return CHORDMODIFIER_PITCH;
}
}
return YY_START == notes;
}
+bool
+My_lily_lexer::chord_state_b () const
+{
+ return YY_START == chords;
+}
+
bool
My_lily_lexer::lyric_state_b () const
{
#include "debug.hh"
#include "main.hh"
-Musical_pitch::Musical_pitch ()
+Musical_pitch::Musical_pitch (int n, int a, int o, bool c)
{
- init ();
-}
-
-void
-Musical_pitch::init ()
-{
- notename_i_ = 0;
- octave_i_ = 0;
- accidental_i_ = 0;
- cautionary_b_ = false;
+ notename_i_ = n;
+ accidental_i_ = a;
+ octave_i_ = o;
+ cautionary_b_ = c;
}
void
{"alternative", ALTERNATIVE},
{"bar", BAR},
{"cadenza", CADENZA},
+ {"chordmodifiers", CHORDMODIFIERS},
+ {"chords", CHORDS},
{"clef", CLEF},
{"cm", CM_T},
{"consists", CONSISTS},
scope_l_arr_.push (toplevel_scope_p_);
errorlevel_i_ = 0;
note_tab_p_ = new Notename_table;
+ chordmodifier_tab_p_ = new Notename_table;
+ main_input_b_ = false;
}
int
if (!monitor->silent_b ("InitLexer") && check_debug)
set_debug (1);
+
new_input (main_input_str_, source_global_l);
+ if (safe_global_b)
+ allow_includes_b_ = false;
print_declarations(true);
}
}
Musical_pitch
-My_lily_lexer::lookup_pitch (String s)
+My_lily_lexer::lookup_notename (String s)
{
return (*note_tab_p_)[s];
}
+Musical_pitch
+My_lily_lexer::lookup_chordmodifier (String s)
+{
+ return (*chordmodifier_tab_p_)[s];
+}
+
bool
My_lily_lexer::notename_b (String s) const
{
}
void
-My_lily_lexer::add_notename (String s, Musical_pitch p)
+My_lily_lexer::set_notename_table (Notename_table *p)
{
- (*note_tab_p_)[s] = p;
+ delete note_tab_p_;
+ note_tab_p_ = p;
+}
+
+bool
+My_lily_lexer::chordmodifier_b (String s) const
+{
+ return chordmodifier_tab_p_->elem_b (s);
}
void
-My_lily_lexer::set_notename_table(Notename_table *p)
+My_lily_lexer::set_chordmodifier_table (Notename_table *p)
{
- delete note_tab_p_;
- note_tab_p_ = p;
+ delete chordmodifier_tab_p_;
+ chordmodifier_tab_p_ = p;
}
char
source file of the GNU LilyPond music typesetter
(c) 1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ Jan Nieuwenhuizen <janneke@gnu.org>
*/
#include "my-lily-parser.hh"
return velt_p;
}
+Simultaneous_music *
+My_lily_parser::get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Duration d)
+{
+ Simultaneous_music*v = new Request_chord;
+ v->set_spot (here_input ());
+
+ Note_req* n = new Note_req;
+ n->pitch_ = tonic;
+ n->duration_ = d;
+ v->add_music (n);
+
+ for (int i = 0; i < add_arr_p->size (); i++)
+ {
+ Musical_pitch p = tonic;
+ Musical_pitch q = (*add_arr_p)[i];
+ // duh, c7 should mean <c bes>
+ if (q.notename_i_ == 6)
+ q.accidental_i_--;
+ p.transpose (q);
+ (*add_arr_p)[i] = p;
+ }
+ add_arr_p->sort (Musical_pitch::compare);
+ for (int i = 0; i < sub_arr_p->size (); i++)
+ {
+ Musical_pitch p = tonic;
+ Musical_pitch q = (*add_arr_p)[i];
+ // duh, c7 should mean <c bes>
+ if (q.notename_i_ == 6)
+ q.accidental_i_--;
+ p.transpose (q);
+ (*sub_arr_p)[i] = p;
+ }
+ sub_arr_p->sort (Musical_pitch::compare);
+
+ Musical_pitch third (2);
+ Musical_pitch mthird (2, -1);
+ Musical_pitch missing;
+ missing = tonic;
+ missing.transpose (third);
+
+ Musical_pitch p;
+ p = tonic;
+ p.transpose (third);
+ p.transpose (mthird);
+
+ /*
+ must have minimum at 5 (3 is added automatically as missing)
+ */
+ if (!add_arr_p->size ())
+ add_arr_p->push (p);
+ else if ((add_arr_p->top () < p) && (add_arr_p->top ().notename_i_ != p.notename_i_))
+ add_arr_p->push (p);
+ add_arr_p->sort (Musical_pitch::compare);
+
+ Array<Musical_pitch> triads;
+ triads.push (third); // c e
+ triads.push (mthird); // d f
+ triads.push (mthird); // e g
+ triads.push (third); // f a
+ // 7 always seems means 7-...
+ triads.push (third); // g b
+// triads.push (mthird); // g bes
+ triads.push (mthird); // a c
+ triads.push (mthird); // b d
+
+ /*
+ if first addition is 4, assume sus4 and don't add third implicitely
+ */
+ Musical_pitch sus (3);
+ sus.transpose (tonic);
+ if (add_arr_p->size ())
+ if ((*add_arr_p)[0] == sus)
+ missing.transpose (mthird);
+
+ /*
+ add missing triads
+ */
+ for (int i = 0; i < add_arr_p->size (); i++)
+ {
+ Musical_pitch p = (*add_arr_p)[i];
+ if (p > missing)
+ while (p > missing)
+ {
+ if (p.notename_i_ != missing.notename_i_)
+ {
+ if ((missing.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
+ {
+ Musical_pitch special_seven = missing;
+ Musical_pitch lower (0, -1);
+ special_seven.transpose (lower);
+ add_arr_p->insert (special_seven, i++);
+ }
+ else
+ add_arr_p->insert (missing, i++);
+ }
+ missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]);
+ }
+ else
+ i++;
+ }
+
+ /*
+ add all that aren't subtracted
+ */
+ for (int i = 0; i < add_arr_p->size (); i++)
+ {
+ Musical_pitch p = (*add_arr_p)[i];
+ Note_req* n = new Note_req;
+ n->pitch_ = p;
+ n->duration_ = d;
+ for (int j = 0; j < sub_arr_p->size (); j++)
+ {
+ if (p == (*sub_arr_p)[j])
+ {
+ delete n;
+ n = 0;
+ break;
+ }
+ }
+ if (n)
+ v->add_music (n);
+ }
+
+ v->set_spot (here_input ());
+ return v;
+}
+
Simultaneous_music *
My_lily_parser::get_note_element (Note_req *rq, Duration * duration_p)
{
return Input (f_l, here_ch_C());
}
-void
-My_lily_parser::add_notename (String s, Musical_pitch p)
-{
- lexer_p_->add_notename (s, p);
-
-}
-
Paper_def*
My_lily_parser::default_paper_p ()
{
// mmm
Mudela_version oldest_version ("1.0.7");
-Mudela_version version ("1.0.11");
+Mudela_version version ("1.0.12");
// needed for bison.simple's malloc() and free()
Array<Musical_pitch> *pitch_arr;
Array<String> * strvec;
Array<int> *intvec;
+ Atom * symbol;
Box *box;
- Simultaneous_music *chord;
+ Notename_table *chordmodifiertab;
Duration *duration;
+ General_script_def * script;
Identifier *id;
- Translator* trans;
Music *music;
Music_list *music_list;
Score *score;
Paper_def *paper;
Real real;
Request * request;
- General_script_def * script;
Scalar *scalar;
+ Simultaneous_music *chord;
String *string;
- Atom * symbol;
Symtable * symtable;
Symtables* symtables;
- Text_def * textdef;
Tempo_req *tempo;
+ Text_def * textdef;
+ Translator* trans;
char c;
const char *consstr;
int i;
%token BAR
%token BEAMPLET
%token CADENZA
+%token CHORDMODIFIERS
+%token CHORDS
%token CLEF
%token CM_T
%token CONSISTS
%type <i> dots
%token <i> DIGIT
%token <pitch> NOTENAME_PITCH
+%token <pitch> CHORDMODIFIER_PITCH
%token <id> DURATION_IDENTIFIER
%token <id> IDENTIFIER
%token <id> NOTENAME_TABLE_IDENTIFIER
%type <pitch> explicit_musical_pitch steno_musical_pitch musical_pitch absolute_musical_pitch
%type <notereq> steno_notepitch
%type <pitch_arr> pitch_list
+%type <music> chord
+%type <pitch_arr> chord_additions chord_subtractions
+%type <pitch> chord_note
%type <midi> midi_block midi_body
%type <duration> duration_length
%type <symtable> symtable symtable_body
%type <trans> translator_spec translator_spec_body
%type <tempo> tempo_request
-%type <notenametab> notenames_body notenames_block
-%expect 4
+%type <notenametab> notenames_body notenames_block chordmodifiers_block
+
+%expect 6
%left '-' '+'
notenames_block {
THIS->lexer_p_->set_notename_table ($1);
}
+ | chordmodifiers_block {
+ THIS->lexer_p_->set_chordmodifier_table ($1);
+ }
| mudela_header {
delete header_global_p;
header_global_p = $1;
;
+chordmodifiers_block:
+ CHORDMODIFIERS '{' notenames_body '}' { $$ = $3; }
+ ;
+
+
notenames_block:
NOTENAMES '{' notenames_body '}' { $$ = $3; }
;
$$ = new Score_identifier ($1, SCORE_IDENTIFIER);
}
+ | chordmodifiers_block {
+ $$ = new Notename_table_identifier ($1, NOTENAME_TABLE_IDENTIFIER);
+ }
| notenames_block {
$$ = new Notename_table_identifier ($1, NOTENAME_TABLE_IDENTIFIER);
}
{ $$ = $3;
THIS->lexer_p_->pop_state ();
}
-
+ | CHORDS
+ { THIS->lexer_p_->push_chord_state (); }
+ Music
+ {
+ $$ = $3;
+ THIS->lexer_p_->pop_state ();
+ }
| LYRICS
{ THIS->lexer_p_->push_lyric_state (); }
Music
simple_element:
steno_notepitch notemode_duration {
- if (!THIS->lexer_p_->note_state_b ())
+ if (!THIS->lexer_p_->note_state_b ()
+ && !THIS->lexer_p_->chord_state_b ())
THIS->parser_error (_ ("have to be in Note mode for notes"));
$1->duration_ = *$2;
$$ = THIS->get_note_element ($1, $2);
$$ = THIS->get_word_element (*$1, $2);
delete $1;
}
+ | '@' chord {
+ if (!THIS->lexer_p_->chord_state_b ())
+ THIS->parser_error (_ ("have to be in Chord mode for chords"));
+ $$ = $2;
+ }
+ ;
+
+
+chord:
+ notemode_duration steno_musical_pitch chord_additions chord_subtractions {
+ $$ = THIS->get_chord (*$2, $3, $4, *$1);
+ };
+
+chord_additions:
+ {
+ $$ = new Array<Musical_pitch>;
+ }
+ | chord_additions chord_note {
+ $1->push (*$2);
+ $$ = $1;
+ }
+ | chord_additions CHORDMODIFIER_PITCH {
+ /*
+ urg, this is kind of ugly.
+ all but "sus" chord modifiers can be
+ handled as chord_additions...
+ */
+ $1->push (*$2);
+ $$ = $1;
+ }
;
+chord_note:
+ UNSIGNED {
+ $$ = new Musical_pitch;
+ $$->notename_i_ = ($1 - 1) % 7;
+ $$->octave_i_ = $1 > 7 ? 1 : 0;
+ $$->accidental_i_ = 0;
+ }
+ | UNSIGNED '+' {
+ $$ = new Musical_pitch;
+ $$->notename_i_ = ($1 - 1) % 7;
+ $$->octave_i_ = $1 > 7 ? 1 : 0;
+ $$->accidental_i_ = 1;
+ }
+ | UNSIGNED '-' {
+ $$ = new Musical_pitch;
+ $$->notename_i_ = ($1 - 1) % 7;
+ $$->octave_i_ = $1 > 7 ? 1 : 0;
+ $$->accidental_i_ = -1;
+ }
+ ;
+
+chord_subtractions:
+ {
+ $$ = new Array<Musical_pitch>;
+ }
+ | '^' chord_subtractions chord_note {
+ $2->push (*$3);
+ $$ = $2;
+ }
+ ;
/*
UTILITIES