20#ifndef PLYWOOT_HEADER_PARSER_HPP
21#define PLYWOOT_HEADER_PARSER_HPP
70 detail::HeaderScanner::Token
expected,
71 detail::HeaderScanner::Token
found,
72 const std::string &tokenString)
84 std::vector<detail::HeaderScanner::Token>
expected,
85 detail::HeaderScanner::Token
found,
86 const std::string &tokenString)
88 "unexpected token '" + detail::to_string(
found) +
"' found, expected a token in the set {" +
93 [](auto &&x, auto &&y) {
94 return x +
", " + detail::to_string(std::forward<
decltype(y)>(y));
105 const std::vector<detail::HeaderScanner::Token> &
expected()
const {
return expected_; }
109 detail::HeaderScanner::Token
found()
const {
return found_; }
113 std::vector<detail::HeaderScanner::Token> expected_;
115 detail::HeaderScanner::Token found_;
120namespace plywoot::detail {
126 using Token = detail::HeaderScanner::Token;
133 HeaderParser(std::istream &is) : scanner_{is}
135 accept(Token::MagicNumber);
138 accept(Token::Format);
139 switch (scanner_.nextToken())
142 format_ = PlyFormat::Ascii;
144 case Token::BinaryLittleEndian:
145 format_ = PlyFormat::BinaryLittleEndian;
147 case Token::BinaryBigEndian:
148 format_ = PlyFormat::BinaryBigEndian;
151 throw InvalidFormat(scanner_.tokenString());
153 scanner_.nextToken();
156 while (scanner_.nextToken() == Token::Comment) { comments_.push_back(scanner_.comment()); }
160 switch (scanner_.token())
162 case Token::EndHeader:
165 elements_.push_back(parseElement());
168 comments_.push_back(scanner_.comment());
169 scanner_.nextToken();
172 throw UnexpectedToken(
173 {Token::EndHeader, Token::Element, Token::Comment}, scanner_.token(), scanner_.tokenString());
176 }
while (scanner_.token() != Token::EndHeader);
183 const std::vector<Comment> &comments()
const {
return comments_; }
187 const std::vector<PlyElement> &elements()
const {
return elements_; }
192 PlyFormat format()
const {
return format_; }
197 void accept(Token expected)
199 if (scanner_.nextToken() != expected)
203 if (!(expected == Token::Identifier && scanner_.isKeyword(scanner_.token())))
205 throw UnexpectedToken(expected, scanner_.token(), scanner_.tokenString());
217 return PlyDataType::Char;
219 return PlyDataType::UChar;
221 return PlyDataType::Short;
223 return PlyDataType::UShort;
225 return PlyDataType::Int;
227 return PlyDataType::UInt;
229 return PlyDataType::Float;
231 return PlyDataType::Double;
233 throw UnexpectedToken(
234 {Token::Char, Token::UChar, Token::Short, Token::UShort, Token::Int, Token::UInt, Token::Float,
236 t, scanner_.tokenString());
241 PlyElement parseElement()
243 accept(Token::Identifier);
244 std::string name{scanner_.tokenString()};
246 accept(Token::Number);
247 std::size_t size{scanner_.tokenNumber()};
249 PlyElement result{std::move(name), size};
252 while (scanner_.nextToken() == Token::Property || scanner_.token() == Token::Comment)
254 if (scanner_.token() == Token::Property)
261 switch (scanner_.nextToken())
264 sizeType = tokenToDataType(scanner_.nextToken());
265 type = tokenToDataType(scanner_.nextToken());
266 accept(Token::Identifier);
267 result.addProperty(scanner_.tokenString(), type, sizeType);
270 type = tokenToDataType(scanner_.token());
271 accept(Token::Identifier);
272 result.addProperty(scanner_.tokenString(), type);
278 assert(scanner_.token() == Token::Comment);
279 comments_.push_back(scanner_.comment());
287 std::vector<Comment> comments_;
291 std::vector<PlyElement> elements_;
293 detail::HeaderScanner scanner_;
Base class for all exceptions thrown by PLYwoot.
Exception thrown in case the input contains an unexpected token.
const std::vector< detail::HeaderScanner::Token > & expected() const
UnexpectedToken(std::vector< detail::HeaderScanner::Token > expected, detail::HeaderScanner::Token found, const std::string &tokenString)
UnexpectedToken(detail::HeaderScanner::Token expected, detail::HeaderScanner::Token found, const std::string &tokenString)
detail::HeaderScanner::Token found() const
PlyDataType
Enumeration of data types supported by the PLY format.