MuseScore/bww2mxml/lexer.cpp
2012-05-26 14:49:10 +02:00

498 lines
14 KiB
C++

//=============================================================================
// BWW to MusicXML converter
// Part of MusE Score
// Linux Music Score Editor
// $Id: lexer.cpp 4873 2011-10-19 19:33:04Z lvinken $
//
// Copyright (C) 2010 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
/**
\file
BWW file lexical analysis.
Loosely based on BWW file format - BNF specification by tjm found in
http://forums.bobdunsire.com/forums/showthread.php?t=123219
*/
#include <QtCore/QRegExp>
#include <QtCore/QtDebug>
#include "lexer.h"
namespace Bww {
/**
Lexer constructor, \a inDevice is the input.
*/
Lexer::Lexer(QIODevice *inDevice)
: in(inDevice),
lineNumber(-1),
value(NONE)
{
qDebug() << "Lexer::Lexer() begin";
// Initialize the grace note translation table
// Single Grace notes
graceMap["ag"] = "LA";
graceMap["bg"] = "B";
graceMap["cg"] = "C";
graceMap["dg"] = "D";
graceMap["eg"] = "E";
graceMap["fg"] = "F";
graceMap["gg"] = "HG";
graceMap["tg"] = "HA";
// Regular Doublings
graceMap["dblg"] = "HG LG D";
graceMap["dbla"] = "HG LA D";
graceMap["dbb"] = "HG B D";
graceMap["dbc"] = "HG C D";
graceMap["dbd"] = "HG D E";
graceMap["dbe"] = "HG E F";
graceMap["dbf"] = "HG F HG";
graceMap["dbhg"] = "HG F";
graceMap["dbha"] = "HA HG";
// Thumb Doublings
/*
graceMap["thdblg"] = "HA LG D";
graceMap["thdbla"] = "HA LA D";
graceMap["thdbb"] = "HA B D";
graceMap["thdbc"] = "HA C D";
graceMap["thdbd"] = "HA D E";
graceMap["thdbe"] = "HA E F";
graceMap["thdbf"] = "HA F HG";
graceMap["thdbhg"] = "HA HG F";
*/
graceMap["tdblg"] = "HA LG D";
graceMap["tdbla"] = "HA LA D";
graceMap["tdbb"] = "HA B D";
graceMap["tdbc"] = "HA C D";
graceMap["tdbd"] = "HA D E";
graceMap["tdbe"] = "HA E F";
graceMap["tdbf"] = "HA F HG";
// Half Doublings
graceMap["hdblg"] = "LG D";
graceMap["hdbla"] = "LA D";
graceMap["hdbb"] = "B D";
graceMap["hdbc"] = "C D";
graceMap["hdbd"] = "D E";
graceMap["hdbe"] = "E F";
graceMap["hdbf"] = "F HG";
/*
graceMap["hdbhg"] = "HG F";
graceMap["hdbha"] = "HA HG";
*/
// Single Strikes (same as single grace notes)
graceMap["strlg"] = "LG";
graceMap["strla"] = "LA";
graceMap["strb"] = "B";
graceMap["strc"] = "C";
graceMap["strd"] = "D";
graceMap["stre"] = "E";
graceMap["strf"] = "F";
graceMap["strhg"] = "HG";
/*
graceMap["strha"] = "HA";
*/
// G Grace note, Thumb and Half Strikes
graceMap["gstla"] = "HG LA LG";
graceMap["gstb"] = "HG B LG";
graceMap["gstc"] = "HG C LG";
graceMap["gstd"] = "HG D LG";
graceMap["lgstd"] = "HG D C";
graceMap["gste"] = "HG E LA";
graceMap["gstf"] = "HG F E";
graceMap["tstla"] = "HA LA LG";
graceMap["tstb"] = "HA B LG";
graceMap["tstc"] = "HA C LG";
graceMap["tstd"] = "HA D LG";
graceMap["ltstd"] = "HA D C";
graceMap["tste"] = "HA E LA";
graceMap["tstf"] = "HA F E";
graceMap["tsthg"] = "HA HG F";
graceMap["hstla"] = "LA LG";
graceMap["hstb"] = "B LG";
graceMap["hstc"] = "C LG";
graceMap["hstd"] = "D LG";
graceMap["lhstd"] = "D C";
graceMap["hste"] = "E LA";
graceMap["hstf"] = "F E";
graceMap["hsthg"] = "HG F";
// Regular Grips
graceMap["grp"] = "LG D LG";
graceMap["hgrp"] = "D LG";
graceMap["grpb"] = "LG B LG";
// G Grace note, Thumb and Half Grips
graceMap["ggrpla"] = "HG LA LG D LG";
graceMap["ggrpb"] = "HG B LG D LG";
graceMap["ggrpc"] = "HG C LG D LG";
graceMap["ggrpd"] = "HG D LG D LG";
graceMap["ggrpdb"] = "HG D LG B LG";
graceMap["ggrpe"] = "HG E LG D LG";
graceMap["ggrpf"] = "HG F LG F LG";
graceMap["tgrpla"] = "HA LA LG D LG";
graceMap["tgrpb"] = "HA B LG D LG";
graceMap["tgrpc"] = "HA C LG D LG";
graceMap["tgrpd"] = "HA D LG D LG";
graceMap["tgrpdb"] = "HA D LG B LG";
graceMap["tgrpe"] = "HA E LG D LG";
graceMap["tgrpf"] = "HA F LG F LG";
graceMap["tgrphg"] = "HA HG LG F LG";
graceMap["hgrpla"] = "LA LG D LG";
graceMap["hgrpb"] = "B LG D LG";
graceMap["hgrpc"] = "C LG D LG";
graceMap["hgrpd"] = "D LG D LG";
graceMap["hgrpdb"] = "D LG B LG";
graceMap["hgrpe"] = "E LG D LG";
graceMap["hgrpf"] = "F LG F LG";
graceMap["hgrphg"] = "HG LG D LG";
graceMap["hgrpha"] = "HA LG D LG";
// Taorluaths and Bublys
graceMap["tar"] = "LG D LG E";
graceMap["tarb"] = "LG B LG E";
graceMap["htar"] = "D LG E";
graceMap["bubly"] = "LG D LG C LG";
graceMap["hbubly"] = "D LG C LG";
// Birls
graceMap["brl"] = "LG LA LG";
graceMap["abr"] = "LA LG LA LG";
graceMap["gbr"] = "HG LA LG LA LG";
graceMap["tbr"] = "HA LA LG LA LG";
// Light, Heavy and Half D Throws
graceMap["thrd"] = "LG D C";
graceMap["hvthrd"] = "LG D LG C";
graceMap["hthrd"] = "D C";
graceMap["hhvthrd"] = "D LG C";
// Regular, Thumb Grace Note and Half Peles
graceMap["pella"] = "HG LA E LA LG";
graceMap["pelb"] = "HG B E B LG";
graceMap["pelc"] = "HG C E C LG";
graceMap["peld"] = "HG D E D LG";
graceMap["lpeld"] = "HG D E D C";
graceMap["pele"] = "HG E F E LA";
graceMap["pelf"] = "HG F HG F E";
graceMap["tpella"] = "HA LA E LA LG";
graceMap["tpelb"] = "HA B E B LG";
graceMap["tpelc"] = "HA C E C LG";
graceMap["tpeld"] = "HA D E D LG";
graceMap["ltpeld"] = "HA D E D C";
graceMap["tpele"] = "HA E F E LA";
graceMap["tpelf"] = "HA F HG F E";
graceMap["tpelhg"] = "HA HG HA HG F";
graceMap["hpella"] = "LA E LA LG";
graceMap["hpelb"] = "B E B LG";
graceMap["hpelc"] = "C E C LG";
graceMap["hpeld"] = "D E D LG";
graceMap["lhpeld"] = "D E D C";
graceMap["hpele"] = "E F E LA";
graceMap["hpelf"] = "F HG F E";
graceMap["hpelhg"] = "HG HA HG F";
// Regular Double Strikes
graceMap["st2la"] = "LG LA LG";
graceMap["st2b"] = "LG B LG";
graceMap["st2c"] = "LG C LG";
graceMap["st2d"] = "LG D LG";
graceMap["lst2d"] = "C D C";
graceMap["st2e"] = "LA E LA";
graceMap["st2f"] = "E F E";
graceMap["st2hg"] = "F HG F";
graceMap["st2ha"] = "HG HA HG";
// G Grace note, Thumb and Half Double Strikes
graceMap["gst2la"] = "HG LA LG LA LG";
graceMap["gst2b"] = "HG B LG B LG";
graceMap["gst2c"] = "HG C LG C LG";
graceMap["gst2d"] = "HG D LG D LG";
graceMap["lgst2d"] = "HG D C D C";
graceMap["gst2e"] = "HG E LA E LA";
graceMap["gst2f"] = "HG F E F E";
graceMap["tst2la"] = "HA LA LG LA LG";
graceMap["tst2b"] = "HA B LG B LG";
graceMap["tst2c"] = "HA C LG C LG";
graceMap["tst2d"] = "HA D LG D LG";
graceMap["ltst2d"] = "HA D C D C";
graceMap["tst2e"] = "HA E LA E LA";
graceMap["tst2f"] = "HA F E F E";
graceMap["tst2hg"] = "HA HG F HG F";
graceMap["hst2la"] = "LA LG LA LG";
graceMap["hst2b"] = "B LG B LG";
graceMap["hst2c"] = "C LG C LG";
graceMap["hst2d"] = "D LG D LG";
graceMap["lhst2d"] = "D C D C";
graceMap["hst2e"] = "E LA E LA";
graceMap["hst2f"] = "F E F E";
graceMap["hst2hg"] = "HG F HG F";
graceMap["hst2ha"] = "HA HG HA HG";
// Regular Triple Strikes
graceMap["st3la"] = "LG LA LG LA LG";
graceMap["st3b"] = "LG B LG B LG";
graceMap["st3c"] = "LG C LG C LG";
graceMap["st3d"] = "LG D LG D LG";
graceMap["lst3d"] = "C D C D C";
graceMap["st3e"] = "LA E LA E LA";
graceMap["st3f"] = "E F E F E";
graceMap["st3hg"] = "F HG F HG F";
graceMap["st3ha"] = "HG HA HG HA HG";
// G Grace note, Thumb and Half Triple Strikes
graceMap["gst3la"] = "HG LA LG LA LG LA LG";
graceMap["gst3b"] = "HG B LG B LG B LG";
graceMap["gst3c"] = "HG C LG C LG C LG";
graceMap["gst3d"] = "HG D LG D LG D LG";
graceMap["lgst3d"] = "HG D C D C D C";
graceMap["gst3e"] = "HG E LA E LA E LA";
graceMap["gst3f"] = "HG F E F E F E";
graceMap["tst3la"] = "HA LA LG LA LG LA LG";
graceMap["tst3b"] = "HA B LG B LG B LG";
graceMap["tst3c"] = "HA C LG C LG C LG";
graceMap["tst3d"] = "HA D LG D LG D LG";
graceMap["ltst3d"] = "HA D C D C D C";
graceMap["tst3e"] = "HA E LA E LA E LA";
graceMap["tst3f"] = "HA F E F E F E";
graceMap["tst3hg"] = "HA HG F HG F HG F";
graceMap["hst3la"] = "LA LG LA LG LA LG";
graceMap["hst3b"] = "B LG B LG B LG";
graceMap["hst3c"] = "C LG C LG C LG";
graceMap["hst3d"] = "D LG D LG D LG";
graceMap["lhst3d"] = "D C D C D C";
graceMap["hst3e"] = "E LA E LA E LA";
graceMap["hst3f"] = "F E F E F E";
graceMap["hst3hg"] = "HG F HG F HG F";
graceMap["hst3ha"] = "HA HG HA HG HA HG";
// Double Grace notes
graceMap["dlg"] = "D LG";
graceMap["dla"] = "D LA";
graceMap["db"] = "D B";
graceMap["dc"] = "D C";
graceMap["elg"] = "E LG";
graceMap["ela"] = "E LA";
graceMap["eb"] = "E B";
graceMap["ec"] = "E C";
graceMap["ed"] = "E D";
graceMap["flg"] = "F LG";
graceMap["fla"] = "F LA";
graceMap["fb"] = "F B";
graceMap["fc"] = "F C";
graceMap["fd"] = "F D";
graceMap["fe"] = "F E";
graceMap["glg"] = "HG LG";
graceMap["gla"] = "HG LA";
graceMap["gb"] = "HG B";
graceMap["gc"] = "HG C";
graceMap["gd"] = "HG D";
graceMap["ge"] = "HG E";
graceMap["gf"] = "HG F";
graceMap["tlg"] = "HA LG";
graceMap["tla"] = "HA LA";
graceMap["tb"] = "HA B";
graceMap["tc"] = "HA C";
graceMap["td"] = "HA D";
graceMap["te"] = "HA E";
graceMap["tf"] = "HA F";
graceMap["thg"] = "HA HG";
getSym();
qDebug() << "Lexer::Lexer() end";
}
/**
Get the next symbol, update type and value.
*/
void Lexer::getSym()
{
qDebug() << "Lexer::getSym()";
// if unparsed words remaining, use these
if (list.size() > 0)
{
categorizeWord(list.at(0));
list.removeFirst();
return;
}
// read the next non-empty line
do
{
line = in.readLine();
++lineNumber;
if (line.isNull())
{
// end of file
qDebug() << "-> end of file";
type = NONE;
value = "";
return;
}
}
while (line == "");
qDebug() << "getSym: read line" << line;
QRegExp rHeaderIgnore("^Bagpipe Reader|^MIDINoteMappings|^FrequencyMappings"
"|^InstrumentMappings|^GracenoteDurations|^FontSizes"
"|^TuneFormat");
QRegExp rTuneTempo("^TuneTempo");
if (rHeaderIgnore.indexIn(line) == 0)
{
type = COMMENT;
value = "";
qDebug()
<< "-> header ignore,"
<< "type:" << symbolToString(type)
<< "value:" << value
;
line = "";
return;
}
else if (rTuneTempo.indexIn(line) == 0)
{
type = TEMPO;
value = line;
qDebug()
<< "-> tempo,"
<< "type:" << symbolToString(type)
<< "value:" << value
;
line = "";
return;
}
else if (line.at(0) == '"')
{
type = STRING;
value = line;
qDebug()
<< "-> quoted string,"
<< "type:" << symbolToString(type)
<< "value:" << value
;
line = "";
}
else
{
// split line into space-separated words
list = line.trimmed().split(QRegExp("\\s+"));
qDebug()
<< "-> words"
<< list
;
categorizeWord(list.at(0));
list.removeFirst();
}
line = "";
}
/**
Return the current symbols type.
*/
Symbol Lexer::symType() const
{
return type;
}
/**
Return the current symbols value.
*/
QString Lexer::symValue() const
{
return value;
}
/**
Determine the symbol type for \a word.
*/
void Lexer::categorizeWord(QString word)
{
qDebug() << "Lexer::categorizeWord(" << word << ")";
// default values
type = NONE;
value = word;
QRegExp rClef("&");
QRegExp rKey("sharp[cf]");
QRegExp rTSig("\\d+_(1|2|4|8|16|32)");
QRegExp rPart("I!''|I!|''!I|!I|'intro|[2-9]|'[12]|_'");
QRegExp rBar("!|!t|!!t");
QRegExp rNote("(LG|LA|[B-F]|HG|HA)[lr]?_(1|2|4|8|16|32)");
QRegExp rTie("\\^t[es]");
QRegExp rTriplet("\\^3[es]");
QRegExp rDot("'([hl][ag]|[b-f])");
if (rClef.exactMatch(word))
type = CLEF;
else if (rKey.exactMatch(word))
type = KEY;
else if (rTSig.exactMatch(word))
type = TSIG;
else if (rPart.exactMatch(word))
type = PART;
else if (rBar.exactMatch(word))
type = BAR;
else if (rNote.exactMatch(word))
type = NOTE;
else if (rTie.exactMatch(word))
type = TIE;
else if (rTriplet.exactMatch(word))
type = TRIPLET;
else if (rDot.exactMatch(word))
type = DOT;
else if (graceMap.contains(word))
{
type = GRACE;
value = graceMap.value(word);
}
else
type = UNKNOWN;
qDebug()
<< " type: " << qPrintable(symbolToString(type))
<< " value: '" << qPrintable(value) << "'"
;
}
} // namespace Bww