diff --git a/alib2cli/src/lexer/CharSequence.cpp b/alib2cli/src/lexer/CharSequence.cpp deleted file mode 100644 index bb428d05b759dd2ecfb223dc7c5c7568f3ec8814..0000000000000000000000000000000000000000 --- a/alib2cli/src/lexer/CharSequence.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "CharSequence.h" - -#include <algorithm> -#include <numeric> - -#include <alib/string> - -namespace cli { - -void CharSequence::fetch(bool readNextLine) -{ - if (!readNextLine) - return; - - bool first = linePtr == nullptr; - std::string line; - for (std::string tmpLine; m_lineInterface->readline(tmpLine, first);) { - if (std::all_of(tmpLine.begin(), tmpLine.end(), ext::isspace)) { - line += tmpLine; - line += '\n'; - continue; - } - - if (!tmpLine.empty() && tmpLine.back() == '\\') { - tmpLine.back() = '\n'; - line += tmpLine; - first = false; - } else { - line += tmpLine; - line += '\n'; - break; - } - } - - if (std::all_of(line.begin(), line.end(), ext::isspace)) - return; - - m_lines.push_back(std::move(line)); - - this->linePtr = m_lines.back().c_str(); -} - -int CharSequence::getCharacter() const -{ - if (!putbackBuffer.empty()) - return putbackBuffer.back(); - else if (linePtr == nullptr) - return EOF; - else - return *linePtr; -} - -void CharSequence::advance(bool readNextLine) -{ - if (getCharacter() == '\n') { - ++m_line; - m_position = 0; - } else if (getCharacter() != EOF) { - ++m_position; - } - - if (!putbackBuffer.empty()) { - putbackBuffer.pop_back(); - } else if (linePtr == nullptr) { - fetch(readNextLine); - } else { - if (*linePtr != '\0') - ++linePtr; - if (*linePtr == '\0') - fetch(readNextLine); - } -} - -std::string CharSequence::getData() const -{ - return std::accumulate(m_lines.begin(), m_lines.end(), std::string()); -} - -} /* namespace cli */ diff --git a/alib2cli/src/lexer/CharSequence.h b/alib2cli/src/lexer/CharSequence.h deleted file mode 100644 index ae3b25e8ffd2d1269225723a75b778294e5d116d..0000000000000000000000000000000000000000 --- a/alib2cli/src/lexer/CharSequence.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include <memory> -#include <string> -#include <vector> - -#include <readline/LineInterface.h> - -namespace cli { - -class CharSequence { - std::shared_ptr<LineInterface> m_lineInterface; - std::string putbackBuffer; - - const char* linePtr = nullptr; - std::vector<std::string> m_lines; - - void fetch(bool readNextLine); - - std::string getData() const; - - size_t m_line = 0; - size_t m_position = 0; - -public: - explicit CharSequence(std::shared_ptr<cli::LineInterface> reader) - : m_lineInterface(std::move(reader)) - { - } - - template <std::derived_from<LineInterface> Interface> - explicit CharSequence(Interface&& reader) - : m_lineInterface(std::make_shared<Interface>(std::forward<Interface>(reader))) - { // NOLINT(bugprone-forwarding-reference-overload) - } - - CharSequence(CharSequence&&) = default; - - CharSequence(const CharSequence&) = delete; - - CharSequence& operator=(CharSequence&&) = delete; - - CharSequence& operator=(const CharSequence&) = delete; - - ~CharSequence() - { - if (m_lineInterface) - m_lineInterface->lineCallback(getData()); - } - - int getCharacter() const; - - void advance(bool readNextLine); - - void putback(std::string string, size_t line, size_t position) - { - m_line = line; - m_position = position; - putbackBuffer.insert(putbackBuffer.end(), string.rbegin(), string.rend()); - } - - size_t getLine() const - { - return m_line; - } - - size_t getPosition() const - { - return m_position; - } -}; - -} /* namespace cli */ diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp deleted file mode 100644 index c36503105cee56ef8a5b005c887c254e071db05b..0000000000000000000000000000000000000000 --- a/alib2cli/src/lexer/Lexer.cpp +++ /dev/null @@ -1,685 +0,0 @@ -#include <lexer/Lexer.h> - -#include <alib/string> - -namespace cli { - -Lexer::Token Lexer::nextToken(bool readNextLine) -{ - Token res{"", "", TokenType::ERROR}; - - res.m_raw_line = m_source.getLine(); - res.m_raw_position = m_source.getPosition(); - - switch (m_hint) { - case Hint::NONE: - goto q0; - case Hint::FILE: - goto qFile; - case Hint::TYPE: - goto qType; - } - -q0: - if (m_source.getCharacter() == EOF) { - res.m_type = TokenType::EOT; - return res; - } - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::EOS; - return res; - } - if (ext::isspace(m_source.getCharacter())) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q0; - } - - res.m_line = m_source.getLine(); - res.m_position = m_source.getPosition(); - - if (m_source.getCharacter() == '<') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::LESS_THAN; - goto q10; - } - if (m_source.getCharacter() == '>') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::MORE_THAN; - goto q11; - } - if (m_source.getCharacter() == '(') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::LEFT_PAREN; - return res; - } - if (m_source.getCharacter() == ')') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::RIGHT_PAREN; - return res; - } - if (m_source.getCharacter() == '{') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::LEFT_BRACE; - return res; - } - if (m_source.getCharacter() == '}') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::RIGHT_BRACE; - return res; - } - if (m_source.getCharacter() == '[') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::LEFT_BRACKET; - return res; - } - if (m_source.getCharacter() == ']') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::RIGHT_BRACKET; - return res; - } - if (m_source.getCharacter() == '@') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::AT_SIGN; - return res; - } - if (m_source.getCharacter() == '$') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::DOLLAR_SIGN; - return res; - } - if (m_source.getCharacter() == '&') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::AMPERSAND_SIGN; - goto q8; - } - if (m_source.getCharacter() == '|') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::PIPE_SIGN; - goto q9; - } - if (m_source.getCharacter() == '^') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::CARET_SIGN; - return res; - } - if (m_source.getCharacter() == ':') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::COLON_SIGN; - return res; - } - if (m_source.getCharacter() == ';') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::SEMICOLON_SIGN; - return res; - } - if (m_source.getCharacter() == '=') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::ASSIGN; - goto q12; - } - if (m_source.getCharacter() == '#') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::HASH_SIGN; - return res; - } - if (m_source.getCharacter() == ',') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::COMMA; - return res; - } - if (m_source.getCharacter() == '-') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q2; - } - if (m_source.getCharacter() == '+') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::PLUS_SIGN; - goto q7; - } - if (m_source.getCharacter() == '/') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::SLASH_SIGN; - goto qComment; - } - if (m_source.getCharacter() == '*') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::ASTERISK_SIGN; - return res; - } - if (m_source.getCharacter() == '~') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::TILDE_SIGN; - return res; - } - if (m_source.getCharacter() == '!') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::EXCLAMATION_SIGN; - goto q13; - } - if (m_source.getCharacter() == '%') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::PERCENTAGE_SIGN; - return res; - } - if (m_source.getCharacter() == '.') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::DOT; - goto q14; - } - - if (m_source.getCharacter() == '"') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_type = TokenType::STRING; - m_source.advance(true); - goto q4; - } - - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q1; - } - - if ((m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q3; - } - - if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q3Escape; - } - - res.m_type = TokenType::ERROR; - return res; - -q1: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::UNSIGNED; - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q1; - } else if (m_source.getCharacter() == '.') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::DOUBLE; - goto q15; - } else { - res.m_type = TokenType::UNSIGNED; - return res; - } -q2: - if (m_source.getCharacter() == '\0') { - res.m_value = ""; - res.m_type = TokenType::MINUS_SIGN; - return res; - } - if (m_source.getCharacter() == '-') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q2Prime; - } - - if ((m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z') - || (m_source.getCharacter() == ':')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q3; - } else if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q3Escape; - } - - res.m_value = ""; - res.m_type = TokenType::MINUS_SIGN; - return res; - -q2Prime: - if (m_source.getCharacter() == '\0') { - res.m_value = ""; - res.m_type = TokenType::DEC; - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9') - || (m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z') - || (m_source.getCharacter() == ':')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q3; - } else if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q3Escape; - } - - res.m_value = ""; - res.m_type = TokenType::DEC; - return res; - -q3: - if (m_source.getCharacter() == '\0') { - res.m_type = is_kw(res.m_value); - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9') - || (m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z') - || (m_source.getCharacter() == ':' || m_source.getCharacter() == '_')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q3; - } else if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q3Escape; - } else { - res.m_type = is_kw(res.m_value); - return res; - } - -q3Escape: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::ERROR; - return res; - } - - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q3; - -q4: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::ERROR; - return res; - } - if (m_source.getCharacter() == '"') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q6; - } - if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q5; - } else { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q4; - } - -q5: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::ERROR; - return res; - } - - if (m_source.getCharacter() == 'n') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += '\n'; - } else if (m_source.getCharacter() == 't') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += '\t'; - } else if (m_source.getCharacter() == '"') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += '"'; - } else { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - } - - m_source.advance(true); - goto q4; - -q6: - if (m_source.getCharacter() == '\0') { - return res; - } - if (ext::isspace(m_source.getCharacter())) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q6; - } - if (m_source.getCharacter() == '"') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto q4; - } else { - return res; - } - -q7: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '+') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::INC; - } else { - return res; - } - -q8: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '&') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::AND; - } else { - return res; - } - -q9: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '|') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::OR; - } else { - return res; - } - -q10: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '=') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::LESS_THAN_OR_EQUAL; - } else { - return res; - } - -q11: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '=') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::MORE_THAN_OR_EQUAL; - } else { - return res; - } - -q12: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '=') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::EQUAL; - } else { - return res; - } - -q13: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if (m_source.getCharacter() == '=') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::NOT_EQUAL; - } else { - return res; - } - -q14: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - res.m_type = TokenType::DOUBLE; - goto q15; - } else { - return res; - } - -q15: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9')) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto q15; - } else { - return res; - } - -qFile: - if (m_source.getCharacter() == EOF) { - res.m_type = TokenType::EOT; - return res; - } - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::EOS; - return res; - } - if (ext::isspace(m_source.getCharacter())) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto qFile; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9') - || (m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z') - || m_source.getCharacter() == '/' || m_source.getCharacter() == '.' || m_source.getCharacter() == '-' - || m_source.getCharacter() == '~' || m_source.getCharacter() == '_' || m_source.getCharacter() == ':') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto qFile2; - } else { - goto q0; - } - -qFile2: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::FILE; - return res; - } - if ((m_source.getCharacter() >= '0' && m_source.getCharacter() <= '9') - || (m_source.getCharacter() >= 'a' && m_source.getCharacter() <= 'z') - || (m_source.getCharacter() >= 'A' && m_source.getCharacter() <= 'Z') - || m_source.getCharacter() == '/' || m_source.getCharacter() == '.' || m_source.getCharacter() == '-' - || m_source.getCharacter() == '~' || m_source.getCharacter() == '_' || m_source.getCharacter() == ':') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto qFile2; - } else if (m_source.getCharacter() == '\\') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - goto qFileEscape; - } else { - res.m_type = TokenType::FILE; - return res; - } - -qFileEscape: - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::ERROR; - return res; - } - - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto qFile2; - -qType: - if (m_source.getCharacter() == EOF) { - res.m_type = TokenType::EOT; - return res; - } - if (m_source.getCharacter() == '\0') { - res.m_type = TokenType::EOS; - return res; - } - if (ext::isspace(m_source.getCharacter())) { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - goto qType; - } - if (m_source.getCharacter() == ')') { - goto q0; - } - - { - unsigned lparens = 0; - while (m_source.getCharacter() != '\0') { - if (m_source.getCharacter() == '(') - ++lparens; - else if (m_source.getCharacter() == ')' && lparens > 0) - --lparens; - else if (m_source.getCharacter() == ')') { - break; - } - res.m_raw += static_cast<char>(m_source.getCharacter()); - res.m_value += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - } - res.m_value = ext::rtrim(res.m_value); - - res.m_type = TokenType::TYPE; - return res; - } - -qComment: - if (m_source.getCharacter() == EOF) { - return res; - } - if (m_source.getCharacter() == '\0') { - return res; - } - - if (m_source.getCharacter() == '/') { - res.m_value = ""; - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - - while (m_source.getCharacter() != EOF && m_source.getCharacter() != '\n' && m_source.getCharacter() != '\0') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - } - - if (m_source.getCharacter() == '\n') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - } - } else if (m_source.getCharacter() == '*') { - res.m_value = ""; - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - - do { - while (m_source.getCharacter() != EOF && m_source.getCharacter() != '*' && m_source.getCharacter() != '\0') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - } - - if (m_source.getCharacter() == '*') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(true); - } - } while (m_source.getCharacter() != EOF && m_source.getCharacter() != '/' && m_source.getCharacter() != '\0'); - - if (m_source.getCharacter() == '/') { - res.m_raw += static_cast<char>(m_source.getCharacter()); - m_source.advance(readNextLine); - } - } else { - return res; - } - - goto q0; -} - -} /* namespace cli */ diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h deleted file mode 100644 index 477ac4271a4c25501adb49a106e23ecc80aa5e53..0000000000000000000000000000000000000000 --- a/alib2cli/src/lexer/Lexer.h +++ /dev/null @@ -1,247 +0,0 @@ -#pragma once - -#include <memory> -#include <sstream> - -#include <ext/iostream> - -#include <alib/string> - -#include <exception/CommonException.h> - -#include <lexer/CharSequence.h> - -namespace cli { - -class Lexer { -public: - enum class Hint { - NONE, - TYPE, - FILE - }; - -private: - CharSequence m_source; - Hint m_hint; - -public: - enum class TokenType : unsigned { - IDENTIFIER, - UNSIGNED, - DOUBLE, - STRING, - - LESS_THAN, - LESS_THAN_OR_EQUAL, - MORE_THAN, - MORE_THAN_OR_EQUAL, - EQUAL, - NOT_EQUAL, - - LEFT_PAREN, - RIGHT_PAREN, - LEFT_BRACE, - RIGHT_BRACE, - LEFT_BRACKET, - RIGHT_BRACKET, - - DOLLAR_SIGN, - AT_SIGN, - AMPERSAND_SIGN, - PIPE_SIGN, - CARET_SIGN, - COLON_SIGN, - SEMICOLON_SIGN, - MINUS_SIGN, - PLUS_SIGN, - SLASH_SIGN, - ASTERISK_SIGN, - TILDE_SIGN, - EXCLAMATION_SIGN, - PERCENTAGE_SIGN, - HASH_SIGN, - - AND, - OR, - DEC, - INC, - ASSIGN, - - COMMA, - DOT, - - FILE, - TYPE, - ERROR, - EOT, - EOS - }; - - friend bool operator<(TokenType first, TokenType second) - { - return static_cast<unsigned>(first) < static_cast<unsigned>(second); - } - - static std::string tokenTypeToString(TokenType type) - { - switch (type) { - case TokenType::IDENTIFIER: - return "identifier"; - case TokenType::UNSIGNED: - return "unsigned"; - case TokenType::DOUBLE: - return "double"; - case TokenType::STRING: - return "string"; - - case TokenType::LESS_THAN: - return "less_than"; - case TokenType::LESS_THAN_OR_EQUAL: - return "less_than_or_equal"; - case TokenType::MORE_THAN: - return "more_than"; - case TokenType::MORE_THAN_OR_EQUAL: - return "more_or_equal_operator"; - case TokenType::EQUAL: - return "equal"; - case TokenType::NOT_EQUAL: - return "not_equal"; - - case TokenType::LEFT_PAREN: - return "left_paren"; - case TokenType::RIGHT_PAREN: - return "right_paren"; - case TokenType::LEFT_BRACE: - return "left_brace"; - case TokenType::RIGHT_BRACE: - return "right_brace"; - case TokenType::LEFT_BRACKET: - return "left_bracket"; - case TokenType::RIGHT_BRACKET: - return "right_bracket"; - - case TokenType::DOLLAR_SIGN: - return "dolar_sign"; - case TokenType::AT_SIGN: - return "at_sign"; - case TokenType::AMPERSAND_SIGN: - return "ampersand_sign"; - case TokenType::PIPE_SIGN: - return "pipe_sign"; - case TokenType::CARET_SIGN: - return "caret_sign"; - case TokenType::COLON_SIGN: - return "colon_sign"; - case TokenType::SEMICOLON_SIGN: - return "semicolon_sign"; - case TokenType::MINUS_SIGN: - return "minus_sign"; - case TokenType::PLUS_SIGN: - return "plus_sign"; - case TokenType::SLASH_SIGN: - return "slash_sign"; - case TokenType::ASTERISK_SIGN: - return "asterisk_sign"; - case TokenType::TILDE_SIGN: - return "tilde_sign"; - case TokenType::EXCLAMATION_SIGN: - return "exclemation_sign"; - case TokenType::PERCENTAGE_SIGN: - return "percentage_sign"; - case TokenType::HASH_SIGN: - return "hash_sign"; - - case TokenType::AND: - return "and"; - case TokenType::OR: - return "or"; - case TokenType::DEC: - return "dec"; - case TokenType::INC: - return "inc"; - case TokenType::ASSIGN: - return "assign"; - - case TokenType::COMMA: - return "comma"; - case TokenType::DOT: - return "dot"; - - case TokenType::FILE: - return "file"; - case TokenType::TYPE: - return "type"; - case TokenType::ERROR: - return "error"; - case TokenType::EOT: - return "eot"; - case TokenType::EOS: - return "eos"; - default: - throw exception::CommonException("Unhandled case in Lexer::tokenTypeToString"); - } - } - - static TokenType is_kw(const std::string& /* identifier */) - { - return TokenType::IDENTIFIER; - } - - struct Token { - std::string m_value; - std::string m_raw; - TokenType m_type; - - size_t m_line = 0; - size_t m_position = 0; - - size_t m_raw_line = 0; - size_t m_raw_position = 0; - - friend std::ostream& operator<<(std::ostream& out, const Token& token) - { - out << Lexer::tokenTypeToString(token.m_type); - - if (token.m_value.empty()) - return out; - - switch (token.m_type) { - case TokenType::IDENTIFIER: - case TokenType::UNSIGNED: - case TokenType::DOUBLE: - return out << ": " << token.m_value; - case TokenType::STRING: - return out << ": \"" << token.m_value << "\""; - default: - return out; - } - } - - bool operator<(const Token& token) const - { - return std::tie(m_type, m_value) < std::tie(token.m_type, token.m_value); // m_raw omitted intentionally - } - }; - - explicit Lexer(CharSequence source) - : m_source(std::move(source)) - , m_hint(Hint::NONE) - { - m_source.advance(true); - } - - Token nextToken(bool readNextLine = false); - - void putback(Token&& token) - { - m_source.putback(std::move(token.m_raw), token.m_raw_line, token.m_raw_position); - } - - void setHint(Hint hint) - { - m_hint = hint; - } -}; - -} /* namespace cli */ diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp deleted file mode 100644 index 3022b04b465608c1645ce2d0275d5f3961fcbe12..0000000000000000000000000000000000000000 --- a/alib2cli/src/parser/Parser.cpp +++ /dev/null @@ -1,941 +0,0 @@ -#include <parser/Parser.h> - -#include <ast/statements/CastStatement.h> -#include <ast/statements/ContainerStatement.h> -#include <ast/statements/FileStatement.h> -#include <ast/statements/ImmediateStatement.h> -#include <ast/statements/PreviousResultStatement.h> -#include <ast/statements/ResultFileStatement.h> -#include <ast/statements/ResultVariableStatement.h> -#include <ast/statements/SingleStatement.h> -#include <ast/statements/ValueStatement.h> -#include <ast/statements/VariableStatement.h> - -#include <ast/args/BindedArg.h> -#include <ast/args/ImmediateArg.h> - -#include <ast/command/AlgorithmsIntrospectionCommand.h> -#include <ast/command/AstIntrospectionCommand.h> -#include <ast/command/BindingsIntrospectionCommand.h> -#include <ast/command/BlockCommand.h> -#include <ast/command/BreakCommand.h> -#include <ast/command/CalcCommand.h> -#include <ast/command/CastsIntrospectionCommand.h> -#include <ast/command/ClearMeasurements.h> -#include <ast/command/ContinueCommand.h> -#include <ast/command/DataTypesIntrospectionCommand.h> -#include <ast/command/DeclareRunnableCommand.h> -#include <ast/command/EOTCommand.h> -#include <ast/command/EvalCommand.h> -#include <ast/command/ExecuteCommand.h> -#include <ast/command/HelpCommand.h> -#include <ast/command/IfCommand.h> -#include <ast/command/InterpretCommand.h> -#include <ast/command/LoadCommand.h> -#include <ast/command/NormalizeDenormalizeIntrospectionCommand.h> -#include <ast/command/OperatorsIntrospectionCommand.h> -#include <ast/command/OverloadsIntrospectionCommand.h> -#include <ast/command/PrintCommand.h> -#include <ast/command/QuitCommand.h> -#include <ast/command/ReturnCommand.h> -#include <ast/command/SetCommand.h> -#include <ast/command/ShowMeasurements.h> -#include <ast/command/StartMeasurementFrame.h> -#include <ast/command/StopMeasurementFrame.h> -#include <ast/command/UndeclareRunnableCommand.h> -#include <ast/command/UnloadCommand.h> -#include <ast/command/VarDeclareCommand.h> -#include <ast/command/VariablesIntrospectionCommand.h> -#include <ast/command/WhileCommand.h> - -#include <ast/expression/ActualTypeExpression.h> -#include <ast/expression/BatchExpression.h> -#include <ast/expression/BinaryExpression.h> -#include <ast/expression/CastExpression.h> -#include <ast/expression/DeclaredTypeExpression.h> -#include <ast/expression/FunctionCallExpression.h> -#include <ast/expression/ImmediateExpression.h> -#include <ast/expression/MethodCallExpression.h> -#include <ast/expression/PostfixExpression.h> -#include <ast/expression/PrefixExpression.h> -#include <ast/expression/VariableExpression.h> - -namespace cli { - -std::unique_ptr<CategoryOption> Parser::category_option() -{ - if (check_then_match(cli::Lexer::TokenType::COLON_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<CategoryOption>(value); - } else { - return nullptr; - } -} - -std::unique_ptr<TypeOption> Parser::optional_type_option() -{ - if (check_then_match(cli::Lexer::TokenType::COLON_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<TypeOption>(std::move(value)); - } else { - return nullptr; - } -} - -std::unique_ptr<Arg> Parser::file() -{ - setHint(Lexer::Hint::FILE); - if (check_then_match(cli::Lexer::TokenType::HASH_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<BindedArg>(std::move(value)); - } else if (check(cli::Lexer::TokenType::STRING)) { - return std::make_unique<ImmediateArg>(matchString()); - } else { - return std::make_unique<ImmediateArg>(matchFile()); - } -} - -std::unique_ptr<Arg> Parser::type() -{ - setHint(Lexer::Hint::TYPE); - if (check(cli::Lexer::TokenType::STRING)) - return std::make_unique<ImmediateArg>(matchString()); - else - return std::make_unique<ImmediateArg>(matchType()); -} - -std::unique_ptr<Arg> Parser::arg() -{ - if (check_then_match(cli::Lexer::TokenType::HASH_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<BindedArg>(std::move(value)); - } else { - std::string value = matchIdentifier(); - return std::make_unique<ImmediateArg>(value); - } -} - -std::unique_ptr<Arg> Parser::optional_arg() -{ - if (check(cli::Lexer::TokenType::HASH_SIGN, cli::Lexer::TokenType::IDENTIFIER)) - return arg(); - else - return nullptr; -} - -std::unique_ptr<Arg> Parser::template_arg() -{ - match(cli::Lexer::TokenType::AT_SIGN); - if (check(cli::Lexer::TokenType::STRING)) - return std::make_unique<ImmediateArg>(matchString()); - else - return arg(); -} - -std::unique_ptr<Arg> Parser::optional_variable() -{ - if (check_then_match(cli::Lexer::TokenType::DOLLAR_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<ImmediateArg>(value); - } else { - return nullptr; - } -} - -std::unique_ptr<Arg> Parser::optional_binding() -{ - if (check_then_match(cli::Lexer::TokenType::HASH_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<ImmediateArg>(value); - } else { - return nullptr; - } -} - -std::shared_ptr<Statement> Parser::in_redirect() -{ - if (check_then_match(cli::Lexer::TokenType::LEFT_PAREN)) { - std::shared_ptr<StatementList> res = statement_list(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - return res; - } else { - std::unique_ptr<Arg> fileType; - - if (check_then_match(cli::Lexer::TokenType::LEFT_BRACKET)) { - fileType = arg(); - match(cli::Lexer::TokenType::RIGHT_BRACKET); - } - - std::unique_ptr<TypeOption> type = optional_type_option(); - return std::make_shared<FileStatement>(file(), std::move(fileType), std::move(type)); - } -} - -std::unique_ptr<Statement> Parser::out_redirect() -{ - if (check_then_match(cli::Lexer::TokenType::DOLLAR_SIGN)) { - std::unique_ptr<Arg> name = arg(); - return std::make_unique<ResultVariableStatement>(std::move(name)); - } else { - std::unique_ptr<Arg> fileType; - - if (check_then_match(cli::Lexer::TokenType::LEFT_BRACKET)) { - fileType = arg(); - match(cli::Lexer::TokenType::RIGHT_BRACKET); - } - - return std::make_unique<ResultFileStatement>(file(), std::move(fileType)); - } -} - -std::shared_ptr<Statement> Parser::common() -{ - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::DOLLAR_SIGN)) { - std::unique_ptr<Arg> name = arg(); - return std::make_shared<VariableStatement>(std::move(name)); - } else if (check_then_match(cli::Lexer::TokenType::LESS_THAN)) { - return in_redirect(); - } else if (check(cli::Lexer::TokenType::STRING)) { - std::string value = matchString(); - return std::make_shared<ImmediateStatement<std::string>>(value); - } else if (check(cli::Lexer::TokenType::UNSIGNED)) { - int value = matchInteger(); - return std::make_shared<ImmediateStatement<int>>(value); - } else if (check(cli::Lexer::TokenType::DOUBLE)) { - double value = matchDouble(); - return std::make_shared<ImmediateStatement<double>>(value); - } else if (check_then_match(cli::Lexer::TokenType::HASH_SIGN)) { - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_shared<ValueStatement>(std::make_unique<BindedArg>(std::move(value))); - } else if (check_then_match(cli::Lexer::TokenType::LEFT_BRACE)) { - ext::vector<std::shared_ptr<Statement>> params; - while (!check(cli::Lexer::TokenType::RIGHT_BRACE)) - params.emplace_back(param()); - - std::shared_ptr<Statement> res = std::make_shared<ContainerStatement>("Set", std::move(params)); - match(cli::Lexer::TokenType::RIGHT_BRACE); - return res; - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding common rule. Token is " + ext::to_string(m_current) + "."); - } -} - -std::shared_ptr<Statement> Parser::param() -{ - clearCheckOptions(); - if (check(cli::Lexer::TokenType::DOLLAR_SIGN, cli::Lexer::TokenType::LESS_THAN, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::DOUBLE, cli::Lexer::TokenType::HASH_SIGN, cli::Lexer::TokenType::LEFT_BRACE)) { - return common(); - } else if (check_then_match(cli::Lexer::TokenType::MINUS_SIGN)) { - return std::make_shared<PreviousResultStatement>(); - } else if (check(cli::Lexer::TokenType::IDENTIFIER)) { - std::string value = matchIdentifier(); - return std::make_shared<ImmediateStatement<std::string>>(value); - } else if (check_then_match(cli::Lexer::TokenType::LEFT_PAREN)) { - std::unique_ptr<Arg> result_type = type(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - std::shared_ptr<Statement> castedParam = param(); - return std::make_shared<CastStatement>(std::move(result_type), castedParam); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding param rule. Token is " + ext::to_string(m_current) + "."); - } -} - -std::shared_ptr<Statement> Parser::statement() -{ - clearCheckOptions(); - if (check(cli::Lexer::TokenType::DOLLAR_SIGN, cli::Lexer::TokenType::LESS_THAN, cli::Lexer::TokenType::STRING, cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::DOUBLE, cli::Lexer::TokenType::HASH_SIGN, cli::Lexer::TokenType::LEFT_BRACE)) { - return common(); - } else if (check(cli::Lexer::TokenType::IDENTIFIER)) { - std::unique_ptr<Arg> name = std::make_unique<ImmediateArg>(matchIdentifier()); - ext::vector<std::unique_ptr<cli::Arg>> templateArgs; - while (check(cli::Lexer::TokenType::AT_SIGN)) - templateArgs.emplace_back(template_arg()); - - std::unique_ptr<CategoryOption> category = category_option(); - ext::vector<std::shared_ptr<Statement>> params; - while (!check(cli::Lexer::TokenType::MORE_THAN, cli::Lexer::TokenType::PIPE_SIGN, cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::RIGHT_PAREN, cli::Lexer::TokenType::SEMICOLON_SIGN)) { - params.emplace_back(param()); - } - - return std::make_shared<SingleStatement>(std::move(name), std::move(templateArgs), std::move(params), std::move(category)); - } else if (check_then_match(cli::Lexer::TokenType::LEFT_PAREN)) { - std::unique_ptr<Arg> result_type = type(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - std::shared_ptr<Statement> castedStatement = statement(); - return std::make_shared<CastStatement>(std::move(result_type), castedStatement); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding statement rule. Token is " + ext::to_string(m_current) + "."); - } -} - -std::shared_ptr<StatementList> Parser::statement_list() -{ - ext::vector<std::shared_ptr<Statement>> list; - list.emplace_back(statement()); - while (check(cli::Lexer::TokenType::PIPE_SIGN, cli::Lexer::TokenType::MORE_THAN)) { - if (check_then_match(cli::Lexer::TokenType::PIPE_SIGN)) { - list.emplace_back(statement()); - } else { - match(cli::Lexer::TokenType::MORE_THAN); - list.emplace_back(out_redirect()); - } - } - return std::make_shared<StatementList>(std::move(list)); -} - -std::pair<bool, bool> Parser::introspect_cast_from_to() -{ - bool from = false; - bool to = false; - while (check_then_match(cli::Lexer::TokenType::COLON_SIGN)) { - clearCheckOptions(); - if (check_nonreserved_kw("from")) { - match_nonreserved_kw("from"); - from = true; - } else if (check_nonreserved_kw("to")) { - match_nonreserved_kw("to"); - to = true; - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding introspect_cast_type. Token is " + ext::to_string(m_current) + "."); - } - } - return std::make_pair(from, to); -} - -std::unique_ptr<Command> Parser::introspect_command() -{ - clearCheckOptions(); - if (check_then_match_nonreserved_kw("algorithms")) { - std::unique_ptr<cli::Arg> param = optional_arg(); - return std::make_unique<AlgorithmsIntrospectionCommand>(std::move(param)); - } else if (check_then_match_nonreserved_kw("overloads")) { - std::unique_ptr<cli::Arg> param = arg(); - - ext::vector<std::unique_ptr<cli::Arg>> templateArgs; - while (check(cli::Lexer::TokenType::AT_SIGN)) - templateArgs.emplace_back(template_arg()); - - return std::make_unique<OverloadsIntrospectionCommand>(std::move(param), std::move(templateArgs)); - } else if (check_then_match_nonreserved_kw("operators")) { - return std::make_unique<OperatorsIntrospectionCommand>(); - } else if (check_then_match_nonreserved_kw("datatypes")) { - std::unique_ptr<cli::Arg> param = optional_arg(); - return std::make_unique<DataTypesIntrospectionCommand>(std::move(param)); - } else if (check_then_match_nonreserved_kw("casts")) { - std::pair<bool, bool> from_to = introspect_cast_from_to(); - std::unique_ptr<cli::Arg> param = optional_arg(); - return std::make_unique<CastsIntrospectionCommand>(std::move(param), from_to.first, from_to.second); - } else if (check_then_match_nonreserved_kw("normalizations")) { - return std::make_unique<NormalizeDenormalizeIntrospectionCommand>(NormalizeDenormalizeIntrospectionCommand::What::NORMALIZE); - } else if (check_then_match_nonreserved_kw("denormalizations")) { - return std::make_unique<NormalizeDenormalizeIntrospectionCommand>(NormalizeDenormalizeIntrospectionCommand::What::DENORMALIZE); - } else if (check_then_match_nonreserved_kw("variables")) { - std::unique_ptr<cli::Arg> param = optional_variable(); - return std::make_unique<VariablesIntrospectionCommand>(std::move(param)); - } else if (check_then_match_nonreserved_kw("bindings")) { - std::unique_ptr<cli::Arg> param = optional_arg(); - return std::make_unique<BindingsIntrospectionCommand>(std::move(param)); - } else if (check_then_match_nonreserved_kw("ast")) { - return std::make_unique<AstIntrospectionCommand>(command()); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding introspection_command rule. Token is " + ext::to_string(m_current) + "."); - } -} - -std::unique_ptr<CommandList> Parser::block() -{ - incNestedLevel(); - match_nonreserved_kw("begin"); - - ext::vector<std::unique_ptr<Command>> list; - while (!check_nonreserved_kw("end")) - list.emplace_back(semicolon_command()); - - decNestedLevel(); - match_nonreserved_kw("end"); - return std::make_unique<CommandList>(std::move(list)); -} - -std::unique_ptr<Command> Parser::semicolon_command() -{ - bool semicolonFreeCommand = check_nonreserved_kw("begin", "if", "while"); - std::unique_ptr<Command> res = command(); - if (!semicolonFreeCommand) - match(cli::Lexer::TokenType::SEMICOLON_SIGN); - return res; -} - -std::unique_ptr<Expression> Parser::expression() -{ - return assign_expression(); -} - -std::unique_ptr<Expression> Parser::batch() -{ - std::shared_ptr<StatementList> res = statement_list(); - return std::make_unique<BatchExpression>(std::move(res)); -} - -std::unique_ptr<Expression> Parser::expression_or_batch() -{ - if (check_then_match_nonreserved_kw("batch")) { - return batch(); - } else { - check_then_match_nonreserved_kw("expression"); // optional token - return expression(); - } -} - -std::unique_ptr<Expression> Parser::batch_or_expression() -{ - if (check_then_match_nonreserved_kw("expression")) { - return expression(); - } else { - check_then_match_nonreserved_kw("batch"); // optional token - return batch(); - } -} - -std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> Parser::qualifiedType() -{ - abstraction::TypeQualifiers::TypeQualifierSet typeQualifiers = abstraction::TypeQualifiers::TypeQualifierSet::NONE; - - if (check_then_match_nonreserved_kw("const")) - typeQualifiers = typeQualifiers | abstraction::TypeQualifiers::TypeQualifierSet::CONST; - - std::unique_ptr<Arg> type = arg(); - - if (check_then_match(cli::Lexer::TokenType::AND)) - typeQualifiers = typeQualifiers | abstraction::TypeQualifiers::TypeQualifierSet::RREF; - else if (check_then_match(cli::Lexer::TokenType::AMPERSAND_SIGN)) - typeQualifiers = typeQualifiers | abstraction::TypeQualifiers::TypeQualifierSet::LREF; - - return std::make_pair(typeQualifiers, std::move(type)); -} - -std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> Parser::runnableParam() -{ - std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> qualType = qualifiedType(); - - match(cli::Lexer::TokenType::DOLLAR_SIGN); - std::unique_ptr<Arg> name = arg(); - - return std::make_pair(qualType.first, std::move(name)); -} - -std::unique_ptr<Command> Parser::command() -{ - clearCheckOptions(); - if (check_then_match_nonreserved_kw("execute")) { - std::unique_ptr<Expression> expr = batch_or_expression(); - return std::make_unique<ExecuteCommand>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("print")) { - std::unique_ptr<Expression> expr = batch_or_expression(); - return std::make_unique<PrintCommand>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("quit")) { - std::unique_ptr<Expression> expr; - if (!check(cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN)) - expr = batch_or_expression(); - - return std::make_unique<QuitCommand>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("exit")) { - std::unique_ptr<Expression> expr; - if (!check(cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN)) - expr = batch_or_expression(); - - return std::make_unique<QuitCommand>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("return")) { - std::unique_ptr<Expression> expr; - if (!check(cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT, cli::Lexer::TokenType::SEMICOLON_SIGN)) - expr = expression_or_batch(); - - return std::make_unique<ReturnCommand>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("help")) { - std::unique_ptr<cli::Arg> command = optional_arg(); - return std::make_unique<HelpCommand>(std::move(command)); - } else if (check_then_match_nonreserved_kw("introspect")) { - return introspect_command(); - } else if (check_then_match_nonreserved_kw("set")) { - std::string param = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - std::string value = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING); - return std::make_unique<SetCommand>(std::move(param), std::move(value)); - } else if (check_then_match_nonreserved_kw("show")) { - std::string param = getTokenValue(); - match_nonreserved_kw("measurements"); - match_nonreserved_kw("as"); - if (check_then_match_nonreserved_kw("list")) { - return std::make_unique<ShowMeasurements>(measurements::MeasurementFormat::LIST); - } else { - match_nonreserved_kw("tree"); - return std::make_unique<ShowMeasurements>(measurements::MeasurementFormat::TREE); - } - } else if (check_then_match_nonreserved_kw("clear")) { - match_nonreserved_kw("measurements"); - return std::make_unique<ClearMeasurements>(); - } else if (check_then_match_nonreserved_kw("start")) { - measurements::Type type; - if (check_then_match_nonreserved_kw("root")) { - type = measurements::Type::ROOT; - } else if (check_then_match_nonreserved_kw("overall")) { - type = measurements::Type::OVERALL; - } else if (check_then_match_nonreserved_kw("init")) { - type = measurements::Type::INIT; - } else if (check_then_match_nonreserved_kw("finalize")) { - type = measurements::Type::FINALIZE; - } else if (check_then_match_nonreserved_kw("main")) { - type = measurements::Type::MAIN; - } else if (check_then_match_nonreserved_kw("auxiliary")) { - type = measurements::Type::AUXILIARY; - } else if (check_then_match_nonreserved_kw("preprocess")) { - type = measurements::Type::PREPROCESS; - } else { - match_nonreserved_kw("algorithm"); - type = measurements::Type::ALGORITHM; - } - - match_nonreserved_kw("measurement"); - match_nonreserved_kw("frame"); - - std::string frameName = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER); - return std::make_unique<StartMeasurementFrame>(std::move(frameName), type); - } else if (check_then_match_nonreserved_kw("stop")) { - match_nonreserved_kw("measurement"); - match_nonreserved_kw("frame"); - - return std::make_unique<StopMeasurementFrame>(); - } else if (check_then_match_nonreserved_kw("load")) { - setHint(Lexer::Hint::FILE); - std::string libraryName = getTokenValue(); - match(cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING); - - return std::make_unique<LoadCommand>(std::move(libraryName)); - } else if (check_then_match_nonreserved_kw("unload")) { - setHint(Lexer::Hint::FILE); - std::string libraryName = getTokenValue(); - match(cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING); - - return std::make_unique<UnloadCommand>(std::move(libraryName)); - } else if (check_then_match_nonreserved_kw("calc")) { - std::unique_ptr<Expression> expr = expression(); - return std::make_unique<CalcCommand>(std::move(expr)); - } else if (check_nonreserved_kw("begin")) { - return std::make_unique<BlockCommand>(block()); - } else if (check_then_match_nonreserved_kw("eval")) { - std::string evalString = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING); - return std::make_unique<EvalCommand>(std::move(evalString)); - } else if (check_then_match_nonreserved_kw("interpret")) { - setHint(Lexer::Hint::FILE); - std::string fileName = getTokenValue(); - match(cli::Lexer::TokenType::FILE, cli::Lexer::TokenType::STRING); - - return std::make_unique<InterpretCommand>(std::move(fileName)); - } else if (check_then_match_nonreserved_kw("if")) { - if (globalScope()) - throw exception::CommonException("Statement not available in global scope."); - match(cli::Lexer::TokenType::LEFT_PAREN); - std::unique_ptr<Expression> condition = expression_or_batch(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - - match_nonreserved_kw("then"); - std::unique_ptr<Command> thenBranch = semicolon_command(); - - std::unique_ptr<Command> elseBranch; - if (check_nonreserved_kw("else")) { - match_nonreserved_kw("else"); - elseBranch = semicolon_command(); - } - - return std::make_unique<IfCommand>(std::move(condition), std::move(thenBranch), std::move(elseBranch)); - } else if (check_then_match_nonreserved_kw("while")) { - if (globalScope()) - throw exception::CommonException("Statement not available in global scope."); - - match(cli::Lexer::TokenType::LEFT_PAREN); - std::unique_ptr<Expression> condition = expression_or_batch(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - - match_nonreserved_kw("do"); - std::unique_ptr<Command> body = semicolon_command(); - - return std::make_unique<WhileCommand>(std::move(condition), std::move(body)); - } else if (check_then_match_nonreserved_kw("break")) { - if (globalScope()) - throw exception::CommonException("Statement not available in global scope."); - return std::make_unique<BreakCommand>(); - } else if (check_then_match_nonreserved_kw("continue")) { - if (globalScope()) - throw exception::CommonException("Statement not available in global scope."); - return std::make_unique<ContinueCommand>(); - } else if (check_then_match_nonreserved_kw("declare")) { - std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> qualType = qualifiedType(); - - match(cli::Lexer::TokenType::DOLLAR_SIGN); - std::unique_ptr<Arg> name = arg(); - - match(cli::Lexer::TokenType::ASSIGN); - - std::unique_ptr<Expression> expr = expression(); - - return std::make_unique<VarDeclareCommand>(std::move(name), qualType.first, std::move(expr)); - } else if (check_then_match_nonreserved_kw("procedure")) { - if (!globalScope()) - throw exception::CommonException("Statement available in global scope only."); - - std::string routineName = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING); - - std::vector<std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>>> params; - match(cli::Lexer::TokenType::LEFT_PAREN); - if (!check(cli::Lexer::TokenType::RIGHT_PAREN)) { - params.push_back(Parser::runnableParam()); - - while (check(cli::Lexer::TokenType::COMMA)) { - match(cli::Lexer::TokenType::COMMA); - params.push_back(Parser::runnableParam()); - } - } - match(cli::Lexer::TokenType::RIGHT_PAREN); - - std::unique_ptr<Command> body = command(); - - return std::make_unique<DeclareRunnableCommand>(std::move(routineName), std::move(params), std::move(body)); - } else if (check_then_match_nonreserved_kw("function")) { - if (!globalScope()) - throw exception::CommonException("Statement available in global scope only."); - - std::string routineName = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING); - - std::vector<std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>>> params; - match(cli::Lexer::TokenType::LEFT_PAREN); - if (!check(cli::Lexer::TokenType::RIGHT_PAREN)) { - params.push_back(Parser::runnableParam()); - - while (check(cli::Lexer::TokenType::COMMA)) { - match(cli::Lexer::TokenType::COMMA); - params.push_back(Parser::runnableParam()); - } - } - match(cli::Lexer::TokenType::RIGHT_PAREN); - - match_nonreserved_kw("returning"); - - std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> returnType = qualifiedType(); - - std::unique_ptr<Command> body = command(); - - return std::make_unique<DeclareRunnableCommand>(std::move(routineName), std::move(params), std::move(returnType), std::move(body)); - } else if (check_then_match_nonreserved_kw("undeclare")) { - if (!globalScope()) - throw exception::CommonException("Statement available in global scope only."); - - std::string routineName = getTokenValue(); - match(cli::Lexer::TokenType::UNSIGNED, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING); - - std::vector<abstraction::TypeQualifiers::TypeQualifierSet> params; - match(cli::Lexer::TokenType::LEFT_PAREN); - if (!check(cli::Lexer::TokenType::RIGHT_PAREN)) { - params.push_back(Parser::qualifiedType().first); - - while (check(cli::Lexer::TokenType::COMMA)) { - match(cli::Lexer::TokenType::COMMA); - params.push_back(Parser::qualifiedType().first); - } - } - match(cli::Lexer::TokenType::RIGHT_PAREN); - - return std::make_unique<UndeclareRunnableCommand>(std::move(routineName), std::move(params)); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding parse rule. Token is " + ext::to_string(m_current) + "."); - } -} - -std::unique_ptr<CommandList> Parser::parse() -{ - ext::vector<std::unique_ptr<Command>> list; - - if (check(cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT)) { - list.emplace_back(std::make_unique<EOTCommand>()); - return std::make_unique<CommandList>(std::move(list)); - } - - list.emplace_back(command()); - while (check_then_match(cli::Lexer::TokenType::SEMICOLON_SIGN)) - list.emplace_back(command()); - - match(cli::Lexer::TokenType::EOS, cli::Lexer::TokenType::EOT); - return std::make_unique<CommandList>(std::move(list)); -} - -std::unique_ptr<Expression> Parser::assign_expression() -{ - std::unique_ptr<Expression> res = or_expression(); - if (check_then_match(cli::Lexer::TokenType::ASSIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::ASSIGN, std::move(res), assign_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::or_expression() -{ - std::unique_ptr<Expression> res = and_expression(); - while (check_then_match(cli::Lexer::TokenType::OR)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::LOGICAL_OR, std::move(res), and_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::and_expression() -{ - std::unique_ptr<Expression> res = bitwise_or_expression(); - while (check_then_match(cli::Lexer::TokenType::AND)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::LOGICAL_AND, std::move(res), bitwise_or_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::bitwise_or_expression() -{ - std::unique_ptr<Expression> res = bitwise_and_expression(); - while (check_then_match(cli::Lexer::TokenType::PIPE_SIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::BINARY_OR, std::move(res), bitwise_and_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::bitwise_and_expression() -{ - std::unique_ptr<Expression> res = bitwise_xor_expression(); - while (check_then_match(cli::Lexer::TokenType::AMPERSAND_SIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::BINARY_AND, std::move(res), bitwise_xor_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::bitwise_xor_expression() -{ - std::unique_ptr<Expression> res = equality_expression(); - while (check_then_match(cli::Lexer::TokenType::CARET_SIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::BINARY_XOR, std::move(res), equality_expression()); - - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::equality_expression() -{ - std::unique_ptr<Expression> res = relational_expression(); - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::EQUAL)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::EQUALS, std::move(res), relational_expression()); - } else if (check_then_match(cli::Lexer::TokenType::NOT_EQUAL)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::NOT_EQUALS, std::move(res), relational_expression()); - } - restoreCheckOptions(checkOptions); - return res; -} - -std::unique_ptr<Expression> Parser::relational_expression() -{ - std::unique_ptr<Expression> res = add_expression(); - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::LESS_THAN)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::LESS, std::move(res), add_expression()); - } else if (check_then_match(cli::Lexer::TokenType::LESS_THAN_OR_EQUAL)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::LESS_OR_EQUAL, std::move(res), add_expression()); - } else if (check_then_match(cli::Lexer::TokenType::MORE_THAN)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::MORE, std::move(res), add_expression()); - } else if (check_then_match(cli::Lexer::TokenType::MORE_THAN_OR_EQUAL)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::MORE_OR_EQUAL, std::move(res), add_expression()); - } - restoreCheckOptions(checkOptions); - return res; -} - -std::unique_ptr<Expression> Parser::add_expression() -{ - std::unique_ptr<Expression> res = mul_expression(); - while (check(cli::Lexer::TokenType::PLUS_SIGN, cli::Lexer::TokenType::MINUS_SIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::PLUS_SIGN)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::ADD, std::move(res), mul_expression()); - } else { - match(cli::Lexer::TokenType::MINUS_SIGN); - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::SUB, std::move(res), mul_expression()); - } - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::mul_expression() -{ - std::unique_ptr<Expression> res = prefix_expression(); - while (check(cli::Lexer::TokenType::ASTERISK_SIGN, cli::Lexer::TokenType::PERCENTAGE_SIGN, cli::Lexer::TokenType::SLASH_SIGN)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::ASTERISK_SIGN)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::MUL, std::move(res), prefix_expression()); - } else if (check_then_match(cli::Lexer::TokenType::PERCENTAGE_SIGN)) { - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::MOD, std::move(res), prefix_expression()); - } else { - match(cli::Lexer::TokenType::SLASH_SIGN); - res = std::make_unique<BinaryExpression>(abstraction::Operators::BinaryOperators::DIV, std::move(res), prefix_expression()); - } - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::prefix_expression() -{ - clearCheckOptions(); - if (check_then_match_nonreserved_kw("cast")) { - match(cli::Lexer::TokenType::LEFT_PAREN); - std::unique_ptr<Arg> result_type = type(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<CastExpression>(std::move(result_type), std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::PLUS_SIGN)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::PLUS, std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::MINUS_SIGN)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::MINUS, std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::EXCLAMATION_SIGN)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::LOGICAL_NOT, std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::TILDE_SIGN)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::BINARY_NEG, std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::INC)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::INCREMENT, std::move(expression)); - } else if (check_then_match(cli::Lexer::TokenType::DEC)) { - std::unique_ptr<Expression> expression = prefix_expression(); - return std::make_unique<PrefixExpression>(abstraction::Operators::PrefixOperators::DECREMENT, std::move(expression)); - } else { - return suffix_expression(); - } -} - -std::unique_ptr<Expression> Parser::suffix_expression() -{ - std::unique_ptr<Expression> res = atom(); - clearCheckOptions(); - while (check(cli::Lexer::TokenType::DOT, cli::Lexer::TokenType::INC, cli::Lexer::TokenType::DEC)) { - auto checkOptions = getCheckOptions(); - clearCheckOptions(); - if (check_then_match(cli::Lexer::TokenType::DOT)) { - std::string memberName = getTokenValue(); - match(cli::Lexer::TokenType::IDENTIFIER); - std::vector<std::unique_ptr<Expression>> params = bracketed_expression_list(); - res = std::make_unique<MethodCallExpression>(std::move(res), std::move(memberName), std::move(params)); - } else if (check_then_match(cli::Lexer::TokenType::INC)) { - res = std::make_unique<PostfixExpression>(abstraction::Operators::PostfixOperators::INCREMENT, std::move(res)); - } else if (check_then_match(cli::Lexer::TokenType::DEC)) { - res = std::make_unique<PostfixExpression>(abstraction::Operators::PostfixOperators::DECREMENT, std::move(res)); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding suffix_expression rule. Token is " + ext::to_string(m_current) + "."); - } - restoreCheckOptions(checkOptions); - } - return res; -} - -std::unique_ptr<Expression> Parser::atom() -{ - if (check_then_match_nonreserved_kw("actual_type", "type")) { - match(cli::Lexer::TokenType::LEFT_PAREN); - std::unique_ptr<Expression> expr = expression(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - return std::make_unique<ActualTypeExpression>(std::move(expr)); - } else if (check_then_match_nonreserved_kw("declared_type")) { - match(cli::Lexer::TokenType::LEFT_PAREN); - std::unique_ptr<Expression> expr = expression(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - return std::make_unique<ActualTypeExpression>(std::move(expr)); - } else if (check(cli::Lexer::TokenType::IDENTIFIER)) { - std::string routineName = getTokenValue(); - match(cli::Lexer::TokenType::IDENTIFIER); - std::vector<std::unique_ptr<Expression>> params = bracketed_expression_list(); - return std::make_unique<FunctionCallExpression>(routineName, std::move(params)); - } else if (check_then_match(cli::Lexer::TokenType::DOLLAR_SIGN)) { - std::unique_ptr<Arg> name = arg(); - return std::make_unique<VariableExpression>(std::move(name)); - } else if (check_then_match(cli::Lexer::TokenType::LEFT_PAREN)) { - std::unique_ptr<Expression> expr = expression(); - match(cli::Lexer::TokenType::RIGHT_PAREN); - return expr; - } else if (check(cli::Lexer::TokenType::STRING)) { - std::string value = matchString(); - return std::make_unique<ImmediateExpression<std::string>>(value); - } else if (check(cli::Lexer::TokenType::UNSIGNED)) { - int value = matchInteger(); - return std::make_unique<ImmediateExpression<int>>(value); - } else if (check(cli::Lexer::TokenType::DOUBLE)) { - double value = matchDouble(); - return std::make_unique<ImmediateExpression<double>>(value); - } else { - throw exception::CommonException(lineInfo() + "Mismatched set " + ext::to_string(getCheckOptions()) + " while expanding prefix_expression and atom rules. Token is " + ext::to_string(m_current) + "."); - } -} - -std::vector<std::unique_ptr<Expression>> Parser::bracketed_expression_list() -{ - std::vector<std::unique_ptr<Expression>> res; - match(cli::Lexer::TokenType::LEFT_PAREN); - if (!check(cli::Lexer::TokenType::RIGHT_PAREN)) { - res.push_back(expression()); - while (check_then_match(cli::Lexer::TokenType::COMMA)) - res.push_back(expression()); - } - match(cli::Lexer::TokenType::RIGHT_PAREN); - return res; -} - -} /* namespace cli */ diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h deleted file mode 100644 index fb13a0d85c7ea6e2b3890a9f0fc6b2e4c0aec27e..0000000000000000000000000000000000000000 --- a/alib2cli/src/parser/Parser.h +++ /dev/null @@ -1,283 +0,0 @@ -#pragma once - -#include <ext/algorithm> - -#include <ast/Arg.h> -#include <ast/Expression.h> -#include <ast/Option.h> -#include <ast/Statement.h> - -#include <ast/options/CategoryOption.h> -#include <ast/options/TypeOption.h> - -#include <ast/command/CommandList.h> - -#include <ast/statements/StatementList.h> - -#include <lexer/Lexer.h> - -#include <exception/CommonException.h> - -namespace cli { - -class Parser { - cli::Lexer m_lexer; - cli::Lexer::Token m_current; - unsigned m_forceLexerReadNext = {0}; - - ext::set<cli::Lexer::Token> m_checkedOptions; - - void clearCheckOptions() - { - m_checkedOptions.clear(); - } - - const ext::set<cli::Lexer::Token>& getCheckOptions() - { - return m_checkedOptions; - } - - void restoreCheckOptions(ext::set<cli::Lexer::Token> checkOptions) - { - m_checkedOptions = std::move(checkOptions); - } - - std::string lineInfo() const - { - return std::string("Line ") + ext::to_string(m_current.m_line) + " at position " + ext::to_string(m_current.m_position) + ": "; - } - - Parser(cli::Lexer lexer) - : m_lexer(std::move(lexer)) - , m_current(m_lexer.nextToken(true)) - { - } - -public: - static std::unique_ptr<cli::CommandList> parse(cli::Lexer&& lexer) - { - // TODO: Remove, with whole class. Used only for backward compatibility testing - return Parser(std::move(lexer)).parse(); - } - - void setHint(Lexer::Hint hint) - { - m_lexer.setHint(hint); - m_lexer.putback(std::move(m_current)); - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - m_lexer.setHint(Lexer::Hint::NONE); - } - - template <class... TokenTypes> - bool check(TokenTypes... tokens) - { - m_checkedOptions.merge(std::set<cli::Lexer::Token>{cli::Lexer::Token{"", "", tokens}...}); - return (... || (m_current.m_type == tokens)); - } - - template <class... NonreservedTokens> - bool check_nonreserved_kw(const NonreservedTokens&... kw) - { - m_checkedOptions.merge(std::set<cli::Lexer::Token>{cli::Lexer::Token{kw, "", cli::Lexer::TokenType::IDENTIFIER}...}); - return m_current.m_type == Lexer::TokenType::IDENTIFIER && (... || (m_current.m_value == kw)); - } - - template <class... TokenTypes> - bool match(cli::Lexer::TokenType token, TokenTypes... tokens) - { - if (!check(token, tokens...)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a token " + (Lexer::tokenTypeToString(token) + ... + (", " + Lexer::tokenTypeToString(tokens))) + ". Actual was " + Lexer::tokenTypeToString(m_current.m_type) + ". Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return true; - } - - template <class... NonreservedTokens> - bool match_nonreserved_kw(const std::string& kw, const NonreservedTokens&... kws) - { - if (!check_nonreserved_kw(kw, kws...)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a non reseved keyword: " + (kw + ... + (std::string(", ") + kws)) + ". Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return true; - } - - template <class... TokenTypes> - bool check_then_match(cli::Lexer::TokenType token, TokenTypes... tokens) - { - if (!check(token, tokens...)) - return false; - - match(token, tokens...); - return true; - } - - template <class... NonreservedTokens> - bool check_then_match_nonreserved_kw(const std::string& kw, const NonreservedTokens&... kws) - { - if (!check_nonreserved_kw(kw, kws...)) - return false; - - match_nonreserved_kw(kw, kws...); - return true; - } - - std::string matchIdentifier() - { - if (!check(Lexer::TokenType::IDENTIFIER)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching an identifier. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - std::string res = m_current.m_value; - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - std::string matchString() - { - if (!check(Lexer::TokenType::STRING)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a string. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - std::string res = m_current.m_value; - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - std::string matchType() - { - if (!check(Lexer::TokenType::TYPE)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a type. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - std::string res = m_current.m_value; - - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - std::string matchFile() - { - if (!check(Lexer::TokenType::FILE)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a file. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - std::string res = m_current.m_value; - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - int matchInteger() - { - if (!check(Lexer::TokenType::UNSIGNED)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching an integer. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - int res = ext::from_string<int>(m_current.m_value); - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - double matchDouble() - { - if (!check(Lexer::TokenType::DOUBLE)) - throw exception::CommonException(lineInfo() + "Mismatched token while matching a double. Tokens in active set " + ext::to_string(getCheckOptions()) + "."); - double res = ext::from_string<double>(m_current.m_value); - m_current = m_lexer.nextToken(m_forceLexerReadNext > 0); - return res; - } - - const std::string& getTokenValue() const - { - return m_current.m_value; - } - - void incNestedLevel() - { - ++m_forceLexerReadNext; - } - - void decNestedLevel() - { - --m_forceLexerReadNext; - } - - bool globalScope() const - { - return m_forceLexerReadNext == 0; - } - - std::unique_ptr<Expression> assign_expression(); - - std::unique_ptr<Expression> or_expression(); - - std::unique_ptr<Expression> and_expression(); - - std::unique_ptr<Expression> bitwise_or_expression(); - - std::unique_ptr<Expression> bitwise_and_expression(); - - std::unique_ptr<Expression> bitwise_xor_expression(); - - std::unique_ptr<Expression> equality_expression(); - - std::unique_ptr<Expression> relational_expression(); - - std::unique_ptr<Expression> add_expression(); - - std::unique_ptr<Expression> mul_expression(); - - std::unique_ptr<Expression> cast_expression(); - - std::unique_ptr<Expression> prefix_expression(); - - std::unique_ptr<Expression> suffix_expression(); - - std::unique_ptr<Expression> atom(); - - std::vector<std::unique_ptr<Expression>> bracketed_expression_list(); - - std::unique_ptr<CategoryOption> category_option(); - - std::unique_ptr<TypeOption> optional_type_option(); - - std::unique_ptr<Arg> file(); - - std::unique_ptr<Arg> type(); - - std::unique_ptr<Arg> arg(); - - std::unique_ptr<Arg> optional_arg(); - - std::unique_ptr<Arg> template_arg(); - - std::unique_ptr<Arg> optional_variable(); - - std::unique_ptr<Arg> optional_binding(); - - std::shared_ptr<Statement> in_redirect(); - - std::shared_ptr<Statement> common(); - - std::shared_ptr<Statement> param(); - - std::shared_ptr<Statement> statement(); - - std::shared_ptr<StatementList> statement_list(); - - std::unique_ptr<Statement> out_redirect(); - - std::pair<bool, bool> introspect_cast_from_to(); - - std::unique_ptr<Command> introspect_command(); - - std::unique_ptr<CommandList> block(); - - std::unique_ptr<Expression> expression(); - - std::unique_ptr<Expression> batch(); - - std::unique_ptr<Expression> expression_or_batch(); - - std::unique_ptr<Expression> batch_or_expression(); - - std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> qualifiedType(); - - std::pair<abstraction::TypeQualifiers::TypeQualifierSet, std::unique_ptr<Arg>> runnableParam(); - - std::unique_ptr<Command> command(); - - std::unique_ptr<Command> semicolon_command(); - - std::unique_ptr<CommandList> parse(); -}; - -} /* namespace cli */