Skip to content

Commit

Permalink
- Added support for quoted strings in the command line parser
Browse files Browse the repository at this point in the history
- Removed the redundant include directories vector in the command line parser and store it in the compiler context instead
- Initial #define support
  • Loading branch information
GregorGullwi committed Apr 7, 2023
1 parent 71559ed commit b9caf7b
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ x64/Debug/FlashCpp.tlog/FlashCpp.lastbuildstate
x64/Debug/FlashCpp.tlog/link.command.1.tlog
x64/Debug/FlashCpp.tlog/link.read.1.tlog
x64/Debug/FlashCpp.tlog/link.write.1.tlog
Debug/
.vs/
21 changes: 21 additions & 0 deletions CppProperties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"configurations": [
{
"inheritEnvironments": [
"msvc_x64"
],
"name": "x64-Debug",
"includePath": [
"${env.INCLUDE}",
"${workspaceRoot}\\**"
],
"defines": [
"WIN32",
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"intelliSenseMode": "windows-msvc-x64"
}
]
}
128 changes: 79 additions & 49 deletions src/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,61 +5,91 @@

class CommandLineParser {
public:
CommandLineParser(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
std::string_view arg = argv[i];
CommandLineParser(int argc, char* argv[], CompileContext& context) {
bool inQuotedString = false;
char quoteChar = '\0';
std::string quotedString;

if (arg.size() >= 2 && arg[0] == '-') {
if (arg.size() >= 3 && arg[1] == '-') {
// Option with long name, e.g. --option=value
auto equal_pos = arg.find('=');
if (equal_pos == std::string_view::npos) {
optionValues_[arg.substr(2)] = std::monostate{};
} else {
optionValues_[arg.substr(2, equal_pos - 2)] = arg.substr(equal_pos + 1);
}
} else {
// Option with short name, e.g. -o value
if (arg == "-I" && i + 1 < argc) {
includeDirs_.push_back(argv[++i]);
} else if (i + 1 >= argc) {
optionValues_[arg.substr(1)] = std::monostate{};
} else {
optionValues_[arg.substr(1)] = argv[++i];
}
}
} else {
inputFileArgs_.push_back(arg);
}
}
}
for (int i = 1; i < argc; i++) {
std::string_view arg = argv[i];

bool hasOption(std::string_view optionName) const {
return optionValues_.count(optionName) > 0;
}
if (inQuotedString) {
quotedString += " ";
quotedString += arg;

bool hasFlag(std::string_view flagName) const {
return optionValues_.count(flagName) > 0 && std::holds_alternative<std::monostate>(optionValues_.at(flagName)) == true;
}
if (arg.back() == quoteChar) {
inQuotedString = false;
context.addIncludeDir(quotedString.substr(0, quotedString.size() - 1));
quotedString.clear();
}
continue;
}

std::variant<std::monostate, std::string_view> optionValue(std::string_view optionName) const {
auto it = optionValues_.find(optionName);
if (it != optionValues_.end()) {
return it->second;
}
return std::monostate{};
}
if (arg.size() >= 2 && arg[0] == '-') {
if (arg.size() >= 3 && arg[1] == '-') {
// Option with long name, e.g. --option=value
auto equal_pos = arg.find('=');
if (equal_pos == std::string_view::npos) {
optionValues_[arg.substr(2)] = std::monostate{};
}
else {
optionValues_[arg.substr(2, equal_pos - 2)] = arg.substr(equal_pos + 1);
}
}
else {
// Option with short name, e.g. -o value
if (arg == "-I" && i + 1 < argc) {
std::string_view nextArg = argv[++i];

const std::vector<std::string_view>& inputFileArgs() const {
return inputFileArgs_;
}
if (nextArg.front() == '"' || nextArg.front() == '\'') {
inQuotedString = true;
quoteChar = nextArg.front();
quotedString = nextArg.substr(1);
if (nextArg.back() == quoteChar) {
inQuotedString = false;
context.addIncludeDir(quotedString.substr(0, quotedString.size() - 1));
quotedString.clear();
}
}
else {
context.addIncludeDir(nextArg);
}
}
else if (i + 1 >= argc) {
optionValues_[arg.substr(1)] = std::monostate{};
}
else {
optionValues_[arg.substr(1)] = argv[++i];
}
}
}
else {
inputFileArgs_.push_back(arg);
}
}
}

const std::vector<std::string_view>& includeDirs() const {
return includeDirs_;
}
bool hasOption(std::string_view optionName) const {
return optionValues_.count(optionName) > 0;
}

bool hasFlag(std::string_view flagName) const {
return optionValues_.count(flagName) > 0 && std::holds_alternative<std::monostate>(optionValues_.at(flagName)) == true;
}

std::variant<std::monostate, std::string_view> optionValue(std::string_view optionName) const {
auto it = optionValues_.find(optionName);
if (it != optionValues_.end()) {
return it->second;
}
return std::monostate{};
}

const std::vector<std::string_view>& inputFileArgs() const {
return inputFileArgs_;
}

private:
std::map<std::string_view, std::variant<std::monostate, std::string_view>> optionValues_;
std::vector<std::string_view> inputFileArgs_;
std::vector<std::string_view> includeDirs_;
std::map<std::string_view, std::variant<std::monostate, std::string_view>> optionValues_;
std::vector<std::string_view> inputFileArgs_;
};
53 changes: 50 additions & 3 deletions src/FileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

#pragma once

struct DefineDirective {
std::string_view name;
std::vector<std::string_view> args;
std::vector<std::string> body;
};

class FileReader {
public:
FileReader(const CompileContext& settings, FileTree& tree) : settings_(settings), tree_(tree) {}
Expand All @@ -23,7 +29,7 @@ class FileReader {

std::string line;
while (std::getline(stream, line)) {
if (line.rfind("#include", 0) == 0) {
if (line.find("#include", 0) == 0) {
std::istringstream iss(line);
std::string token;
iss >> token;
Expand All @@ -34,7 +40,7 @@ class FileReader {
if (token.size() < 2 || (token.front() != '"' && token.front() != '<') || (token.front() == '"' && token.back() != '"') || (token.front() == '<' && token.back() != '>')) {
continue;
}
std::string_view filename(token.substr(1, token.size() - 2));
std::string filename(token.substr(1, token.size() - 2));
bool found = false;
for (const auto& include_dir : settings_.getIncludeDirs()) {
std::string include_file(include_dir);
Expand All @@ -50,7 +56,11 @@ class FileReader {
std::cerr << "Failed to include file: " << filename << std::endl;
return false;
}
}
}
else if (line.find("#define", 0) == 0) {
std::istringstream iss(line.substr(7)); // Skip the "#define"
handleDefine(iss);
}
}

//settings_.addDependency(file);
Expand All @@ -59,6 +69,43 @@ class FileReader {
}

private:
void handleDefine(std::istringstream& iss) {
std::string name;
iss >> name;
if (name.empty()) {
return;
}

DefineDirective directive;
directive.name = name;

if (iss.peek() == '(') {
std::string arg;
while (std::getline(iss, arg, ',')) {
iss.get(); // Consume the comma or opening parenthesis
directive.args.push_back(arg);
if (iss.peek() == ')') {
iss.get(); // Consume the closing parenthesis
break;
}
}
}

std::string line;
while (std::getline(iss, line)) {
if (line.rfind("\\", 0) == 0) {
directive.body.push_back(line.substr(0, line.size() - 1));
}
else {
directive.body.push_back(line);
break;
}
}

defines_[directive.name] = directive;
}

const CompileContext& settings_;
FileTree& tree_;
std::map<std::string_view, DefineDirective> defines_;
};
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "CommandLineParser.h"

int main(int argc, char *argv[]) {
CommandLineParser parser(argc, argv);
CompileContext context;
CompileContext context;
CommandLineParser parser(argc, argv, context);

if (parser.hasOption("h") || parser.hasOption("help")) {
std::cout << "Help message" << std::endl;
Expand Down

0 comments on commit b9caf7b

Please sign in to comment.