avoid memory corruption with multiple replacements, deinit fixes, clean up output
This commit is contained in:
parent
c325012ce4
commit
46fd8f585c
1 changed files with 25 additions and 12 deletions
37
src/root.zig
37
src/root.zig
|
@ -365,7 +365,7 @@ pub const Parser = struct {
|
||||||
/// sentenceObject and sentenceAction will return non-zero results. If that
|
/// sentenceObject and sentenceAction will return non-zero results. If that
|
||||||
/// condition cannot be satisfied, error.NoValidParse will be returned
|
/// condition cannot be satisfied, error.NoValidParse will be returned
|
||||||
pub fn adaptiveParse(self: *Parser, sentence: [:0]const u8, replacements: std.StaticStringMap([]const u8)) !ParseTree {
|
pub fn adaptiveParse(self: *Parser, sentence: [:0]const u8, replacements: std.StaticStringMap([]const u8)) !ParseTree {
|
||||||
var altered_buf: [1024]u8 = undefined;
|
var final_buf: [1024]u8 = undefined;
|
||||||
|
|
||||||
const replacement_keys = replacements.keys();
|
const replacement_keys = replacements.keys();
|
||||||
const replacement_values = replacements.values();
|
const replacement_values = replacements.values();
|
||||||
|
@ -374,6 +374,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
// Step 1: Replacements
|
// Step 1: Replacements
|
||||||
for (replacement_keys, replacement_values) |key, value| {
|
for (replacement_keys, replacement_values) |key, value| {
|
||||||
|
var altered_buf: [1024]u8 = undefined;
|
||||||
const altered_size = std.mem.replacementSize(
|
const altered_size = std.mem.replacementSize(
|
||||||
u8,
|
u8,
|
||||||
altered,
|
altered,
|
||||||
|
@ -394,7 +395,8 @@ pub const Parser = struct {
|
||||||
);
|
);
|
||||||
|
|
||||||
altered_buf[altered_size] = 0; // add sentinel
|
altered_buf[altered_size] = 0; // add sentinel
|
||||||
altered = altered_buf[0..altered_size :0];
|
@memcpy(final_buf[0 .. altered_size + 1], altered_buf[0 .. altered_size + 1]);
|
||||||
|
altered = final_buf[0..altered_size :0];
|
||||||
|
|
||||||
if (replacement_count > 0)
|
if (replacement_count > 0)
|
||||||
// we have altered the deal. Pray we don't alter it further
|
// we have altered the deal. Pray we don't alter it further
|
||||||
|
@ -406,13 +408,19 @@ pub const Parser = struct {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var tree = self.parse(altered) catch |err| {
|
var tree = self.parse(altered) catch |err| {
|
||||||
if (shouldLog())
|
if (shouldLog()) {
|
||||||
std.log.err("Failed to parse sentence: {}\n\t{s}", .{ err, altered });
|
if (altered.len > 0)
|
||||||
|
std.log.err("Failed to parse sentence: {}\n\t{s}", .{ err, altered })
|
||||||
|
else
|
||||||
|
std.log.err("Sentence is empty: not parsing", .{});
|
||||||
|
}
|
||||||
// continue;
|
// continue;
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
var tree_ptr: ?*ParseTree = &tree;
|
||||||
|
errdefer if (tree_ptr) |p| p.deinit();
|
||||||
|
|
||||||
std.log.debug("adaptiveParse (step 1 - replacements):\n\toriginal:\n\t\t{s}\n\taltered:\n\t\t{s}\n{f}", .{
|
std.log.debug("adaptiveCommandParse (step 1 - replacements):\n\toriginal:\n\t\t{s}\n\taltered:\n\t\t{s}\n{f}", .{
|
||||||
sentence,
|
sentence,
|
||||||
altered,
|
altered,
|
||||||
tree,
|
tree,
|
||||||
|
@ -424,6 +432,7 @@ pub const Parser = struct {
|
||||||
nulls_removed = false;
|
nulls_removed = false;
|
||||||
for (tree.words) |word| {
|
for (tree.words) |word| {
|
||||||
if (std.mem.indexOf(u8, word, "[?]")) |i| {
|
if (std.mem.indexOf(u8, word, "[?]")) |i| {
|
||||||
|
var altered_buf: [1024]u8 = undefined;
|
||||||
nulls_removed = true;
|
nulls_removed = true;
|
||||||
// We need to alter this further
|
// We need to alter this further
|
||||||
const trimmed = word[0..i];
|
const trimmed = word[0..i];
|
||||||
|
@ -436,8 +445,13 @@ pub const Parser = struct {
|
||||||
);
|
);
|
||||||
const len = altered.len - (removals * trimmed.len);
|
const len = altered.len - (removals * trimmed.len);
|
||||||
altered_buf[len] = 0;
|
altered_buf[len] = 0;
|
||||||
altered = altered_buf[0..len :0];
|
@memcpy(final_buf[0 .. len + 1], altered_buf[0 .. len + 1]);
|
||||||
|
altered = final_buf[0..len :0];
|
||||||
|
|
||||||
|
if (altered.len == 0) {
|
||||||
|
std.log.info("Removed null word '{s}' in sentence {d} time(s). Sentence now empty", .{ trimmed, removals });
|
||||||
|
return error.SentenceEmptyAfterNullRemoval;
|
||||||
|
}
|
||||||
std.log.info("Removed null word '{s}' in sentence {d} time(s). Sentence now:\n\t{s}", .{
|
std.log.info("Removed null word '{s}' in sentence {d} time(s). Sentence now:\n\t{s}", .{
|
||||||
trimmed,
|
trimmed,
|
||||||
removals,
|
removals,
|
||||||
|
@ -446,11 +460,13 @@ pub const Parser = struct {
|
||||||
// Retry parsing with the word removed
|
// Retry parsing with the word removed
|
||||||
tree.deinit();
|
tree.deinit();
|
||||||
tree = self.parse(altered) catch |err| {
|
tree = self.parse(altered) catch |err| {
|
||||||
|
tree_ptr = null;
|
||||||
if (shouldLog())
|
if (shouldLog())
|
||||||
std.log.err("Failed to parse altered sentence: {}\n\t{s}", .{ err, altered });
|
std.log.err("Failed to parse altered sentence: {}\n\t{s}", .{ err, altered });
|
||||||
// continue;
|
// continue;
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
tree_ptr = &tree;
|
||||||
break; // we will remove these words conservatively...
|
break; // we will remove these words conservatively...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,9 +491,9 @@ pub const Parser = struct {
|
||||||
|
|
||||||
// Validate that we can extract action and object before returning
|
// Validate that we can extract action and object before returning
|
||||||
const action_words = tree.sentenceAction() catch |err| {
|
const action_words = tree.sentenceAction() catch |err| {
|
||||||
if (shouldLog())
|
// This is the first catch, so we don't want to log here as it
|
||||||
std.log.err("Failed to extract action: {}\n", .{err});
|
// gets super noisy
|
||||||
tree.deinit();
|
std.log.debug("Failed to extract action: {}\n", .{err});
|
||||||
return err;
|
return err;
|
||||||
// continue;
|
// continue;
|
||||||
};
|
};
|
||||||
|
@ -485,7 +501,6 @@ pub const Parser = struct {
|
||||||
|
|
||||||
if (action_words.len == 0) {
|
if (action_words.len == 0) {
|
||||||
std.log.info("Failed to extract action from sentence", .{});
|
std.log.info("Failed to extract action from sentence", .{});
|
||||||
tree.deinit();
|
|
||||||
return error.SentenceActionNotFound;
|
return error.SentenceActionNotFound;
|
||||||
// continue;
|
// continue;
|
||||||
}
|
}
|
||||||
|
@ -493,7 +508,6 @@ pub const Parser = struct {
|
||||||
const object_words = tree.sentenceObject() catch |err| {
|
const object_words = tree.sentenceObject() catch |err| {
|
||||||
if (shouldLog())
|
if (shouldLog())
|
||||||
std.log.err("Failed to extract object: {}\n", .{err});
|
std.log.err("Failed to extract object: {}\n", .{err});
|
||||||
tree.deinit();
|
|
||||||
// continue;
|
// continue;
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
@ -501,7 +515,6 @@ pub const Parser = struct {
|
||||||
|
|
||||||
if (object_words.len == 0) {
|
if (object_words.len == 0) {
|
||||||
std.log.info("Failed to extract object from sentence", .{});
|
std.log.info("Failed to extract object from sentence", .{});
|
||||||
tree.deinit();
|
|
||||||
// continue;
|
// continue;
|
||||||
return error.SentenceObjectNotFound;
|
return error.SentenceObjectNotFound;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue