blob: a2cc0da3530ab7e3bcb7f969a54905bc3fc0388a [file] [log] [blame]
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VERIBLE_VERILOG_CST_VERILOG_MATCHERS_H_
#define VERIBLE_VERILOG_CST_VERILOG_MATCHERS_H_
#include "common/analysis/matcher/matcher_builders.h"
#include "common/text/symbol.h"
#include "verilog/CST/verilog_nonterminals.h"
#include "verilog/parser/verilog_token_enum.h"
namespace verilog {
// These are locally defined macros (undef'd at end of header) to enable
// concise description of Path Matchers.
#define N(tag) verible::NodeTag(NodeEnum::tag)
#define L(tag) verible::LeafTag(tag)
// NodeMatcher matches a syntax tree node with a specific tag.
// This is a template type alias.
template <NodeEnum NodeTag>
using NodeMatcher =
verible::matcher::TagMatchBuilder<verible::SymbolKind::kNode, NodeEnum,
NodeTag>;
// LeafMatcher matches a syntax tree leaf with a specific tag.
// This is a template type alias.
template <int LeafTag>
using LeafMatcher =
verible::matcher::TagMatchBuilder<verible::SymbolKind::kLeaf, int, LeafTag>;
// Declaration of Leaf Matchers
// TODO(fangism): auto-generate leaf matches for named enum constants.
// Matches against system task or function identifiers, which are functions
// or tasks that begin with a $ character
//
// For instance, matches:
// $psprintf(...);
// $foo_bar(...);
//
static const LeafMatcher<SystemTFIdentifier> SystemTFIdentifierLeaf;
// Matches against macro call identifiers, which are identifiers
// begin with a ` character.
//
// For instance, matches '`MACRO' in:
// `MACRO()
// `MACRO();
//
static const LeafMatcher<MacroCallId> MacroCallIdLeaf;
// Declaration of Node Matchers
// Declare every syntax tree node matcher.
// NodekFoo is a matcher that matches against syntax tree nodes tagged kFoo.
#define CONSIDER(tag) extern const NodeMatcher<NodeEnum::tag> Node##tag;
#include "verilog/CST/verilog_nonterminals_foreach.inc" // IWYU pragma: keep
#undef CONSIDER
// Declare every syntax tree single-node path matcher.
// PathkFoo is a PathMatcher that matches against a single node tagged kFoo.
#define CONSIDER(tag) \
extern const verible::matcher::PathMatchBuilder<1> Path##tag;
#include "verilog/CST/verilog_nonterminals_foreach.inc" // IWYU pragma: keep
#undef CONSIDER
// These matchers match on a specific type of AST Node
// NodekGenerateBlock matches against generate blocks
//
// For instance, matches:
// generate
// if (TypeIsPosedge) begin : gen_posedge
// always @(posedge clk) foo <= bar;
// end
// endgenerate
//
// NodekVoidcast matches against voidcasts
//
// For instance, matches:
// void'(foo());
//
// NodekExpression matches against expressions
//
// For instance, matches:
// x = y; // assignment expression.
// y = foo() // assignment expression and function call expression
//
// NodekActualParameterList matches against the parameter list provided
// to a parameterized module during instantiation.
//
// For instance, matches "#(1, 2, 3) in
// foo #(1, 2, 3) bar;
//
// NodekGateInstance matches against the gate list for instantiated modules.
//
// For instance, matches "bar(port1, port2)" in
// foo bar(port1, port2);
//
// NodekAlwaysStatement matches against an always statement block.
//
// For instance, matches "always @* begin ... end" in
// module foo;
// always @* begin
// c = d;
// end
// endmodule
// Declarations of Traversal Matchers
//
// These matchers allow traversal between specific nodes
// Matches against the expression contained within a voidcast.
//
// For instance,
// VoidcastNode(VoidcastHasExpression());
// matches all of
// void'(expression());
//
static auto VoidcastHasExpression =
verible::matcher::MakePathMatcher({N(kParenGroup), N(kExpression)});
// Matches against a top level function call contained within an expression.
//
// For instance,
// ExpressionNode(ExpressionHasFunctionCall());
// matches "foo()" in
// x = foo();
//
static const auto ExpressionHasFunctionCall = verible::matcher::MakePathMatcher(
{N(kReferenceCallBase), N(kFunctionCall)});
// Matches a randomize call extension, or a call to an object's randomize
// method contained within an expression.
//
// For instance,
// ExpressionNode(ExpressionHasRandomizeCallExtension());
// matches
// result = obj.randomize();
//
static const auto ExpressionHasRandomizeCallExtension =
verible::matcher::MakePathMatcher(
{N(kReferenceCallBase), N(kRandomizeMethodCallExtension)});
// Matches a randomize function call contained within an expression.
//
// For instance,
// ExpressionNode(ExpressionHasRandomizeFunction());
// matches
// result = randomize(obj);
//
static const auto ExpressionHasRandomizeFunction =
verible::matcher::MakePathMatcher({N(kRandomizeFunctionCall)});
// Matches against the SymbolIdentifier leaf containing the name
// of a function
//
// For instance,
// ExpressionNode(ExpressionHasFunctionCall(FunctionCallHasId()));
// matches
// x = foo(); // innermost matcher matches "foo" token
//
static const auto UnqualifiedReferenceHasId = verible::matcher::MakePathMatcher(
{N(kLocalRoot), N(kUnqualifiedId), L(SymbolIdentifier)});
static const auto FunctionCallHasId = UnqualifiedReferenceHasId;
// Matches if the WIDTH in "WIDTH 'BASE DIGITS" is a constant (decimal).
//
// For instance,
// NodekNumber(NumberHasConstantWidth())
// matches
// "32" in "32'h0"
//
// TODO(fangism): The path matcher actually finds the constant in any
// child node position. To be more precise, we only want to look at the
// leftmost child, as in a positional-child-matcher.
static const auto NumberHasConstantWidth =
verible::matcher::MakePathMatcher({L(TK_DecNumber)});
// Matches if the base of "'BASE DIGITS" is binary.
//
// For instance,
// NodekNumber(NumberIsBinary())
// matches
// "'b" in "4'b1111"
//
static const auto NumberIsBinary =
verible::matcher::MakePathMatcher({L(TK_BinBase)});
// Matches the digits of "'BASE DIGITS" when base is binary.
//
// For instance,
// NodekNumber(NumberHasBinaryDigits())
// matches
// "1111" in "4'b1111"
//
static const auto NumberHasBinaryDigits =
verible::matcher::MakePathMatcher({L(TK_BinDigits)});
// Matches if the LITERAL in "WIDTH'LITERAL" specifies a numeric base ([bdho]).
//
// For instance,
// NodekNumber(NumberHasBasedLiteral())
// matches
// "'b1111" in "4'b1111"
//
static const auto NumberHasBasedLiteral =
verible::matcher::MakePathMatcher({N(kBaseDigits)});
// Matches against the positional parameter list contained within an
// actual parameter list if one exists.
//
// For instance,
// ActualParameterListNode(ActualParameterListHasPositionalParameterList());
// matches
// foo #(1, 2) bar;
// and does not match
// foo $(.param(1), .param2(2));
//
static const auto ActualParameterListHasPositionalParameterList =
verible::matcher::MakePathMatcher(
{N(kParenGroup), N(kActualParameterPositionalList)});
// Matches the port list of a gate instance.
// For instance,
// ActualGateInstanceNode(GateInstanceHasPortList());
// matches
// foo bar(port1, port2);
//
static const auto GateInstanceHasPortList =
verible::matcher::MakePathMatcher({N(kParenGroup), N(kPortActualList)});
// Matches against a node's child tagged with kBegin.kLabel if one exists.
//
// For instance, matches ": gen_posedge" within
// generate
// if (TypeIsPosedge) begin : gen_posedge
// always @(posedge clk) foo <= bar;
// end
// endgenerate
static const auto HasBeginLabel =
verible::matcher::MakePathMatcher({N(kBegin), N(kLabel)});
// Matches event controls that use *.
// For instance,
//
// matches down to '*' in:
// always @* begin
// c = d;
// end
// and does not match:
// always_comb begin
// c = d;
// end
static const auto AlwaysStatementHasEventControlStar =
verible::matcher::MakePathMatcher(
{N(kProceduralTimingControlStatement), N(kEventControl), L('*')});
// Matches occurrence of the 'always' keyword.
// This is needed to distinguish between various kAlwaysStatement's.
// This matches 'always', but not 'always_ff', nor 'always_comb'.
static const auto AlwaysKeyword =
verible::matcher::MakePathMatcher({L(TK_always)});
// Matches occurrence of the 'always_comb' keyword.
// This is needed to distinguish between various kAlwaysStatement's.
static const auto AlwaysCombKeyword =
verible::matcher::MakePathMatcher({L(TK_always_comb)});
// Matches occurrence of the 'always_ff' keyword.
// This is needed to distinguish between various kAlwaysStatement's.
static const auto AlwaysFFKeyword =
verible::matcher::MakePathMatcher({L(TK_always_ff)});
// Matches legacy-style begin-block inside generate region.
//
// For instance, matches:
//
// generate
// begin
// ...
// end
// endgenerate
//
static const auto HasGenerateBlock = verible::matcher::MakePathMatcher(
{N(kGenerateItemList), N(kGenerateBlock)});
static const auto ReferenceHasHierarchy =
verible::matcher::MakePathMatcher({N(kHierarchyExtension)});
static const auto ReferenceHasIndex =
verible::matcher::MakePathMatcher({N(kSelectVariableDimension)});
// Matches the LHS of an assignment (lvalue) to a local variable.
// For instance, matches 'var' in:
//
// var = ...;
//
// where `var` could also be a complex reference, such as var.x, or var[k].
static const auto LValueOfAssignment =
verible::matcher::MakePathMatcher({N(kLPValue), N(kReferenceCallBase)});
// Matches the RHS of an assignment that is a function call.
// For instance, matches "bar(...)" in:
//
// ... = bar(...);
//
// and matches "zz.bar(...)" in:
//
// ... = zz.bar(...);
//
// and matches "zz::bar(...)" in:
//
// ... = zz::bar(...);
//
static const auto RValueIsFunctionCall = verible::matcher::MakePathMatcher(
{N(kExpression), N(kReferenceCallBase), N(kFunctionCall)});
// Matches a function call if it is qualified.
// For instance, matches:
//
// foo::bar(...);
//
// but not:
//
// bar(...);
//
static const auto FunctionCallIsQualified =
verible::matcher::MakePathMatcher({N(kLocalRoot), N(kQualifiedId)});
// Matches the arguments of a function call.
// For instance, matches "a", "b", "c" (including commas) of:
//
// foo("a", "b", "c");
//
// Note: This does not match macro call arguments.
//
static const auto FunctionCallArguments =
verible::matcher::MakePathMatcher({N(kParenGroup), N(kArgumentList)});
// Matches sub-ranges of array declarations.
// For instances, matches the subtree "[x:y]" in both:
//
// wire [x:y] w;
// wire w [x:y];
//
static const auto DeclarationDimensionsHasRanges =
verible::matcher::MakePathMatcher({N(kDimensionRange)});
// Matches with a default case item.
// For instance, matches:
//
// casez (in)
// default : return 3
// endcase
//
// but not:
//
// casez (in)
// 1: return 0;
// endcase
//
static const auto HasDefaultCase =
verible::matcher::MakePathMatcher({N(kDefaultItem)});
// Clean up macros
#undef N
#undef L
} // namespace verilog
#endif // VERIBLE_VERILOG_CST_VERILOG_MATCHERS_H_