Better error propagation

This commit is contained in:
Matthias Neeracher 2007-10-21 22:06:06 +00:00
parent 2ac1ed067c
commit d530d4ae38

View File

@ -3,45 +3,20 @@
# VLLilypondType.reader - Import lilypond files # VLLilypondType.reader - Import lilypond files
# #
DEBUG = false
require File.dirname($0)+'/plistWriter' require File.dirname($0)+'/plistWriter'
require File.dirname($0)+'/vl' require File.dirname($0)+'/vl'
OUTPUT = {'measures' => []} OUTPUT = {'measures' => []}
CHORDS = []
# NOTES = []
# Lex STANZAS= []
# MEAS = []
tokens = []
INFILE.each do |line|
line.chomp!.sub!(/%.*/, "")
line.scan(%r$\G\s*(\{|\}|\(|\)|\||=|~|<<|>>|--|#'|#\(|##t|##f|\\\w+|\".*?\"|\w[-+\w\d.',:*/]+|.)$) do |token|
tokens.push(token[0])
end
end
#
# Parse
#
nestLevel = 0
block = nil
level = -1
stack = []
repeats = []
chords = []
notes = []
lyrics = []
stanzas = []
lastDur = 1
tied = false
repeat = 0
timeNum = 4
timeDenom = 4
key = 0
mode = 'minor'
lyricFlags= 0
$RELPITCH = 0 $RELPITCH = 0
$timeNum = 4
$timeDenom= 4
$key = 0
$mode = '\major'
PITCH = { PITCH = {
?c => 0, ?c => 0,
@ -202,6 +177,31 @@ def lySteps(steps)
return s return s
end end
def parseLilypond
#
# Lex
#
tokens = []
INFILE.each do |line|
line.chomp!.sub!(/%.*/, "")
line.scan(%r$\G\s*(\{|\}|\(|\)|\||=|~|<<|>>|--|#'|#\(|##t|##f|\\\w+|\".*?\"|\w[-+\w\d.',:*/]+|.)$) do |token|
tokens.push(token[0])
end
end
#
# Parse
#
nestLevel = 0
block = nil
level = -1
stack = []
repeats = []
lyrics = []
lastDur = 1
tied = false
repeat = 0
lyricFlags= 0
while tokens.length > 0 while tokens.length > 0
token = tokens.shift token = tokens.shift
# #
@ -249,8 +249,8 @@ while tokens.length > 0
chord = {'pitch' => pitch, 'root' => root, 'steps' => ext, chord = {'pitch' => pitch, 'root' => root, 'steps' => ext,
'durNum'=> d[0], 'durDenom' => d[1]} 'durNum'=> d[0], 'durDenom' => d[1]}
p token, chord if DEBUG p token, chord if $DEBUG
chords.push(chord) CHORDS.push(chord)
redo redo
end end
when 'voice' when 'voice'
@ -273,12 +273,12 @@ while tokens.length > 0
note = {'pitch' => pitch, 'durNum'=> d[0], 'durDenom' => d[1]} note = {'pitch' => pitch, 'durNum'=> d[0], 'durDenom' => d[1]}
note['tied'] = VL::TiedWithPrev if tied note['tied'] = VL::TiedWithPrev if tied
p token, note if DEBUG p token, note if $DEBUG
notes.push(note) NOTES.push(note)
tied = false tied = false
redo redo
elsif token == '~' elsif token == '~'
if note = notes.last if note = NOTES.last
note['tied'] ||= 0 note['tied'] ||= 0
note['tied'] |= VL::TiedWithNext note['tied'] |= VL::TiedWithNext
end end
@ -289,7 +289,7 @@ while tokens.length > 0
level = nestLevel level = nestLevel
repeats.push(repeat) repeats.push(repeat)
repeat = tokens[1].to_i repeat = tokens[1].to_i
notes.push({'begin-repeat' => true, 'times' => repeat}) NOTES.push({'begin-repeat' => true, 'times' => repeat})
tokens[0..1] = nil tokens[0..1] = nil
redo redo
elsif token == '\alternative' elsif token == '\alternative'
@ -298,7 +298,7 @@ while tokens.length > 0
level = nestLevel+1 level = nestLevel+1
voltas = 0 voltas = 0
curVoltas = nil curVoltas = nil
notes.push({'begin-ending' => true}) NOTES.push({'begin-ending' => true})
elsif token == '\times' && tokens[0] =~ %r|^(\d+)/(\d+)| elsif token == '\times' && tokens[0] =~ %r|^(\d+)/(\d+)|
$timesNum = $1.to_i $timesNum = $1.to_i
$timesDen = $2.to_i $timesDen = $2.to_i
@ -310,22 +310,22 @@ while tokens.length > 0
lyrics.last[1] |= VL::TiedWithNext if lyrics.size > 0 lyrics.last[1] |= VL::TiedWithNext if lyrics.size > 0
lyricFlags = VL::TiedWithPrev lyricFlags = VL::TiedWithPrev
elsif token == '\skip' elsif token == '\skip'
p ["", 0] if DEBUG p ["", 0] if $DEBUG
lyrics.push ["", 0] lyrics.push ["", 0]
lyricFlags = 0 lyricFlags = 0
if tokens[0] =~ /\d+/ if tokens[0] =~ /\d+/
tokens[0..0] = nil tokens[0..0] = nil
end end
elsif token =~ /\\skip\d+/ elsif token =~ /\\skip\d+/
p ["", 0] if DEBUG p ["", 0] if $DEBUG
lyrics.push ["", 0] lyrics.push ["", 0]
lyricFlags = 0 lyricFlags = 0
elsif token =~ /"(.*)"/ elsif token =~ /"(.*)"/
p [$1, lyricFlags] if DEBUG p [$1, lyricFlags] if $DEBUG
lyrics.push [$1, lyricFlags] lyrics.push [$1, lyricFlags]
lyricFlags = 0 lyricFlags = 0
elsif token =~ /^\w.*/ elsif token =~ /^\w.*/
p [token, lyricFlags] if DEBUG p [token, lyricFlags] if $DEBUG
lyrics.push [token, lyricFlags] lyrics.push [token, lyricFlags]
lyricFlags = 0 lyricFlags = 0
end end
@ -350,7 +350,7 @@ while tokens.length > 0
end end
if type == "repeat" if type == "repeat"
if tokens[0] != '\alternative' if tokens[0] != '\alternative'
notes.push({'end-repeat' => true}) NOTES.push({'end-repeat' => true})
repeat = repeats.pop repeat = repeats.pop
end end
elsif type == "endings" elsif type == "endings"
@ -363,14 +363,14 @@ while tokens.length > 0
curVoltas <<= 1 curVoltas <<= 1
end end
end end
notes.push({'end-ending' => true, 'volta' => curVoltas, NOTES.push({'end-ending' => true, 'volta' => curVoltas,
'last'=>last}) 'last'=>last})
voltas |= curVoltas voltas |= curVoltas
curVoltas = 0 curVoltas = 0
if last if last
repeat = repeats.pop repeat = repeats.pop
else else
notes.push({'begin-ending' => true}) NOTES.push({'begin-ending' => true})
stack.push([block, level, "endings"]) stack.push([block, level, "endings"])
level = nestLevel level = nestLevel
end end
@ -383,7 +383,7 @@ while tokens.length > 0
stack.push([block, level, ""]) stack.push([block, level, ""])
block = token block = token
level = nestLevel level = nestLevel
stanzas.push(lyrics= []) if block == '\lyricmode' STANZAS.push(lyrics= []) if block == '\lyricmode'
when '\chordmode' when '\chordmode'
stack.push([block, level, ""]) stack.push([block, level, ""])
block = '\chords' block = '\chords'
@ -395,7 +395,7 @@ while tokens.length > 0
stack.push([block, level, ""]) stack.push([block, level, ""])
block = '\lyricmode' block = '\lyricmode'
level = nestLevel level = nestLevel
stanzas.push(lyrics= []) STANZAS.push(lyrics= [])
tokens[0..0] = nil tokens[0..0] = nil
end end
when '\relative' when '\relative'
@ -410,8 +410,8 @@ while tokens.length > 0
level = nestLevel level = nestLevel
when '\time' when '\time'
if tokens[0] =~ %r{(\d+)/(\d+)} if tokens[0] =~ %r{(\d+)/(\d+)}
timeNum = $1.to_i $timeNum = $1.to_i
timeDenom = $2.to_i $timeDenom = $2.to_i
tokens[0..0] = nil tokens[0..0] = nil
end end
if block != 'voice' if block != 'voice'
@ -421,8 +421,8 @@ while tokens.length > 0
end end
when '\key' when '\key'
p = lyPitch(tokens[0], 0) p = lyPitch(tokens[0], 0)
mode = tokens[1] $mode = tokens[1]
key = mode == '\minor' ? MINORKEY[p] : MAJORKEY[p] $key = $mode == '\minor' ? MINORKEY[p] : MAJORKEY[p]
tokens[0..1] = nil tokens[0..1] = nil
if block != 'voice' if block != 'voice'
stack.push([block, level, ""]) stack.push([block, level, ""])
@ -434,37 +434,38 @@ while tokens.length > 0
when '\alternative' when '\alternative'
end end
end end
end
measureLen = VL::Fract.new(timeNum, timeDenom)
#
# Make measures
#
measCount= -1
measures = []
def peek(where, what) def peek(where, what)
return where.first && where.first[what] return where.first && where.first[what]
end end
while notes.size > 0 || chords.size > 0 def makeMeasures
measureLen = VL::Fract.new($timeNum, $timeDenom)
#
# Make measures
#
measCount= -1
while NOTES.size > 0 || CHORDS.size > 0
measCount += 1 measCount += 1
meas = {} meas = {}
meas['measure'] = measCount meas['measure'] = measCount
meas['properties'] = 0 meas['properties'] = 0
if peek(notes, 'begin-repeat') if peek(NOTES, 'begin-repeat')
rep = notes.shift rep = NOTES.shift
meas['begin-repeat'] = {'times' => rep['times']} meas['begin-repeat'] = {'times' => rep['times']}
end end
if peek(notes, 'begin-ending') if peek(NOTES, 'begin-ending')
notes.shift NOTES.shift
meas['begin-ending'] = {} meas['begin-ending'] = {}
end end
if chords.size > 0 if CHORDS.size > 0
mchords = [] mchords = []
len = VL::Fract.new(0, 1) len = VL::Fract.new(0, 1)
while len < measureLen && chords.size > 0 while len < measureLen && CHORDS.size > 0
chord = chords.shift chord = CHORDS.shift
chordLen = VL::Fract.new(chord['durNum'], chord['durDenom']) chordLen = VL::Fract.new(chord['durNum'], chord['durDenom'])
if len+chordLen > measureLen if len+chordLen > measureLen
remLen = len+chordLen-measureLen remLen = len+chordLen-measureLen
@ -472,18 +473,18 @@ while notes.size > 0 || chords.size > 0
remChord = chord.dup remChord = chord.dup
remChord['durNum'] = remLen.num remChord['durNum'] = remLen.num
remChord['durDenom'] = remLen.denom remChord['durDenom'] = remLen.denom
chords.unshift(remChord) CHORDS.unshift(remChord)
end end
mchords.push(chord) mchords.push(chord)
len += chordLen len += chordLen
end end
meas['chords'] = mchords meas['chords'] = mchords
end end
if notes.size > 0 if NOTES.size > 0
mnotes = [] mnotes = []
len = VL::Fract.new(0, 1) len = VL::Fract.new(0, 1)
while len < measureLen && notes.size > 0 while len < measureLen && NOTES.size > 0
note = notes.shift note = NOTES.shift
noteLen = VL::Fract.new(note['durNum'], note['durDenom']) noteLen = VL::Fract.new(note['durNum'], note['durDenom'])
if len+noteLen > measureLen if len+noteLen > measureLen
remLen = len+noteLen-measureLen remLen = len+noteLen-measureLen
@ -493,14 +494,14 @@ while notes.size > 0 || chords.size > 0
remNote['durDenom'] = remLen.denom remNote['durDenom'] = remLen.denom
remNote['tied'] = (remNote['tied'] || 0) | VL::TiedWithPrev remNote['tied'] = (remNote['tied'] || 0) | VL::TiedWithPrev
note['tied'] = (note['tied'] || 0) | VL::TiedWithNext note['tied'] = (note['tied'] || 0) | VL::TiedWithNext
notes.unshift(remNote) NOTES.unshift(remNote)
end end
if note['pitch'] != VL::NoPitch && if note['pitch'] != VL::NoPitch &&
(!note['tied'] || (note['tied'] & VL::TiedWithPrev) == 0) (!note['tied'] || (note['tied'] & VL::TiedWithPrev) == 0)
ly = [] ly = []
stanza = 0 stanza = 0
stanzas.each_index do |i| STANZAS.each_index do |i|
lyrics = stanzas[i] lyrics = STANZAS[i]
if lyrics.size > 0 if lyrics.size > 0
stanza = i+1 stanza = i+1
syll = lyrics.shift syll = lyrics.shift
@ -519,26 +520,34 @@ while notes.size > 0 || chords.size > 0
end end
meas['melody'] = mnotes meas['melody'] = mnotes
end end
if peek(notes, 'end-ending') if peek(NOTES, 'end-ending')
ending = notes.shift ending = NOTES.shift
meas['end-ending'] = {'last' => ending['last'], 'volta' => ending['volta']} meas['end-ending'] = {'last' => ending['last'], 'volta' => ending['volta']}
end end
if peek(notes, 'end-repeat') if peek(NOTES, 'end-repeat')
notes.shift NOTES.shift
meas['end-repeat'] = {} meas['end-repeat'] = {}
end end
measures.push(meas) MEAS.push(meas)
end
end end
OUTPUT['measures'] = measures begin
parseLilypond
makeMeasures
OUTPUT['measures'] = MEAS
OUTPUT['properties'] = [{ OUTPUT['properties'] = [{
'key' => key, 'key' => $key,
'mode' => mode == '\minor' ? -1 : 1, 'mode' => $mode == '\minor' ? -1 : 1,
'timeNum' => timeNum, 'timeNum' => $timeNum,
'timeDenom' => timeDenom 'timeDenom' => $timeDenom
}] }]
writePlist($stdout, OUTPUT) writePlist($stdout, OUTPUT)
rescue => except
$stderr.print except.message, "\n", except.backtrace.join("\n"), "\n"
end
# Local Variables: # Local Variables:
# mode:ruby # mode:ruby