shushus

Спринт 16. Таблица.

Jun 20th, 2023
811
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 39.36 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. FindANTLR.cmake
  3. -----------------------------------------------------------------------
  4. find_package(Java QUIET COMPONENTS Runtime)
  5.  
  6. if(NOT ANTLR_EXECUTABLE)
  7.   find_program(ANTLR_EXECUTABLE
  8.                NAMES antlr.jar antlr4.jar antlr-4.jar antlr-4.12.0-complete.jar)
  9. endif()
  10.  
  11. if(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE)
  12.   execute_process(
  13.       COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}
  14.       OUTPUT_VARIABLE ANTLR_COMMAND_OUTPUT
  15.       ERROR_VARIABLE ANTLR_COMMAND_ERROR
  16.       RESULT_VARIABLE ANTLR_COMMAND_RESULT
  17.       OUTPUT_STRIP_TRAILING_WHITESPACE)
  18.  
  19.   if(ANTLR_COMMAND_RESULT EQUAL 0)
  20.     string(REGEX MATCH "Version [0-9]+(\\.[0-9]+)*" ANTLR_VERSION ${ANTLR_COMMAND_OUTPUT})
  21.     string(REPLACE "Version " "" ANTLR_VERSION ${ANTLR_VERSION})
  22.   else()
  23.     message(
  24.         SEND_ERROR
  25.         "Command '${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}' "
  26.         "failed with the output '${ANTLR_COMMAND_ERROR}'")
  27.   endif()
  28.  
  29.   macro(ANTLR_TARGET Name InputFile)
  30.     set(ANTLR_OPTIONS LEXER PARSER LISTENER VISITOR)
  31.     set(ANTLR_ONE_VALUE_ARGS PACKAGE OUTPUT_DIRECTORY DEPENDS_ANTLR)
  32.     set(ANTLR_MULTI_VALUE_ARGS COMPILE_FLAGS DEPENDS)
  33.     cmake_parse_arguments(ANTLR_TARGET
  34.                           "${ANTLR_OPTIONS}"
  35.                           "${ANTLR_ONE_VALUE_ARGS}"
  36.                           "${ANTLR_MULTI_VALUE_ARGS}"
  37.                           ${ARGN})
  38.  
  39.     set(ANTLR_${Name}_INPUT ${InputFile})
  40.  
  41.     get_filename_component(ANTLR_INPUT ${InputFile} NAME_WE)
  42.  
  43.     if(ANTLR_TARGET_OUTPUT_DIRECTORY)
  44.       set(ANTLR_${Name}_OUTPUT_DIR ${ANTLR_TARGET_OUTPUT_DIRECTORY})
  45.     else()
  46.       set(ANTLR_${Name}_OUTPUT_DIR
  47.           ${CMAKE_CURRENT_BINARY_DIR}/antlr4cpp_generated_src/${ANTLR_INPUT})
  48.     endif()
  49.  
  50.     unset(ANTLR_${Name}_CXX_OUTPUTS)
  51.  
  52.     if((ANTLR_TARGET_LEXER AND NOT ANTLR_TARGET_PARSER) OR
  53.        (ANTLR_TARGET_PARSER AND NOT ANTLR_TARGET_LEXER))
  54.       list(APPEND ANTLR_${Name}_CXX_OUTPUTS
  55.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.h
  56.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.cpp)
  57.       set(ANTLR_${Name}_OUTPUTS
  58.           ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.interp
  59.           ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.tokens)
  60.     else()
  61.       list(APPEND ANTLR_${Name}_CXX_OUTPUTS
  62.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.h
  63.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.cpp
  64.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.h
  65.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.cpp)
  66.       list(APPEND ANTLR_${Name}_OUTPUTS
  67.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.interp
  68.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.tokens)
  69.     endif()
  70.  
  71.     if(ANTLR_TARGET_LISTENER)
  72.       list(APPEND ANTLR_${Name}_CXX_OUTPUTS
  73.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.h
  74.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.cpp
  75.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.h
  76.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.cpp)
  77.       list(APPEND ANTLR_TARGET_COMPILE_FLAGS -listener)
  78.     endif()
  79.  
  80.     if(ANTLR_TARGET_VISITOR)
  81.       list(APPEND ANTLR_${Name}_CXX_OUTPUTS
  82.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.h
  83.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.cpp
  84.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.h
  85.            ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.cpp)
  86.       list(APPEND ANTLR_TARGET_COMPILE_FLAGS -visitor)
  87.     endif()
  88.  
  89.     if(ANTLR_TARGET_PACKAGE)
  90.       list(APPEND ANTLR_TARGET_COMPILE_FLAGS -package ${ANTLR_TARGET_PACKAGE})
  91.     endif()
  92.  
  93.     list(APPEND ANTLR_${Name}_OUTPUTS ${ANTLR_${Name}_CXX_OUTPUTS})
  94.  
  95.     if(ANTLR_TARGET_DEPENDS_ANTLR)
  96.       if(ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT)
  97.         list(APPEND ANTLR_TARGET_DEPENDS
  98.              ${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT})
  99.         list(APPEND ANTLR_TARGET_DEPENDS
  100.              ${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_OUTPUTS})
  101.       else()
  102.         message(SEND_ERROR
  103.                 "ANTLR target '${ANTLR_TARGET_DEPENDS_ANTLR}' not found")
  104.       endif()
  105.     endif()
  106.  
  107.     add_custom_command(
  108.         OUTPUT ${ANTLR_${Name}_OUTPUTS}
  109.         COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}
  110.                 ${InputFile}
  111.                 -o ${ANTLR_${Name}_OUTPUT_DIR}
  112.                 -no-listener
  113.                 -Dlanguage=Cpp
  114.                 ${ANTLR_TARGET_COMPILE_FLAGS}
  115.         DEPENDS ${InputFile}
  116.                 ${ANTLR_TARGET_DEPENDS}
  117.         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  118.         COMMENT "Building ${Name} with ANTLR ${ANTLR_VERSION}")
  119.   endmacro(ANTLR_TARGET)
  120.  
  121. endif(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE)
  122.  
  123. include(FindPackageHandleStandardArgs)
  124. find_package_handle_standard_args(
  125.     ANTLR
  126.     REQUIRED_VARS ANTLR_EXECUTABLE Java_JAVA_EXECUTABLE
  127.     VERSION_VAR ANTLR_VERSION)
  128. -----------------------------------------------------------------------
  129. CMakeLists.txt
  130. -----------------------------------------------------------------------
  131. cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
  132. project(spreadsheet)
  133.  
  134. set(CMAKE_CXX_STANDARD 17)
  135. if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
  136.     set(
  137.         CMAKE_CXX_FLAGS_DEBUG
  138.         "${CMAKE_CXX_FLAGS_DEBUG} /JMC"
  139.     )
  140. else()
  141.     set(
  142.         CMAKE_CXX_FLAGS
  143.         "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-implicit-fallthrough"
  144.     )
  145. endif()
  146.  
  147. set(ANTLR_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/antlr-4.12.0-complete.jar)
  148. include(${CMAKE_CURRENT_SOURCE_DIR}/FindANTLR.cmake)
  149.  
  150. add_definitions(
  151.     -DANTLR4CPP_STATIC
  152.     -D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
  153. )
  154.  
  155. set(WITH_STATIC_CRT OFF CACHE BOOL "Visual C++ static CRT for ANTLR" FORCE)
  156. add_subdirectory(antlr4_runtime)
  157.  
  158. antlr_target(FormulaParser Formula.g4 LEXER PARSER LISTENER)
  159.  
  160. include_directories(
  161.     ${ANTLR4_INCLUDE_DIRS}
  162.     ${ANTLR_FormulaParser_OUTPUT_DIR}
  163.     ${CMAKE_CURRENT_SOURCE_DIR}/antlr4_runtime/runtime/src
  164. )
  165.  
  166. file(GLOB sources
  167.     *.cpp
  168.     *.h
  169. )
  170.  
  171. add_executable(
  172.     spreadsheet
  173.     ${ANTLR_FormulaParser_CXX_OUTPUTS}
  174.     ${sources}
  175. )
  176.  
  177. target_link_libraries(spreadsheet antlr4_static)
  178. if(MSVC)
  179.     target_compile_options(antlr4_static PRIVATE /W0)
  180. endif()
  181.  
  182. install(
  183.     TARGETS spreadsheet
  184.     DESTINATION bin
  185.     EXPORT spreadsheet
  186. )
  187.  
  188. set_directory_properties(PROPERTIES VS_STARTUP_PROJECT spreadsheet)
  189. -----------------------------------------------------------------------
  190. common.h
  191. -----------------------------------------------------------------------
  192. #pragma once
  193.  
  194. #include <iosfwd>
  195. #include <memory>
  196. #include <stdexcept>
  197. #include <string>
  198. #include <string_view>
  199. #include <variant>
  200. #include <vector>
  201.  
  202. struct Position {
  203.     int row = 0;
  204.     int col = 0;
  205.  
  206.     bool operator==(Position rhs) const;
  207.     bool operator<(Position rhs) const;
  208.  
  209.     bool IsValid() const;
  210.     std::string ToString() const;
  211.  
  212.     static Position FromString(std::string_view str);
  213.  
  214.     static const int MAX_ROWS = 16384;
  215.     static const int MAX_COLS = 16384;
  216.     static const Position NONE;
  217. };
  218.  
  219. struct Size {
  220.     int rows = 0;
  221.     int cols = 0;
  222.  
  223.     bool operator==(Size rhs) const;
  224. };
  225.  
  226. class FormulaError : public std::runtime_error {
  227. public:
  228.     using std::runtime_error::runtime_error;
  229. };
  230.  
  231. std::ostream& operator<<(std::ostream& output, FormulaError fe);
  232.  
  233. class FormulaException : public std::runtime_error {
  234. public:
  235.     using std::runtime_error::runtime_error;
  236. };
  237.  
  238. class InvalidPositionException : public std::out_of_range {
  239. public:
  240.     using std::out_of_range::out_of_range;
  241. };
  242.  
  243. class TableTooBigException : public std::runtime_error {
  244. public:
  245.     using std::runtime_error::runtime_error;
  246. };
  247.  
  248. inline constexpr char FORMULA_SIGN = '=';
  249. inline constexpr char ESCAPE_SIGN = '\'';
  250.  
  251. class CellInterface {
  252. public:
  253.    
  254.     using Value = std::variant<std::string, double, FormulaError>;
  255.     virtual ~CellInterface() = default;
  256.     virtual void Set(std::string text) = 0;
  257.     virtual Value GetValue() const = 0;
  258.     virtual std::string GetText() const = 0;
  259. };
  260.  
  261. class SheetInterface {
  262. public:
  263.    
  264.     virtual ~SheetInterface() = default;
  265.     virtual void SetCell(Position pos, std::string text) = 0;
  266.     virtual const CellInterface* GetCell(Position pos) const = 0;
  267.     virtual CellInterface* GetCell(Position pos) = 0;
  268.     virtual void ClearCell(Position pos) = 0;
  269.     virtual Size GetPrintableSize() const = 0;
  270.     virtual void PrintValues(std::ostream& output) const = 0;
  271.     virtual void PrintTexts(std::ostream& output) const = 0;
  272. };
  273.  
  274. std::unique_ptr<SheetInterface> CreateSheet();
  275. -----------------------------------------------------------------------
  276. Formula.g4
  277. -----------------------------------------------------------------------
  278. grammar Formula;
  279.  
  280. main
  281.     : expr EOF
  282.     ;
  283.  
  284. expr
  285.     : '(' expr ')'  # Parens
  286.     | (ADD | SUB) expr  # UnaryOp
  287.     | expr (MUL | DIV) expr  # BinaryOp
  288.     | expr (ADD | SUB) expr  # BinaryOp
  289.     | NUMBER  # Literal
  290.     ;
  291.  
  292. fragment INT: [-+]? UINT ;
  293. fragment UINT: [0-9]+ ;
  294. fragment EXPONENT: [eE] INT;
  295. NUMBER
  296.     : UINT EXPONENT?
  297.     | UINT? '.' UINT EXPONENT?
  298.     ;
  299.  
  300. ADD: '+' ;
  301. SUB: '-' ;
  302. MUL: '*' ;
  303. DIV: '/' ;
  304. WS: [ \t\n\r]+ -> skip ;
  305. -----------------------------------------------------------------------
  306. FormulaAST.h
  307. -----------------------------------------------------------------------
  308. #pragma once
  309.  
  310. #include "FormulaLexer.h"
  311. #include "common.h"
  312.  
  313. #include <forward_list>
  314. #include <functional>
  315. #include <stdexcept>
  316.  
  317. namespace ASTImpl {
  318. class Expr;
  319. }
  320.  
  321. class ParsingError : public std::runtime_error {
  322.     using std::runtime_error::runtime_error;
  323. };
  324.  
  325. class FormulaAST {
  326. public:
  327.     explicit FormulaAST(std::unique_ptr<ASTImpl::Expr> root_expr);
  328.     FormulaAST(FormulaAST&&) = default;
  329.     FormulaAST& operator=(FormulaAST&&) = default;
  330.     ~FormulaAST();
  331.  
  332.     double Execute() const;
  333.     void Print(std::ostream& out) const;
  334.     void PrintFormula(std::ostream& out) const;
  335.  
  336. private:
  337.     std::unique_ptr<ASTImpl::Expr> root_expr_;
  338. };
  339.  
  340. FormulaAST ParseFormulaAST(std::istream& in);
  341. FormulaAST ParseFormulaAST(const std::string& in_str);
  342. -----------------------------------------------------------------------
  343. FormulaAST.cpp
  344. -----------------------------------------------------------------------
  345. #include "FormulaAST.h"
  346.  
  347. #include "FormulaBaseListener.h"
  348. #include "FormulaLexer.h"
  349. #include "FormulaParser.h"
  350.  
  351. #include <cassert>
  352. #include <cmath>
  353. #include <memory>
  354. #include <optional>
  355. #include <sstream>
  356.  
  357. namespace ASTImpl {
  358.  
  359. enum ExprPrecedence {
  360.     EP_ADD,
  361.     EP_SUB,
  362.     EP_MUL,
  363.     EP_DIV,
  364.     EP_UNARY,
  365.     EP_ATOM,
  366.     EP_END,
  367. };
  368.  
  369. enum PrecedenceRule {
  370.     PR_NONE = 0b00,              
  371.     PR_LEFT = 0b01,              
  372.     PR_RIGHT = 0b10,              
  373.     PR_BOTH = PR_LEFT | PR_RIGHT,  
  374. };
  375.  
  376. constexpr PrecedenceRule PRECEDENCE_RULES[EP_END][EP_END] = {
  377.     /* EP_ADD */ {PR_NONE, PR_NONE, PR_NONE, PR_NONE, PR_NONE, PR_NONE},
  378.     /* EP_SUB */ {PR_RIGHT, PR_RIGHT, PR_NONE, PR_NONE, PR_NONE, PR_NONE},
  379.     /* EP_MUL */ {PR_BOTH, PR_BOTH, PR_NONE, PR_NONE, PR_NONE, PR_NONE},
  380.     /* EP_DIV */ {PR_BOTH, PR_BOTH, PR_RIGHT, PR_RIGHT, PR_NONE, PR_NONE},
  381.     /* EP_UNARY */ {PR_BOTH, PR_BOTH, PR_NONE, PR_NONE, PR_NONE, PR_NONE},
  382.     /* EP_ATOM */ {PR_NONE, PR_NONE, PR_NONE, PR_NONE, PR_NONE, PR_NONE},
  383. };
  384.  
  385. class Expr {
  386. public:
  387.     virtual ~Expr() = default;
  388.     virtual void Print(std::ostream& out) const = 0;
  389.     virtual void DoPrintFormula(std::ostream& out, ExprPrecedence precedence) const = 0;
  390.     virtual double Evaluate() const = 0;
  391.  
  392.     virtual ExprPrecedence GetPrecedence() const = 0;
  393.  
  394.     void PrintFormula(std::ostream& out, ExprPrecedence parent_precedence,
  395.                       bool right_child = false) const {
  396.         auto precedence = GetPrecedence();
  397.         auto mask = right_child ? PR_RIGHT : PR_LEFT;
  398.         bool parens_needed = PRECEDENCE_RULES[parent_precedence][precedence] & mask;
  399.        
  400.         if (parens_needed) {out << '(';}
  401.  
  402.         DoPrintFormula(out, precedence);
  403.  
  404.         if (parens_needed) {out << ')';}
  405.     }
  406. };
  407.  
  408. namespace {
  409. class BinaryOpExpr final : public Expr {
  410. public:
  411.     enum Type : char {
  412.         Add = '+',
  413.         Subtract = '-',
  414.         Multiply = '*',
  415.         Divide = '/',
  416.     };
  417.  
  418. public:
  419.    
  420.     explicit BinaryOpExpr(Type type, std::unique_ptr<Expr> lhs, std::unique_ptr<Expr> rhs) : type_(type)
  421.                                                                                            , lhs_(std::move(lhs))
  422.                                                                                            , rhs_(std::move(rhs)) {}
  423.  
  424.     void Print(std::ostream& out) const override {
  425.        
  426.         out << '(' << static_cast<char>(type_) << ' ';
  427.        
  428.         lhs_->Print(out);
  429.        
  430.         out << ' ';
  431.        
  432.         rhs_->Print(out);
  433.        
  434.         out << ')';
  435.     }
  436.  
  437.     void DoPrintFormula(std::ostream& out, ExprPrecedence precedence) const override {
  438.        
  439.         lhs_->PrintFormula(out, precedence);
  440.        
  441.         out << static_cast<char>(type_);
  442.        
  443.         rhs_->PrintFormula(out, precedence, true);
  444.     }
  445.  
  446.     ExprPrecedence GetPrecedence() const override {
  447.        
  448.         switch (type_) {
  449.                
  450.             case Add:
  451.                 return EP_ADD;
  452.                
  453.             case Subtract:
  454.                 return EP_SUB;
  455.                
  456.             case Multiply:
  457.                 return EP_MUL;
  458.                
  459.             case Divide:
  460.                 return EP_DIV;
  461.                
  462.             default:
  463.                 assert(false);
  464.                 return static_cast<ExprPrecedence>(INT_MAX);
  465.         }
  466.     }
  467.  
  468.     double Evaluate() const override {
  469.        
  470.         switch (type_) {
  471.                
  472.             case Add:
  473.                 return lhs_->Evaluate() + rhs_->Evaluate();
  474.                
  475.             case Subtract:
  476.                 return lhs_->Evaluate() - rhs_->Evaluate();
  477.                
  478.             case Multiply:
  479.                 return lhs_->Evaluate() * rhs_->Evaluate();
  480.            
  481.             case Divide:
  482.                
  483.                 if (rhs_->Evaluate() != 0) {
  484.                     return lhs_->Evaluate() / rhs_->Evaluate();
  485.                    
  486.                 } else {
  487.                     throw FormulaError("DIV/0");
  488.                 }  
  489.            
  490.             default:
  491.                 throw FormulaError("unidentified operation type");
  492.         }
  493.     }
  494.  
  495. private:
  496.     Type type_;
  497.     std::unique_ptr<Expr> lhs_;
  498.     std::unique_ptr<Expr> rhs_;
  499. };
  500.  
  501. class UnaryOpExpr final : public Expr {
  502. public:
  503.     enum Type : char {
  504.         UnaryPlus = '+',
  505.         UnaryMinus = '-',
  506.     };
  507.  
  508. public:
  509.    
  510.     explicit UnaryOpExpr(Type type, std::unique_ptr<Expr> operand) : type_(type)
  511.                                                                    , operand_(std::move(operand)) {}
  512.  
  513.     void Print(std::ostream& out) const override {
  514.        
  515.         out << '(' << static_cast<char>(type_) << ' ';
  516.        
  517.         operand_->Print(out);
  518.        
  519.         out << ')';
  520.     }
  521.  
  522.     void DoPrintFormula(std::ostream& out, ExprPrecedence precedence) const override {
  523.         out << static_cast<char>(type_);
  524.         operand_->PrintFormula(out, precedence);
  525.     }
  526.  
  527.     ExprPrecedence GetPrecedence() const override {return EP_UNARY;}
  528.  
  529.     double Evaluate() const override {
  530.      
  531.         switch (type_) {
  532.                
  533.             case UnaryPlus:
  534.                 return operand_->Evaluate();
  535.                
  536.             case UnaryMinus:
  537.                 return -operand_->Evaluate();
  538.            
  539.             default:
  540.                 throw FormulaError("unidentified operation type");
  541.         }
  542.     }
  543.  
  544. private:
  545.     Type type_;
  546.     std::unique_ptr<Expr> operand_;
  547. };
  548.  
  549. class NumberExpr final : public Expr {
  550. public:
  551.    
  552.     explicit NumberExpr(double value) : value_(value) {}
  553.  
  554.     void Print(std::ostream& out) const override {out << value_;}
  555.     void DoPrintFormula(std::ostream& out, ExprPrecedence) const override {out << value_;}
  556.     ExprPrecedence GetPrecedence() const override {return EP_ATOM;}
  557.     double Evaluate() const override {return value_;}
  558.  
  559. private:
  560.     double value_;
  561. };
  562.  
  563. class ParseASTListener final : public FormulaBaseListener {
  564. public:
  565.     std::unique_ptr<Expr> MoveRoot() {
  566.         assert(args_.size() == 1);
  567.         auto root = std::move(args_.front());
  568.         args_.clear();
  569.  
  570.         return root;
  571.     }
  572.  
  573. public:
  574.     void exitUnaryOp(FormulaParser::UnaryOpContext* ctx) override {
  575.         assert(args_.size() >= 1);
  576.  
  577.         auto operand = std::move(args_.back());
  578.  
  579.         UnaryOpExpr::Type type;
  580.         if (ctx->SUB()) {
  581.             type = UnaryOpExpr::UnaryMinus;
  582.         } else {
  583.             assert(ctx->ADD() != nullptr);
  584.             type = UnaryOpExpr::UnaryPlus;
  585.         }
  586.  
  587.         auto node = std::make_unique<UnaryOpExpr>(type, std::move(operand));
  588.         args_.back() = std::move(node);
  589.     }
  590.  
  591.     void exitLiteral(FormulaParser::LiteralContext* ctx) override {
  592.         double value = 0;
  593.         auto valueStr = ctx->NUMBER()->getSymbol()->getText();
  594.         std::istringstream in(valueStr);
  595.         in >> value;
  596.         if (!in) {
  597.             throw ParsingError("Invalid number: " + valueStr);
  598.         }
  599.  
  600.         auto node = std::make_unique<NumberExpr>(value);
  601.         args_.push_back(std::move(node));
  602.     }
  603.  
  604.     void exitBinaryOp(FormulaParser::BinaryOpContext* ctx) override {
  605.         assert(args_.size() >= 2);
  606.  
  607.         auto rhs = std::move(args_.back());
  608.         args_.pop_back();
  609.  
  610.         auto lhs = std::move(args_.back());
  611.  
  612.         BinaryOpExpr::Type type;
  613.         if (ctx->ADD()) {
  614.             type = BinaryOpExpr::Add;
  615.         } else if (ctx->SUB()) {
  616.             type = BinaryOpExpr::Subtract;
  617.         } else if (ctx->MUL()) {
  618.             type = BinaryOpExpr::Multiply;
  619.         } else {
  620.             assert(ctx->DIV() != nullptr);
  621.             type = BinaryOpExpr::Divide;
  622.         }
  623.  
  624.         auto node = std::make_unique<BinaryOpExpr>(type, std::move(lhs), std::move(rhs));
  625.         args_.back() = std::move(node);
  626.     }
  627.  
  628.     void visitErrorNode(antlr4::tree::ErrorNode* node) override {
  629.         throw ParsingError("Error when parsing: " + node->getSymbol()->getText());
  630.     }
  631.  
  632. private:
  633.     std::vector<std::unique_ptr<Expr>> args_;
  634. };
  635.  
  636. class BailErrorListener : public antlr4::BaseErrorListener {
  637. public:
  638.     void syntaxError(antlr4::Recognizer* /* recognizer */, antlr4::Token* /* offendingSymbol */,
  639.                      size_t /* line */, size_t /* charPositionInLine */, const std::string& msg,
  640.                      std::exception_ptr /* e */
  641.                      ) override {
  642.         throw ParsingError("Error when lexing: " + msg);
  643.     }
  644. };
  645.  
  646. }//end namespace
  647. }//end namespace ASTImpl
  648.  
  649. FormulaAST ParseFormulaAST(std::istream& in) {
  650.     using namespace antlr4;
  651.  
  652.     ANTLRInputStream input(in);
  653.  
  654.     FormulaLexer lexer(&input);
  655.     ASTImpl::BailErrorListener error_listener;
  656.     lexer.removeErrorListeners();
  657.     lexer.addErrorListener(&error_listener);
  658.  
  659.     CommonTokenStream tokens(&lexer);
  660.  
  661.     FormulaParser parser(&tokens);
  662.     auto error_handler = std::make_shared<BailErrorStrategy>();
  663.     parser.setErrorHandler(error_handler);
  664.     parser.removeErrorListeners();
  665.  
  666.     tree::ParseTree* tree = parser.main();
  667.     ASTImpl::ParseASTListener listener;
  668.     tree::ParseTreeWalker::DEFAULT.walk(&listener, tree);
  669.  
  670.     return FormulaAST(listener.MoveRoot());
  671. }
  672.  
  673. FormulaAST ParseFormulaAST(const std::string& in_str) {
  674.     std::istringstream in(in_str);
  675.     try {
  676.         return ParseFormulaAST(in);
  677.     } catch (const std::exception& exc) {
  678.         std::throw_with_nested(FormulaException(exc.what()));
  679.     }
  680. }
  681.  
  682. void FormulaAST::Print(std::ostream& out) const {root_expr_->Print(out);}
  683. void FormulaAST::PrintFormula(std::ostream& out) const {root_expr_->PrintFormula(out, ASTImpl::EP_ATOM);}
  684. double FormulaAST::Execute() const {return root_expr_->Evaluate();}
  685. FormulaAST::FormulaAST(std::unique_ptr<ASTImpl::Expr> root_expr) : root_expr_(std::move(root_expr)) {}
  686. FormulaAST::~FormulaAST() = default;
  687. -----------------------------------------------------------------------
  688. main.cpp
  689. -----------------------------------------------------------------------
  690.   #include "common.h"
  691.   #include "test_runner_p.h"
  692.  
  693.   inline std::ostream& operator<<(std::ostream& output, Position pos) {
  694.       return output << "(" << pos.row << ", " << pos.col << ")";
  695.   }
  696.  
  697.   inline Position operator"" _pos(const char* str, std::size_t) {
  698.       return Position::FromString(str);
  699.   }
  700.  
  701.   inline std::ostream& operator<<(std::ostream& output, Size size) {
  702.       return output << "(" << size.rows << ", " << size.cols << ")";
  703.   }
  704.  
  705.   inline std::ostream& operator<<(std::ostream& output, const CellInterface::Value& value) {
  706.       std::visit(
  707.           [&](const auto& x) {
  708.               output << x;
  709.           },
  710.           value);
  711.       return output;
  712.   }
  713.  
  714.   namespace {
  715.  
  716.   void TestEmpty() {
  717.       auto sheet = CreateSheet();
  718.       ASSERT_EQUAL(sheet->GetPrintableSize(), (Size{0, 0}));
  719.   }
  720.  
  721.   void TestInvalidPosition() {
  722.       auto sheet = CreateSheet();
  723.       try {
  724.           sheet->SetCell(Position{-1, 0}, "");
  725.       } catch (const InvalidPositionException&) {}
  726.      
  727.       try {
  728.           sheet->GetCell(Position{0, -2});
  729.       } catch (const InvalidPositionException&) {}
  730.      
  731.       try {
  732.           sheet->ClearCell(Position{Position::MAX_ROWS, 0});
  733.       } catch (const InvalidPositionException&) {}
  734.   }
  735.  
  736.   void TestSetCellPlainText() {
  737.       auto sheet = CreateSheet();
  738.      
  739.       auto checkCell = [&](Position pos, std::string text) {
  740.           sheet->SetCell(pos, text);
  741.           CellInterface* cell = sheet->GetCell(pos);
  742.           ASSERT(cell != nullptr);
  743.           ASSERT_EQUAL(cell->GetText(), text);
  744.           ASSERT_EQUAL(std::get<std::string>(cell->GetValue()), text);
  745.       };      
  746.      
  747.       checkCell("A1"_pos, "Hello");
  748.       checkCell("A1"_pos, "World");
  749.       checkCell("B2"_pos, "Purr");
  750.       checkCell("A3"_pos, "Meow");
  751.      
  752.       const SheetInterface& constSheet = *sheet;
  753.       ASSERT_EQUAL(constSheet.GetCell("B2"_pos)->GetText(), "Purr");
  754.      
  755.       sheet->SetCell("A3"_pos, "'=escaped");
  756.       CellInterface* cell = sheet->GetCell("A3"_pos);
  757.       ASSERT_EQUAL(cell->GetText(), "'=escaped");
  758.       ASSERT_EQUAL(std::get<std::string>(cell->GetValue()), "=escaped");
  759.      
  760.   }
  761.  
  762.   void TestClearCell() {
  763.       auto sheet = CreateSheet();
  764.  
  765.       sheet->SetCell("C2"_pos, "Me gusta");
  766.       sheet->ClearCell("C2"_pos);
  767.       ASSERT(sheet->GetCell("C2"_pos) == nullptr);
  768.  
  769.       sheet->ClearCell("A1"_pos);
  770.       sheet->ClearCell("J10"_pos);
  771.   }
  772.    
  773.   void TestPrint() {
  774.       auto sheet = CreateSheet();
  775.       sheet->SetCell("A2"_pos, "meow");
  776.       sheet->SetCell("B2"_pos, "=1+2");
  777.       sheet->SetCell("A1"_pos, "=1/0");
  778.  
  779.       ASSERT_EQUAL(sheet->GetPrintableSize(), (Size{2, 2}));
  780.  
  781.       std::ostringstream texts;
  782.       sheet->PrintTexts(texts);  
  783.       ASSERT_EQUAL(texts.str(), "=1/0\t\nmeow\t=1+2\n");
  784.  
  785.       std::ostringstream values;
  786.       sheet->PrintValues(values);
  787.       ASSERT_EQUAL(values.str(), "#DIV/0!\t\nmeow\t3\n");
  788.  
  789.       sheet->ClearCell("B2"_pos);
  790.       ASSERT_EQUAL(sheet->GetPrintableSize(), (Size{2, 1}));    
  791.   }
  792.  
  793.   }//end namespace
  794.  
  795.   int main() {    
  796.      
  797.       TestRunner tr;    
  798.      
  799.       RUN_TEST(tr, TestEmpty);
  800.       RUN_TEST(tr, TestInvalidPosition);
  801.       RUN_TEST(tr, TestSetCellPlainText);
  802.       RUN_TEST(tr, TestClearCell);          
  803.       RUN_TEST(tr, TestPrint);  
  804.      
  805.       return 0;
  806.   }
  807.  
  808. -----------------------------------------------------------------------
  809. test_runner_p.h
  810. -----------------------------------------------------------------------
  811. #pragma once
  812.  
  813. #include <iostream>
  814. #include <map>
  815. #include <set>
  816. #include <sstream>
  817. #include <stdexcept>
  818. #include <string>
  819. #include <unordered_map>
  820. #include <vector>
  821.  
  822. namespace TestRunnerPrivate {
  823.   template <typename K, typename V, template <typename, typename> class Map>
  824.   std::ostream& PrintMap(std::ostream& os, const Map<K, V>& m) {
  825.     os << "{";
  826.     bool first = true;
  827.     for (const auto& kv : m) {
  828.       if (!first) {
  829.         os << ", ";
  830.       }
  831.       first = false;
  832.       os << kv.first << ": " << kv.second;
  833.     }
  834.     return os << "}";
  835.   }
  836. }
  837.  
  838. template <class T>
  839. std::ostream& operator<<(std::ostream& os, const std::vector<T>& s) {
  840.   os << "{";
  841.   bool first = true;
  842.   for (const auto& x : s) {
  843.     if (!first) {
  844.       os << ", ";
  845.     }
  846.     first = false;
  847.     os << x;
  848.   }
  849.   return os << "}";
  850. }
  851.  
  852. template <class T>
  853. std::ostream& operator<<(std::ostream& os, const std::set<T>& s) {
  854.   os << "{";
  855.   bool first = true;
  856.   for (const auto& x : s) {
  857.     if (!first) {
  858.       os << ", ";
  859.     }
  860.     first = false;
  861.     os << x;
  862.   }
  863.   return os << "}";
  864. }
  865.  
  866. template <class K, class V>
  867. std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) {
  868.   return TestRunnerPrivate::PrintMap(os, m);
  869. }
  870.  
  871. template <class K, class V>
  872. std::ostream& operator<<(std::ostream& os, const std::unordered_map<K, V>& m) {
  873.   return TestRunnerPrivate::PrintMap(os, m);
  874. }
  875.  
  876. template <class T, class U>
  877. void AssertEqual(const T& t, const U& u, const std::string& hint = {}) {
  878.   if (!(t == u)) {
  879.     std::ostringstream os;
  880.     os << "Assertion failed: " << t << " != " << u;
  881.     if (!hint.empty()) {
  882.       os << " hint: " << hint;
  883.     }
  884.     throw std::runtime_error(os.str());
  885.   }
  886. }
  887.  
  888. inline void Assert(bool b, const std::string& hint) {
  889.   AssertEqual(b, true, hint);
  890. }
  891.  
  892. class TestRunner {
  893. public:
  894.   template <class TestFunc>
  895.   void RunTest(TestFunc func, const std::string& test_name) {
  896.     try {
  897.       func();
  898.       std::cerr << test_name << " OK" << std::endl;
  899.     } catch (std::exception& e) {
  900.       ++fail_count;
  901.       std::cerr << test_name << " fail: " << e.what() << std::endl;
  902.     } catch (...) {
  903.       ++fail_count;
  904.       std::cerr << "Unknown exception caught" << std::endl;
  905.     }
  906.   }
  907.  
  908.   ~TestRunner() {
  909.     std::cerr.flush();
  910.     if (fail_count > 0) {
  911.       std::cerr << fail_count << " unit tests failed. Terminate" << std::endl;
  912.       exit(1);
  913.     }
  914.   }
  915.  
  916. private:
  917.   int fail_count = 0;
  918. };
  919.  
  920. #ifndef FILE_NAME
  921. #define FILE_NAME __FILE__
  922. #endif
  923.  
  924. #define ASSERT_EQUAL(x, y)                                               \
  925.   {                                                                      \
  926.     std::ostringstream __assert_equal_private_os;                        \
  927.     __assert_equal_private_os << #x << " != " << #y << ", " << FILE_NAME \
  928.                               << ":" << __LINE__;                        \
  929.     AssertEqual(x, y, __assert_equal_private_os.str());                  \
  930.   }
  931.  
  932. #define ASSERT(x)                                                  \
  933.   {                                                                \
  934.     std::ostringstream __assert_private_os;                        \
  935.     __assert_private_os << #x << " is false, " << FILE_NAME << ":" \
  936.                         << __LINE__;                               \
  937.     Assert(x, __assert_private_os.str());                          \
  938.   }
  939.  
  940. #define RUN_TEST(tr, func) tr.RunTest(func, #func)
  941. -----------------------------------------------------------------------
  942. formula.h
  943. -----------------------------------------------------------------------
  944. #pragma once
  945.  
  946. #include "common.h"
  947.  
  948. #include "FormulaAST.h"
  949.  
  950. #include <memory>
  951. #include <variant>
  952.  
  953. class FormulaInterface {
  954. public:
  955.     using Value = std::variant<double, FormulaError>;
  956.  
  957.     virtual ~FormulaInterface() = default;
  958.     virtual Value Evaluate() const = 0;
  959.     virtual std::string GetExpression() const = 0;
  960. };
  961.  
  962. std::unique_ptr<FormulaInterface> ParseFormula(std::string expression);
  963. -----------------------------------------------------------------------
  964. formula.cpp
  965. -----------------------------------------------------------------------
  966. #include "formula.h"
  967.  
  968. #include "FormulaAST.h"
  969.  
  970. #include <algorithm>
  971. #include <cassert>
  972. #include <cctype>
  973. #include <sstream>
  974.  
  975. using namespace std::literals;
  976.  
  977. std::ostream& operator<<(std::ostream& output, FormulaError fe) {
  978.     return output << "#DIV/0!";
  979. }
  980.  
  981. namespace {
  982. class Formula : public FormulaInterface {
  983. public:
  984.    
  985.     explicit Formula(std::string expression) try : ast_(ParseFormulaAST(expression)) {}
  986.     catch (...) {
  987.         throw FormulaException("formula is syntactically incorrect");
  988.     }
  989.    
  990.     Value Evaluate() const override {
  991.        
  992.         try {
  993.             return ast_.Execute();
  994.            
  995.         } catch (const FormulaError& evaluate_error) {
  996.             return evaluate_error;
  997.         }
  998.     }
  999.    
  1000.     std::string GetExpression() const override {
  1001.         std::ostringstream out;
  1002.         ast_.PrintFormula(out);
  1003.        
  1004.         return out.str();
  1005.     }
  1006.  
  1007. private:
  1008.     FormulaAST ast_;
  1009. };
  1010.    
  1011. }//end namespace
  1012.  
  1013. std::unique_ptr<FormulaInterface> ParseFormula(std::string expression) {
  1014.     return std::make_unique<Formula>(std::move(expression));
  1015. }
  1016. -----------------------------------------------------------------------
  1017. cell.cpp
  1018. -----------------------------------------------------------------------
  1019. #include "cell.h"
  1020. #include "sheet.h"
  1021.  
  1022. #include <cassert>
  1023. #include <iostream>
  1024. #include <string>
  1025. #include <optional>
  1026.  
  1027. Cell::Cell() : impl_(std::make_unique<EmptyImpl>()) {}
  1028. Cell::~Cell() = default;
  1029.  
  1030. void Cell::Set(std::string text) {
  1031.    
  1032.     if (text.empty()) {
  1033.         impl_ = std::make_unique<EmptyImpl>();
  1034.         return;
  1035.        
  1036.     } else if (text.size() >= 2 && text.at(0) == FORMULA_SIGN) {
  1037.         impl_ = std::move(std::make_unique<FormulaImpl>(std::move(text)));
  1038.         return;
  1039.        
  1040.     } else {
  1041.         impl_ = std::move(std::make_unique<TextImpl>(std::move(text)));
  1042.         return;
  1043.     }
  1044. }
  1045.  
  1046. void Cell::Clear() {
  1047.     impl_ = std::make_unique<EmptyImpl>();
  1048. }
  1049.  
  1050. Cell::Value Cell::GetValue() const {return impl_->GetValue();}
  1051. std::string Cell::GetText() const {return impl_->GetText();}
  1052.  
  1053. Cell::Value Cell::EmptyImpl::GetValue() const {return "";}
  1054. std::string Cell::EmptyImpl::GetText() const {return "";}
  1055.  
  1056. Cell::TextImpl::TextImpl(std::string text) : text_(std::move(text)) {}
  1057.  
  1058. Cell::Value Cell::TextImpl::GetValue() const {
  1059.     if (text_.empty()) {
  1060.         throw std::logic_error("it is empty impl, not text");
  1061.        
  1062.     } else if (text_.at(0) == ESCAPE_SIGN) {
  1063.         return text_.substr(1);
  1064.        
  1065.     } else {
  1066.         return text_;    
  1067.     }      
  1068. }
  1069.  
  1070. std::string Cell::TextImpl::GetText() const {return text_;}
  1071.  
  1072. Cell::FormulaImpl::FormulaImpl(std::string text) : formula_ptr_(ParseFormula(text.substr(1))) {}
  1073.  
  1074. Cell::Value Cell::FormulaImpl::GetValue() const {            
  1075.     auto helper = formula_ptr_->Evaluate();
  1076.    
  1077.     if (std::holds_alternative<double>(helper)) {
  1078.         return std::get<double>(helper);
  1079.     } else {
  1080.         return std::get<FormulaError>(helper);  
  1081.     }      
  1082. }
  1083.  
  1084. std::string Cell::FormulaImpl::GetText() const {return FORMULA_SIGN + formula_ptr_->GetExpression();}
  1085. -----------------------------------------------------------------------
  1086. cell.h
  1087. -----------------------------------------------------------------------
  1088. #pragma once
  1089.  
  1090. #include "common.h"
  1091. #include "formula.h"
  1092.  
  1093. class Cell : public CellInterface {
  1094. public:
  1095.     Cell();
  1096.     ~Cell();
  1097.  
  1098.     void Set(std::string text);
  1099.     void Clear();
  1100.  
  1101.     Value GetValue() const override;
  1102.     std::string GetText() const override;
  1103.  
  1104. private:
  1105.    
  1106.     class Impl {
  1107.     public:
  1108.        
  1109.         virtual Value GetValue() const = 0;
  1110.         virtual std::string GetText() const = 0;
  1111.        
  1112.         virtual ~Impl() = default;
  1113.     };
  1114.    
  1115.     class EmptyImpl : public Impl {
  1116.     public:    
  1117.        
  1118.         Value GetValue() const override;
  1119.         std::string GetText() const override;      
  1120.     };
  1121.    
  1122.     class TextImpl : public Impl {
  1123.     public:
  1124.        
  1125.         explicit TextImpl(std::string text);
  1126.         Value GetValue() const override;      
  1127.         std::string GetText() const override;
  1128.        
  1129.     private:
  1130.         std::string text_;        
  1131.     };
  1132.    
  1133.     class FormulaImpl : public Impl {
  1134.     public:
  1135.        
  1136.         explicit FormulaImpl(std::string text);
  1137.         Value GetValue() const override;
  1138.         std::string GetText() const override;
  1139.        
  1140.     private:
  1141.         std::unique_ptr<FormulaInterface> formula_ptr_;        
  1142.     };
  1143.    
  1144.     std::unique_ptr<Impl> impl_;
  1145. };
  1146. -----------------------------------------------------------------------
  1147. sheet.h
  1148. -----------------------------------------------------------------------
  1149. #pragma once
  1150.  
  1151. #include "cell.h"
  1152. #include "common.h"
  1153.  
  1154. #include <functional>
  1155. #include <vector>
  1156.  
  1157. using Table = std::vector<std::vector<std::unique_ptr<Cell>>>;
  1158.  
  1159. class Sheet : public SheetInterface {
  1160. public:
  1161.     ~Sheet();
  1162.  
  1163.     void SetCell(Position pos, std::string text) override;
  1164.  
  1165.     const CellInterface* GetCell(Position pos) const override;
  1166.     CellInterface* GetCell(Position pos) override;
  1167.  
  1168.     void ClearCell(Position pos) override;
  1169.  
  1170.     Size GetPrintableSize() const override;
  1171.  
  1172.     void PrintValues(std::ostream& output) const override;
  1173.     void PrintTexts(std::ostream& output) const override;
  1174.  
  1175. private:
  1176.     Table cells_;
  1177. };
  1178. -----------------------------------------------------------------------
  1179. sheet.cpp
  1180. -----------------------------------------------------------------------
  1181. #include "sheet.h"
  1182.  
  1183. #include "cell.h"
  1184. #include "common.h"
  1185.  
  1186. #include <algorithm>
  1187. #include <functional>
  1188. #include <iostream>
  1189. #include <optional>
  1190.  
  1191. using namespace std::literals;
  1192.  
  1193. Sheet::~Sheet() {}
  1194.  
  1195. void Sheet::SetCell(Position pos, std::string text) {
  1196.    
  1197.     if (pos.IsValid()) {
  1198.        
  1199.         cells_.resize(std::max(pos.row + 1, int(std::size(cells_))));
  1200.         cells_[pos.row].resize(std::max(pos.col + 1, int(std::size(cells_[pos.row]))));
  1201.  
  1202.         if (!cells_[pos.row][pos.col]) {
  1203.             cells_[pos.row][pos.col] = std::make_unique<Cell>();            
  1204.         }
  1205.  
  1206.         cells_[pos.row][pos.col]->Set(std::move(text));
  1207.        
  1208.     } else {
  1209.         throw InvalidPositionException("invalid cell position. setsell");
  1210.     }    
  1211. }
  1212.  
  1213. const CellInterface* Sheet::GetCell(Position pos) const {
  1214.  
  1215.     if (pos.IsValid()) {
  1216.        
  1217.         if (pos.row < int(std::size(cells_)) && pos.col < int(std::size(cells_[pos.row]))) {
  1218.      
  1219.             if (cells_[pos.row][pos.col].get()->GetText() == "") {
  1220.                 return nullptr;
  1221.                
  1222.             } else {
  1223.                 return cells_[pos.row][pos.col].get();
  1224.             }            
  1225.            
  1226.         } else {
  1227.             return nullptr;
  1228.         }
  1229.        
  1230.     } else {
  1231.         throw InvalidPositionException("invalid cell position. getcell");
  1232.     }
  1233. }
  1234.  
  1235. CellInterface* Sheet::GetCell(Position pos) {
  1236.    
  1237.     if (pos.IsValid()) {
  1238.        
  1239.         if (pos.row < int(std::size(cells_)) && pos.col < int(std::size(cells_[pos.row]))) {
  1240.            
  1241.             if (cells_[pos.row][pos.col].get()->GetText() == "") {
  1242.                 return nullptr;
  1243.                
  1244.             } else {
  1245.                 return cells_[pos.row][pos.col].get();
  1246.             }              
  1247.            
  1248.         } else {
  1249.             return nullptr;
  1250.         }
  1251.        
  1252.     } else {
  1253.         throw InvalidPositionException("invalid cell position. getcell");
  1254.     }
  1255. }
  1256.  
  1257. void Sheet::ClearCell(Position pos) {
  1258.    
  1259.     if (pos.IsValid()) {
  1260.        
  1261.         if (pos.row < int(std::size(cells_)) && pos.col < int(std::size(cells_[pos.row]))) {
  1262.            
  1263.             if (cells_[pos.row][pos.col]) {cells_[pos.row][pos.col]->Clear();}
  1264.         }
  1265.        
  1266.     } else {    
  1267.         throw InvalidPositionException("invalid cell position. clearcell");
  1268.     }
  1269. }
  1270.  
  1271. Size Sheet::GetPrintableSize() const {
  1272.    
  1273.     Size size;
  1274.    
  1275.     for (int row = 0; row < int(std::size(cells_)); ++row) {      
  1276.         for (int col = (int(std::size(cells_[row])) - 1); col >= 0; --col) {
  1277.  
  1278.             if (cells_[row][col]) {
  1279.                
  1280.                 if (cells_[row][col]->GetText().empty()) {
  1281.                     continue;
  1282.                    
  1283.                 } else {
  1284.                     size.rows = std::max(size.rows, row + 1);
  1285.                     size.cols = std::max(size.cols, col + 1);
  1286.                     break;
  1287.                 }
  1288.             }
  1289.         }
  1290.     }
  1291.    
  1292.     return size;
  1293. }
  1294.  
  1295. void Sheet::PrintValues(std::ostream& output) const {
  1296.    
  1297.     for (int row = 0; row < GetPrintableSize().rows; ++row) {    
  1298.         for (int col = 0; col < GetPrintableSize().cols; ++col) {
  1299.            
  1300.             if (col > 0) {output << '\t';}
  1301.            
  1302.             if (col < int(std::size(cells_[row]))) {                  
  1303.                 if (cells_[row][col]) {std::visit([&output](const auto& obj){output << obj;},
  1304.                                        cells_[row][col]->GetValue());}
  1305.             }
  1306.         }
  1307.        
  1308.         output << '\n';
  1309.     }
  1310. }
  1311.            
  1312. void Sheet::PrintTexts(std::ostream& output) const {
  1313.    
  1314.     for (int row = 0; row < GetPrintableSize().rows; ++row) {        
  1315.         for (int col = 0; col < GetPrintableSize().cols; ++col) {
  1316.            
  1317.             if (col) {output << '\t';}
  1318.            
  1319.             if (col < int(std::size(cells_[row]))) {                
  1320.                 if (cells_[row][col]) {output << cells_[row][col]->GetText();}
  1321.             }
  1322.         }
  1323.        
  1324.         output << '\n';
  1325.     }
  1326. }
  1327.  
  1328. std::unique_ptr<SheetInterface> CreateSheet() {return std::make_unique<Sheet>();}
  1329. -----------------------------------------------------------------------
  1330. structures.cpp
  1331. -----------------------------------------------------------------------
  1332. #include "common.h"
  1333.  
  1334. #include <cctype>
  1335. #include <sstream>
  1336. #include <algorithm>
  1337.  
  1338. const int LETTERS = 26;
  1339. const int MAX_POSITION_LENGTH = 17;
  1340. const int MAX_POS_LETTER_COUNT = 3;
  1341.  
  1342. const Position Position::NONE = {-1, -1};
  1343.  
  1344. bool Position::operator==(const Position rhs) const {return row == rhs.row && col == rhs.col;}
  1345. bool Position::operator<(const Position rhs) const {return std::tie(row, col) < std::tie(rhs.row, rhs.col);}
  1346.  
  1347. bool Position::IsValid() const {return row >= 0 && col >= 0 && row < MAX_ROWS && col < MAX_COLS;}
  1348.  
  1349. std::string Position::ToString() const {
  1350.     if (!IsValid()) {
  1351.         return "";
  1352.     }
  1353.  
  1354.     std::string result;
  1355.     result.reserve(MAX_POSITION_LENGTH);
  1356.     int c = col;
  1357.     while (c >= 0) {
  1358.         result.insert(result.begin(), 'A' + c % LETTERS);
  1359.         c = c / LETTERS - 1;
  1360.     }
  1361.  
  1362.     result += std::to_string(row + 1);
  1363.  
  1364.     return result;
  1365. }
  1366.  
  1367. Position Position::FromString(std::string_view str) {
  1368.     auto it = std::find_if(str.begin(), str.end(), [](const char c) {
  1369.         return !(std::isalpha(c) && std::isupper(c));
  1370.     });
  1371.    
  1372.     auto letters = str.substr(0, it - str.begin());
  1373.     auto digits = str.substr(it - str.begin());
  1374.  
  1375.     if (letters.empty() || digits.empty()) {return Position::NONE;}
  1376.     if (letters.size() > MAX_POS_LETTER_COUNT) {return Position::NONE;}
  1377.     if (!std::isdigit(digits[0])) {return Position::NONE;}
  1378.  
  1379.     int row;
  1380.     std::istringstream row_in{std::string{digits}};
  1381.    
  1382.     if (!(row_in >> row) || !row_in.eof()) {
  1383.         return Position::NONE;
  1384.     }
  1385.  
  1386.     int col = 0;
  1387.     for (char ch : letters) {
  1388.         col *= LETTERS;
  1389.         col += ch - 'A' + 1;
  1390.     }
  1391.  
  1392.     return {row - 1, col - 1};
  1393. }
  1394.  
  1395. bool Size::operator==(Size rhs) const {return cols == rhs.cols && rows == rhs.rows;}
Advertisement
Add Comment
Please, Sign In to add comment