Skip to content

Commit

Permalink
Move to C++11
Browse files Browse the repository at this point in the history
NOTE: I did this manually, but most of this
could have been done with clang-tidy modernize
checks.

I did it manually largely to talk through the WHY

* Use `noexcept` where appropriate
* `constexpr` All The Things (That C++11 allows)
* Move to `enum struct`
* Rename .h files .hpp because they are not intended
  for consumption by C, only by C++
* use `std::array` where appropriate
* use move / forward where appropriate
* use `auto` where appropriate
  • Loading branch information
lefticus committed Jan 15, 2024
1 parent 6766844 commit 21a2e03
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 190 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.21)

# Only set the cxx_standard if it is not set by someone else
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 98)
set(CMAKE_CXX_STANDARD 11)
endif()

# strongly encouraged to enable this globally to avoid conflicts between
Expand Down
18 changes: 7 additions & 11 deletions src/infiz/infiz.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
// infiz.cpp

#include "../libinfiz/Evaluator.hpp"
#include "../libinfiz/RationalNumber.h"
#include "../libinfiz/Stack.h"
#include "../libinfiz/StringTokenizer.h"

#include <cstdlib>
#include <array>
#include <iostream>

const int max_line = 255;
constexpr int max_line = 255;

int main(int /*argc*/, char * /*args*/[])

Check failure on line 10 in src/infiz/infiz.cpp

View workflow job for this annotation

GitHub Actions / Test (windows-2019, llvm-15.0.2, Ninja Multi-Config, Release, OFF, OFF)

an exception may be thrown in function 'main' which should not throw exceptions [bugprone-exception-escape,-warnings-as-errors]

Check failure on line 10 in src/infiz/infiz.cpp

View workflow job for this annotation

GitHub Actions / Test (windows-2019, llvm-15.0.2, Ninja Multi-Config, Debug, OFF, OFF)

an exception may be thrown in function 'main' which should not throw exceptions [bugprone-exception-escape,-warnings-as-errors]
{
std::array<char, max_line> input{};

char input[max_line];// NOLINT

std::cin.getline(static_cast<char *>(input), max_line - 1, '\n');
std::cin.getline(input.data(), max_line - 1, '\n');

while (std::cin.good()) {
StringTokenizer tokenizer(static_cast<const char *>(input));
const RationalNumber answer = evaluateExpression(tokenizer);
StringTokenizer tokenizer(input.data());
const auto answer = evaluateExpression(tokenizer);
std::cout << "answer: ";

if (answer.getDenominator() == 1) {
Expand All @@ -28,6 +24,6 @@ int main(int /*argc*/, char * /*args*/[])
std::cout << answer.getNumerator() << '/' << answer.getDenominator() << " (" << answer.getFloat() << ")" << '\n';
}

std::cin.getline(static_cast<char *>(input), max_line - 1, '\n');
std::cin.getline(input.data(), max_line - 1, '\n');
}
}
2 changes: 0 additions & 2 deletions src/libinfiz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ include(GenerateExportHeader)

add_library(libinfiz
Evaluator.cpp
RationalNumber.cpp
StringTokenizer.cpp)


Expand All @@ -15,7 +14,6 @@ target_link_libraries(libinfiz PRIVATE infiz_options infiz_warnings)
target_include_directories(libinfiz ${WARNING_GUARD} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>)

target_compile_features(libinfiz PUBLIC cxx_std_20)

set_target_properties(
libinfiz
Expand Down
81 changes: 41 additions & 40 deletions src/libinfiz/Evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,39 @@
#include <cstdlib>


int precedence(Operators input)
int precedence(Operators input) noexcept
{
switch (input) {
case CLOSE_PAREN:
case Operators::CLOSE_PAREN:
return 3;
case PLUS_SIGN:
case MINUS_SIGN:
case Operators::PLUS_SIGN:
case Operators::MINUS_SIGN:
return 1;
case MULTIPLY_SIGN:
case DIVIDE_SIGN:
case Operators::MULTIPLY_SIGN:
case Operators::DIVIDE_SIGN:
return 2;
case OPEN_PAREN:
case Operators::OPEN_PAREN:
return 0;
}

return 0;
}


void evaluateStacks(Stack<RationalNumber> &numbers, Stack<int> &operators)
void evaluateStacks(Stack<RationalNumber> &numbers, Stack<Operators> &operators)
{
bool eatOpenParen = false;
bool cont = true;

if (*operators.peek() == CLOSE_PAREN) {
if (!operators.empty() && *operators.peek() == Operators::CLOSE_PAREN) {
eatOpenParen = true;
operators.pop();
}

while ((operators.peek() != NULL) && cont) {// NOLINT
while (!operators.empty() && cont && (operators.peek() != nullptr)) {

switch (*operators.peek()) {
case OPEN_PAREN:
case Operators::OPEN_PAREN:
if (eatOpenParen) {
operators.pop();
cont = false;
Expand All @@ -45,97 +45,99 @@ void evaluateStacks(Stack<RationalNumber> &numbers, Stack<int> &operators)

break;

case PLUS_SIGN: {
case Operators::PLUS_SIGN: {
operators.pop();
const RationalNumber operand2 = numbers.pop();
const RationalNumber operand1 = numbers.pop();
const auto operand2 = numbers.pop();
const auto operand1 = numbers.pop();
numbers.push(operand1 + operand2);
break;
}

case MINUS_SIGN: {
case Operators::MINUS_SIGN: {
operators.pop();
numbers.push(-numbers.pop());
break;
}

case MULTIPLY_SIGN: {
case Operators::MULTIPLY_SIGN: {
operators.pop();
const RationalNumber operand2 = numbers.pop();
const RationalNumber operand1 = numbers.pop();
const auto operand2 = numbers.pop();
const auto operand1 = numbers.pop();
numbers.push(operand1 * operand2);
break;
}

case DIVIDE_SIGN: {
case Operators::DIVIDE_SIGN: {
operators.pop();
const RationalNumber operand2 = numbers.pop();
const RationalNumber operand1 = numbers.pop();
const auto operand2 = numbers.pop();
const auto operand1 = numbers.pop();
numbers.push(operand1 / operand2);
break;
}

case Operators::CLOSE_PAREN:
break;// we want to continue
}
}
}


RationalNumber evaluateExpression(StringTokenizer &tokenizer)
{
Stack<int> operators;
Stack<Operators> operators;
Stack<RationalNumber> numbers;

while (tokenizer.hasMoreTokens()) {

std::string next = tokenizer.nextToken();
auto next = tokenizer.nextToken();

Operators value = PLUS_SIGN;
auto value = Operators::PLUS_SIGN;

if (!next.empty()) {
bool operation = false;
auto operation = false;
switch (next[0]) {
case '+':
value = PLUS_SIGN;
value = Operators::PLUS_SIGN;
operation = true;
break;
case '/':
value = DIVIDE_SIGN;
value = Operators::DIVIDE_SIGN;
operation = true;
break;
case '-':
value = MINUS_SIGN;
value = Operators::MINUS_SIGN;
operation = true;
break;
case '*':
value = MULTIPLY_SIGN;
value = Operators::MULTIPLY_SIGN;
operation = true;
break;
case ')':
value = CLOSE_PAREN;
value = Operators::CLOSE_PAREN;
operation = true;
break;
case '(':
value = OPEN_PAREN;
value = Operators::OPEN_PAREN;
operation = true;
break;

default:
operation = false;
numbers.push(RationalNumber(atoi(next.c_str()), 1));// NOLINT
numbers.emplace(atoi(next.c_str()), 1);// NOLINT
break;
}

if (operation) {
switch (value) {
case OPEN_PAREN:
case Operators::OPEN_PAREN:
operators.push(value);
break;
case CLOSE_PAREN:
case Operators::CLOSE_PAREN:
operators.push(value);
evaluateStacks(numbers, operators);
break;
default:
if (operators.peek() != NULL// NOLINT
&& precedence(value) <= precedence(static_cast<Operators>(*operators.peek()))) {
if (operators.peek() != nullptr && precedence(value) <= precedence(*operators.peek())) {
evaluateStacks(numbers, operators);
}
operators.push(value);
Expand All @@ -145,12 +147,11 @@ RationalNumber evaluateExpression(StringTokenizer &tokenizer)
}
}

if (operators.peek() != NULL)// NOLINT
evaluateStacks(numbers, operators);
if (operators.peek() != nullptr) { evaluateStacks(numbers, operators); }

if (numbers.peek() != NULL) {// NOLINT
if (numbers.peek() != nullptr) {
return *numbers.peek();
} else {
return RationalNumber(0, 0);// NOLINT
return { 0, 0 };
}
}
11 changes: 5 additions & 6 deletions src/libinfiz/Evaluator.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#ifndef INFIZ_EVALUATOR_HPP
#define INFIZ_EVALUATOR_HPP

#include "RationalNumber.h"
#include "Stack.h"
#include "StringTokenizer.h"
#include "RationalNumber.hpp"
#include "Stack.hpp"
#include "StringTokenizer.hpp"

enum Operators { PLUS_SIGN, CLOSE_PAREN, OPEN_PAREN, MINUS_SIGN, DIVIDE_SIGN, MULTIPLY_SIGN };
enum struct Operators { PLUS_SIGN, CLOSE_PAREN, OPEN_PAREN, MINUS_SIGN, DIVIDE_SIGN, MULTIPLY_SIGN };


int precedence(Operators input);
RationalNumber evaluateExpression(StringTokenizer &tokenizer);
void evaluateStacks(Stack<RationalNumber> &numbers, Stack<int> &operators);
void evaluateStacks(Stack<RationalNumber> &numbers, Stack<Operators> &operators);

#endif
51 changes: 0 additions & 51 deletions src/libinfiz/RationalNumber.cpp

This file was deleted.

31 changes: 0 additions & 31 deletions src/libinfiz/RationalNumber.h

This file was deleted.

Loading

0 comments on commit 21a2e03

Please sign in to comment.