Slang is a modular Solidity compiler tooling library that provides a declarative Query API for pattern matching in Solidity Abstract Syntax Trees (ASTs). This document covers all the expressions and patterns that can be used with the Slang Query API.
Note: All node types and examples in this documentation have been verified against the Slang v1.2.0 version to ensure accuracy.
- Basic Query Syntax
- Node Types
- Pattern Matching
- Query Execution
- Common Patterns
- Examples
- Best Practices
A query is a pattern that matches a certain set of nodes in a tree. The expression to match a given node consists of a pair of brackets ([]
) containing two things:
- The node's kind - The type of AST node to match
- Optional child patterns - Patterns that match the node's children
[NodeKind];
[NodeKind[ChildNodeKind][AnotherChildNodeKind]];
[NodeKind
label: [ChildNodeKind]
[AnotherChildNodeKind]
]
[NodeKind['specific_text']];
[
NodeKind[_], // Matches any node kind
];
All node types listed below have been verified to work with Slang v1.2.0.
ConstantDefinition
- Constant declarationsConstructorDefinition
- Constructor declarationsContractDefinition
- Contract declarationsEnumDefinition
- Enum declarationsErrorDefinition
- Error declarationsEventDefinition
- Event declarationsFallbackFunctionDefinition
- Fallback function declarationsFunctionDefinition
- Function declarationsInterfaceDefinition
- Interface declarationsLibraryDefinition
- Library declarationsModifierDefinition
- Modifier declarationsReceiveFunctionDefinition
- Receive function declarationsStateVariableDefinition
- State variable declarationsStructDefinition
- Struct declarationsUnnamedFunctionDefinition
- Unnamed function declarationsUserDefinedValueTypeDefinition
- Custom value type declarationsYulFunctionDefinition
- Yul (assembly) function declarations
AssemblyStatement
- Assembly blocksBreakStatement
- Break statementsContinueStatement
- Continue statementsDoWhileStatement
- Do-while loopsEmitStatement
- Emit statementsExpressionStatement
- Expression statementsForStatement
- For loopsIfStatement
- If statementsReturnStatement
- Return statementsRevertStatement
- Revert statementsStatement
- Generic statement (abstract)ThrowStatement
- Throw statements (deprecated)TryStatement
- Try statementsTupleDeconstructionStatement
- Tuple destructuringVariableDeclarationStatement
- Variable declarationsWhileStatement
- While loopsYulBreakStatement
- Yul break statementsYulContinueStatement
- Yul continue statementsYulForStatement
- Yul for loopsYulIfStatement
- Yul if statementsYulLeaveStatement
- Yul leave statementsYulStackAssignmentStatement
- Yul stack assignmentsYulStatement
- Generic Yul statementYulSwitchStatement
- Yul switch statementsYulVariableAssignmentStatement
- Yul variable assignmentsYulVariableDeclarationStatement
- Yul variable declarations
AdditiveExpression
- Addition and subtractionAssignmentExpression
- Assignment operationsCallOptionsExpression
- Call options (value, gas)ConditionalExpression
- Ternary operatorExponentiationExpression
- ExponentiationExpression
- Generic expression (abstract)FunctionCallExpression
- Function callsIndexAccessExpression
- Array/mapping accessMemberAccessExpression
- Member access (dot notation)MultiplicativeExpression
- Multiplication, division, moduloNewExpression
- New keyword expressionsPostfixExpression
- Postfix operations (++, --)PrefixExpression
- Prefix operations (++, --, !, ~, -, +)ßTypeExpression
- Type expressionsVersionExpression
- Version expressions (pragma)YulExpression
- Generic Yul expressionYulFunctionCallExpression
- Yul function calls
AndExpression
- Logical AND (&&)OrExpression
- Logical OR (||)EqualityExpression
- Equality operations (==, !=)InequalityExpression
- Inequality operations (<, >, <=, >=)BitwiseAndExpression
- Bitwise AND (&)BitwiseOrExpression
- Bitwise OR (|)BitwiseXorExpression
- Bitwise XOR (^)ShiftExpression
- Bit shift operations (<<, >>)
ArrayExpression
- Array literalsDecimalNumberExpression
- Decimal numbersHexNumberExpression
- Hexadecimal numbersHexStringLiteral
- Hex string literalsHexStringLiterals
- Multiple hex string literalsIdentifierPath
- Identifier paths (qualified names)NumberUnit
- Number units (wei, ether, etc.)SimpleVersionLiteral
- Simple version literalsStringExpression
- String expressionsStringLiteral
- String literal tokensStringLiterals
- Multiple string literalsTupleExpression
- Tuple expressionsUnicodeStringLiteral
- Unicode string literalsUnicodeStringLiterals
- Multiple unicode string literalsVersionLiteral
- Version literalsYulLiteral
- Yul literals
AddressType
- Address type with optional payableArrayTypeName
- Array typesElementaryType
- Basic types (uint, address, bool, etc.)FunctionType
- Function typesFunctionTypeAttribute
- Function type attributesFunctionTypeAttributes
- Multiple function type attributesInheritanceType
- Inheritance type specificationsInheritanceTypes
- Multiple inheritance typesMappingKeyType
- Mapping key typesMappingType
- Mapping typesTypeName
- Generic type name (abstract)TypedTupleMember
- Typed tuple membersVariableDeclarationType
- Variable declaration types
The following are abstract base types that can match multiple specific node types:
Expression
- Any expression typeStatement
- Any statement typeTypeName
- Any type name
Note: These abstract types are useful for broad pattern matching when you don't need to match specific expression or statement types.
ImportDirective
- Import statementsPragmaDirective
- Pragma directivesSourceUnit
- Root node of a Solidity fileUsingDirective
- Using statements
Edge labels are used to specify relationships between parent and child nodes in query patterns. Here are the available edge labels:
Common Labels:
name
- Node name/identifierbody
- Function/contract bodyparameters
- Function parametersarguments
- Function call argumentsexpression
- Expression contentcondition
- Conditional expressionsstatements
- Statement blocksmembers
- Contract/struct membersattributes
- Node attributesoperator
- Operators in expressionsoperand
- Expression operandsleftOperand
,rightOperand
- Binary expression operands
All Available Edge Labels (138 total):
Common Pattern Labels:
name
- Node name/identifierbody
- Function/contract bodyparameters
- Function parametersarguments
- Function call argumentsexpression
- Expression contentcondition
- Conditional expressionsstatements
- Statement blocksmembers
- Contract/struct membersattributes
- Node attributesoperator
- Operators in expressionsoperand
- Expression operandsleftOperand
,rightOperand
- Binary expression operands
Keyword Labels:
AbicoderKeyword
- abicoder keyword labelAbstractKeyword
- abstract keyword labelAddressKeyword
- address keyword labelAnonymousKeyword
- anonymous keyword labelAsKeyword
- as keyword labelAssemblyKeyword
- assembly keyword labelAtKeyword
- at keyword labelBreakKeyword
- break keyword labelCaseKeyword
- case keyword labelCatchKeyword
- catch keyword labelConstantKeyword
- constant keyword labelConstructorKeyword
- constructor keyword labelContinueKeyword
- continue keyword labelContractKeyword
- contract keyword labelDefaultKeyword
- default keyword labelDoKeyword
- do keyword labelElseKeyword
- else keyword labelEmitKeyword
- emit keyword labelEnumKeyword
- enum keyword labelErrorKeyword
- error keyword labelEventKeyword
- event keyword labelExperimentalKeyword
- experimental keyword labelFallbackKeyword
- fallback keyword labelForKeyword
- for keyword labelFromKeyword
- from keyword labelFunctionKeyword
- function keyword labelGlobalKeyword
- global keyword labelIfKeyword
- if keyword labelImportKeyword
- import keyword labelIndexedKeyword
- indexed keyword labelInterfaceKeyword
- interface keyword labelIsKeyword
- is keyword labelLayoutKeyword
- layout keyword labelLeaveKeyword
- leave keyword labelLetKeyword
- let keyword labelLibraryKeyword
- library keyword labelMappingKeyword
- mapping keyword labelModifierKeyword
- modifier keyword labelNewKeyword
- new keyword labelOverrideKeyword
- override keyword labelPayableKeyword
- payable keyword labelPragmaKeyword
- pragma keyword labelReceiveKeyword
- receive keyword labelReturnKeyword
- return keyword labelReturnsKeyword
- returns keyword labelRevertKeyword
- revert keyword labelSolidityKeyword
- solidity keyword labelStructKeyword
- struct keyword labelSwitchKeyword
- switch keyword labelThrowKeyword
- throw keyword labelTryKeyword
- try keyword labelTypeKeyword
- type keyword labelUncheckedKeyword
- unchecked keyword labelUsingKeyword
- using keyword labelVarKeyword
- var keyword labelWhileKeyword
- while keyword label
Structural Labels:
Alias
- Alias specificationsArguments
- Function call argumentsAssignment
- Assignment operationsAsterisk
- Asterisk operatorsAttributes
- Node attributesBlock
- Code blocksBody
- Function/contract bodiesCases
- Switch casesCatchClauses
- Try-catch clausesClause
- Generic clausesCloseBrace
- Closing bracesCloseBracket
- Closing bracketsCloseParen
- Closing parenthesesColon
- Colon punctuationCondition
- Conditional expressionsElements
- Array/tuple elementsElseBranch
- Else branchesEnd
- End markersEqual
- Equality operatorsEqualGreaterThan
- Mapping arrows (=>)Error
- Error specificationsEvent
- Event specificationsExpression
- Expression contentFalseExpression
- False expressionsFeature
- Feature specificationsFlags
- Flag specificationsIdentifier
- IdentifiersIndex
- Array indicesInheritance
- Inheritance specificationsInitialization
- Initialization expressionsItem
- Generic itemsItems
- Collections of itemsIterator
- Loop iteratorsKeyType
- Mapping key typesLabel
- LabelsLeadingTrivia
- Leading whitespace/commentsLeftOperand
- Left operandsLiteral
- Literal valuesMember
- Member specificationsMembers
- Collections of membersMinus
- Minus operatorsMinusGreaterThan
- Function arrows (->)Missing
- Missing elementsName
- Names/identifiersOpenBrace
- Opening bracesOpenBracket
- Opening bracketsOpenParen
- Opening parenthesesOperand
- Generic operandsOperator
- OperatorsOptions
- Option specificationsOverridden
- Override specificationsParameters
- Function parametersPath
- Import/using pathsPaths
- Collections of pathsPeriod
- Period punctuationPragma
- Pragma directivesQuestionMark
- Question mark operatorsReturns
- Return specificationsRightOperand
- Right operandsRoot
- Root nodesSemicolon
- Semicolon punctuationSeparator
- SeparatorsSets
- Collections/setsSpecifiers
- Various specifiersStart
- Start markersStatements
- Statement collectionsStorageLocation
- Storage location specificationsSymbols
- Symbol collectionsTarget
- Target specificationsTrailingTrivia
- Trailing whitespace/commentsTrueExpression
- True expressionsTypeName
- Type namesTypes
- Type collectionsUnit
- UnitsUnrecognized
- Unrecognized elementsValue
- ValuesValueType
- Value typesVariable
- Variable specificationsVariableType
- Variable typesVariables
- Variable collectionsVariant
- VariantsVersion
- Version specifications
Terminal kinds represent the actual tokens, keywords, and operators in Solidity code. There are 296 terminal kinds available:
Basic Keywords:
AbicoderKeyword
- abicoder keywordAbstractKeyword
- abstract keywordAddressKeyword
- address keywordAfterKeyword
- after keywordAliasKeyword
- alias keywordAnonymousKeyword
- anonymous keywordApplyKeyword
- apply keywordAsKeyword
- as keywordAssemblyKeyword
- assembly keywordAtKeyword
- at keywordAutoKeyword
- auto keywordBoolKeyword
- bool keywordBreakKeyword
- break keywordByteKeyword
- byte keywordBytesKeyword
- bytes keywordCallDataKeyword
- calldata keywordCaseKeyword
- case keywordCatchKeyword
- catch keywordConstantKeyword
- constant keywordConstructorKeyword
- constructor keywordContinueKeyword
- continue keywordContractKeyword
- contract keywordCopyOfKeyword
- copyof keywordDaysKeyword
- days keywordDefaultKeyword
- default keywordDefineKeyword
- define keywordDeleteKeyword
- delete keywordDoKeyword
- do keywordElseKeyword
- else keywordEmitKeyword
- emit keywordEnumKeyword
- enum keywordErrorKeyword
- error keywordEtherKeyword
- ether keywordEventKeyword
- event keywordExperimentalKeyword
- experimental keywordExternalKeyword
- external keywordFallbackKeyword
- fallback keywordFalseKeyword
- false keywordFinalKeyword
- final keywordFinneyKeyword
- finney keywordFixedKeyword
- fixed keywordForKeyword
- for keywordFromKeyword
- from keywordFunctionKeyword
- function keywordGlobalKeyword
- global keywordGweiKeyword
- gwei keywordHexKeyword
- hex keywordHoursKeyword
- hours keywordIfKeyword
- if keywordImmutableKeyword
- immutable keywordImplementsKeyword
- implements keywordImportKeyword
- import keywordInKeyword
- in keywordIndexedKeyword
- indexed keywordInlineKeyword
- inline keywordIntKeyword
- int keywordInterfaceKeyword
- interface keywordInternalKeyword
- internal keywordIsKeyword
- is keywordLayoutKeyword
- layout keywordLetKeyword
- let keywordLibraryKeyword
- library keywordMacroKeyword
- macro keywordMappingKeyword
- mapping keywordMatchKeyword
- match keywordMemoryKeyword
- memory keywordMinutesKeyword
- minutes keywordModifierKeyword
- modifier keywordMutableKeyword
- mutable keywordNewKeyword
- new keywordNullKeyword
- null keywordOfKeyword
- of keywordOverrideKeyword
- override keywordPartialKeyword
- partial keywordPayableKeyword
- payable keywordPragmaKeyword
- pragma keywordPrivateKeyword
- private keywordPromiseKeyword
- promise keywordPublicKeyword
- public keywordPureKeyword
- pure keywordReceiveKeyword
- receive keywordReferenceKeyword
- reference keywordRelocatableKeyword
- relocatable keywordReturnKeyword
- return keywordReturnsKeyword
- returns keywordRevertKeyword
- revert keywordSealedKeyword
- sealed keywordSecondsKeyword
- seconds keywordSizeOfKeyword
- sizeof keywordSolidityKeyword
- solidity keywordStaticKeyword
- static keywordStorageKeyword
- storage keywordStringKeyword
- string keywordStructKeyword
- struct keywordSuperKeyword
- super keywordSupportsKeyword
- supports keywordSwitchKeyword
- switch keywordSzaboKeyword
- szabo keywordThisKeyword
- this keywordThrowKeyword
- throw keywordTransientKeyword
- transient keywordTrueKeyword
- true keywordTryKeyword
- try keywordTypeDefKeyword
- typedef keywordTypeKeyword
- type keywordTypeOfKeyword
- typeof keywordUfixedKeyword
- ufixed keywordUintKeyword
- uint keywordUncheckedKeyword
- unchecked keywordUsingKeyword
- using keywordVarKeyword
- var keywordViewKeyword
- view keywordVirtualKeyword
- virtual keywordWeeksKeyword
- weeks keywordWeiKeyword
- wei keywordWhileKeyword
- while keywordYearsKeyword
- years keyword
Operators and Punctuation:
Ampersand
- & (bitwise AND)AmpersandAmpersand
- && (logical AND)AmpersandEqual
- &= (bitwise AND assignment)Asterisk
- * (multiplication)AsteriskAsterisk
- ** (exponentiation)AsteriskEqual
- *= (multiplication assignment)Bang
- ! (logical NOT)BangEqual
- != (not equal)Bar
- | (bitwise OR)BarBar
- || (logical OR)BarEqual
- |= (bitwise OR assignment)Caret
- ^ (bitwise XOR)CaretEqual
- ^= (bitwise XOR assignment)CloseBrace
- } (closing brace)CloseBracket
- ] (closing bracket)CloseParen
- ) (closing parenthesis)Colon
- : (colon)ColonEqual
- := (assignment in Yul)Comma
- , (comma)Equal
- = (assignment)EqualColon
- =: (Yul assignment)EqualEqual
- == (equality)EqualGreaterThan
- => (mapping arrow)GreaterThan
- > (greater than)GreaterThanEqual
- >= (greater than or equal)GreaterThanGreaterThan
- >> (right shift)GreaterThanGreaterThanEqual
- >>= (right shift assignment)GreaterThanGreaterThanGreaterThan
- >>> (unsigned right shift)GreaterThanGreaterThanGreaterThanEqual
- >>>= (unsigned right shift assignment)LessThan
- < (less than)LessThanEqual
- <= (less than or equal)LessThanLessThan
- << (left shift)LessThanLessThanEqual
- <<= (left shift assignment)Minus
- - (subtraction)MinusEqual
- -= (subtraction assignment)MinusGreaterThan
- -> (function return arrow)MinusMinus
- -- (decrement)OpenBrace
- { (opening brace)OpenBracket
- [ (opening bracket)OpenParen
- ( (opening parenthesis)Percent
- % (modulo)PercentEqual
- %= (modulo assignment)Period
- . (dot/member access)Plus
- + (addition)PlusEqual
- += (addition assignment)PlusPlus
- ++ (increment)QuestionMark
- ? (ternary operator)Semicolon
- ; (semicolon)Slash
- / (division)SlashEqual
- /= (division assignment)Tilde
- ~ (bitwise NOT)
Literals and Identifiers:
DecimalLiteral
- Decimal number literalsDoubleQuotedHexStringLiteral
- Double-quoted hex string literalsDoubleQuotedStringLiteral
- Double-quoted string literalsDoubleQuotedUnicodeStringLiteral
- Double-quoted unicode string literalsDoubleQuotedVersionLiteral
- Double-quoted version literalsHexLiteral
- Hexadecimal literalsIdentifier
- Identifiers (variable/function names)SingleQuotedHexStringLiteral
- Single-quoted hex string literalsSingleQuotedStringLiteral
- Single-quoted string literalsSingleQuotedUnicodeStringLiteral
- Single-quoted unicode string literalsSingleQuotedVersionLiteral
- Single-quoted version literalsVersionSpecifier
- Version specifier tokens
Comments and Whitespace:
EndOfLine
- End of line tokensMultiLineComment
- Multi-line commentsMultiLineNatSpecComment
- Multi-line NatSpec commentsSingleLineComment
- Single-line commentsSingleLineNatSpecComment
- Single-line NatSpec commentsWhitespace
- Whitespace tokens
Special Tokens:
Missing
- Missing tokens (for error recovery)Unrecognized
- Unrecognized tokens
Yul (Assembly) Keywords:
Complete set of Yul/assembly keywords with Yul
prefix:
All Solidity keywords in Yul (assembly) context:
YulAbstractKeyword
- abstract in YulYulAfterKeyword
- after in YulYulAliasKeyword
- alias in YulYulAnonymousKeyword
- anonymous in YulYulApplyKeyword
- apply in YulYulAsKeyword
- as in YulYulAssemblyKeyword
- assembly in YulYulAutoKeyword
- auto in YulYulBoolKeyword
- bool in YulYulBreakKeyword
- break in YulYulBytesKeyword
- bytes in YulYulCallDataKeyword
- calldata in YulYulCaseKeyword
- case in YulYulCatchKeyword
- catch in YulYulConstantKeyword
- constant in YulYulConstructorKeyword
- constructor in YulYulContinueKeyword
- continue in YulYulContractKeyword
- contract in YulYulCopyOfKeyword
- copyof in YulYulDaysKeyword
- days in YulYulDefaultKeyword
- default in YulYulDefineKeyword
- define in YulYulDeleteKeyword
- delete in YulYulDoKeyword
- do in YulYulElseKeyword
- else in YulYulEmitKeyword
- emit in YulYulEnumKeyword
- enum in YulYulEtherKeyword
- ether in YulYulEventKeyword
- event in YulYulExternalKeyword
- external in YulYulFallbackKeyword
- fallback in YulYulFalseKeyword
- false in YulYulFinalKeyword
- final in YulYulFinneyKeyword
- finney in YulYulFixedKeyword
- fixed in YulYulForKeyword
- for in YulYulFunctionKeyword
- function in YulYulGweiKeyword
- gwei in YulYulHexKeyword
- hex in YulYulHoursKeyword
- hours in YulYulIfKeyword
- if in YulYulImmutableKeyword
- immutable in YulYulImplementsKeyword
- implements in YulYulImportKeyword
- import in YulYulInKeyword
- in in YulYulIndexedKeyword
- indexed in YulYulInlineKeyword
- inline in YulYulIntKeyword
- int in YulYulInterfaceKeyword
- interface in YulYulInternalKeyword
- internal in YulYulIsKeyword
- is in YulYulLeaveKeyword
- leave in YulYulLetKeyword
- let in YulYulLibraryKeyword
- library in YulYulMacroKeyword
- macro in YulYulMappingKeyword
- mapping in YulYulMatchKeyword
- match in YulYulMemoryKeyword
- memory in YulYulMinutesKeyword
- minutes in YulYulModifierKeyword
- modifier in YulYulMutableKeyword
- mutable in YulYulNewKeyword
- new in YulYulNullKeyword
- null in YulYulOfKeyword
- of in YulYulOverrideKeyword
- override in YulYulPartialKeyword
- partial in YulYulPayableKeyword
- payable in YulYulPragmaKeyword
- pragma in YulYulPrivateKeyword
- private in YulYulPromiseKeyword
- promise in YulYulPublicKeyword
- public in YulYulPureKeyword
- pure in YulYulReceiveKeyword
- receive in YulYulReferenceKeyword
- reference in YulYulRelocatableKeyword
- relocatable in YulYulReturnsKeyword
- returns in YulYulSealedKeyword
- sealed in YulYulSecondsKeyword
- seconds in YulYulSizeOfKeyword
- sizeof in YulYulStaticKeyword
- static in YulYulStorageKeyword
- storage in YulYulStringKeyword
- string in YulYulStructKeyword
- struct in YulYulSuperKeyword
- super in YulYulSupportsKeyword
- supports in YulYulSwitchKeyword
- switch in YulYulSzaboKeyword
- szabo in YulYulThisKeyword
- this in YulYulThrowKeyword
- throw in YulYulTrueKeyword
- true in YulYulTryKeyword
- try in YulYulTypeDefKeyword
- typedef in YulYulTypeKeyword
- type in YulYulTypeOfKeyword
- typeof in YulYulUfixedKeyword
- ufixed in YulYulUintKeyword
- uint in YulYulUncheckedKeyword
- unchecked in YulYulUsingKeyword
- using in YulYulVarKeyword
- var in YulYulViewKeyword
- view in YulYulVirtualKeyword
- virtual in YulYulWeeksKeyword
- weeks in YulYulWeiKeyword
- wei in YulYulWhileKeyword
- while in YulYulYearsKeyword
- years in YulYulDecimalLiteral
- Decimal literals in YulYulHexLiteral
- Hex literals in YulYulIdentifier
- Identifiers in Yul context
Additional structural node types for specific language constructs:
Parameter and Argument Types:
Parameter
- Function parameterParameters
- Function parameter listParametersDeclaration
- Parameter declaration blockArgumentsDeclaration
- Arguments declaration blockNamedArgument
- Named function argumentNamedArgumentGroup
- Group of named argumentsNamedArguments
- Named argument listNamedArgumentsDeclaration
- Named arguments declarationPositionalArguments
- Positional argument listPositionalArgumentsDeclaration
- Positional arguments declaration
Member and Attribute Types:
ContractMember
- Single contract memberContractMembers
- Contract member listStructMember
- Single struct memberStructMembers
- Struct member listInterfaceMembers
- Interface member listLibraryMembers
- Library member listEnumMembers
- Enum member listConstructorAttribute
- Constructor attributeConstructorAttributes
- Constructor attribute listFunctionAttribute
- Function attributeFunctionAttributes
- Function attribute listStateVariableAttribute
- State variable attributeStateVariableAttributes
- State variable attribute listModifierAttribute
- Modifier attributeModifierAttributes
- Modifier attribute listFallbackFunctionAttribute
- Fallback function attributeFallbackFunctionAttributes
- Fallback function attribute listReceiveFunctionAttribute
- Receive function attributeReceiveFunctionAttributes
- Receive function attribute listUnnamedFunctionAttribute
- Unnamed function attributeUnnamedFunctionAttributes
- Unnamed function attribute listModifierInvocation
- Modifier invocation
Import and Using Types:
ImportClause
- Import clauseImportAlias
- Import aliasImportDeconstruction
- Import deconstructionImportDeconstructionSymbol
- Import deconstruction symbolImportDeconstructionSymbols
- Import deconstruction symbol listPathImport
- Path importNamedImport
- Named importUsingClause
- Using clauseUsingTarget
- Using targetUsingOperator
- Using operatorUsingAlias
- Using aliasUsingDeconstruction
- Using deconstructionUsingDeconstructionSymbol
- Using deconstruction symbolUsingDeconstructionSymbols
- Using deconstruction symbol list
Block and Statement Types:
Block
- Code blockUncheckedBlock
- Unchecked code blockFunctionBody
- Function bodyStatements
- Statement listElseBranch
- Else branchForStatementCondition
- For statement conditionForStatementInitialization
- For statement initialization
Error and Event Types:
ErrorParameter
- Error parameterErrorParameters
- Error parameter listErrorParametersDeclaration
- Error parameters declarationEventParameter
- Event parameterEventParameters
- Event parameter listEventParametersDeclaration
- Event parameters declarationCatchClause
- Catch clauseCatchClauseError
- Catch clause errorCatchClauses
- Catch clause list
Version and Pragma Types:
AbicoderPragma
- Abicoder pragmaExperimentalPragma
- Experimental pragmaExperimentalFeature
- Experimental featureVersionPragma
- Version pragma (mapped from Pragma)VersionRange
- Version rangeVersionTerm
- Version termVersionOperator
- Version operatorVersionExpressionSet
- Version expression setVersionExpressionSets
- Version expression sets
Type and Value Types:
MappingKey
- Mapping keyMappingValue
- Mapping valueArrayValues
- Array valuesTupleMember
- Tuple memberTupleValue
- Tuple valueTupleValues
- Tuple valuesTupleDeconstructionElement
- Tuple deconstruction elementTupleDeconstructionElements
- Tuple deconstruction elementsUntypedTupleMember
- Untyped tuple memberStateVariableDefinitionValue
- State variable definition valueVariableDeclarationValue
- Variable declaration value
Inheritance and Override Types:
InheritanceSpecifier
- Inheritance specifierContractSpecifier
- Contract specifierContractSpecifiers
- Contract specifier listOverrideSpecifier
- Override specifierOverridePaths
- Override pathsOverridePathsDeclaration
- Override paths declarationStorageLayoutSpecifier
- Storage layout specifierStorageLocation
- Storage location
Assembly and Other Types:
AssemblyFlags
- Assembly flagsAssemblyFlagsDeclaration
- Assembly flags declarationCallOptions
- Call optionsIndexAccessEnd
- Index access endReturnsDeclaration
- Returns declarationSourceUnitMember
- Source unit memberSourceUnitMembers
- Source unit membersFunctionName
- Function name
Yul (Assembly) Specific Types:
YulArguments
- Yul argumentsYulAssignmentOperator
- Yul assignment operatorYulBlock
- Yul blockYulColonAndEqual
- Yul colon and equal (:=)YulDefaultCase
- Yul default caseYulEqualAndColon
- Yul equal and colon (=:)YulLabel
- Yul labelYulParameters
- Yul parametersYulParametersDeclaration
- Yul parameters declarationYulPath
- Yul pathYulPaths
- Yul pathsYulReturnsDeclaration
- Yul returns declarationYulStackAssignmentOperator
- Yul stack assignment operatorYulStatements
- Yul statementsYulSwitchCase
- Yul switch caseYulSwitchCases
- Yul switch casesYulValueCase
- Yul value caseYulVariableDeclarationValue
- Yul variable declaration valueYulVariableNames
- Yul variable names
A query is a pattern that matches a certain set of nodes in a tree. The expression to match a given node consists of a pair of brackets ([]) containing two things: the node's kind, and optionally, a series of other patterns that match the node's children. For example, this pattern would match any MultiplicativeExpression node that has two children Expression nodes, with an Asterisk node in between:
[MultiplicativeExpression
[Expression]
[Asterisk]
[Expression]
]
The children of a node can optionally be labeled. The label is a property of the edge from the node to the child, and is not a property of the child. For example, this pattern will match a MultiplicativeExpression node with the two Expression children labeled left_operand and right_operand:
[MultiplicativeExpression
left_operand: [Expression]
[Asterisk]
right_operand: [Expression]
]
You can also match a node's textual content using a string literal. For example, this pattern would match a MultiplicativeExpression with a * operator (for clarity):
[MultiplicativeExpression
left_operand: [_]
operator: ["*"]
right_operand: [_]
]
If you don't care about the kind of a node, you can use an underscore _, which matches any kind. For example, this pattern will match a MultiplicativeExpression node with any two children with any kind, as long as one of them is labeled left_operand:
[MultiplicativeExpression
left_operand: [_]
[_]
]
Children can be elided. For example, this would produce multiple matches for a MultiplicativeExpression where at least one of the children is an expression of a StringExpression variant, where each match is associated with each of the StringExpression children:
[MultiplicativeExpression
[Expression
[StringExpression]
]
]
Trivia nodes (whitespace, comments, etc.) will be skipped over when running a query. Furthermore, trivia nodes cannot be explicitly (or implicitly with _) matched by queries.
Capturing# When matching patterns, you may want to process specific nodes within the pattern. Captures allow you to associate names with specific nodes in a pattern, so that you can later refer to those nodes by those names. Capture names are written before the nodes that they refer to, and start with an @ character.
For example, this pattern would match any struct definition and it would associate the name struct_name with the identifier:
[StructDefinition
@struct_name name: [Identifier]
]
And this pattern would match all event definitions for a contract, associating the name event_name with the event name, contract_name with the containing contract name:
[ContractDefinition
@contract_name name: [Identifier]
members: [ContractMembers
[ContractMember
[EventDefinition
@event_name name: [Identifier]
]
]
]
]
Quantification# You can surround a sequence of patterns in parenthesis (()), followed by a ?, _ or + operator. The ? operator matches zero or one repetitions of a pattern, the _ operator matches zero or more, and the + operator matches one or more.
For example, this pattern would match a sequence of one or more import directives at the top of the file:
[SourceUnit
members: [
_
([_ @import [ImportDirective]])+
]
]
This pattern would match a structure definition with one or more members, capturing their names:
[StructDefinition
@name name: [_]
members: [
_
([_ @member [Identifier]])+
]
]
This pattern would match all function calls, capturing a string argument if one was present:
[FunctionCallExpression
arguments: [ArgumentsDeclaration
variant: [PositionalArgumentsDeclaration
arguments: [PositionalArguments
(@arg [Expression variant: [StringExpression]])?
]
]
]
]
Alternation# An alternation is written as a sequence of patterns separated by | and surrounded by parentheses.
For example, this pattern would match a call to either a variable or an object property. In the case of a variable, capture it as @function, and in the case of a property, capture it as @method:
[FunctionCallExpression
operand: [Expression
(
@function variant: [Identifier]
| @method variant: [MemberAccessExpression]
)
]
]
This pattern would match a set of possible keyword terminals, capturing them as @keyword:
@keyword (
["break"]
| ["delete"]
| ["else"]
| ["for"]
| ["function"]
| ["if"]
| ["return"]
| ["try"]
| ["while"]
)
Adjacency# By using the adjacency operator . you can constrain a pattern to only match the first or the last child nodes.
For example, the following pattern would match only the first parameter declaration in a function definition:
[FunctionDefinition
[ParametersDeclaration
[Parameters
.
@first_param [Parameter]
]
]
]
And conversely the following will match only the last parameter:
[FunctionDefinition
[ParametersDeclaration
[Parameters
@last_param [Parameter]
.
]
]
]
If the adjacency operator is used in between two patterns it constrains matches on both patterns to occur consecutively, ie. without any other sibling node in between. For example, this pattern matches pairs of consecutive statements:
[Statements
@stmt1 [Statement]
.
@stmt2 [Statement]
]
// Match any function definition
Query.create(`[FunctionDefinition]`);
// Match any function call
Query.create(`[FunctionCallExpression]`);
// Match function calls with member access
Query.create(`
[FunctionCallExpression
[MemberAccessExpression]
]
`);
// Match assignment expressions
Query.create(`
[AssignmentExpression
[Identifier]
[Expression]
]
`);
// Match binary expressions with labeled operands
Query.create(`
[BinaryExpression
left_operand: [Expression]
operator: [_]
right_operand: [Expression]
]
`);
// Match specific function calls
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["transfer"]
]
]
`);
// Match any expression with any children
Query.create(`
[Expression
[_]
]
`);
import { Query } from '@nomicfoundation/slang/cst';
const query = Query.create(`[FunctionDefinition]`);
// Single query
const matches = cursor.query([query]);
// Multiple queries
const queries = [
Query.create(`[FunctionDefinition]`),
Query.create(`[ContractDefinition]`),
];
const matches = cursor.query(queries);
for (const match of matches) {
const cursor = match.root;
const nodeText = cursor.node.unparse();
const location = cursor.textRange;
console.log(`Found match: ${nodeText}`);
console.log(`Location: Line ${location.start.line}`);
}
// Low-level calls
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["call"]
]
]
`);
// Delegate calls
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["delegatecall"]
]
]
`);
// Transfer calls
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["transfer"]
]
]
`);
// Assignment expressions
Query.create(`[AssignmentExpression]`);
// State variable modifications
Query.create(`
[AssignmentExpression
[IndexAccessExpression]
[_]
]
`);
// Require statements
Query.create(`
[FunctionCallExpression
[Identifier "require"]
]
`);
// Modifier usage
Query.create(`
[ModifierInvocation]
`);
// Block timestamp usage
Query.create(`
[MemberAccessExpression
[Identifier "block"]
["timestamp"]
]
`);
// Block number usage
Query.create(`
[MemberAccessExpression
[Identifier "block"]
["number"]
]
`);
// Payable functions (look for payable keyword in function attributes)
Query.create(`
[FunctionDefinition
[FunctionAttributes
[FunctionAttribute
[_]
]
]
]
`);
// Receive functions
Query.create(`[ReceiveFunctionDefinition]`);
// Fallback functions
Query.create(`[FallbackFunctionDefinition]`);
// Constructor definitions
Query.create(`[ConstructorDefinition]`);
// Try statements
Query.create(`[TryStatement]`);
// Revert statements
Query.create(`[RevertStatement]`);
// Custom errors
Query.create(`
[RevertStatement
[FunctionCallExpression
[Identifier]
]
]
`);
// Event emissions
Query.create(`[EmitStatement]`);
// Specific event emissions
Query.create(`
[EmitStatement
[FunctionCallExpression
[Identifier "Transfer"]
]
]
`);
// Addition/Subtraction
Query.create(`[AdditiveExpression]`);
// Multiplication/Division
Query.create(`[MultiplicativeExpression]`);
// Exponentiation
Query.create(`[ExponentiationExpression]`);
// All arithmetic operations
const arithmeticQueries = [
Query.create(`[AdditiveExpression]`),
Query.create(`[MultiplicativeExpression]`),
Query.create(`[ExponentiationExpression]`),
];
import { Query } from '@nomicfoundation/slang/cst';
const functionCallQuery = Query.create(`[FunctionCallExpression]`);
const matches = cursor.query([functionCallQuery]);
for (const match of matches) {
console.log('Function call:', match.root.node.unparse());
}
const etherTransferQuery = Query.create(`
[CallOptionsExpression
[NamedArgument
[Identifier "value"]
[_]
]
]
`);
const matches = cursor.query([etherTransferQuery]);
for (const match of matches) {
console.log('Ether transfer found:', match.root.node.unparse());
}
const unsafeArithmeticQueries = [
Query.create(`[AdditiveExpression]`),
Query.create(`[MultiplicativeExpression]`),
Query.create(`[ExponentiationExpression]`),
];
const matches = cursor.query(unsafeArithmeticQueries);
for (const match of matches) {
// Check if it's inside an unchecked block
const text = match.root.node.unparse();
console.log('Arithmetic operation:', text);
}
const accessControlQuery = Query.create(`
[FunctionCallExpression
[Identifier "require"]
[_]
]
`);
const matches = cursor.query([accessControlQuery]);
for (const match of matches) {
const requireCall = match.root.node.unparse();
if (requireCall.includes('msg.sender') && requireCall.includes('owner')) {
console.log('Access control found:', requireCall);
}
}
const tokenTransferQueries = [
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["transfer"]
]
]
`),
Query.create(`
[FunctionCallExpression
[MemberAccessExpression
[_]
["transferFrom"]
]
]
`),
];
const matches = cursor.query(tokenTransferQueries);
for (const match of matches) {
console.log('Token transfer:', match.root.node.unparse());
}
Instead of using wildcards everywhere, be specific about the node types you're looking for:
// Good
Query.create(`[FunctionCallExpression]`);
// Less efficient
Query.create(`[_]`);
When looking for different patterns, combine them in a single query execution:
const queries = [
Query.create(`[FunctionCallExpression]`),
Query.create(`[AssignmentExpression]`),
Query.create(`[EmitStatement]`),
];
const matches = cursor.query(queries);
When matching complex patterns, use labels to make your queries more readable:
Query.create(`
[FunctionCallExpression
function: [MemberAccessExpression
object: [Identifier]
member: ["transfer"]
]
arguments: [ArgumentList
[_]
[_]
]
]
`);
Always wrap query creation in try-catch blocks:
try {
const query = Query.create(`[FunctionCallExpression]`);
const matches = cursor.query([query]);
} catch (error) {
console.error('Query error:', error.message);
}
- Use the most specific node types possible
- Avoid deep nesting when not necessary
- Batch multiple queries together
- Consider the scope of your search (use
cursor.spawn()
for subtrees)
Test your queries with simple examples before using them on large codebases:
// Test with a simple contract first
const testSource = `
contract Test {
function transfer(address to, uint amount) public {
// test code
}
}
`;
- Invalid Node Kind: Using a non-existent node type
- Syntax Errors: Malformed query syntax
- Nesting Errors: Incorrect child-parent relationships
// This will throw an error - invalid node kind
try {
Query.create(`[NonExistentNode]`);
} catch (error) {
console.log(error.message); // 'NonExistentNode' is not a valid node kind
}
// This will throw an error - syntax error
try {
Query.create(`[FunctionDefinition`); // Missing closing bracket
} catch (error) {
console.log(error.message); // Parse error
}
This documentation covers all 653 components available in Slang v1.2.0:
Category | Count | Description |
---|---|---|
Definitions | 17 | Contract, function, struct, enum, etc. definitions |
Statements | 26 | Control flow, declarations, Yul statements |
Expressions | 17 | Function calls, assignments, arithmetic, etc. |
Logical/Bitwise Expressions | 8 | Boolean and bitwise operations |
Primary Expressions/Literals | 16 | Identifiers, literals, arrays, tuples |
Types | 13 | Type specifications and declarations |
Abstract Node Types | 3 | Base types for broad matching |
Top-Level Constructs | 4 | File-level constructs |
Terminal Kinds | 296 | Keywords, operators, punctuation |
Edge Labels | 138 | Labels for parent-child relationships |
Other Node Types | 118 | Specialized structural nodes |
Total | 653 | Complete coverage of Slang AST |