Askl Syntax Reference
Askl is a pattern-matching query language designed for source code analysis. It allows you to find functions, trace dependencies, and build custom views of your codebase.
Overview
An Askl query consists of statements that select and filter code symbols (functions, methods, etc.) and define relationships between them through scopes.
Basic Structure
statement1;
statement2 {
nested_statement
}
Core Concepts
1. Statements
A statement is the fundamental unit of an Askl query. Each statement contains:
- Commands: One or more verbs that define what to select or filter
- Scope: Optional nested statements that define relationships
Statement Separation
Use semicolons to separate consecutive statements:
"foo"; # First statement
"bar" # Second statement (semicolon optional at end)
Without semicolons, verbs belong to the same statement:
"foo" "bar" # Single statement with two selector verbs
2. Scopes and Relationships
Scopes use {}
syntax to define parent-child relationships:
"parent_function" {
"child_function"
}
Important: Scopes only show results if the actual relationship exists in the code. If parent_function
doesn’t call child_function
, no results are displayed.
Scope Types
- Callee scope:
parent { child }
- shows what parent calls - Caller scope:
{ "parent" }
- shows what calls parent - Nested scopes:
a { b { c } }
- multi-level relationships
3. Pattern Matching
Askl uses exact, case-sensitive token matching on fully qualified names:
"cli.Run"
matches functions containing both “cli” and “Run” tokens"cli"
will NOT match “click” (exact matching)- Matching works on the complete package path + function name
Verbs
Verbs are commands that instruct the query engine what to do. They use the syntax:
@verb(positional_args, key=value)
Core Verbs
@select (Function Selection)
Selects symbols whose names match a specific pattern.
Full syntax:
@select(name="cli.Run")
Shortcut syntax:
"cli.Run"
Pattern matching rules:
- Exact, case-sensitive token matching
- Matches against fully qualified names (package.function)
- Must contain ALL specified tokens
Examples:
"main" # Functions containing "main"
"http.Handler" # Functions containing both "http" and "Handler"
"user.Create" # Functions containing both "user" and "Create"
@ignore (Symbol Filtering)
Excludes symbols matching a pattern from current and nested statements.
Syntax:
@ignore("pattern")
Examples:
@ignore("test") "main" {} # Ignore test functions
@ignore("builtin") @ignore("fmt") "process" {} # Multiple ignores
@preamble (Global Configuration)
Applies verbs to the global scope, affecting all subsequent statements.
Syntax:
@preamble
@ignore("builtin")
@ignore("test")
"main" # This and all following queries ignore builtin and test
Use cases:
- Global ignore patterns
- Session-wide configuration
- Reducing noise across all queries
@forced (Override Relationships)
Forces display of relationships that don’t exist in the actual code.
Syntax:
"parent" {
!"forced_child"
}
When to use:
- Function pointer calls not detected by analysis
- Complex runtime relationships
- Simplified architectural views
- Working around analysis limitations
Query Rules and Validation
Required Elements
Every global statement must contain at least one selection verb at some nesting level.
Valid examples:
"foo" {}; # Direct selection
{"foo"}; # Selection in scope
{{{"foo"}}} # Deeply nested selection
Invalid example:
{{{{}}}} # No selection anywhere
Statement Structure
# Multiple statements
"statement1";
"statement2" {
"nested"
};
"statement3"