/* * Copyright 2023 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "input.h" #ifndef parser_input_impl_h #define parser_input_impl_h inline std::optional ParseInput::peek() { if (!empty()) { return *lexer; } return {}; } inline bool ParseInput::takeLParen() { auto t = peek(); if (!t || !t->isLParen()) { return false; } ++lexer; return true; } inline bool ParseInput::takeRParen() { auto t = peek(); if (!t || !t->isRParen()) { return false; } ++lexer; return true; } inline bool ParseInput::takeUntilParen() { while (true) { auto t = peek(); if (!t) { return false; } if (t->isLParen() || t->isRParen()) { return true; } ++lexer; } } inline std::optional ParseInput::takeID() { if (auto t = peek()) { if (auto id = t->getID()) { ++lexer; // See comment on takeName. return Name(std::string(*id)); } } return {}; } inline std::optional ParseInput::takeKeyword() { if (auto t = peek()) { if (auto keyword = t->getKeyword()) { ++lexer; return *keyword; } } return {}; } inline bool ParseInput::takeKeyword(std::string_view expected) { if (auto t = peek()) { if (auto keyword = t->getKeyword()) { if (*keyword == expected) { ++lexer; return true; } } } return false; } inline std::optional ParseInput::takeOffset() { if (auto t = peek()) { if (auto keyword = t->getKeyword()) { if (keyword->substr(0, 7) != "offset="sv) { return {}; } Lexer subLexer(keyword->substr(7)); if (subLexer == subLexer.end()) { return {}; } if (auto o = subLexer->getU64()) { ++subLexer; if (subLexer == subLexer.end()) { ++lexer; return o; } } } } return std::nullopt; } inline std::optional ParseInput::takeAlign() { if (auto t = peek()) { if (auto keyword = t->getKeyword()) { if (keyword->substr(0, 6) != "align="sv) { return {}; } Lexer subLexer(keyword->substr(6)); if (subLexer == subLexer.end()) { return {}; } if (auto a = subLexer->getU32()) { ++subLexer; if (subLexer == subLexer.end()) { ++lexer; return a; } } } } return {}; } inline std::optional ParseInput::takeU64() { if (auto t = peek()) { if (auto n = t->getU64()) { ++lexer; return n; } } return std::nullopt; } inline std::optional ParseInput::takeS64() { if (auto t = peek()) { if (auto n = t->getS64()) { ++lexer; return n; } } return {}; } inline std::optional ParseInput::takeI64() { if (auto t = peek()) { if (auto n = t->getI64()) { ++lexer; return n; } } return {}; } inline std::optional ParseInput::takeU32() { if (auto t = peek()) { if (auto n = t->getU32()) { ++lexer; return n; } } return std::nullopt; } inline std::optional ParseInput::takeS32() { if (auto t = peek()) { if (auto n = t->getS32()) { ++lexer; return n; } } return {}; } inline std::optional ParseInput::takeI32() { if (auto t = peek()) { if (auto n = t->getI32()) { ++lexer; return n; } } return {}; } inline std::optional ParseInput::takeU8() { if (auto t = peek()) { if (auto n = t->getU32()) { if (n <= std::numeric_limits::max()) { ++lexer; return uint8_t(*n); } } } return {}; } inline std::optional ParseInput::takeF64() { if (auto t = peek()) { if (auto d = t->getF64()) { ++lexer; return d; } } return std::nullopt; } inline std::optional ParseInput::takeF32() { if (auto t = peek()) { if (auto f = t->getF32()) { ++lexer; return f; } } return std::nullopt; } inline std::optional ParseInput::takeString() { if (auto t = peek()) { if (auto s = t->getString()) { ++lexer; return s; } } return {}; } inline std::optional ParseInput::takeName() { // TODO: Move this to lexer and validate UTF. if (auto str = takeString()) { // Copy to a std::string to make sure we have a null terminator, otherwise // the `Name` constructor won't work correctly. // TODO: Update `Name` to use string_view instead of char* and/or to take // rvalue strings to avoid this extra copy. return Name(std::string(*str)); } return {}; } inline bool ParseInput::takeSExprStart(std::string_view expected) { auto original = lexer; if (takeLParen() && takeKeyword(expected)) { return true; } lexer = original; return false; } inline Index ParseInput::getPos() { if (auto t = peek()) { return lexer.getIndex() - t->span.size(); } return lexer.getIndex(); } inline Err ParseInput::err(Index pos, std::string reason) { std::stringstream msg; msg << lexer.position(pos) << ": error: " << reason; return Err{msg.str()}; } #endif // parser_input_impl_h