1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef TrenchBroom_Parser 21 #define TrenchBroom_Parser 22 23 #include "Exceptions.h" 24 #include "StringUtils.h" 25 #include "IO/ParserStatus.h" 26 #include "IO/Token.h" 27 28 #include <map> 29 30 namespace TrenchBroom { 31 namespace IO { 32 template <typename TokenType> 33 class Parser { 34 protected: 35 typedef std::map<TokenType, String> TokenNameMap; 36 private: 37 typedef TokenTemplate<TokenType> Token; 38 mutable TokenNameMap m_tokenNames; 39 public: ~Parser()40 virtual ~Parser() {} 41 protected: check(const TokenType typeMask,const Token & token)42 bool check(const TokenType typeMask, const Token& token) const { 43 return (token.type() & typeMask) != 0; 44 } 45 expect(const TokenType typeMask,const Token & token)46 void expect(const TokenType typeMask, const Token& token) const { 47 if (!check(typeMask, token)) 48 throw ParserException(token.line(), token.column()) << expectString(tokenName(typeMask), token); 49 } 50 expect(ParserStatus & status,const TokenType typeMask,const Token & token)51 void expect(ParserStatus& status, const TokenType typeMask, const Token& token) const { 52 if (!check(typeMask, token)) 53 expect(status, tokenName(typeMask), token); 54 } 55 expect(ParserStatus & status,const String & typeName,const Token & token)56 void expect(ParserStatus& status, const String& typeName, const Token& token) const { 57 const String msg = expectString(typeName, token); 58 status.error(token.line(), token.column(), msg); 59 throw ParserException(token.line(), token.column(), msg); 60 } 61 private: expectString(const String & expected,const Token & token)62 String expectString(const String& expected, const Token& token) const { 63 const String data(token.begin(), token.end()); 64 StringStream msg; 65 msg << " Expected " << expected << ", but got '" << data << "'"; 66 return msg.str(); 67 } 68 protected: 69 tokenName(const TokenType typeMask)70 String tokenName(const TokenType typeMask) const { 71 if (m_tokenNames.empty()) 72 m_tokenNames = tokenNames(); 73 74 StringList names; 75 typename TokenNameMap::const_iterator it, end; 76 for (it = m_tokenNames.begin(), end = m_tokenNames.end(); it != end; ++it) { 77 const TokenType type = it->first; 78 const String& name = it->second; 79 if ((typeMask & type) != 0) 80 names.push_back(name); 81 } 82 83 if (names.empty()) 84 return "unknown token type"; 85 if (names.size() == 1) 86 return names[0]; 87 return StringUtils::join(names, ", ", ", or ", " or "); 88 } 89 private: 90 virtual TokenNameMap tokenNames() const = 0; 91 }; 92 } 93 } 94 95 #endif /* defined(TrenchBroom_Parser) */ 96