OSDN Git Service

tempo コマンド追加とコマンド引数が正しく読み込めていなかったのを修正
authorstarg <starg@users.osdn.me>
Sun, 21 Aug 2016 13:14:13 +0000 (22:14 +0900)
committerstarg <starg@users.osdn.me>
Sun, 21 Aug 2016 13:14:13 +0000 (22:14 +0900)
12 files changed:
include/ir2midi/context.hpp
include/ir2midi/ir2midi.hpp
include/message/id.hpp
src/driver/msgcallback.cpp
src/ir2midi/CMakeLists.txt
src/ir2midi/command_tempo.cpp [new file with mode: 0644]
src/ir2midi/command_tempo.hpp [new file with mode: 0644]
src/ir2midi/ir2midi.cpp
src/parser/action_state_attribute.hpp
src/parser/action_state_composition.hpp
src/parser/action_state_literal.hpp
src/parser/parser_composition.hpp

index e970053..734341d 100644 (file)
@@ -1,6 +1,7 @@
 
 #pragma once
 
+#include <string>
 #include <vector>
 
 #include <midi/event.hpp>
@@ -32,6 +33,15 @@ private:
     int m_LastEventTime = 0;
 };
 
+class IIR2MIDICompiler
+{
+public:
+    virtual ~IIR2MIDICompiler() = default;
+
+    virtual std::string GetSourceName() const = 0;
+    virtual TrackCompilerContext& GetTrackContext(int trackNumber) = 0;
+};
+
 } // namespace IR2MIDI
 
 } // namespace YAMML
index 6f37caa..044883a 100644 (file)
@@ -18,7 +18,7 @@ namespace YAMML
 namespace IR2MIDI
 {
 
-class IR2MIDICompiler : public Compiler::CompilerBase, public boost::static_visitor<>
+class IR2MIDICompiler : public Compiler::CompilerBase, public IIR2MIDICompiler, public boost::static_visitor<>
 {
 public:
     explicit IR2MIDICompiler(const IR::Module& ir) : m_IR(ir)
@@ -30,6 +30,8 @@ public:
     {
     }
 
+    virtual ~IR2MIDICompiler() = default;
+
     bool Compile(const std::string& entryPoint);
 
     MIDI::MIDIFile& GetMIDI();
@@ -41,6 +43,9 @@ public:
     void operator()(int trackNumber, const IR::Event& ev);
     void operator()(int trackNumber, const IR::BlockReference& blockRef);
 
+    virtual std::string GetSourceName() const override;
+    virtual TrackCompilerContext& GetTrackContext(int trackNumber) override;
+
 private:
     bool CompileTrackBlock(const std::string& trackBlockName);
     void CompileBlock(int trackNumber, IR::BlockReference blockRef);
@@ -50,7 +55,6 @@ private:
     void EnsureTrackInitialized(int number);
 
     MIDI::MIDITrack& GetTrack(int trackNumber);
-    TrackCompilerContext& GetTrackContext(int trackNumber);
 
     IR::Module m_IR;
     MIDI::MIDIFile m_MIDI;
index 3a86f03..e3f9b01 100644 (file)
@@ -14,7 +14,6 @@ enum class MessageID : int
     UnknownInComposition2IR,
     UnknownInIR2MIDI,
     UnprocessedAttribute,
-    UnprocessedCommand,
     DuplicatedCompositionName,
     DuplicatedPhraseName,
     NoSuchPhraseName,
@@ -70,7 +69,14 @@ enum class MessageID : int
     GrammarPhrase2,
     GrammarPhrase3,
     GrammarPhrase4,
-    GrammarPhraseName
+    GrammarPhraseName,
+
+    // IR2MIDI
+    InvalidCommandName,
+    WrongNumberOfCommandArguments,
+    WrongTypeOfCommandArgument,
+
+    InvalidTempo
 };
 
 } // namespace Message
index a3abb0f..bb996d5 100644 (file)
@@ -34,7 +34,6 @@ MessagePrinter::MessagePrinter(IStdErrWriter* pStdErrWriter)
         {Message::MessageID::UnknownInPhrase2IR, ICEMessage + " (Phrase2IR: Phrase = '{0}', Message = '{1}')"},
         {Message::MessageID::UnknownInComposition2IR, ICEMessage + " (Composition2IR: Composition = '{0}', Message = '{1}')"},
         {Message::MessageID::UnknownInIR2MIDI, ICEMessage + " (IR2MIDI: Message = '{0}')"},
-        {Message::MessageID::UnprocessedCommand, ICEMessage + " (Unprocessed command: '{0}')"},
         {Message::MessageID::UnprocessedAttribute, ICEMessage + " (Unprocessed attribute: '{0}')"},
         {Message::MessageID::DuplicatedCompositionName, "composition named '{0}' is already defined"},
         {Message::MessageID::DuplicatedPhraseName, "phrase named '{0}' is already defined"},
@@ -91,7 +90,14 @@ MessagePrinter::MessagePrinter(IStdErrWriter* pStdErrWriter)
         {Message::MessageID::GrammarPhrase2, "parse error: GrammarPhrase2"},
         {Message::MessageID::GrammarPhrase3, "parse error: GrammarPhrase3"},
         {Message::MessageID::GrammarPhrase4, "parse error: GrammarPhrase4"},
-        {Message::MessageID::GrammarPhraseName, "parse error: GrammarPhraseName"}
+        {Message::MessageID::GrammarPhraseName, "parse error: GrammarPhraseName"},
+
+        // IR2MIDI
+        {Message::MessageID::InvalidCommandName, "invalid command '{0}'"},
+        {Message::MessageID::WrongNumberOfCommandArguments, "wrong number of arguments passed to command '{0}'; {2} expected, {1} found"},
+        {Message::MessageID::WrongTypeOfCommandArgument, "command argument {1} has a wrong type; expecting '{2}' here"},
+
+        {Message::MessageID::InvalidTempo, "invalid tempo value"}
     },
     m_pStdErrWriter{pStdErrWriter}
 {
index daf2ff5..61cc650 100644 (file)
@@ -2,9 +2,11 @@
 set(IR2MIDIHeaders
     ../../include/ir2midi/context.hpp
     ../../include/ir2midi/ir2midi.hpp
+    command_tempo.hpp
 )
 
 set(IR2MIDISources
+    command_tempo.cpp
     context.cpp
     ir2midi.cpp
 )
diff --git a/src/ir2midi/command_tempo.cpp b/src/ir2midi/command_tempo.cpp
new file mode 100644 (file)
index 0000000..2f978bf
--- /dev/null
@@ -0,0 +1,84 @@
+
+#include <boost/variant.hpp>
+
+#include "command_tempo.hpp"
+
+#include <midi/event.hpp>
+
+namespace YAMML
+{
+
+namespace IR2MIDI
+{
+
+std::vector<Message::MessageItem> ProcessTempo(IIR2MIDICompiler* pCompiler, const AST::Command& ast)
+{
+    std::vector<Message::MessageItem> messages;
+
+    if (ast.Arguments.size() != 1)
+    {
+        messages.push_back(
+            Message::MessageItem{
+                Message::MessageKind::Error,
+                Message::MessageID::WrongNumberOfCommandArguments,
+                pCompiler->GetSourceName(),
+                ast.Location,
+                {"tempo", std::to_string(ast.Arguments.size()), "1"}
+            }
+        );
+
+        return messages;
+    }
+
+    if (ast.Arguments[0].Value.type() != typeid(long))
+    {
+        messages.push_back(
+            Message::MessageItem{
+                Message::MessageKind::Error,
+                Message::MessageID::WrongTypeOfCommandArgument,
+                pCompiler->GetSourceName(),
+                ast.Location,
+                {"tempo", "1", "int"}
+            }
+        );
+
+        return messages;
+    }
+
+    auto tempo = boost::get<long>(ast.Arguments[0].Value);
+
+    if (tempo <= 0)
+    {
+        messages.push_back(
+            Message::MessageItem{
+                Message::MessageKind::Error,
+                Message::MessageID::InvalidTempo,
+                pCompiler->GetSourceName(),
+                ast.Location,
+                {std::to_string(tempo)}
+            }
+        );
+
+        return messages;
+    }
+
+    unsigned int usecPerQuater = 60 * 1'000'000 / tempo;
+
+    pCompiler->GetTrackContext(0).PushEvent(
+        0,
+        MIDI::MetaEvent{
+            MIDI::MetaEventKind::SetTempo,
+            {
+                static_cast<std::uint8_t>((usecPerQuater & 0xFF0000) >> 16),
+                static_cast<std::uint8_t>((usecPerQuater & 0xFF00) >> 8),
+                static_cast<std::uint8_t>(usecPerQuater & 0xFF)
+            }
+        }
+    );
+
+    return messages;
+}
+
+} // namespace IR2MIDI
+
+} // namespace YAMML
diff --git a/src/ir2midi/command_tempo.hpp b/src/ir2midi/command_tempo.hpp
new file mode 100644 (file)
index 0000000..f4c0a1c
--- /dev/null
@@ -0,0 +1,21 @@
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <ast/composition.hpp>
+#include <ir2midi/context.hpp>
+#include <message/message.hpp>
+
+namespace YAMML
+{
+
+namespace IR2MIDI
+{
+
+std::vector<Message::MessageItem> ProcessTempo(IIR2MIDICompiler* pCompiler, const AST::Command& ast);
+
+} // namespace IR2MIDI
+
+} // namespace YAMML
index a5cd5ba..47589d2 100644 (file)
@@ -7,6 +7,8 @@
 #include <ir2midi/ir2midi.hpp>
 #include <message/message.hpp>
 
+#include "command_tempo.hpp"
+
 namespace YAMML
 {
 
@@ -138,15 +140,22 @@ void IR2MIDICompiler::operator()(const IR::TrackList& ir)
 
 void IR2MIDICompiler::operator()(const AST::Command& ast)
 {
-    throw Exceptions::MessageException(
-        Message::MessageItem{
-            Message::MessageKind::FetalError,
-            Message::MessageID::UnprocessedCommand,
-            m_IR.Name,
-            ast.Location,
-            {ast.Name}
-        }
-    );
+    if (ast.Name == "tempo")
+    {
+        AddMessages(ProcessTempo(this, ast));
+    }
+    else
+    {
+        AddMessage(
+            Message::MessageItem{
+                Message::MessageKind::Error,
+                Message::MessageID::InvalidCommandName,
+                m_IR.Name,
+                ast.Location,
+                {ast.Name}
+            }
+        );
+    }
 }
 
 void IR2MIDICompiler::operator()(int trackNumber, const IR::Event& ev)
@@ -264,8 +273,14 @@ MIDI::MIDITrack& IR2MIDICompiler::GetTrack(int trackNumber)
     return m_MIDI.Tracks[static_cast<std::size_t>(trackNumber)];
 }
 
+std::string IR2MIDICompiler::GetSourceName() const
+{
+    return m_IR.Name;
+}
+
 TrackCompilerContext& IR2MIDICompiler::GetTrackContext(int trackNumber)
 {
+    EnsureTrackInitialized(trackNumber);
     return m_Contexts[static_cast<std::size_t>(trackNumber)];
 }
 
index 4186382..1c44990 100644 (file)
@@ -57,6 +57,11 @@ public:
         st.ASTNode.Arguments.push_back(ASTNode);
     }
 
+    void OnParse(const AST::Literal& ast)
+    {
+        ASTNode.Value = ast;
+    }
+
     AST::AttributeArgument ASTNode;
 };
 
index ea2bd2b..9f150ca 100644 (file)
@@ -181,6 +181,11 @@ public:
         st.ASTNode.Arguments.push_back(ASTNode);
     }
 
+    void OnParse(const AST::Literal& ast)
+    {
+        ASTNode = ast;
+    }
+
     AST::Literal ASTNode;
 };
 
index 62fc9cd..ea7d51e 100644 (file)
@@ -43,7 +43,7 @@ public:
     template<typename TParentState, typename... TCommonStates>
     void success(TParentState& st, TCommonStates&...)
     {
-        st.ASTNode.Value = ASTNode;
+        st.OnParse(ASTNode);
     }
 
     AST::Literal ASTNode;
index 4ac85ac..2a0f8c0 100644 (file)
@@ -17,7 +17,7 @@ namespace Parser
 namespace Grammar
 {
 
-class CommandArgument : public Value
+class CommandArgument : public pegtl::seq<Value>
 {
 };