Parsing a superset of the language and then using extra checks to detect bad syntax accepted by the superset is a well known and very effective way of being error tolerant and implementing decent error recovery.
It is a great strategy. One of my favorite examples of this is Rust. When talking about what synatax "await" should use, we decided on a postfix syntax: "foo.await" . But there was concern that because JavaScript and other languages use "await foo", it would be confusing.
Solution?
async fn foo() {
}
fn main() {
let x = async { await foo() };
}
error: incorrect use of `await`
--> src/main.rs:6:13
|
6 | let x = async { await foo() };
| ^^^^^^^^^^^ help: `await` is a postfix operation: `foo().await`
Do exactly that: parse the incorrect form and emit a good diagnostic.
Solution?
Do exactly that: parse the incorrect form and emit a good diagnostic.