Class: HeadMusic::Notation::LilyPond::MusicItemReader
- Inherits:
-
Object
- Object
- HeadMusic::Notation::LilyPond::MusicItemReader
- Defined in:
- lib/head_music/notation/lily_pond/music_item_reader.rb
Overview
Reads the items a sequence of music is made of — notes, rests, chords, ties, bar checks, and the \key, \time, and \clef commands that appear among them — into the stream of the context that holds them. Everything that opens a level of its own belongs to the MusicReader that calls this one.
Instance Attribute Summary collapse
-
#cursor ⇒ Object
readonly
private
Returns the value of attribute cursor.
-
#duration_reader ⇒ Object
readonly
private
Returns the value of attribute duration_reader.
-
#readers ⇒ Object
readonly
private
Returns the value of attribute readers.
Instance Method Summary collapse
- #chord_note ⇒ Object private
-
#initialize(cursor, readers) ⇒ MusicItemReader
constructor
A new instance of MusicItemReader.
-
#located(command) ⇒ Object
private
A key or meter reader rejects a token without knowing where in the document it came from, so an error that carries no line is given the line of the command that introduced it.
- #read_bar_check(context) ⇒ Object
- #read_chord(context) ⇒ Object
- #read_clef ⇒ Object
- #read_key(context) ⇒ Object
- #read_note(context) ⇒ Object
- #read_rest(context) ⇒ Object
- #read_tie(context) ⇒ Object
- #read_time(context) ⇒ Object
- #read_whole_bar_rest(context) ⇒ Object
- #reject_multiplier(token) ⇒ Object private
Constructor Details
#initialize(cursor, readers) ⇒ MusicItemReader
Returns a new instance of MusicItemReader.
9 10 11 12 13 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 9 def initialize(cursor, readers) @cursor = cursor @readers = readers @duration_reader = DurationReader.new end |
Instance Attribute Details
#cursor ⇒ Object (readonly, private)
Returns the value of attribute cursor.
78 79 80 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 78 def cursor @cursor end |
#duration_reader ⇒ Object (readonly, private)
Returns the value of attribute duration_reader.
78 79 80 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 78 def duration_reader @duration_reader end |
#readers ⇒ Object (readonly, private)
Returns the value of attribute readers.
78 79 80 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 78 def readers @readers end |
Instance Method Details
#chord_note ⇒ Object (private)
80 81 82 83 84 85 86 87 88 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 80 def chord_note token = cursor.advance raise cursor.unsupported_token(token) if token.type == :unsupported raise cursor.error(%(Unexpected token "#{token.lexeme}" inside a chord), token) unless token.type == :note raise cursor.error("Chord notes cannot carry durations", token) if token.duration reject_multiplier(token) token end |
#located(command) ⇒ Object (private)
A key or meter reader rejects a token without knowing where in the document it came from, so an error that carries no line is given the line of the command that introduced it.
99 100 101 102 103 104 105 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 99 def located(command) yield rescue ParseError => parse_error raise parse_error if parse_error.line_number raise cursor.error(parse_error., command) end |
#read_bar_check(context) ⇒ Object
49 50 51 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 49 def (context) context.stream.(cursor.advance.line) end |
#read_chord(context) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 33 def read_chord(context) opener = cursor.advance notes = [] notes << chord_note until cursor.peek.type == :close_chord closer = cursor.advance raise cursor.error("Empty chord", opener) if notes.empty? reject_multiplier(closer) pitches = readers.current.chord_pitches(notes) context.stream.add_note(pitches, duration_reader.rhythmic_value(closer), opener.line) end |
#read_clef ⇒ Object
68 69 70 71 72 73 74 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 68 def read_clef command = cursor.advance token = cursor.advance return if token && (%i[word string].include?(token.type) || (token.type == :note && token.duration.nil?)) raise cursor.error("\\clef expects a clef name", token || command) end |
#read_key(context) ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 53 def read_key(context) command = cursor.advance pitch_token = cursor.advance mode_token = cursor.advance located(command) do context.stream.change_key_signature(KeyReader.key_signature(pitch_token, mode_token), command.line) end end |
#read_note(context) ⇒ Object
15 16 17 18 19 20 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 15 def read_note(context) token = cursor.advance reject_multiplier(token) pitch = readers.current.pitch(token) context.stream.add_note([pitch], duration_reader.rhythmic_value(token), token.line) end |
#read_rest(context) ⇒ Object
22 23 24 25 26 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 22 def read_rest(context) token = cursor.advance reject_multiplier(token) context.stream.add_rest(duration_reader.rhythmic_value(token), token.line) end |
#read_tie(context) ⇒ Object
45 46 47 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 45 def read_tie(context) context.stream.open_tie(cursor.advance.line) end |
#read_time(context) ⇒ Object
62 63 64 65 66 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 62 def read_time(context) command = cursor.advance meter_token = cursor.advance located(command) { context.stream.change_meter(MeterReader.meter(meter_token), command.line) } end |
#read_whole_bar_rest(context) ⇒ Object
28 29 30 31 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 28 def (context) token = cursor.advance context.stream.(duration_reader.(token), token.line) end |
#reject_multiplier(token) ⇒ Object (private)
90 91 92 93 94 |
# File 'lib/head_music/notation/lily_pond/music_item_reader.rb', line 90 def reject_multiplier(token) return unless token.multiplier raise cursor.unsupported("Duration multipliers on notes and rests are not supported", token) end |