Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> A more grammar-specific variation of this idea is to skip input until a pre-determined synchronisation token (e.g. ‘;’ in Java) is reached [8 , p. 3], or to try inserting a single synchronisation token. Such strategies are often unsuccessful, leading to a cascade of spurious syntax errors (see Figure 1 for an example). Programmers quickly learn that only the location of the first error in a file – not the reported repair, nor the location of subsequent errors – can be relied upon to be accurate.

  C.java:2: error: ’;’ expected 
    int x y; 
         ^ 
  C.java:2: error: <identifier> expected 
    int x y; 
           ^
This is a common problem, but the solution here for the example shown is for the parser not to attempt to recover that statement and ignore everything until it reaches the "synchronization point" (I call them "landmarks"), which sounds like what their were arguing for at first. Doing that would make the AST be marked with a node along the lines of "some int named x with errors", and would completely skip everything between the `x` and the `;`. Because an error has been reported, there will be no output binary, but the second error will not be emitted.

Beyond the parser, the AST needs to keep around a lot of extra information for error recovery that would otherwise not be needed. An example from rustc[1] (what I'm familiar with) is structs and struct variants that have had some parse error. We recover the parse and keep a node for the variant in the AST signaling the existence of a parse error, which means that later passes of the compiler can type and borrow check, but if it finds a use that is either missing or adding fields we do not emit an error for it[2][3] under the assumption that the parse error caused the field being used to not be captured in the AST node for the variant. This can have quite dramatic impact on the quantity of errors being emitted.

[1]: https://github.com/rust-lang/rust/blob/7e11379f3b4c376fbb9a6...

[2]: https://github.com/rust-lang/rust/blob/7e11379f3b4c376fbb9a6...

[3]: https://github.com/rust-lang/rust/blob/7e11379f3b4c376fbb9a6...



I think we are in agreement that skipping over large chunks of input is rarely a good idea. In Section 7 ("Using error recovery in practice") we show how you can make fine-grained decisions about what to do when recovery has happened in our Rust parsing system. The more fine-grained you go, the more code you have to write, but it allows you to do exactly the sorts of things that rustc does with structs if you want. https://softdevteam.github.io/grmtools/master/book/errorreco... is a more approachable version of the same stuff.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: