Fix minor bugs and add language detection.
This commit is contained in:
@@ -59,4 +59,5 @@ It should support:
|
|||||||
### TODO:
|
### TODO:
|
||||||
|
|
||||||
- Make "g" command work.
|
- Make "g" command work.
|
||||||
- properly handle escapes for %q ' etc in ruby parser (rn everything is escapable.)
|
- Switch to proper posix style Shard objects (to distinguish 1 empty line from no lines.)
|
||||||
|
- Use proper ruby binding context to keep locals across <pre>`</pre> function calls.
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ struct BEd {
|
|||||||
internal::functions::Function eof_op;
|
internal::functions::Function eof_op;
|
||||||
std::array<std::optional<internal::functions::Suffix>, 26> suffixes;
|
std::array<std::optional<internal::functions::Suffix>, 26> suffixes;
|
||||||
internal::theme::Theme theme;
|
internal::theme::Theme theme;
|
||||||
|
std::unordered_map<std::string, std::string> extention_to_language;
|
||||||
|
std::unordered_map<std::string, std::string> filename_to_language;
|
||||||
std::unordered_map<std::string, internal::syntax::Language *> languages;
|
std::unordered_map<std::string, internal::syntax::Language *> languages;
|
||||||
internal::io::IO io;
|
internal::io::IO io;
|
||||||
internal::vase::AppendStorage append{"/tmp"};
|
internal::vase::AppendStorage append{"/tmp"};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ struct Buffer {
|
|||||||
virtual bool waste() = 0;
|
virtual bool waste() = 0;
|
||||||
virtual uint64_t lines() = 0;
|
virtual uint64_t lines() = 0;
|
||||||
virtual uint64_t bytes() = 0;
|
virtual uint64_t bytes() = 0;
|
||||||
virtual void set_filename(std::filesystem::path path) = 0;
|
virtual void set_filename(BEd &ctx, std::filesystem::path path) = 0;
|
||||||
virtual std::filesystem::path filename() = 0;
|
virtual std::filesystem::path filename() = 0;
|
||||||
virtual void saved_hook() = 0;
|
virtual void saved_hook() = 0;
|
||||||
virtual void load(BEd &ctx, vase::Shard *text) = 0;
|
virtual void load(BEd &ctx, vase::Shard *text) = 0;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct ClipBuffer : Buffer {
|
|||||||
uint64_t lines() override;
|
uint64_t lines() override;
|
||||||
uint64_t bytes() override;
|
uint64_t bytes() override;
|
||||||
void load(BEd &ctx, vase::Shard *text) override;
|
void load(BEd &ctx, vase::Shard *text) override;
|
||||||
void set_filename(std::filesystem::path path) override;
|
void set_filename(BEd &ctx, std::filesystem::path path) override;
|
||||||
std::filesystem::path filename() override;
|
std::filesystem::path filename() override;
|
||||||
vase::Shard *copy(uint64_t start_line, uint64_t end_line) override;
|
vase::Shard *copy(uint64_t start_line, uint64_t end_line) override;
|
||||||
void substitute(
|
void substitute(
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct GenericBuffer : ShardBuffer {
|
|||||||
void saved_hook() override;
|
void saved_hook() override;
|
||||||
bool waste() override;
|
bool waste() override;
|
||||||
void load(BEd &ctx, vase::Shard *text) override;
|
void load(BEd &ctx, vase::Shard *text) override;
|
||||||
void set_filename(std::filesystem::path path) override;
|
void set_filename(BEd &ctx, std::filesystem::path path) override;
|
||||||
std::filesystem::path filename() override;
|
std::filesystem::path filename() override;
|
||||||
void substitute(
|
void substitute(
|
||||||
BEd &ctx, uint64_t start_line, uint64_t end_line,
|
BEd &ctx, uint64_t start_line, uint64_t end_line,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct ReadonlyBuffer : ShardBuffer {
|
|||||||
void load(BEd &, vase::Shard *) override {
|
void load(BEd &, vase::Shard *) override {
|
||||||
throw ed_error("This buffer is read-only.");
|
throw ed_error("This buffer is read-only.");
|
||||||
}
|
}
|
||||||
void set_filename(std::filesystem::path) override {}
|
void set_filename(BEd &, std::filesystem::path) override {}
|
||||||
std::filesystem::path filename() override {
|
std::filesystem::path filename() override {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "storage/storage.h"
|
#include "storage/storage.h"
|
||||||
|
|
||||||
namespace bed::internal::vase {
|
namespace bed::internal::vase {
|
||||||
|
// TODO: rewrite with invariant, text ends with a newline, as right now both 1 real and empty line and no text mean teh same thing,
|
||||||
|
// which causes a ton of issues.
|
||||||
|
|
||||||
struct Shard {
|
struct Shard {
|
||||||
enum struct Kind : uint8_t {
|
enum struct Kind : uint8_t {
|
||||||
Branch,
|
Branch,
|
||||||
|
|||||||
@@ -47,7 +47,14 @@ BEd::BEd(std::vector<std::string> args)
|
|||||||
internal::functions::Suffix::register_suffixes(*this);
|
internal::functions::Suffix::register_suffixes(*this);
|
||||||
internal::scripting::register_basic(*this);
|
internal::scripting::register_basic(*this);
|
||||||
languages["ruby"] = new internal::syntax::Language(internal::syntax::ruby::lang_ruby());
|
languages["ruby"] = new internal::syntax::Language(internal::syntax::ruby::lang_ruby());
|
||||||
|
extention_to_language[".rb"] = "ruby";
|
||||||
languages["c"] = new internal::syntax::Language(internal::syntax::c::lang_c());
|
languages["c"] = new internal::syntax::Language(internal::syntax::c::lang_c());
|
||||||
|
extention_to_language[".h"] = "c";
|
||||||
|
extention_to_language[".hh"] = "c";
|
||||||
|
extention_to_language[".h++"] = "c";
|
||||||
|
extention_to_language[".c"] = "c";
|
||||||
|
extention_to_language[".cc"] = "c";
|
||||||
|
extention_to_language[".c++"] = "c";
|
||||||
buffers["clip"] = new internal::buffer::ClipBuffer("clip");
|
buffers["clip"] = new internal::buffer::ClipBuffer("clip");
|
||||||
current() = {"default", 0};
|
current() = {"default", 0};
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -249,11 +249,17 @@ void GenericBuffer::load(BEd &ctx, vase::Shard *text) {
|
|||||||
ctx.prev().end = text->lines + 1;
|
ctx.prev().end = text->lines + 1;
|
||||||
}
|
}
|
||||||
ctx.current() = {name, lines()};
|
ctx.current() = {name, lines()};
|
||||||
|
syntax::Language *lang = parse.lang;
|
||||||
syntax::release(parse);
|
syntax::release(parse);
|
||||||
parse = syntax::make_parser(root, lines(), nullptr);
|
if (save_path.has_extension()) {
|
||||||
|
auto it = ctx.extention_to_language.find(save_path.extension().string());
|
||||||
|
if (it != ctx.extention_to_language.end())
|
||||||
|
lang = ctx.languages[it->second];
|
||||||
|
}
|
||||||
|
parse = syntax::make_parser(root, lines(), lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericBuffer::set_filename(std::filesystem::path path) {
|
void GenericBuffer::set_filename(BEd &, std::filesystem::path path) {
|
||||||
save_path = path;
|
save_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void ClipBuffer::load(BEd &ctx, vase::Shard *text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipBuffer::set_filename(std::filesystem::path) {}
|
void ClipBuffer::set_filename(BEd &, std::filesystem::path) {}
|
||||||
|
|
||||||
std::filesystem::path ClipBuffer::filename() {
|
std::filesystem::path ClipBuffer::filename() {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
||||||
auto path = std::get<std::filesystem::path>(arg);
|
auto path = std::get<std::filesystem::path>(arg);
|
||||||
s = vase::Shard::from_file(path);
|
s = vase::Shard::from_file(path);
|
||||||
buf.set_filename(path);
|
buf.set_filename(ctx, path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
ctx.escape_command(cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
@@ -191,7 +191,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
||||||
auto path = std::get<std::filesystem::path>(arg);
|
auto path = std::get<std::filesystem::path>(arg);
|
||||||
s = vase::Shard::from_file(path);
|
s = vase::Shard::from_file(path);
|
||||||
buf.set_filename(path);
|
buf.set_filename(ctx, path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
ctx.escape_command(cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
@@ -234,7 +234,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
auto &addr = std::get<std::string>(addr_);
|
auto &addr = std::get<std::string>(addr_);
|
||||||
auto &buf = ctx.buffer(addr);
|
auto &buf = ctx.buffer(addr);
|
||||||
if (std::holds_alternative<std::filesystem::path>(arg))
|
if (std::holds_alternative<std::filesystem::path>(arg))
|
||||||
buf.set_filename(std::get<std::filesystem::path>(arg));
|
buf.set_filename(ctx, std::get<std::filesystem::path>(arg));
|
||||||
else if (std::holds_alternative<ShellArg>(arg))
|
else if (std::holds_alternative<ShellArg>(arg))
|
||||||
throw ed_error("Can't save shell command as save path.");
|
throw ed_error("Can't save shell command as save path.");
|
||||||
if (buf.filename().empty())
|
if (buf.filename().empty())
|
||||||
@@ -590,7 +590,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
auto path = std::get<std::filesystem::path>(arg);
|
auto path = std::get<std::filesystem::path>(arg);
|
||||||
s = vase::Shard::from_file(path);
|
s = vase::Shard::from_file(path);
|
||||||
if (buf.filename().empty())
|
if (buf.filename().empty())
|
||||||
buf.set_filename(path);
|
buf.set_filename(ctx, path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
ctx.escape_command(cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
@@ -740,7 +740,7 @@ void Function::register_posix(BEd &ctx) {
|
|||||||
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
if (std::holds_alternative<std::filesystem::path>(arg)) {
|
||||||
auto path = std::get<std::filesystem::path>(arg);
|
auto path = std::get<std::filesystem::path>(arg);
|
||||||
vase::write_file(path, text);
|
vase::write_file(path, text);
|
||||||
buf.set_filename(path);
|
buf.set_filename(ctx, path);
|
||||||
} else if (std::holds_alternative<ShellArg>(arg)) {
|
} else if (std::holds_alternative<ShellArg>(arg)) {
|
||||||
auto cmd = std::get<ShellArg>(arg).cmd;
|
auto cmd = std::get<ShellArg>(arg).cmd;
|
||||||
ctx.escape_command(cmd, buf.filename().string());
|
ctx.escape_command(cmd, buf.filename().string());
|
||||||
|
|||||||
+193
-76
@@ -106,6 +106,197 @@ void handle_string(CParser &p, std::vector<io::Token> *tokens, bool string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_number(CParser &p, std::vector<io::Token> *tokens) {
|
||||||
|
bool integer = true;
|
||||||
|
uint32_t start = p.i;
|
||||||
|
if (p.peek() == '0') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == 'x' || p.peek() == 'X') {
|
||||||
|
p.advance();
|
||||||
|
if (!(is_hex(p.peek()) || p.peek() == '.'))
|
||||||
|
return;
|
||||||
|
while (is_hex(p.peek())) {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!(is_hex(p.peek())))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool need_p = false;
|
||||||
|
if (p.peek() == '.') {
|
||||||
|
need_p = true;
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
while (is_hex(p.peek())) {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!(is_hex(p.peek())))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.peek() == 'p' || p.peek() == 'P') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '-' || p.peek() == '+')
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (need_p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (p.peek() == 'b' || p.peek() == 'B') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() != '0' && p.peek() != '1')
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
while (p.peek() == '0' || p.peek() == '1') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!(p.peek() == '0' || p.peek() == '1'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '7') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '7'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.peek() == '.') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '7') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '7'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.peek() == 'e' || p.peek() == 'E') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '-' || p.peek() == '+')
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (p.peek() == '.') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
goto after_decimal;
|
||||||
|
} else {
|
||||||
|
p.advance();
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.peek() == '.') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
after_decimal:
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.peek() == 'e' || p.peek() == 'E') {
|
||||||
|
integer = false;
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '-' || p.peek() == '+')
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
while ('0' <= p.peek() && p.peek() <= '9') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == '\'') {
|
||||||
|
p.advance();
|
||||||
|
if (!('0' <= p.peek() && p.peek() <= '9'))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (integer) {
|
||||||
|
if (p.peek() == 'u' || p.peek() == 'U') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == 'w') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() != 'b')
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
if (p.peek() == 'W') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() != 'B')
|
||||||
|
return;
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
if (p.peek() == 'l' || p.peek() == 'L')
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == 'l' || p.peek() == 'L')
|
||||||
|
p.advance();
|
||||||
|
} else if (p.peek() == 'l' || p.peek() == 'L') {
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == 'l' || p.peek() == 'L')
|
||||||
|
p.advance();
|
||||||
|
if (p.peek() == 'u' || p.peek() == 'U')
|
||||||
|
p.advance();
|
||||||
|
} else if (p.peek_str(2) == "wb" || p.peek_str(2) == "WB") {
|
||||||
|
p.advance(2);
|
||||||
|
} else if (p.peek() == 'f' || p.peek() == 'F' || p.peek() == 'l' || p.peek() == 'L') {
|
||||||
|
p.advance();
|
||||||
|
} else if ((p.peek() == 'd' || p.peek() == 'D')
|
||||||
|
&& (p.peek(1) == 'f' || p.peek(1) == 'F' || p.peek(1) == 'd' || p.peek(1) == 'D' || p.peek(1) == 'l' || p.peek(1) == 'L')) {
|
||||||
|
p.advance(2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p.peek() == 'f' || p.peek() == 'F' || p.peek() == 'l' || p.peek() == 'L')
|
||||||
|
p.advance();
|
||||||
|
else if ((p.peek() == 'd' || p.peek() == 'D')
|
||||||
|
&& (p.peek(1) == 'f' || p.peek(1) == 'F' || p.peek(1) == 'd' || p.peek(1) == 'D' || p.peek(1) == 'l' || p.peek(1) == 'L'))
|
||||||
|
p.advance(2);
|
||||||
|
}
|
||||||
|
if (identifier_char(p.peek()) || p.peek() == '.')
|
||||||
|
return;
|
||||||
|
tokens->push_back({start, p.i, io::Token::Number});
|
||||||
|
}
|
||||||
|
|
||||||
void handle_syntax(CParser &p, std::vector<io::Token> *tokens, std::vector<ParseEvent> *events) {
|
void handle_syntax(CParser &p, std::vector<io::Token> *tokens, std::vector<ParseEvent> *events) {
|
||||||
if (p.peek() == '/' && p.peek(1) == '/') {
|
if (p.peek() == '/' && p.peek(1) == '/') {
|
||||||
p.current().state = CState::CInternalState::INLINE_COMMENT;
|
p.current().state = CState::CInternalState::INLINE_COMMENT;
|
||||||
@@ -165,82 +356,8 @@ void handle_syntax(CParser &p, std::vector<io::Token> *tokens, std::vector<Parse
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
def:
|
def:
|
||||||
if ('0' <= p.peek() && p.peek() <= '9') {
|
if (('0' <= p.peek() && p.peek() <= '9') || p.peek() == '.') {
|
||||||
// TODO: add floats/doubles
|
handle_number(p, tokens);
|
||||||
uint32_t start = p.i;
|
|
||||||
if (p.peek() == '0') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == 'x' || p.peek() == 'X') {
|
|
||||||
p.advance();
|
|
||||||
while (is_hex(p.peek())) {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\'') {
|
|
||||||
p.advance();
|
|
||||||
if (!(is_hex(p.peek())))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (p.peek() == 'b' || p.peek() == 'B') {
|
|
||||||
p.advance();
|
|
||||||
while (p.peek() == '0' || p.peek() == '1') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\'') {
|
|
||||||
p.advance();
|
|
||||||
if (!(p.peek() == '0' || p.peek() == '1'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while ('0' <= p.peek() && p.peek() <= '7') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\'') {
|
|
||||||
p.advance();
|
|
||||||
if (!('0' <= p.peek() && p.peek() <= '7'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p.advance();
|
|
||||||
while ('0' <= p.peek() && p.peek() <= '9') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == '\'') {
|
|
||||||
p.advance();
|
|
||||||
if (!('0' <= p.peek() && p.peek() <= '9'))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p.peek() == 'u' || p.peek() == 'U') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == 'w') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() != 'b')
|
|
||||||
return;
|
|
||||||
p.advance();
|
|
||||||
}
|
|
||||||
if (p.peek() == 'W') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() != 'B')
|
|
||||||
return;
|
|
||||||
p.advance();
|
|
||||||
}
|
|
||||||
if (p.peek() == 'l' || p.peek() == 'L')
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == 'l' || p.peek() == 'L')
|
|
||||||
p.advance();
|
|
||||||
} else if (p.peek() == 'l' || p.peek() == 'L') {
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == 'l' || p.peek() == 'L')
|
|
||||||
p.advance();
|
|
||||||
if (p.peek() == 'u' || p.peek() == 'U')
|
|
||||||
p.advance();
|
|
||||||
} else if (p.peek_str(2) == "wb" || p.peek_str(2) == "WB") {
|
|
||||||
p.advance(2);
|
|
||||||
} else if (identifier_char(p.peek())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tokens->push_back({start, p.i, io::Token::Number});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p.advance();
|
p.advance();
|
||||||
|
|||||||
@@ -1000,6 +1000,7 @@ bool handle_syntax(RubyParser &p, std::vector<io::Token> *tokens, std::vector<Pa
|
|||||||
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
p.current().flags &= ~RubyState::RubyInternalState::EXPECTING_EXPRESSION;
|
||||||
tokens->push_back({p.i, p.i + j, io::Token::Function});
|
tokens->push_back({p.i, p.i + j, io::Token::Function});
|
||||||
p.advance(j);
|
p.advance(j);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
uint32_t start = p.i;
|
uint32_t start = p.i;
|
||||||
if (p.peek(j) == ':') {
|
if (p.peek(j) == ':') {
|
||||||
|
|||||||
@@ -179,7 +179,10 @@ Shard *insert(AppendStorage *ap, Shard *root, Shard *text, uint64_t line) {
|
|||||||
if (!root) {
|
if (!root) {
|
||||||
if (line != 0)
|
if (line != 0)
|
||||||
throw ed_error("line out of range");
|
throw ed_error("line out of range");
|
||||||
|
if (text)
|
||||||
Shard::retain(text);
|
Shard::retain(text);
|
||||||
|
else
|
||||||
|
text = newline(ap);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
if (line > root->lines + 1)
|
if (line > root->lines + 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user