# HCL Parser
adnv includes a custom HCL (HashiCorp Configuration Language) parser for analyzing Terraform files. This parser is purpose-built for dependency extraction, not for full HCL evaluation.
## Why a custom parser?
adnv needs to:
1. Extract `module`, `terraform`, and `required_providers` blocks
2. Parse inline hint comments (`# @adnv source ...`)
3. Track exact byte offsets for in-place updates
4. Continue parsing after errors (resilient parsing)
Standard HCL parsers don't support inline hint comments or partial error recovery.
## Parser architecture
```mermaid
graph LR
A[".tf file"] -->|pest grammar| B[Token pairs]
B -->|AST construction| C[HCL AST]
C -->|Query API| D[Blocks, Attributes, Hints]
```
### Layer 1: PEG Grammar (Pest)
The grammar (`hcl.pest`) defines HCL syntax rules. Pest generates a parser that produces token pairs with span information.
### Layer 2: AST Construction
Token pairs are transformed into typed AST nodes:
| `Body` | Root container (list of attributes and blocks) |
| `Block` | Named block with optional labels: `module "name" { ... }` |
| `Attribute` | Key-value pair: `version = "1.0.0"` |
| `Expression` | Value types: strings, objects, identifiers |
| `InlineHint` | Parsed `# @adnv source` comment |
### Layer 3: Query API
The AST provides methods for navigating and extracting data:
```
Body
├── find_blocks("module") → Iterator<Block>
├── get_block("terraform") → Option<Block>
├── get_attribute("version") → Option<Attribute>
└── get_attributes_with_inline_hints() → Vec<Attribute>
Block
├── id() → "module"
├── args() → ["vpc"]
└── body() → Body (nested)
Attribute
├── name() → "version"
├── expr() → Expression
└── hint() → Option<InlineHint>
```
## Inline hint parsing
Inline hints are special comments parsed by the HCL parser:
```hcl
# @adnv source "helm+https://example.com#name=chart" ">= 1.0.0"
chart_version = "1.2.0"
```
The parser:
1. Detects `# @adnv` prefix in comments
2. Extracts the source URL and optional version constraint
3. Associates the hint with the attribute on the next line
4. Reports errors for malformed hints without stopping the parse
## Error resilience
The parser collects errors and continues:
```rust
let (hcl, errors) = hcl::parse(input)?;
// hcl contains all successfully parsed content
// errors contains issues found during parsing
```
This allows adnv to process files with minor syntax issues or unsupported HCL features.
## Span tracking
Every AST node carries byte-offset spans from the original source. This enables the `update` command to perform surgical text replacements without re-serializing the entire file, preserving comments, formatting, and whitespace.