summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-10-26 15:38:54 +0100
committerRoland Reichwein <mail@reichwein.it>2020-10-26 15:38:54 +0100
commitce77838c4f32b9dc237f0c4b17d1f1e1741254d4 (patch)
treef8b987e81bd94bff0a4035ddfe75d344664ece10
parentaddbdf3cf71c6d332bdf86a101a7df544fe5a9a2 (diff)
Added ProgramOpts
-rw-r--r--Makefile1
-rw-r--r--cpp.cpp23
-rw-r--r--cpp.h2
-rw-r--r--mcc.cpp22
-rw-r--r--programopts.cpp84
-rw-r--r--programopts.h24
6 files changed, 146 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 316e21b..237548b 100644
--- a/Makefile
+++ b/Makefile
@@ -71,6 +71,7 @@ PROGSRC=\
grammer.cpp \
lexer.cpp \
minicc.cpp \
+ programopts.cpp
TESTSRC=\
tests/test-cpp.cpp \
diff --git a/cpp.cpp b/cpp.cpp
index 3b450c2..6e8a28e 100644
--- a/cpp.cpp
+++ b/cpp.cpp
@@ -13,9 +13,12 @@
#include <functional>
#include <unordered_set>
#include <unordered_map>
+#include <filesystem>
using namespace Gram;
+namespace fs = std::filesystem;
+
CPP::CPP(){}
CPP::~CPP(){}
@@ -227,15 +230,27 @@ std::vector<Gram::TreeNode> CPP::analysis(const std::vector<Token>& tokens)
namespace {
CPP::map_type map_translation_unit {
- //{"top-level-declaration-seq", [](){}},
- {"top-level-declaration-seq/top-level-declaration/declaration/function-definition", [](){}},
+ {"/translation-unit/top-level-declaration-seq/top-level-declaration/declaration/function-definition", [](){}},
};
} // anonymous namespace
-void CPP::traverse(index_t node_id, map_type& map)
+void CPP::traverse(index_t node_id, map_type& map, fs::path parent_path)
{
- // TODO
+ fs::path current_path{parent_path / m_nodes[node_id].type};
+
+ // execute callbacks
+ auto it{map.find(current_path.generic_string())};
+ if (it != map.end()) {
+ std::cout << "DEBUG: Found " << current_path << std::endl;
+ }
+
+ // recurse tree
+ for (const auto& child_id: m_nodes[node_id].child_ids) {
+ if (ChildIdIsNode(child_id)) {
+ traverse(child_id, map, current_path);
+ }
+ }
}
// Phase 7.c: Translate
diff --git a/cpp.h b/cpp.h
index dfe09ca..3d82751 100644
--- a/cpp.h
+++ b/cpp.h
@@ -40,6 +40,6 @@ private:
std::vector<Token> m_charTokens; // result of phase 3
std::vector<Gram::TreeNode> m_nodes; // result of phase 7.b
- void traverse(index_t node_id, map_type& map);
+ void traverse(index_t node_id, map_type& map, fs::path parent_path = "/");
};
diff --git a/mcc.cpp b/mcc.cpp
index 7d94cf8..bb89d29 100644
--- a/mcc.cpp
+++ b/mcc.cpp
@@ -5,6 +5,7 @@
#include "cpp.h"
#include "elf.h"
#include "file.h"
+#include "programopts.h"
#include <iostream>
@@ -12,23 +13,33 @@ using namespace std::string_literals;
namespace {
-void usage() {
- std::cout << "Usage: mcc <translation_unit>" << std::endl;
-}
+ void usage() {
+ std::cout << "Usage: mcc <translation_unit>" << std::endl;
+ }
}
int main(int argc, char* argv[])
{
+ // Processing of options in lambdas: each do return true iff parameter was consumed
+ std::map<std::string, std::function<bool(const std::string&)>> option_prefixes{
+ {"-h", [&](const std::string& parameter) -> bool { usage(); return false; }},
+ };
+
try {
CPP cpp;
- if (argc != 2) {
+ ProgramOpts options(argc, argv, option_prefixes);
+ options.process();
+
+ std::vector<std::string> parameters {options.nonOptionArguments()};
+
+ if (parameters.size() != 1) {
usage();
return 1;
}
- fs::path in_filename{argv[1]};
+ fs::path in_filename{parameters[0]};
fs::path out_filename{in_filename.parent_path() / in_filename.stem()};
if (in_filename == out_filename)
@@ -48,3 +59,4 @@ int main(int argc, char* argv[])
return 0;
}
+
diff --git a/programopts.cpp b/programopts.cpp
new file mode 100644
index 0000000..aee8b05
--- /dev/null
+++ b/programopts.cpp
@@ -0,0 +1,84 @@
+#include "programopts.h"
+
+#include <algorithm>
+#include <iterator>
+
+using namespace std::string_literals;
+
+namespace {
+ struct PrefixCmp
+ {
+ bool operator()(const std::string& lhs, const std::string& rhs) const
+ {
+ return !(lhs.starts_with(rhs) || rhs.starts_with(lhs)) && lhs < rhs;
+ }
+ };
+}
+
+struct ProgramOpts::impl
+{
+ int m_argc;
+ char** m_argv;
+ std::string m_programName;
+ std::vector<std::string> m_parameters;
+ std::map<std::string, std::function<bool(const std::string&)>, PrefixCmp> m_option_prefixes;
+};
+
+ProgramOpts::ProgramOpts(int argc, char* argv[], std::map<std::string, std::function<bool(const std::string&)>>& option_prefixes):
+ m_pimpl(std::make_unique<impl>())
+{
+ m_pimpl->m_argc = argc;
+ m_pimpl->m_argv = argv;
+ if (m_pimpl->m_argc >= 1)
+ m_pimpl->m_programName = m_pimpl->m_argv[0];
+ //std::copy(option_prefixes.begin(), option_prefixes.end(), std::inserter(m_pimpl->m_option_prefixes, std::next(m_pimpl->m_option_prefixes.begin())));
+}
+
+ProgramOpts::~ProgramOpts()
+{
+}
+
+void ProgramOpts::process()
+{
+ for (size_t i = 1; i < m_pimpl->m_argc; i++) {
+ std::string arg{ m_pimpl->m_argv[i] };
+ if (arg.size() == 0)
+ throw std::runtime_error("Empty option #"s + std::to_string(i));
+
+ if (arg[0] != '-') { // non-option parameter
+ m_pimpl->m_parameters.push_back(arg);
+ } else {
+ auto prefix_iterator = m_pimpl->m_option_prefixes.find(arg);
+ if (prefix_iterator == m_pimpl->m_option_prefixes.end())
+ throw std::runtime_error("Unknown option: "s + arg);
+ auto& [prefix, f] = *prefix_iterator;
+ std::string optional_parameter;
+ bool parameter_provided{ false };
+
+ if (prefix.size() < arg.size()) {
+ optional_parameter = arg.substr(prefix.size());
+ } else {
+ if (i < m_pimpl->m_argc - 1)
+ optional_parameter = m_pimpl->m_argv[i + 1];
+ if (optional_parameter.size() > 0 && optional_parameter[0] == '-')
+ optional_parameter = "";
+ else
+ parameter_provided = true;
+ }
+ bool parameter_consumed = f(optional_parameter); // call the function from the map
+ if (parameter_provided && parameter_consumed)
+ i++; // skip parameter
+ }
+ }
+}
+
+std::string ProgramOpts::programName()
+{
+ return m_pimpl->m_programName;
+}
+
+std::vector<std::string> ProgramOpts::nonOptionArguments()
+{
+ return m_pimpl->m_parameters;
+}
+
diff --git a/programopts.h b/programopts.h
new file mode 100644
index 0000000..af706f7
--- /dev/null
+++ b/programopts.h
@@ -0,0 +1,24 @@
+// Parse command line options of program
+
+#pragma once
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+class ProgramOpts
+{
+public:
+ // Processing of options in lambdas: each do return true iff parameter was consumed
+ ProgramOpts(int argc, char* argv[], std::map<std::string, std::function<bool(const std::string&)>>& option_prefixes);
+ ~ProgramOpts();
+ void process(); // must be called to run functions per option, given to ctor
+ std::string programName();
+ std::vector<std::string> nonOptionArguments();
+private:
+ struct impl;
+ std::unique_ptr<impl> m_pimpl;
+};
+