Line data Source code
1 : /* Copyright (C) 2025 Robert Schiwon 2 : * 3 : * This file is part of libjdx. 4 : * 5 : * libjdx is free software: you can redistribute it and/or modify it under the 6 : * terms of the GNU Lesser General Public License as published by the Free 7 : * Software Foundation, either version 3 of the License, or (at your option) any 8 : * later version. 9 : * 10 : * libjdx is distributed in the hope that it will be useful, but WITHOUT ANY 11 : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 : * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 13 : * details. 14 : * 15 : * You should have received a copy of the GNU Lesser General Public License 16 : * along with libjdx. If not, see <https://www.gnu.org/licenses/>. 17 : */ 18 : #include "util/MultilineTuplesParser.hpp" 19 : #include "jdx/ParseException.hpp" 20 : #include "util/LdrUtils.hpp" 21 : #include "util/StringUtils.hpp" 22 : 23 27 : libjdx::jdx::util::MultilineTuplesParser::MultilineTuplesParser( 24 : io::TextReader& reader, std::string variableList, std::string ldrName, 25 27 : std::string lineBreakChars) 26 27 : : TuplesParser(std::move(variableList), std::move(ldrName)) 27 : , m_reader{reader} 28 54 : , m_lineBreakChars{std::move(lineBreakChars)} 29 : { 30 27 : } 31 : 32 66 : std::optional<std::string> libjdx::jdx::util::MultilineTuplesParser::nextTuple() 33 : { 34 66 : const auto& ldrName = getLdrName(); 35 132 : std::string tupleString{}; 36 : // find start 37 71 : while (!m_reader.eof()) 38 : { 39 70 : std::streampos pos = m_reader.tellg(); 40 71 : auto line = m_reader.readLine(); 41 71 : auto lineStart = util::stripLineComment(line, true).first; 42 70 : if (isTupleStart(lineStart)) 43 : { 44 50 : tupleString.append(lineStart); 45 50 : break; 46 : } 47 20 : if (util::isLdrStart(lineStart)) 48 : { 49 : // LDR ended, no tuple 50 14 : m_reader.seekg(pos); 51 14 : return std::nullopt; 52 : } 53 6 : if (!lineStart.empty()) 54 : { 55 2 : throw ParseException(std::string{"Illegal string found in "} 56 1 : .append(ldrName) 57 1 : .append(": ") 58 3 : .append(line)); 59 : } 60 : } 61 51 : if (isTupleEnd(tupleString)) 62 : { 63 30 : return tupleString; 64 : } 65 : // read to end of current tuple 66 49 : while (!m_reader.eof()) 67 : { 68 48 : std::streampos pos = m_reader.tellg(); 69 51 : auto line = m_reader.readLine(); 70 51 : auto lineStart = util::stripLineComment(line, true).first; 71 : 72 48 : if (util::isLdrStart(lineStart)) 73 : { 74 : // LDR ended before end of last tuple 75 3 : m_reader.seekg(pos); 76 : throw ParseException( 77 6 : std::string{"No closing parenthesis found for "} 78 3 : .append(ldrName) 79 3 : .append(" entry: ") 80 9 : .append(tupleString)); 81 : } 82 45 : tupleString.append(m_lineBreakChars); 83 45 : tupleString.append(lineStart); 84 45 : if (isTupleEnd(lineStart)) 85 : { 86 17 : return tupleString; 87 : } 88 28 : if (m_reader.eof() || util::isLdrStart(lineStart)) 89 : { 90 : // LDR ended before end of last tuple 91 0 : m_reader.seekg(pos); 92 : throw ParseException( 93 0 : std::string{"No closing parenthesis found for "} 94 0 : .append(ldrName) 95 0 : .append(" entry: ") 96 0 : .append(tupleString)); 97 : } 98 : } 99 : throw ParseException( 100 2 : std::string{"File ended before closing parenthesis was found for "} 101 1 : .append(ldrName) 102 1 : .append(": ") 103 3 : .append(tupleString)); 104 : } 105 : 106 70 : bool libjdx::jdx::util::MultilineTuplesParser::isTupleStart( 107 : const std::string& stringValue) 108 : { 109 70 : std::string value{stringValue}; 110 70 : util::trimLeft(value); 111 140 : return !value.empty() && value.at(0) == '('; 112 : } 113 : 114 96 : bool libjdx::jdx::util::MultilineTuplesParser::isTupleEnd( 115 : const std::string& stringValue) 116 : { 117 96 : std::string value{stringValue}; 118 96 : util::trimRight(value); 119 192 : return !value.empty() && value.back() == ')'; 120 : }