Ripper can only parse static source, while ParseTree can give you the AST as it is at runtime. So with Ripper you give it the name of a file/line number and it can parse it, but it can't get any contextual information available at runtime, or anything that might've changed at runtime. With ParseTree I can give it a Proc object and it can parse it in whatever state it is at that point in time.
In a nutshell, how sourcify works is it gets the source_location for the Proc, which gives you the file name and line number. It uses Ripper to parse the file, and the Proc starting at that line number. It provides an object that can be fed into SexpProcessor to extract information about the block of code within the Proc.
Since it's bound to Proc#source_location one of the limitations is it can't distinguish between two or more Proc objects defined on one line (eg users.select { |u| u.id == 1 }.select{ |u| u.name == 'John Doe' }). However, that doesn't seem to be too much of a limitation.