Rule Language Reference¶
A quick reference to all the builtin functions, operators and actions.
- Functions are used in predicates (i.e. in the
whereclause) of matchers. - Operators can be used to combine multiple expressions within predicates.
- Actions can be taken in the body of match.
- AST Providers can also export Functions and Actions.
- Variables & Conditions can be used for expressing pre-conditions
- Scoped Matchers can be used to restrict a matcher’s breadth and depth.
Example:
Function where not(Public) && Override {
fail("")
}
In the sample matcher above, not is a function, && is an operator and fail is an action.
Functions¶
match(Property, RegExp)¶
Tries to convert the value of Property to a string, and matches it against the regular expression in RegExp.
not(Expression)¶
Converts the value of Expression to a boolean value and performs a logical negation.
count(List)¶
Converts the value of List to a list and returns the number of elements in the list. Returns 0 if List is not an actual list.
Operators¶
Expression1 == Expression2¶
Structural equality operator.
Expression1 != Expression2¶
Negation of Expression1 == Expression2
Expression1 && Expression2¶
Converts both Expression1 and Expression2 to boolean values and performs a boolean “and”.
Expression1 || Expression2¶
Converts both Expression1 and Expression2 to boolean values and performs a boolean “or”.
node.property¶
Access property of the AST node. If the node is actually a list of nodes, the property access works like flatMap: the property access is computed for every node in the list and then compacted into a new list.
Actions¶
fail(Explanation)¶
Reports that an error was found in the current node being matched. Explanation should be a string explaining why is this is a violation and, ideally, how to correct it.
warn(Explanation)¶
Similar to fail(Explanation), but reports a warning instead of an error.
AST Providers¶
Swift¶
The Swift provider only exports one convenience function:
inheritsFrom(ClassName)
This function assumes that a class is being matched and will return true if the string ClassName appears in the inheritance clause of the class declaration. It returns false if either the current node does not have a TypeInheritanceClause (i.e. it’s not a ClassDeclaration) or if the string ClassName does not appear in the inheritance clause.
Python¶
The Python provider currently does not export any function or action.
Variables & Conditions¶
NEAL allows you to declare boolean variables inside a matcher. Those variables can be mutated from nested matchers and used in where clauses and conditions.
Declaring a new variable¶
Variable declarations must be prefix with var and have a initial value assigned to it.
Provider::Matcher {
var is_valid := true
var did_match := false
}
Mutating a variable¶
Variables are block-scoped and can be mutated from nested matchers at any depth.
Provider::Matcher {
var is_valid := true
var did_match := false
NestedMatcher {
did_match := true
}
OtherMatcher {
is_valid := false
}
}
Conditions¶
Conditions are evaluated when exiting the node and can be used in conjunction with variables to check that a series of pre-conditions within that node.
Provider::Matcher {
var is_valid := true
var did_match := false
condition (is_valid && did_match) {
fail("....")
}
NestedMatcher where is_valid {
did_match := true
}
OtherMatcher {
is_valid := false
}
}
Scoped Matchers¶
Any matcher can be scoped to a given property of it’s parent matcher, thus restricting in breadth: instead of searching through all the properties of the current AST node, restrict it to a single property. The choice of the operator used for scoping (> vs >>) can be used to restrict in depth: > will match only immediate children nodes, >> will nodes at any depth.
For example, the following matcher will match class C { var x: String = "" } but not class C { func f() { var x: String = "" } }
Swift::Class {
ClassBody > VariableDeclaration {
fail("...")
}
}
Replacing the > operator with >> would lead to matching both cases.