From d1defaf9199996d65dcc36a86caca7a9b572246e Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Thu, 18 Sep 2025 15:50:08 -0700 Subject: [PATCH] add helper methods for coolio things --- src/root.zig | 118 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/src/root.zig b/src/root.zig index 2efbc95..7d26b9d 100644 --- a/src/root.zig +++ b/src/root.zig @@ -3,8 +3,6 @@ const c = @cImport({ @cInclude("link-includes.h"); }); -pub const sentence = "When your back is is against the whiteboard, I'll be back to back you up"; - pub const Link = struct { left_word: []const u8, right_word: []const u8, @@ -30,6 +28,74 @@ pub const ParseTree = struct { } self.allocator.free(self.links); } + + pub fn firstVerb(self: *ParseTree) ?[]const u8 { + for (self.words) |word| { + if (std.mem.endsWith(u8, word, ".v")) { + return word[0 .. word.len - 2]; + } + } + return null; + } + + 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| { + // 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]); + return al.toOwnedSlice(self.allocator); + } + } + return al.toOwnedSlice(self.allocator); + } + + pub fn sentenceObject(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, ".n")) { + // adjective or noun + for (self.links) |l| { + if (@as(usize, l.left_index) == i and + std.mem.startsWith(u8, l.label, "AN")) + { + // this is an adjective. We need to add both it and the noun to the list + // https://www.link.cs.cmu.edu/link/dict/section-AN.html + 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]); + return al.toOwnedSlice(self.allocator); + } + } + return al.toOwnedSlice(self.allocator); + } }; pub const Parser = struct { @@ -138,5 +204,51 @@ test "parser functionality" { var tree = try parser.parse("The cat sat on the mat"); defer tree.deinit(); - try std.testing.expect(tree.words.len > 0); + // for (tree.links) |w| + // std.debug.print("l: '{s}', r: '{s}', label: '{s}'\n", .{ w.left_word, w.right_word, w.label }); + // + // std.debug.print("{any}\n", .{tree.words.len}); + // LEFT-WALL + // the + // cat.n + // sat.v + // on + // the + // mat.n + // RIGHT-WALL + try std.testing.expect(tree.words.len == 8); // 6 + LEFT_WALL / RIGHT_WALL +} +test "from website" { + const sentence = "When your back is is against the whiteboard, I'll be back to back you up"; + var parser = try Parser.init(std.testing.allocator); + defer parser.deinit(); + + var tree = try parser.parse(sentence); + defer tree.deinit(); +} +test "real usage" { + var parser = try Parser.init(std.testing.allocator); + defer parser.deinit(); + + var tree = try parser.parse("turn on the bedroom light"); + defer tree.deinit(); + + // for (tree.links) |w| + // std.debug.print("l: '{s}', r: '{s}', label: '{s}'\n", .{ w.left_word, w.right_word, w.label }); + // + // for (tree.words) |w| + // std.debug.print("{s}\n", .{w}); + // std.debug.print("{any}\n", .{tree.words.len}); + try std.testing.expect(tree.words.len == 7); // 5 + LEFT_WALL / RIGHT_WALL + try std.testing.expectEqualStrings("turn", tree.firstVerb().?); + const sentence_action = try tree.sentenceAction(); + defer std.testing.allocator.free(sentence_action); + try std.testing.expect(sentence_action.len == 2); + try std.testing.expectEqualStrings("turn", sentence_action[0]); + try std.testing.expectEqualStrings("on", sentence_action[1]); + const sentence_object = try tree.sentenceObject(); + defer std.testing.allocator.free(sentence_object); + try std.testing.expect(sentence_object.len == 2); + try std.testing.expectEqualStrings("bedroom", sentence_object[0]); + try std.testing.expectEqualStrings("light", sentence_object[1]); }