134 lines
3.0 KiB
C++
134 lines
3.0 KiB
C++
#include "internal/address/address.h"
|
|
|
|
namespace bed::internal::address {
|
|
Address::Address(std::string &cmd, uint64_t &i) {
|
|
base = None{};
|
|
auto skip_space = [&] {
|
|
while (i < cmd.size() && (cmd[i] == ' ' || cmd[i] == '\t'))
|
|
++i;
|
|
};
|
|
skip_space();
|
|
if (i >= cmd.size())
|
|
return;
|
|
switch (cmd[i]) {
|
|
case '.':
|
|
base = Current();
|
|
i++;
|
|
break;
|
|
case '$':
|
|
base = Last();
|
|
i++;
|
|
break;
|
|
case '\'': {
|
|
i++;
|
|
if (i < cmd.size() && 'a' <= cmd[i] && cmd[i] <= 'z')
|
|
i++;
|
|
else
|
|
throw address_error("Invalid mark.");
|
|
base = Mark(cmd[i]);
|
|
} break;
|
|
case '/': {
|
|
i++;
|
|
uint64_t start = i;
|
|
while (true) {
|
|
if (i >= cmd.size())
|
|
break;
|
|
if (cmd[i] == '/')
|
|
break;
|
|
else if (cmd[i] == '\\')
|
|
i += 2;
|
|
else if (cmd[i] == '[' && i + 1 < cmd.size() && cmd[i + 1] == '[')
|
|
while (i < cmd.size() && !(cmd[i - 1] == ']' && cmd[i] == ']'))
|
|
i++;
|
|
else if (cmd[i] == '[')
|
|
while (i < cmd.size() && cmd[i] != ']')
|
|
i++;
|
|
else
|
|
i++;
|
|
}
|
|
base = RegexLine(Direction::Forward, cmd.substr(start, i - start));
|
|
} break;
|
|
case '?': {
|
|
i++;
|
|
uint64_t start = i;
|
|
while (true) {
|
|
if (i >= cmd.size())
|
|
break;
|
|
if (cmd[i] == '?')
|
|
break;
|
|
else if (cmd[i] == '\\')
|
|
i += 2;
|
|
else if (cmd[i] == '[' && i + 1 < cmd.size() && cmd[i + 1] == '[')
|
|
while (i < cmd.size() && !(cmd[i - 1] == ']' && cmd[i] == ']'))
|
|
i++;
|
|
else if (cmd[i] == '[')
|
|
while (i < cmd.size() && cmd[i] != ']')
|
|
i++;
|
|
else
|
|
i++;
|
|
}
|
|
base = RegexLine(Direction::Backward, cmd.substr(start, i - start));
|
|
} break;
|
|
case '+': {
|
|
base = Current();
|
|
i++;
|
|
skip_space();
|
|
uint64_t start = i;
|
|
int64_t num = 0;
|
|
while (i < cmd.size() && '0' <= cmd[i] && cmd[i] <= '9') {
|
|
num = num * 10 + (cmd[i] - '0');
|
|
i++;
|
|
}
|
|
if (start == i)
|
|
num = 1;
|
|
offset += num;
|
|
} break;
|
|
case '-': {
|
|
base = Current();
|
|
i++;
|
|
skip_space();
|
|
uint64_t start = i;
|
|
int64_t num = 0;
|
|
while (i < cmd.size() && '0' <= cmd[i] && cmd[i] <= '9') {
|
|
num = num * 10 + (cmd[i] - '0');
|
|
i++;
|
|
}
|
|
if (start == i)
|
|
num = 1;
|
|
offset -= num;
|
|
} break;
|
|
default: {
|
|
if ('0' <= cmd[i] && cmd[i] <= '9') {
|
|
uint64_t num = 0;
|
|
while (i < cmd.size() && '0' <= cmd[i] && cmd[i] <= '9') {
|
|
num = num * 10 + (cmd[i] - '0');
|
|
i++;
|
|
}
|
|
base = Number(num);
|
|
} else {
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
skip_space();
|
|
while (i < cmd.size() && (cmd[i] == '+' || cmd[i] == '-' || ('0' <= cmd[i] && cmd[i] <= '9'))) {
|
|
bool positive = cmd[i] != '-';
|
|
if (cmd[i] == '+' || cmd[i] == '-') {
|
|
i++;
|
|
skip_space();
|
|
}
|
|
uint64_t start = i;
|
|
int64_t num = 0;
|
|
while (i < cmd.size() && '0' <= cmd[i] && cmd[i] <= '9') {
|
|
num = num * 10 + (cmd[i] - '0');
|
|
i++;
|
|
}
|
|
if (start == i)
|
|
num = 1;
|
|
offset += positive ? num : -num;
|
|
skip_space();
|
|
}
|
|
}
|
|
} // namespace bed::internal::address
|