be clear that adaptive parse assumes this is a command

This commit is contained in:
Emil Lerch 2025-09-24 10:33:45 -07:00
parent 46fd8f585c
commit a41c94b2c9
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 31 additions and 32 deletions

View file

@ -231,16 +231,17 @@ pub fn main() !u8 {
defer std.process.argsFree(allocator, args); defer std.process.argsFree(allocator, args);
// Check for --sentence-parse-only option // Check for --sentence-parse-only option
var sentence_parse_only = false; var sentence_parse_only: enum { sentence, command, none } = .none;
var sentence_arg: ?[]const u8 = null; var sentence_arg: ?[]const u8 = null;
for (args[1..]) |arg| { for (args[1..]) |arg| {
if (std.mem.eql(u8, arg, "--sentence-parse-only")) { if (std.mem.eql(u8, arg, "--sentence-parse-only"))
sentence_parse_only = true; sentence_parse_only = .sentence
} else if (sentence_arg == null) { else if (std.mem.eql(u8, arg, "--command-parse-only"))
sentence_parse_only = .command
else if (sentence_arg == null)
sentence_arg = arg; sentence_arg = arg;
} }
}
var stdout_writer = std.fs.File.stdout().writer(&.{}); var stdout_writer = std.fs.File.stdout().writer(&.{});
const stdout = &stdout_writer.interface; const stdout = &stdout_writer.interface;
@ -248,7 +249,7 @@ pub fn main() !u8 {
const stderr = &stderr_writer.interface; const stderr = &stderr_writer.interface;
if (sentence_arg == null) { if (sentence_arg == null) {
try stderr.print("Usage: {s} [--sentence-parse-only] <sentence>\n", .{args[0]}); try stderr.print("Usage: {s} [--sentence-parse-only] [--command-parse-only] <sentence>\n", .{args[0]});
return 1; return 1;
} }
const bin_dir = std.fs.selfExeDirPathAlloc(allocator) catch |err| { const bin_dir = std.fs.selfExeDirPathAlloc(allocator) catch |err| {
@ -263,12 +264,18 @@ pub fn main() !u8 {
return 1; return 1;
}; };
defer parser.deinit(); defer parser.deinit();
if (sentence_parse_only) { if (sentence_parse_only != .none) {
const sentence_z = try allocator.dupeZ(u8, sentence_arg.?); const sentence_z = try allocator.dupeZ(u8, sentence_arg.?);
defer allocator.free(sentence_z); defer allocator.free(sentence_z);
var tree = parser.adaptiveParse(sentence_z, word_replacements) catch |err| { var tree = if (sentence_parse_only == .command)
std.debug.print("Failed to parse sentence: {}\n", .{err}); parser.adaptiveCommandParse(sentence_z, word_replacements) catch {
std.log.err("Failed to parse sentence: {s}", .{sentence_z});
return 1;
}
else
parser.parse(sentence_z) catch {
std.log.err("Failed to parse sentence: {s}", .{sentence_z});
return 1; return 1;
}; };
defer tree.deinit(); defer tree.deinit();
@ -304,7 +311,7 @@ pub fn main() !u8 {
} }
fn processCommand(allocator: std.mem.Allocator, sentence: [:0]const u8, parser: *pos.Parser, devices: *std.StringHashMap([]const u8)) !void { fn processCommand(allocator: std.mem.Allocator, sentence: [:0]const u8, parser: *pos.Parser, devices: *std.StringHashMap([]const u8)) !void {
var tree = parser.adaptiveParse(sentence, word_replacements) catch |err| { var tree = parser.adaptiveCommandParse(sentence, word_replacements) catch |err| {
std.log.err("Failed to parse sentence with all replacements: {}\n", .{err}); std.log.err("Failed to parse sentence with all replacements: {}\n", .{err});
return error.UnrecognizedSentence; return error.UnrecognizedSentence;
}; };

View file

@ -360,11 +360,12 @@ pub const Parser = struct {
_ = c.dictionary_delete(self.dict); _ = c.dictionary_delete(self.dict);
} }
/// Parses a sentence with an attempt to "fix" the sentence. If a valid /// Parses a sentence with an attempt to "fix" the sentence, assuming
/// the sentence is a command with an action and an object. If a valid
/// sentence is found, it will be returned, with the guarantee that /// sentence is found, it will be returned, with the guarantee that
/// 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 adaptiveCommandParse(self: *Parser, sentence: []const u8, replacements: std.StaticStringMap([]const u8)) !ParseTree {
var final_buf: [1024]u8 = undefined; var final_buf: [1024]u8 = undefined;
const replacement_keys = replacements.keys(); const replacement_keys = replacements.keys();
@ -690,7 +691,7 @@ test "real usage - jack" {
try std.testing.expectEqualStrings("bedroom", sentence_object[1]); try std.testing.expectEqualStrings("bedroom", sentence_object[1]);
try std.testing.expectEqualStrings("light", sentence_object[2]); try std.testing.expectEqualStrings("light", sentence_object[2]);
} }
test "adaptiveParse successful without replacements" { test "adaptiveCommandParse successful without replacements" {
var parser = try Parser.init(std.testing.allocator); var parser = try Parser.init(std.testing.allocator);
defer parser.deinit(); defer parser.deinit();
@ -700,10 +701,7 @@ test "adaptiveParse successful without replacements" {
}); });
const sentence = "turn on the kitchen light"; const sentence = "turn on the kitchen light";
const sentence_z = try std.testing.allocator.dupeZ(u8, sentence); var tree = try parser.adaptiveCommandParse(sentence, replacements);
defer std.testing.allocator.free(sentence_z);
var tree = try parser.adaptiveParse(sentence_z, replacements);
defer tree.deinit(); defer tree.deinit();
const action_words = try tree.sentenceAction(); const action_words = try tree.sentenceAction();
@ -719,7 +717,7 @@ test "adaptiveParse successful without replacements" {
try std.testing.expectEqualStrings("light", object_words[1]); try std.testing.expectEqualStrings("light", object_words[1]);
} }
test "adaptiveParse with word replacement" { test "adaptiveCommandParse with word replacement" {
var parser = try Parser.init(std.testing.allocator); var parser = try Parser.init(std.testing.allocator);
defer parser.deinit(); defer parser.deinit();
@ -729,10 +727,8 @@ test "adaptiveParse with word replacement" {
}); });
const sentence = "turn on the kitchen lake"; const sentence = "turn on the kitchen lake";
const sentence_z = try std.testing.allocator.dupeZ(u8, sentence);
defer std.testing.allocator.free(sentence_z);
var tree = try parser.adaptiveParse(sentence_z, replacements); var tree = try parser.adaptiveCommandParse(sentence, replacements);
defer tree.deinit(); defer tree.deinit();
const action_words = try tree.sentenceAction(); const action_words = try tree.sentenceAction();
@ -748,7 +744,7 @@ test "adaptiveParse with word replacement" {
try std.testing.expectEqualStrings("light", object_words[1]); try std.testing.expectEqualStrings("light", object_words[1]);
} }
test "adaptiveParse no valid parse" { test "adaptiveCommandParse no valid parse" {
var parser = try Parser.init(std.testing.allocator); var parser = try Parser.init(std.testing.allocator);
defer parser.deinit(); defer parser.deinit();
@ -758,22 +754,20 @@ test "adaptiveParse no valid parse" {
}); });
const sentence = "xyz abc def"; const sentence = "xyz abc def";
const sentence_z = try std.testing.allocator.dupeZ(u8, sentence);
defer std.testing.allocator.free(sentence_z);
// const ll = std.testing.log_level; // const ll = std.testing.log_level;
// defer std.testing.log_level = ll; // defer std.testing.log_level = ll;
// std.testing.log_level = .debug; // std.testing.log_level = .debug;
try std.testing.expectError( try std.testing.expectError(
error.SentenceCreationFailed, error.SentenceCreationFailed,
parser.adaptiveParse( parser.adaptiveCommandParse(
sentence_z, sentence,
replacements, replacements,
), ),
); );
} }
test "adaptiveParse with word replacement and null removal" { test "adaptiveCommandParse with word replacement and null removal" {
var parser = try Parser.init(std.testing.allocator); var parser = try Parser.init(std.testing.allocator);
defer parser.deinit(); defer parser.deinit();
@ -783,10 +777,8 @@ test "adaptiveParse with word replacement and null removal" {
}); });
const sentence = "alexa turn on the kitchen lake"; const sentence = "alexa turn on the kitchen lake";
const sentence_z = try std.testing.allocator.dupeZ(u8, sentence);
defer std.testing.allocator.free(sentence_z);
var tree = try parser.adaptiveParse(sentence_z, replacements); var tree = try parser.adaptiveCommandParse(sentence, replacements);
defer tree.deinit(); defer tree.deinit();
const action_words = try tree.sentenceAction(); const action_words = try tree.sentenceAction();