Files
integration/luprex/ext/slash-parser.cpp

151 lines
3.4 KiB
C++

#pragma once
#ifndef DONT_INCLUDE_SLASH_PARSER_HPP
#include "slash-parser.hpp"
#endif
#include <charconv>
void SlashCommandParser::skip_white()
{
while ((cursor_ < linelen_) && (ascii_isspace(line_[cursor_])))
{
cursor_++;
}
}
std::string SlashCommandParser::read_word()
{
int start = cursor_;
while ((cursor_ < linelen_) && (!ascii_isspace(line_[cursor_])))
{
cursor_++;
}
std::string result = line_.substr(start, cursor_ - start);
skip_white();
return result;
}
SlashCommandParser::SlashCommandParser(std::string_view Line)
{
line_ = Line;
linelen_ = int(Line.size());
cursor_ = 0;
command_ = read_word();
if ((command_.size() < 2) || (command_[0] != '/'))
{
error_ = "Not a slash-command";
return;
}
if (!ascii_isalpha(command_[1]))
{
error_ = "Slash command must start with ascii alpha";
return;
}
for (int i = 1; i < int(command_.size()); i++)
{
if (!ascii_isalnum(command_[i]))
{
error_ = "Slash-command must be alphanumeric";
return;
}
}
}
bool SlashCommandParser::Parse(std::string_view Command, std::string_view ArgTypes)
{
if (Command != std::string_view(command_)) return false;
args_.clear();
for (int i = 0; i < int(ArgTypes.size()); i++)
{
switch(ArgTypes[i])
{
case 's':
{
std::string word = read_word();
if (word.empty())
{
error_ = "Expected string arg";
return false;
}
args_.emplace_back(word);
break;
}
case 'i':
{
std::string word = read_word();
const char *p = word.c_str();
const char *last = p + word.size();
if ((p < last) && (*p == '+')) p++;
int64_t result;
auto r = std::from_chars(p, last, result, 10);
if ((r.ec != std::errc()) || (r.ptr != last)) {
error_ = "Expected int arg";
return false;
}
args_.emplace_back(result);
break;
}
case 'd':
{
error_ = "Double args not implemented yet.";
break;
}
default:
{
error_ = "Invalid argtypes ";
error_ += ArgTypes;
error_ += " parsing ";
error_ += Command;
return false;
}
}
}
if (cursor_ != linelen_)
{
error_ = "Too many arguments for command: ";
error_ += Command;
return false;
}
error_.clear();
return true;
}
std::string SlashCommandParser::Error() const
{
if (!error_.empty())
{
return error_;
}
else
{
return std::string("Unrecognized command: ") + command_;
}
}
std::string SlashCommandParser::StringArg(int n) const
{
if ((n < 0) || (n >= int(args_.size()))) return "";
return args_[n].s_;
}
int64_t SlashCommandParser::IntArg(int n) const
{
if ((n < 0) || (n >= int(args_.size()))) return 0;
return args_[n].i_;
}
double SlashCommandParser::DoubleArg(int n) const
{
if ((n < 0) || (n >= int(args_.size()))) return 0.0;
return args_[n].d_;
}