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