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;
enum class MessageID
{
- Unknown
+ Unknown,
+ DuplicatedCompositionName,
+ DuplicatedPhraseName
};
} // namespace Message
bool Parse();
void AddMessage(Message::MessageItem msg);
+ const std::string& GetSourceName() const;
+
boost::optional<AST::Module>& GetAST();
const boost::optional<AST::Module>& GetAST() const;
#include <ast/composition.hpp>
#include <ast/module.hpp>
+#include <parser/parser.hpp>
#include "parser_composition.hpp"
{
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;
#include <ast/module.hpp>
#include <ast/phrase.hpp>
+#include <parser/parser.hpp>
#include "parser_phrase.hpp"
{
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)
+#include <algorithm>
#include <utility>
#include <exceptions/parseexception.hpp>
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)
{
m_Messages.push_back(msg);
}
+const std::string & YAMMLParser::GetSourceName() const
+{
+ return m_Source;
+}
+
boost::optional<AST::Module>& YAMMLParser::GetAST()
{
return m_AST;