diff --git a/src/lexer.cpp b/src/lexer.cpp index 91053d4..bdbc84c 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -124,7 +124,7 @@ bool Lexer::consumeSpliceUnquoteOrUnquote() bool Lexer::consumeString() { size_t column = m_column; - std::string text = "\""; + std::string text; static std::unordered_set exit = { '"', @@ -134,12 +134,11 @@ bool Lexer::consumeString() }; bool escape = false; - char character = consume(); - for (;;) { + char character = consume(); // " + while (true) { character = peek(); if (!escape && character == '\\') { - text += '\\'; ignore(); escape = true; continue; @@ -149,16 +148,18 @@ bool Lexer::consumeString() break; } - text += character; + if (escape && character == 'n') { + text += 0xa; // 10 or \n + } + else { + text += character; + } ignore(); escape = false; } - if (character == '"') { - text += character; - } - else { + if (character != '"') { Error::the().addError({ Token::Type::Error, m_line, column, "expected '\"', got EOF" }); } @@ -195,7 +196,7 @@ bool Lexer::consumeKeyword() }; char character = 0; - for (;;) { + while (true) { character = peek(); if (exit.find(character) != exit.end()) { @@ -238,7 +239,7 @@ bool Lexer::consumeValue() }; char character = 0; - for (;;) { + while (true) { character = peek(); if (exit.find(character) != exit.end()) { @@ -270,7 +271,7 @@ bool Lexer::consumeComment() }; char character = 0; - for (;;) { + while (true) { character = peek(); if (exit.find(character) != exit.end()) { diff --git a/src/printer.cpp b/src/printer.cpp index e7399bb..711f7e1 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -15,6 +15,7 @@ #include "lexer.h" #include "printer.h" #include "types.h" +#include "util.h" namespace blaze { @@ -28,7 +29,7 @@ Printer::~Printer() // ----------------------------------------- -std::string Printer::print(ASTNodePtr node) +std::string Printer::print(ASTNodePtr node, bool print_readably) { if (Error::the().hasAnyError()) { init(); @@ -36,10 +37,10 @@ std::string Printer::print(ASTNodePtr node) return m_print; } - return printNoErrorCheck(node); + return printNoErrorCheck(node, print_readably); } -std::string Printer::printNoErrorCheck(ASTNodePtr node) +std::string Printer::printNoErrorCheck(ASTNodePtr node, bool print_readably) { init(); @@ -47,7 +48,7 @@ std::string Printer::printNoErrorCheck(ASTNodePtr node) return {}; } - printImpl(node); + printImpl(node, print_readably); return m_print; } @@ -61,7 +62,7 @@ void Printer::init() m_print = ""; } -void Printer::printImpl(ASTNodePtr node) +void Printer::printImpl(ASTNodePtr node, bool print_readably) { auto printSpacing = [this]() -> void { if (!m_first_node && !m_previous_node_is_list) { @@ -104,7 +105,7 @@ void Printer::printImpl(ASTNodePtr node) m_print += format("{} ", it->first.front() == 0x7f ? ":" + it->first.substr(1) : it->first); // 127 printImpl(it->second); - if (it != elements.end() && std::next(it) != elements.end()) { + if (isLast(it, elements)) { m_print += ' '; } } @@ -112,9 +113,15 @@ void Printer::printImpl(ASTNodePtr node) m_print += '}'; } else if (is(node_raw_ptr)) { - // TODO: Implement string readably printing + std::string text = std::static_pointer_cast(node)->data(); + if (print_readably) { + text = replaceAll(text, "\\", "\\\\"); + text = replaceAll(text, "\"", "\\\""); + text = replaceAll(text, "\n", "\\n"); + text = "\"" + text + "\""; + } printSpacing(); - m_print += format("{}", std::static_pointer_cast(node)->data()); + m_print += format("{}", text); } else if (is(node_raw_ptr)) { printSpacing(); diff --git a/src/printer.h b/src/printer.h index e8ae6eb..2e982ab 100644 --- a/src/printer.h +++ b/src/printer.h @@ -17,12 +17,12 @@ public: Printer(); virtual ~Printer(); - std::string print(ASTNodePtr node); - std::string printNoErrorCheck(ASTNodePtr node); + std::string print(ASTNodePtr node, bool print_readably = true); + std::string printNoErrorCheck(ASTNodePtr node, bool print_readably = true); private: void init(); - void printImpl(ASTNodePtr node); + void printImpl(ASTNodePtr node, bool print_readably = true); void printError(); bool m_first_node { true }; diff --git a/src/reader.cpp b/src/reader.cpp index 1e2a77d..d649bac 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -296,11 +296,6 @@ ASTNodePtr Reader::readString() { std::string symbol = consume().symbol; - // Unbalanced string - if (symbol.size() < 2 || symbol.front() != '"' || symbol.back() != '"') { - Error::the().addError("expected '\"', got EOF"); - } - return makePtr(symbol); } diff --git a/src/step4_if_fn_do.cpp b/src/step4_if_fn_do.cpp index 2e0bf9e..b1319ee 100644 --- a/src/step4_if_fn_do.cpp +++ b/src/step4_if_fn_do.cpp @@ -48,7 +48,7 @@ auto print(blaze::ASTNodePtr exp) -> std::string { blaze::Printer printer; - return printer.print(exp); + return printer.print(exp, true); } auto rep(std::string_view input) -> std::string diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..d5bf7b5 --- /dev/null +++ b/src/util.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +namespace blaze { + +template +inline bool isLast(It it, const C& container) +{ + return (it != container.end()) && (next(it) == container.end()); +} + +inline std::string replaceAll(std::string text, std::string_view search, std::string_view replace) +{ + size_t search_length = search.length(); + size_t replace_length = replace.length(); + size_t position = text.find(search, 0); + while (position != std::string::npos) { + text.replace(position, search_length, replace); + position += replace_length; + position = text.find(search, position); + } + + return text; +} + +} // namespace blaze