Skip to content

Instantly share code, notes, and snippets.

@tompng
Created November 26, 2025 17:38
Show Gist options
  • Select an option

  • Save tompng/551777b9b850b0428c9062745cf763db to your computer and use it in GitHub Desktop.

Select an option

Save tompng/551777b9b850b0428c9062745cf763db to your computer and use it in GitHub Desktop.
Find parse inconsistency of Prism and parse.y
# Found inconsistencies
# a b do end.()
# begin a => a: end; a in a: if 1; case a; in a: end
# def a = a b do 1 end
# a rescue b = *c
# p(not a)
# x = a b and c
# def x = a b and c
# a(a 1 do end)
# a.(a 1 do end)
# a b do end + c
# a b do end.c...; a b do end.c + 1
# a in b: and c
# a and b in c.(1)
# a if b in c + d
# a b do end in a
# a rescue b => c in d
# a rescue b => c::itself
# a rescue b => c..
# a rescue b in c..
# a rescue b => c[]
# a = b c: ^ d; a = b c: => d; a = b c:.d
# a if b c: ^ d; a if b c: => d; a if b c:.d
# !a b:^c; !a b:.c; !a b:.(); !a b:&&c; !a b:>c; not a b:.c
# x = a b in c
# ! a b in c
# a.b c in d
require 'ripper'
require 'prism'
templates = DATA.read.lines.map{_1.gsub('\n', "\n").strip}
nested, bottom = templates.partition { it.include? '_' }
all_templates = templates.to_set
cost_templates = nested.group_by{ |t| t.count('_') }.transform_values { _1.to_set }
add_and_verify = -> (set, template) {
break if set.include? template
4.times do
code = template.gsub('_'){ bottom.sample }
# Skip known patterns
# next if /not|^!|: and|in.+\.\(|end [+&\|\^\.]|and.+in|and.+=>|if.+in|=.+in|=.+a:|end.+in|rescue.+=>|rescue.+in|if.+a:|=.+and|a: end/.match?(code)
unless (!!Ripper.sexp(code)) == Prism.parse_success?(code)
p code
return
end
end
set << template
}
(1..4).each do |cost|
p step: cost
cost_templates[cost]&.each do |template|
parts = template.split('_', -1)
cost2 = cost + parts.size - 1
new_templates = cost_templates[cost2] ||= Set.new
nested.repeated_permutation(parts.size - 1).each do |inner|
add_and_verify.call new_templates, parts.zip(inner).join
end
end
end
__END__
it
1
a
A
_ + _
_ & _
_ | _
_ and _
_ in _
not _
not(_)
~ _
! _
_ ^ _
_ if _
_ rescue _
_ => _
_ _
_ do end
_ do _ end
_ do |_| end
_ _ do end
_ { }
_ { _ }
_(_)
_ {|_|}
_ {||_}
_ {|_|_}
_, _
_ = _
*_
**_
[_]
{_}
...
case _\nwhen _\n_\nend
begin\n_\nrescue _\nend
case _\nin _\n_\nend
def _ = _
_._
_::_
_.(_)
.._
_..
a:
a:_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment