A followup patch of d489b3807f, but for
member functions, this will eliminate a false parse of member
declaration.
Differential Revision: https://reviews.llvm.org/D131720
We happened to introduce a `member-declaration := ;` rule
when inlining the `member-declaration := decl-specifier-seq_opt
member-declarator-list_opt ;`.
And with the `member-declaration := empty-declaration` rule, we had two parses of `;`.
This patch is to restrict the grammar to eliminate the
`member-declaration := ;` rule.
Differential Revision: https://reviews.llvm.org/D131724
The solution is to favor the longest possible nest-name-specifier, and
drop other alternatives by using the guard, per per C++ [basic.lookup.qual.general].
Motivated cases:
```
Foo::Foo() {};
// the constructor can be parsed as:
// - Foo ::Foo(); // where the first Foo is return-type, and ::Foo is the function declarator
// + Foo::Foo(); // where Foo::Foo is the function declarator
```
```
void test() {
// a very slow parsing case when there are many qualifers!
X::Y::Z;
// The statement can be parsed as:
// - X ::Y::Z; // ::Y::Z is the declarator
// - X::Y ::Z; // ::Z is the declarator
// + X::Y::Z; // a declaration without declarator (X::Y::Z is decl-specifier-seq)
// + X::Y::Z; // a qualifed-id expression
}
```
Differential Revision: https://reviews.llvm.org/D130511
Motivating case: `foo bar;` is not a declaration of nothing with `foo` and `bar`
both types.
This is a common and critical ambiguity, clangd/AST.cpp has 20% fewer
ambiguous nodes (1674->1332) after this change.
Differential Revision: https://reviews.llvm.org/D130337
- the grammar ambiguity is eliminated by a guard;
- modify the guard function signatures, now all parameters are folded in
to a single object, avoid a long parameter list (as we will add more
parameters in the near future);
Reviewed By: sammccall
Differential Revision: https://reviews.llvm.org/D130160
After this, NUMERIC_CONSTANT and strings should parse only one way.
There are 8 types of literals, and 24 valid (literal, TokenKind) pairs.
This means adding 8 new named guards (or 24, if we want to assert the token).
It seems fairly clear to me at this point that the guard names are unneccesary
indirection: the guards are in fact coupled to the rule signature.
(Also add the zero guard I forgot in the previous patch.)
Differential Revision: https://reviews.llvm.org/D130066
This eliminates some simple-declaration/function-definition false
parses.
- implement a function to determine whether a declarator ForestNode is a
function declarator;
- extend the standard declarator to two guarded function-declarator and
non-function-declarator nonterminals;
Differential Revision: https://reviews.llvm.org/D129222
The idea is:
- a parse failure is detected when all heads die when trying to shift the next token
- we can recover by choosing a nonterminal we're partway through parsing, and
determining where it ends through nonlocal means (e.g. matching brackets)
- we can find candidates by walking up the stack from the (ex-)heads
- the token range is defined using heuristics attached to grammar rules
- the unparsed region is represented in the forest by an Opaque node
This patch has the core GLR functionality.
It does not allow recovery heuristics to be attached as extensions to
the grammar, but rather infers a brace-based heuristic.
Expected followups:
- make recovery heuristics grammar extensions (depends on D127448)
- add recovery to our grammar for bracketed constructs and sequence nodes
- change the structure of our augmented `_ := start` rules to eliminate some
special-cases in glrParse.
- (if I can work out how): avoid some spurious recovery cases described in comments
(Previously mistakenly committed as a0f4c10ae2)
Differential Revision: https://reviews.llvm.org/D128486
- Extend the GLR parser to allow conditional reduction based on the
guard functions;
- Implement two simple guards (contextual-override/final) for cxx.bnf;
- layering: clangPseudoCXX depends on clangPseudo (as the guard function need
to access the TokenStream);
Differential Revision: https://reviews.llvm.org/D127448
The idea is:
- a parse failure is detected when all heads die when trying to shift
the next token
- we can recover by choosing a nonterminal we're partway through parsing,
and determining where it ends through nonlocal means (e.g. matching brackets)
- we can find candidates by walking up the stack from the (ex-)heads
- the token range is defined using heuristics attached to grammar rules
- the unparsed region is represented in the forest by an Opaque node
This patch has the core GLR functionality.
It does not allow recovery heuristics to be attached as extensions to
the grammar, but rather infers a brace-based heuristic.
Expected followups:
- make recovery heuristics grammar extensions (depends on D127448)
- add recover to our grammar for bracketed constructs and sequence nodes
- change the structure of our augmented `_ := start` rules to eliminate
some special-cases in glrParse.
- (if I can work out how): avoid some spurious recovery cases described
in comments
- grammar changes to eliminate the hard distinction between init-list
and designated-init-list shown in the recovery-init-list.cpp testcase
Differential Revision: https://reviews.llvm.org/D128486
Treat captures as a uniform list, rather than default-captures being special
snowflakes that may only appear at the start.
This accepts a larger set of (incorrect) code, and simplifies error-handling
by making this fit into the usual homogeneous-list pattern.
Differential Revision: https://reviews.llvm.org/D128708
This isn't allowed by the standard grammar but is allowed in C, and clang/GCC
permit it as an extension.
It avoids the need to determine which type of list we have in error-recovery.
While here, also support array index designators `{ [4]=1 }` which are
also legal in C, and common extensions in C++.
Differential Revision: https://reviews.llvm.org/D128687
I expect to eliminate this ambiguity at the grammar level by use of guards,
because it interferes with brace-based error recvoery.
Differential Revision: https://reviews.llvm.org/D127400
The parenthese body should be parameter-declaration-clause, rather
than parameter-declaration-list.
Reviewed By: sammccall
Differential Revision: https://reviews.llvm.org/D125479
The clang lexer lexes it as a dedicated token kind (rather than
identifier), we extend the grammar to handle it.
Differential Revision: https://reviews.llvm.org/D126996