Open dnbln opened 3 years ago
Another idea: detect when a nonterminal references itself and uses type inference. LALRPOP uses a stack and returns an error here: https://github.com/lalrpop/lalrpop/blob/20832c3a6e829ceea98f65b0dd301aaa7fd3aa6c/lalrpop/src/normalize/tyinfer/mod.rs#L166
Our type resolver currently returns ()
as the type if this is detected.
Another idea: detect when a nonterminal references itself and uses type inference. LALRPOP uses a stack and returns an error here: https://github.com/lalrpop/lalrpop/blob/20832c3a6e829ceea98f65b0dd301aaa7fd3aa6c/lalrpop/src/normalize/tyinfer/mod.rs#L166
Our type resolver currently returns
()
as the type if this is detected.
We can try something else: pick other alternatives to try to resolve the type, if available.
Say you have the following:
Recursive = {
Recursive,
NotRecursive,
};
NotRecursive: () = {};
It should be possible to infer the type of Recursive
, knowing there is the NotRecursive
alternative that would not lead to recursion.
Also, this may have a problematic time complexity.
We should keep compatibility with LALRPOP though, which currently returns an error if it detects this case (see link in previous comment). Note that it only does that if the type is implicit. The "NotRecursive" example you shared does (I think, haven't tested yet) get rejected by LALRPOP because it sees the recursion while resolving the type of Recursive
.
I'll try to test this later to verify that this is indeed the case.
Interesting. I tried this out and LALRPOP seems to accept it. I guess we have to figure out how to do this too. Luckily we can look at LALRPOP's code :).
src/parser.lalrpop
:
grammar;
pub Recursive = {
"r" <Recursive>,
NotRecursive,
};
NotRecursive: &'static str = "n" => "test";
src/main.rs
:
use lalrpop_util::lalrpop_mod;
use std::io::{self, Read};
lalrpop_mod!(parser);
fn main() {
let mut input = String::new();
io::stdin().read_to_string(&mut input).unwrap();
let output = parser::RecursiveParser::new().parse(&input);
println!("Output: {:?}", output);
}
Example:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/lalrpop-test`
rrn
Output: Ok("test")
Named / unnamed(implemented)symbol
sCurrently lalrpop denies named and unnamed symbols to be a part of the same alternative. Example:
All the alternatives have action code and the type of the nonterminal wasn't specified(implemented)Example:
Note that lalrpop is able to infer it in cases like(from the second alternative):
After this is implemented, add a quick fix by interrogating the rust plugin about the type and set it on the nonterminal.(implemented)Maybe also as an intent?ImplementedNonterminal reference cannot be resolved(implemented)Example
Also quickfix: depending on the form; if it looks like this:
Then it could be quick-fixed either by adding it to
A
, like:Or by creating it:
While if it looks like this:
It could only be fixed by creating it:
Nonterminal reference doesn't have the expected number of "arguments"
Example:
Quick fix: add / remove until the number is right.
And the hardest, most brutal of them all.
Detect ambiguities in the grammar.
~Honestly I have no idea what black magic happens here in the first place.~