112 lines
3.8 KiB
C++
112 lines
3.8 KiB
C++
//===--- DisambiguateTest.cpp ---------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang-pseudo/Disambiguate.h"
|
|
#include "clang-pseudo/Forest.h"
|
|
#include "clang-pseudo/Token.h"
|
|
#include "clang/Basic/TokenKinds.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
namespace pseudo {
|
|
namespace {
|
|
using testing::ElementsAre;
|
|
using testing::Pair;
|
|
using testing::UnorderedElementsAre;
|
|
|
|
// Common disambiguation test fixture.
|
|
// This is the ambiguous forest representing parses of 'a * b;'.
|
|
class DisambiguateTest : public ::testing::Test {
|
|
protected:
|
|
// Greatly simplified C++ grammar.
|
|
enum Symbol : SymbolID {
|
|
Statement,
|
|
Declarator,
|
|
Expression,
|
|
DeclSpecifier,
|
|
Type,
|
|
Template,
|
|
};
|
|
enum Rule : RuleID {
|
|
/* LHS__RHS1_RHS2 means LHS := RHS1 RHS2 */
|
|
Statement__DeclSpecifier_Declarator_Semi,
|
|
Declarator__Star_Declarator,
|
|
Declarator__Identifier,
|
|
Statement__Expression_Semi,
|
|
Expression__Expression_Star_Expression,
|
|
Expression__Identifier,
|
|
DeclSpecifier__Type,
|
|
DeclSpecifier__Template,
|
|
Type__Identifier,
|
|
Template__Identifier,
|
|
};
|
|
|
|
ForestArena Arena;
|
|
ForestNode &A = Arena.createTerminal(tok::identifier, 0);
|
|
ForestNode &Star = Arena.createTerminal(tok::star, 1);
|
|
ForestNode &B = Arena.createTerminal(tok::identifier, 2);
|
|
ForestNode &Semi = Arena.createTerminal(tok::semi, 3);
|
|
|
|
// Parse as multiplication expression.
|
|
ForestNode &AExpr =
|
|
Arena.createSequence(Expression, Expression__Identifier, &A);
|
|
ForestNode &BExpr =
|
|
Arena.createSequence(Expression, Expression__Identifier, &B);
|
|
ForestNode &Expr =
|
|
Arena.createSequence(Expression, Expression__Expression_Star_Expression,
|
|
{&AExpr, &Star, &BExpr});
|
|
ForestNode &ExprStmt = Arena.createSequence(
|
|
Statement, Statement__Expression_Semi, {&Expr, &Semi});
|
|
// Parse as declaration (`a` may be CTAD or not).
|
|
ForestNode &AType =
|
|
Arena.createSequence(DeclSpecifier, DeclSpecifier__Type,
|
|
&Arena.createSequence(Type, Type__Identifier, &A));
|
|
ForestNode &ATemplate = Arena.createSequence(
|
|
DeclSpecifier, DeclSpecifier__Template,
|
|
&Arena.createSequence(Template, Template__Identifier, &A));
|
|
ForestNode &DeclSpec =
|
|
Arena.createAmbiguous(DeclSpecifier, {&AType, &ATemplate});
|
|
ForestNode &BDeclarator =
|
|
Arena.createSequence(Declarator, Declarator__Identifier, &B);
|
|
ForestNode &BPtr = Arena.createSequence(
|
|
Declarator, Declarator__Star_Declarator, {&Star, &BDeclarator});
|
|
ForestNode &DeclStmt =
|
|
Arena.createSequence(Statement, Statement__DeclSpecifier_Declarator_Semi,
|
|
{&DeclSpec, &Star, &BDeclarator});
|
|
// Top-level ambiguity
|
|
ForestNode &Stmt = Arena.createAmbiguous(Statement, {&ExprStmt, &DeclStmt});
|
|
};
|
|
|
|
TEST_F(DisambiguateTest, Remove) {
|
|
Disambiguation D;
|
|
D.try_emplace(&Stmt, 1); // statement is a declaration, not an expression
|
|
D.try_emplace(&DeclSpec, 0); // a is a type, not a (CTAD) template
|
|
ForestNode *Root = &Stmt;
|
|
removeAmbiguities(Root, D);
|
|
|
|
EXPECT_EQ(Root, &DeclStmt);
|
|
EXPECT_THAT(DeclStmt.elements(), ElementsAre(&AType, &Star, &BDeclarator));
|
|
}
|
|
|
|
TEST_F(DisambiguateTest, DummyStrategy) {
|
|
Disambiguation D = disambiguate(&Stmt, {});
|
|
EXPECT_THAT(D, UnorderedElementsAre(Pair(&Stmt, 1), Pair(&DeclSpec, 1)));
|
|
|
|
ForestNode *Root = &Stmt;
|
|
removeAmbiguities(Root, D);
|
|
EXPECT_EQ(Root, &DeclStmt);
|
|
EXPECT_THAT(DeclStmt.elements(),
|
|
ElementsAre(&ATemplate, &Star, &BDeclarator));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace pseudo
|
|
} // namespace clang
|