From d65a844814470e8be3c816a2933c4388f1b35e64 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 2 Jan 2014 01:49:37 -0500 Subject: [PATCH] Calculator - Added standalone calculator utility. --- src/.gitignore | 1 + src/CMakeLists.txt | 17 ++-- src/calc.cpp | 165 +++++++++++++++++++++++++++++++++++++++ src/commands/CmdCalc.cpp | 2 + 4 files changed, 178 insertions(+), 7 deletions(-) create mode 100644 src/calc.cpp diff --git a/src/.gitignore b/src/.gitignore index 23f134b60..bf44c799a 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,3 +3,4 @@ Makefile.in *_test args parser +calc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6734b5ad5..7079b7f1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,20 +60,23 @@ set (task_SRCS A3.cpp A3.h add_library (task STATIC ${task_SRCS}) add_executable (task_executable main.cpp) -add_executable (parser_executable bnf.cpp) -add_executable (args_executable args.cpp) +add_executable (calc_executable calc.cpp) +add_executable (parser_executable bnf.cpp) +add_executable (args_executable args.cpp) # Yes, 'task' is included twice, otherwise linking fails on assorted OSes. target_link_libraries (task_executable task commands columns task ${TASK_LIBRARIES}) -target_link_libraries (parser_executable task commands columns task ${TASK_LIBRARIES}) -target_link_libraries (args_executable task commands columns task ${TASK_LIBRARIES}) +target_link_libraries (calc_executable task commands columns task ${TASK_LIBRARIES}) +target_link_libraries (parser_executable task commands columns task ${TASK_LIBRARIES}) +target_link_libraries (args_executable task commands columns task ${TASK_LIBRARIES}) set_property (TARGET task_executable PROPERTY OUTPUT_NAME "task") install (TARGETS task_executable DESTINATION ${TASK_BINDIR}) - -set_property (TARGET parser_executable PROPERTY OUTPUT_NAME "parser") -set_property (TARGET args_executable PROPERTY OUTPUT_NAME "args") + +set_property (TARGET calc_executable PROPERTY OUTPUT_NAME "calc") +set_property (TARGET parser_executable PROPERTY OUTPUT_NAME "parser") +set_property (TARGET args_executable PROPERTY OUTPUT_NAME "args") #SET(CMAKE_BUILD_TYPE gcov) #SET(CMAKE_CXX_FLAGS_GCOV "--coverage") diff --git a/src/calc.cpp b/src/calc.cpp new file mode 100644 index 000000000..210370de8 --- /dev/null +++ b/src/calc.cpp @@ -0,0 +1,165 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2013 - 2014, Göteborg Bit Factory. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Context context; + +//////////////////////////////////////////////////////////////////////////////// +// Constants. +bool get (const std::string& name, Variant& value) +{ +/* + // An example, although a bad one because this is supported by default. + if (name == "pi") {value = Variant (3.14159165); return true;} +*/ + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +int main (int argc, char** argv) +{ + int status = 0; + + try + { + bool infix = true; + bool ambiguous = true; + + // Add a source for constants. + Eval e; + e.addSource (namedDates); + e.addSource (get); + + // Combine all the arguments into one expression string. + std::string expression; + for (int i = 1; i < argc; i++) + if (!strcmp (argv[i], "-h") || ! strcmp (argv[i], "--help")) + { + std::cout << "\n" + << "Usage: " << argv[0] << " [options] " + << (infix ? "''" : "''") + << "\n" + << "\n" + << "Options:\n" + << " -h|--help Display this usage\n" + << " -d|--debug Debug mode\n" + << " -i|--infix Infix expression (default)\n" + << " -p|--postfix Postfix expression\n" + << " -a|--ambiguous Choose dates over numbers when ambiguous (default)\n" + << " -n|--noambiguous Choose numbers over dates when ambiguous\n" + << "\n"; + exit (1); + } + else if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "--version")) + { + std::cout << "\n" + << format (STRING_CMD_VERSION_BUILT, "calc", VERSION) +#if defined (DARWIN) + << "darwin" +#elif defined (SOLARIS) + << "solaris" +#elif defined (CYGWIN) + << "cygwin" +#elif defined (HAIKU) + << "haiku" +#elif defined (OPENBSD) + << "openbsd" +#elif defined (FREEBSD) + << "freebsd" +#elif defined (NETBSD) + << "netbsd" +#elif defined (LINUX) + << "linux" +#elif defined (KFREEBSD) + << "gnu-kfreebsd" +#elif defined (GNUHURD) + << "gnu-hurd" +#else + << STRING_CMD_VERSION_UNKNOWN +#endif + << "\n" + << STRING_CMD_VERSION_COPY + << "\n" + << "\n" + << STRING_CMD_VERSION_MIT + << "\n" + << "\n"; + + exit (1); + } + else if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "--debug")) + e.debug (); + else if (!strcmp (argv[i], "-i") || !strcmp (argv[i], "--infix")) + infix = true; + else if (!strcmp (argv[i], "-p") || !strcmp (argv[i], "--postfix")) + infix = false; + else if (!strcmp (argv[i], "-a") || !strcmp (argv[i], "--ambiguous")) + ambiguous = true; + else if (!strcmp (argv[i], "-n") || !strcmp (argv[i], "--noambiguous")) + ambiguous = false; + else + expression += std::string (argv[i]) + " "; + + e.ambiguity (ambiguous); + + Variant result; + if (infix) + e.evaluateInfixExpression (expression, result); + else + e.evaluatePostfixExpression (expression, result); + + // Show the result in string form. + std::cout << (std::string) result + << "\n"; + } + + catch (const std::string& error) + { + std::cerr << error << "\n"; + status = -1; + } + + catch (...) + { + std::cerr << "Unknown error occured. Oops.\n"; + status = -2; + } + + return status; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdCalc.cpp b/src/commands/CmdCalc.cpp index dac64dd4d..2786a9d13 100644 --- a/src/commands/CmdCalc.cpp +++ b/src/commands/CmdCalc.cpp @@ -47,6 +47,8 @@ int CmdCalc::execute (std::string& output) { int rc = 0; + // TODO Configurable infix/postfix + // TODO Configurable date/number precedence return rc; }