From 4e62908a1757f83ff703399252ad50758c4eb237 Mon Sep 17 00:00:00 2001 From: Patrick Simianer Date: Tue, 24 Feb 2026 17:18:29 +0100 Subject: Replace silent rescue with explicit type check in Item constructor When creating an Item from a Rule (not an Item), tail_spans doesn't exist. Check with is_a?(Item) instead of catching the exception silently. Co-Authored-By: Claude Opus 4.6 --- prototype/parse.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'prototype/parse.rb') diff --git a/prototype/parse.rb b/prototype/parse.rb index adf2b91..40a69e7 100644 --- a/prototype/parse.rb +++ b/prototype/parse.rb @@ -90,14 +90,10 @@ class Item < Grammar::Rule rule_or_item.rhs.each_with_index { |x,i| # duplicate rhs partially @rhs << x if x.class == Grammar::NT - begin - if i >= dot - @tail_spans[i] = Span.new(-1, -1) - else - @tail_spans[i] = rule_or_item.tail_spans[i].dup - end - rescue + if i >= dot || !rule_or_item.is_a?(Item) @tail_spans[i] = Span.new(-1, -1) + else + @tail_spans[i] = rule_or_item.tail_spans[i].dup end end } -- cgit v1.2.3 From 44f225d0642d2ecf13f533f68b9ae12d849809ea Mon Sep 17 00:00:00 2001 From: Patrick Simianer Date: Thu, 26 Feb 2026 19:29:18 +0100 Subject: Fix two bugs in prototype parser 1. Inner visit at span (0,1) yielded no sub-spans because visit(1, 0, 1, 1) iterates span from 1 to r-x=0, which is empty. This prevented unary rules like [S] ||| [X,1] from completing at the leftmost span, so S(0,1) was never created. Drop the x=1 parameter (default x=0); scan already handles bounds checking. 2. Self-filling step searched remaining_items for unary NT rules, but those rules could be absent if consumed (advanced) during the parse loop. Look up grammar.start_nt directly instead, which covers all cases. Co-Authored-By: Claude Opus 4.6 --- prototype/parse.rb | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'prototype/parse.rb') diff --git a/prototype/parse.rb b/prototype/parse.rb index 40a69e7..1741030 100644 --- a/prototype/parse.rb +++ b/prototype/parse.rb @@ -152,7 +152,7 @@ def Parse::parse input, n, active_chart, passive_chart, grammar while !active_chart.at(i,j).empty? active_item = active_chart.at(i,j).pop advanced = false - visit(1, i, j, 1) { |k,l| + visit(1, i, j) { |k,l| if passive_chart.has active_item.rhs[active_item.dot].symbol, k, l if k == active_item.right new_item = Item.new active_item, active_item.left, l, active_item.dot+1 @@ -182,16 +182,15 @@ def Parse::parse input, n, active_chart, passive_chart, grammar # 'self-filling' step new_symbols.each { |s| - remaining_items.each { |item| - next if item.dot!=0 - next if item.rhs[item.dot].class!=Grammar::NT - if item.rhs[item.dot].symbol == s - new_item = Item.new item, i, j, item.dot+1 - new_item.tail_spans[new_item.dot-1] = Span.new(i,j) - if new_item.dot==new_item.rhs.size - new_symbols << new_item.lhs.symbol if !new_symbols.include? new_item.lhs.symbol - passive_chart.add new_item, i, j - end + grammar.start_nt.each { |r| + next if r.rhs.size > j-i + next if r.rhs.first.class!=Grammar::NT + next if r.rhs.first.symbol != s + new_item = Item.new r, i, j, 1 + new_item.tail_spans[0] = Span.new(i,j) + if new_item.dot==new_item.rhs.size + new_symbols << new_item.lhs.symbol if !new_symbols.include? new_item.lhs.symbol + passive_chart.add new_item, i, j end } } -- cgit v1.2.3