OSDN Git Service

composition とphrase の名前の重複をエラーとして扱うようにした
authorstarg <starg@users.osdn.me>
Sat, 16 Jul 2016 14:58:49 +0000 (23:58 +0900)
committerstarg <starg@users.osdn.me>
Sat, 16 Jul 2016 14:58:49 +0000 (23:58 +0900)
include/ast/module.hpp
include/message/id.hpp
include/parser/parser.hpp
src/parser/action_state_composition.hpp
src/parser/action_state_phrase.hpp
src/parser/parser.cpp

index fa4bc9f..9ef7b89 100644 (file)
@@ -16,14 +16,31 @@ namespace AST
 class Module final
 {
 public:
-    void Add(const Composition& c)
+    // returns false if an item with the same name already exists
+    bool TryAdd(const Composition& c)
     {
-        Compositions[c.Name] = c;
+        if (Compositions.find(c.Name) == Compositions.end())
+        {
+            Compositions[c.Name] = c;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
     }
 
-    void Add(const Phrase& ph)
+    bool TryAdd(const Phrase& ph)
     {
-        Phrases[ph.Name] = ph;
+        if (Phrases.find(ph.Name) == Phrases.end())
+        {
+            Phrases[ph.Name] = ph;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
     }
 
     std::string Name;
index e0f4b28..8491787 100644 (file)
@@ -9,7 +9,9 @@ namespace Message
 
 enum class MessageID
 {
-    Unknown
+    Unknown,
+    DuplicatedCompositionName,
+    DuplicatedPhraseName
 };
 
 } // namespace Message
index f158e2b..13a7f43 100644 (file)
@@ -35,6 +35,8 @@ public:
     bool Parse();
     void AddMessage(Message::MessageItem msg);
 
+    const std::string& GetSourceName() const;
+
     boost::optional<AST::Module>& GetAST();
     const boost::optional<AST::Module>& GetAST() const;
     
index 2f5796e..08e1191 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <ast/composition.hpp>
 #include <ast/module.hpp>
+#include <parser/parser.hpp>
 
 #include "parser_composition.hpp"
 
@@ -20,9 +21,20 @@ class CompositionState
 {
 public:
     template<typename... TCommonStates>
-    void success(AST::Module& mod, TCommonStates&...)
+    void success(AST::Module& mod, YAMMLParser& parser, TCommonStates&...)
     {
-        mod.Add(ASTNode);
+        if (!mod.TryAdd(ASTNode))
+        {
+            parser.AddMessage(
+                {
+                    Message::MessageKind::Error,
+                    Message::MessageID::DuplicatedCompositionName,
+                    parser.GetSourceName(),
+                    ASTNode.Location,
+                    {ASTNode.Name}
+                }
+            );
+        }
     }
 
     AST::Composition ASTNode;
index ac210d6..54d32db 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <ast/module.hpp>
 #include <ast/phrase.hpp>
+#include <parser/parser.hpp>
 
 #include "parser_phrase.hpp"
 
@@ -22,9 +23,20 @@ class PhraseState
 {
 public:
     template<typename... TCommonStates>
-    void success(AST::Module& mod, TCommonStates&...)
-    {
-        mod.Add(ASTNode);
+    void success(AST::Module& mod, YAMMLParser& parser, TCommonStates&...)
+    {
+        if (!mod.TryAdd(ASTNode))
+        {
+            parser.AddMessage(
+                {
+                    Message::MessageKind::Error,
+                    Message::MessageID::DuplicatedPhraseName,
+                    parser.GetSourceName(),
+                    ASTNode.Location,
+                    {ASTNode.Name}
+                }
+            );
+        }
     }
 
     void OnParse(AST::NoteSequenceBlockWithoutAttributes node)
index 847932b..338b2a8 100644 (file)
@@ -1,4 +1,5 @@
 
+#include <algorithm>
 #include <utility>
 
 #include <exceptions/parseexception.hpp>
@@ -38,14 +39,23 @@ bool YAMMLParser::Parse()
     try
     {
         AST::Module ast;
-        bool result = pegtl::parse<Grammar::Module, pegtl::nothing, Control>(m_Source, m_Name, ast);
+        bool result = pegtl::parse<Grammar::Module, pegtl::nothing, Control>(m_Source, m_Name, ast, *this);
 
-        if (result)
+        bool hasErrors = std::find_if(
+            m_Messages.begin(),
+            m_Messages.end(),
+            [] (auto&& i) { return i.Kind == Message::MessageKind::Error || i.Kind == Message::MessageKind::FetalError; }
+        ) != m_Messages.end();
+
+        if (result && !hasErrors)
         {
             m_AST = std::move(ast);
+            return true;
+        }
+        else
+        {
+            return false;
         }
-
-        return result;
     }
     catch (const Exceptions::ParseException& e)
     {
@@ -59,6 +69,11 @@ void YAMMLParser::AddMessage(Message::MessageItem msg)
     m_Messages.push_back(msg);
 }
 
+const std::string & YAMMLParser::GetSourceName() const
+{
+    return m_Source;
+}
+
 boost::optional<AST::Module>& YAMMLParser::GetAST()
 {
     return m_AST;