use constituent tree for sentence action/enable all tests

This commit is contained in:
Emil Lerch 2025-09-22 13:21:20 -07:00
parent 4e1bf8b4b9
commit 89a9316320
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 44 additions and 26 deletions

View file

@ -322,7 +322,8 @@ fn processCommand(allocator: std.mem.Allocator, sentence: [:0]const u8, parser:
defer tree.deinit();
const action_words = tree.sentenceAction() catch |err| {
std.log.err("Failed to extract action: {}\n", .{err});
if (!builtin.is_test)
std.log.err("Failed to extract action: {}\nParse tree: {f}", .{ err, tree });
continue;
};
defer allocator.free(action_words);
@ -537,7 +538,6 @@ test "processCommand with word replacement like to light - three words" {
var devices = std.StringHashMap([]const u8).init(std.testing.allocator);
defer devices.deinit();
if (true) return error.SkipZigTest;
try devices.put("jack bedroom light", "192.168.1.101");
var parser = try pos.Parser.init(std.testing.allocator);
@ -547,9 +547,9 @@ test "processCommand with word replacement like to light - three words" {
const sentence_z = try std.testing.allocator.dupeZ(u8, sentence);
defer std.testing.allocator.free(sentence_z);
const ll = std.testing.log_level;
std.testing.log_level = .debug;
defer std.testing.log_level = ll;
// const ll = std.testing.log_level;
// std.testing.log_level = .debug;
// defer std.testing.log_level = ll;
try processCommand(std.testing.allocator, sentence_z, &parser, &devices);
try std.testing.expectEqualStrings("192.168.1.101", test_device_entry.value_ptr.*);

View file

@ -82,28 +82,46 @@ pub const ParseTree = struct {
pub fn sentenceAction(self: *ParseTree) ![][]const u8 {
var al: std.ArrayList([]const u8) = .{};
defer al.deinit(self.allocator);
for (self.words, 0..) |word, i| {
if (std.mem.endsWith(u8, word, ".v")) {
// adjective or noun
for (self.links) |l| {
// This should be looking through the consituent tree
// We're looking for a modifying verb, see:
// https://www.link.cs.cmu.edu/link/dict/section-MV.html
if (@as(usize, l.left_index) == i and
std.mem.startsWith(u8, l.label, "MV"))
{
// this is an modifying verb
try al.append(self.allocator, word[0 .. word.len - 2]);
try al.append(
self.allocator,
l.right_word[0 .. std.mem.lastIndexOfScalar(u8, l.right_word, '.') orelse l.right_word.len],
);
return al.toOwnedSlice(self.allocator);
}
}
// no adjective, just this noun
try al.append(self.allocator, word[0 .. word.len - 2]);
if (self.constituent_tree == null) return error.NoConstituentTree;
var node = self.constituent_tree.?;
// https://www.link.cs.cmu.edu/link/dict/section-S.html
if (!std.mem.startsWith(u8, node.label, "S"))
return error.NoSubjectNounFound;
if (node.child == null) @panic("S node must have a child");
node = node.child.?;
// I'm not entirely sure this will be universally true, but we'll see
// in real life testing
// https://www.link.cs.cmu.edu/link/dict/section-V.html
// https://www.link.cs.cmu.edu/link/dict/section-P.html
if (!std.mem.eql(u8, node.label, "VP"))
return error.VerbBeLinkageNotFound;
if (node.child == null) @panic("VP node must have a child");
node = node.child.?;
// This should be our action
if (node.start != node.end)
return error.MultiWordVerbsNotSupported; // this should be our issue...
const verb = self.words[node.start + 1]; // +1 due to LEFT_WALL
if (!std.mem.endsWith(u8, verb, ".v"))
return error.VerbNotLabeledWithDotV;
// From this verb, we can just look at the linkage to find what to append
for (self.links) |l| {
// We're looking for a modifying verb, see:
// https://www.link.cs.cmu.edu/link/dict/section-MV.html
if (@as(usize, l.left_index) == (node.start + 1) and
std.mem.startsWith(u8, l.label, "MV"))
{
// this is an modifying verb
try al.append(self.allocator, verb[0 .. verb.len - 2]);
try al.append(
self.allocator,
l.right_word[0 .. std.mem.lastIndexOfScalar(u8, l.right_word, '.') orelse l.right_word.len],
);
return al.toOwnedSlice(self.allocator);
}
}