Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot recover from gap while searching for lookahead #1231

Closed
bbannier opened this issue Jul 4, 2022 · 0 comments · Fixed by #1242
Closed

Cannot recover from gap while searching for lookahead #1231

bbannier opened this issue Jul 4, 2022 · 0 comments · Fixed by #1242
Assignees
Labels
Bug Something isn't working

Comments

@bbannier
Copy link
Member

bbannier commented Jul 4, 2022

At least in some situations when a parser encounters a gap while searching for a lookahead token one cannot recovery with &synchronize/confirm, e.g.,

# sync.spicy
module foo;

type X = unit {
	a: /A/ &synchronize;

	on %synced { print "sync"; confirm; }
};

public type Xs = unit {
	xs: (X &synchronize)[] { confirm; }
};
// foo.cc
#include "sync.cc"
#include "sync_linker.cc"

int main() {
    hilti::rt::init();
    spicy::rt::init();

    const spicy::rt::Parser* parser = nullptr;
    for ( auto* p : spicy::rt::parsers() ) {
        parser = p;
        break;
    }

    assert(parser);

    auto xs = hilti::rt::reference::make_value<__hlt::foo::Xs>();

    hilti::rt::ValueReference<hilti::rt::Stream> stream;
    stream->append("A");
    stream->append(nullptr, 1);
    stream->append("A");

     __hlt::foo::Xs::parse2(xs, stream, {}, {});
    std::cerr << xs << '\n';
}
$ spicyc -dco sync.cc sync.spicy
$ spicyc -dlo sync_linker.cc sync.spicy
$ $(spicy-config --cxx-launcher --cxx --cxxflags --debug --ldflags) -o foo foo.cc
$ ./foo
llibc++abi.dylib: terminating with uncaught exception of type hilti::rt::MissingData: data is missing (sync.spicy:10:2)

Looking at the backtrace, this error originates in stage 1 parsing which has no recovery code,

frame #5: 0x00000001000b1895 foo`__hlt::foo::Xs::__parse_xs_stage1(this=0x0000000100706d88, __data=0x00007ffeefbfed28, __cur=View @ 0x00007ffeefbfdad8, __trim=(_value = false), __lah=(m_int = 0), __lahe=SafeConstIterator @ 0x00007ffeefbfdab0, __error= Has Value=false , __dst=0x0000000100706d98) at sync.cc:495:49
   492                      for ( ::hilti::rt::regexp::MatchState ms = __hlt::foo::__re_xs_l1.tokenMatcher(); ::hilti::rt::Bool(true);  ) {
   493                          ::hilti::rt::integer::safe<int32_t> rc;
   494                            __location__("sync.spicy:10:2");
-> 495                          std::tie(rc, ncur) = ms.advance(ncur);
   496                            __location__("sync.spicy:10:2");
   497                          if ( ::hilti::rt::integer::safe<int32_t> __x = rc; __x == ::hilti::rt::integer::safe<std::int32_t>{-1} ) {
   498                              if ( ::spicy::rt::detail::waitForInputOrEod(__data, __cur, (*__self).__filters) ) {
(lldb)
frame #6: 0x00000001000b0693 foo`__hlt::foo::Xs::__parse_foo_Xs_stage2(this=0x0000000100706d88, __data=0x00007ffeefbfed28, __cur=View @ 0x00007ffeefbfe128, __trim=(_value = false), __lah=(m_int = 0), __lahe=SafeConstIterator @ 0x00007ffeefbfe100, __error= Has Value=false ) at sync.cc:324:57
   321      spicy::rt::detail::printParserState(std::string("foo::Xs"), __data, __cur, __lah, __lahe, std::string("default"), __trim, __error);
   322      HILTI_RT_DEBUG(std::string("spicy-verbose"), std::string("- parsing production: While: xs  -> while(<look-ahead-found>): foo_X_2"));
   323      ::hilti::rt::debug::indent(std::string("spicy-verbose"));
-> 324      std::tie(__cur, __lah, __lahe, __error) = (*__self).__parse_xs_stage1(__data, __cur, __trim, __lah, __lahe, __error, ::hilti::rt::optional::valueOrInit((*__self).xs));
   325      ::hilti::rt::debug::dedent(std::string("spicy-verbose"));
   326      // End parsing production: While: xs  -> while(<look-ahead-found>): foo_X_2;
   327
@bbannier bbannier added the Bug Something isn't working label Jul 4, 2022
bbannier added a commit that referenced this issue Jul 6, 2022
bbannier added a commit that referenced this issue Jul 6, 2022
During trial mode we might call `advance` to find a synchronization
point. If any of the bits touched by that fall into a gap, this can
trigger a `MissingData` exception.

In this patch we emit an additional `try`/`catch` block around the
`advance` if we search for a lookahead in `Try` mode. We can then
recover from `MissingData` by jumping to the next non-gap block in the
input.

Closes #1231.
@bbannier bbannier self-assigned this Jul 6, 2022
bbannier added a commit that referenced this issue Jul 7, 2022
bbannier added a commit that referenced this issue Jul 7, 2022
During trial mode we might call `advance` to find a synchronization
point. If any of the bits touched by that fall into a gap, this can
trigger a `MissingData` exception.

In this patch we emit an additional `try`/`catch` block around the
`advance` if we search for a lookahead in `Try` mode. We can then
recover from `MissingData` by jumping to the next non-gap block in the
input.

Closes #1231.
bbannier added a commit that referenced this issue Jul 7, 2022
bbannier added a commit that referenced this issue Jul 7, 2022
bbannier added a commit that referenced this issue Jun 23, 2023
In 7c18597 for #1231 we added code to
handle advance failures in trial mode when synchronizing on regexps, but
missed adding the same support for literals. This patch adds that
missing part.

Closes #1464.
bbannier added a commit that referenced this issue Jun 26, 2023
In 7c18597 for #1231 we added code to
handle advance failures in trial mode when synchronizing on regexps, but
missed adding the same support for literals. This patch adds that
missing part.

Closes #1464.

(cherry picked from commit 30903c8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant