Commit ad010efa authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[torque] Refactor annotation handling

This CL introduces an AnnotationSet to unify annotation handling. Grammar
rules now accept a list of annotations (via annotations Symbol), where an
annotation is an Identifier starting with '@'. The new class AnnotationSet
can be used to restrict the allowed annotations and query presence of annotations
in the Make* functions.

Bug: v8:7793
Change-Id: Iad5435d4a94a3bea99aca76c23d2cffffe78a97f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1601142
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61334}
parent ed833ff5
......@@ -208,6 +208,12 @@ struct Identifier : AstNode {
std::string value;
};
struct IdentifierPtrValueEq {
bool operator()(const Identifier* a, const Identifier* b) {
return a->value < b->value;
}
};
struct IdentifierExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IdentifierExpression)
IdentifierExpression(SourcePosition pos,
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <cctype>
#include <set>
#include "src/torque/constants.h"
#include "src/torque/earley-parser.h"
......@@ -604,9 +605,35 @@ base::Optional<ParseResult> MakeMethodDeclaration(
return ParseResult{result};
}
class AnnotationSet {
public:
AnnotationSet(ParseResultIterator* iter,
const std::set<std::string>& allowed) {
auto list = iter->NextAs<std::vector<Identifier*>>();
for (const Identifier* i : list) {
if (allowed.find(i->value) == allowed.end()) {
std::stringstream s;
s << "Annotation " << i->value << " is not allowed here";
ReportLintError(s.str(), i->pos);
}
if (!set_.insert(i->value).second) {
std::stringstream s;
s << "Duplicate annotation " << i->value;
ReportLintError(s.str(), i->pos);
}
}
}
bool Contains(const std::string& s) { return set_.find(s) != set_.end(); }
private:
std::set<std::string> set_;
};
base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) {
auto generate_print = child_results->NextAs<bool>();
AnnotationSet annotations(child_results, {"@generatePrint"});
bool generate_print = annotations.Contains("@generatePrint");
auto is_extern = child_results->NextAs<bool>();
auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
......@@ -1242,12 +1269,18 @@ struct TorqueGrammar : Grammar {
return true;
}
static bool MatchAnnotation(InputPosition* pos) {
InputPosition current = *pos;
if (!MatchString("@", &current)) return false;
if (!MatchIdentifier(&current)) return false;
*pos = current;
return true;
}
static bool MatchIntrinsicName(InputPosition* pos) {
InputPosition current = *pos;
if (!MatchString("%", &current)) return false;
if (!MatchChar(std::isalpha, &current)) return false;
while (MatchChar(std::isalnum, &current) || MatchString("_", pos)) {
}
if (!MatchIdentifier(&current)) return false;
*pos = current;
return true;
}
......@@ -1318,6 +1351,13 @@ struct TorqueGrammar : Grammar {
// Result: Identifier*
Symbol name = {Rule({&identifier}, MakeIdentifier)};
// Result: Identifier*
Symbol annotation = {
Rule({Pattern(MatchAnnotation)}, MakeIdentifierFromMatchedInput)};
// Result: std::vector<Identifier*>
Symbol* annotations = List<Identifier*>(&annotation);
// Result: std::string
Symbol intrinsicName = {
Rule({Pattern(MatchIntrinsicName)}, YieldMatchedInput)};
......@@ -1696,8 +1736,8 @@ struct TorqueGrammar : Grammar {
Rule({Token("const"), &name, Token(":"), &type, Token("generates"),
&externalString, Token(";")},
AsSingletonVector<Declaration*, MakeExternConstDeclaration>()),
Rule({CheckIf(Token("@generatePrint")), CheckIf(Token("extern")),
CheckIf(Token("transient")), Token("class"), &name,
Rule({annotations, CheckIf(Token("extern")), CheckIf(Token("transient")),
Token("class"), &name,
Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
......
......@@ -131,8 +131,8 @@ std::string CurrentPositionAsString() {
throw error;
}
void ReportLintError(const std::string& error) {
LintErrors::Get().push_back({error, CurrentSourcePosition::Get()});
void ReportLintError(const std::string& error, SourcePosition pos) {
LintErrors::Get().push_back({error, pos});
}
void NamingConventionError(const std::string& type, const std::string& name,
......
......@@ -34,7 +34,8 @@ struct LintError {
};
DECLARE_CONTEXTUAL_VARIABLE(LintErrors, std::vector<LintError>);
void ReportLintError(const std::string& error);
void ReportLintError(const std::string& error,
SourcePosition pos = CurrentSourcePosition::Get());
// Prints a LintError with the format "{type} '{name}' doesn't follow
// '{convention}' naming convention".
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment