OSDN Git Service

オクターブ指定のない音符は同じステートメント内の以前の指定を引き継ぐように変更
authorstarg <starg@users.osdn.me>
Tue, 23 Aug 2016 15:38:05 +0000 (00:38 +0900)
committerstarg <starg@users.osdn.me>
Tue, 23 Aug 2016 15:38:05 +0000 (00:38 +0900)
include/message/id.hpp
src/ast2ir/phrase2ir.cpp
src/ast2ir/phrase2ir.hpp
src/driver/msgcallback.cpp

index e3f9b01..e8f02a9 100644 (file)
@@ -21,6 +21,7 @@ enum class MessageID : int
     TrackNumberIsOutOfSafeRange,
     TrackNumberIsOutOfPreferredRange,
     TooLargeRepeatCount,
+    OctaveOutOfRange,
 
     // error_attribute.hpp
     GrammarAttributeArgument,
index 312e598..cbed111 100644 (file)
@@ -70,7 +70,7 @@ bool Phrase2IRCompiler::Compile(const AST::Phrase& ast, IR::BlockReference index
         AutoPop<decltype(m_AttributeStack)> autoPop(m_AttributeStack);
 
         Compile(ast.Block, index);
-        return true;
+        return !HasErrors();
     }
     catch (const Exceptions::MessageException& e)
     {
@@ -96,6 +96,7 @@ bool Phrase2IRCompiler::Compile(const AST::Phrase& ast, IR::BlockReference index
 std::vector<IR::Block::EventType> Phrase2IRCompiler::operator()(const AST::NoteSequenceStatement& ast)
 {
     m_DefaultDuration = TickPerQuarter;
+    m_DefaultOctave = 5;
 
     if (ast.Attributes.empty())
     {
@@ -108,7 +109,6 @@ std::vector<IR::Block::EventType> Phrase2IRCompiler::operator()(const AST::NoteS
         m_AttributeStack.push_back(ast.Attributes);
         AutoPop<decltype(m_AttributeStack)> autoPop(m_AttributeStack);
 
-        // with bounds checking
         m_IR.Blocks[newIndex.ID].Attributes = m_AttributeStack.back();
 
         if (ast.NoteSeq.is_initialized())
@@ -227,11 +227,33 @@ std::vector<IR::Block::EventType> Phrase2IRCompiler::operator()(const AST::Rest&
 
 std::vector<IR::Block::EventType> Phrase2IRCompiler::operator()(const AST::NoteNumber& ast, int duration)
 {
+    if (ast.Octave.is_initialized())
+    {
+        auto octave = ast.Octave.value();
+
+        if (0 <= octave.Value && octave.Value <= 10)
+        {
+            m_DefaultOctave = octave.Value;
+        }
+        else
+        {
+            AddMessage(
+                Message::MessageItem{
+                    Message::MessageKind::Error,
+                    Message::MessageID::OctaveOutOfRange,
+                    m_IR.Name,
+                    octave.Location,
+                    {std::to_string(octave.Value)}
+                }
+            );
+        }
+    }
+
     return {
         IR::Event{
             m_RelativeTime,
             IR::Note{
-                MIDI::NoteNumber(ast.Name.Name, ast.Name.Minor, ast.Octave.get_value_or(AST::NoteOctave{4, ast.Location}).Value),
+                MIDI::NoteNumber(ast.Name.Name, ast.Name.Minor, m_DefaultOctave),
                 100,
                 duration,
                 100
index 06c44a8..c04b180 100644 (file)
@@ -54,6 +54,7 @@ private:
     int m_RelativeTime = 0;
 
     int m_DefaultDuration;
+    int m_DefaultOctave;
 };
 
 } // namespace AST2IR
index bb996d5..4e48e30 100644 (file)
@@ -42,6 +42,7 @@ MessagePrinter::MessagePrinter(IStdErrWriter* pStdErrWriter)
         {Message::MessageID::TrackNumberIsOutOfSafeRange, "track number '{0}' is out of range (must be 0 <= # < {1})"},
         {Message::MessageID::TrackNumberIsOutOfPreferredRange, "track number '{0}' is out of range (must be 0 <= # < {1})"},
         {Message::MessageID::TooLargeRepeatCount, "repeat count '{0}' is too large (must be <= {1})"},
+        {Message::MessageID::OctaveOutOfRange, "octave value '{0}' is out of range (must be between 0 and 10)"},
 
         // error_attribute.hpp
         {Message::MessageID::GrammarAttributeArgument, "parse error: GrammarAttributeArgument"},