adnv 1.5.0

CLI that tracks, checks and auto-updates infrastructure dependency versions across Terraform, Helm, Docker, Git and npm
Documentation
// HCL spec (https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md)

// The top-level scope of an HCL file
Hcl = _{ SOI ~ Body ~ EOI }

// Structural elements
Body      = { (Attribute | AttributeError | Block)* }
Attribute = { InlineHint? ~ Identifier ~ "=" ~ Expression }
AttributeError = { InlineHint{2,} ~ Identifier ~ "=" ~ Expression }
Block     = { Identifier ~ (StringLit | Identifier)* ~ BlockBody }
BlockBody = { "{" ~ Body ~ "}" }

// Expressions
Expression = {
    UnaryOperator? ~
    ExprTerm ~
    (BinaryOperator ~ Expression)? ~
    ("?" ~ Expression ~ ":" ~ Expression)?
}
ExprTerm = {
    (Value | TemplateExpr | FunctionCall | Variable | ForExpr | Parenthesis) ~
    (Splat | GetAttr | Index)*
}
Parenthesis = { "(" ~ Expression ~ ")" }

// Values
Value = _{ LiteralValue | CollectionValue }

// Literal values
LiteralValue = _{ StringLit | NumericLit | BooleanLit | NullLit }

// Identifiers
Identifier     = @{ IdentFirstChar ~ IdentChar* }
IdentChar      = _{ Letter | Decimal | "-" | "_" }
IdentFirstChar = _{ Letter | "_" }
Letter         = _{ 'a'..'z' | 'A'..'Z' }

// Booleans
BooleanLit = @{ Boolean ~ !Identifier }
Boolean    =  { "true" | "false" }

// Null
NullLit = @{ Null ~ !Identifier }
Null    =  { "null" }

// Numeric literals
NumericLit = _{ Float | Int }
Float      = @{ Decimal+ ~ (("." ~ Decimal+ ~ (ExpMark ~ Decimal+)?) | (ExpMark ~ Decimal+)) }
Int        = @{ Decimal+ }
ExpMark    =  { ("e" | "E") ~ ("+" | "-")? }
Decimal    =  { '0'..'9' }

// Collection values
CollectionValue = _{ Tuple | Object }
Tuple           =  { "[" ~ (Expression ~ ("," ~ Expression)* ~ ","?)? ~ "]" }
Object          =  { "{" ~ (ObjectItem ~ (","? ~ ObjectItem)* ~ ","?)? ~ "}" }
ObjectItem      = _{ ObjectItemIdent | ObjectItemExpr }
ObjectItemIdent = _{ Identifier ~ ("=" | ":") ~ Expression }
ObjectItemExpr  = _{ Expression ~ ("=" | ":") ~ Expression }

// Template expressions
TemplateExpr = { QuotedStringTemplate | Heredoc }

// Heredoc templates
Heredoc = ${
    HeredocIntro ~ PUSH(Identifier) ~ NEWLINE ~
    HeredocTemplate ~ NEWLINE ~
    SpaceOrTab* ~ POP
}
HeredocIntro       = _{ HeredocIntroIndent | HeredocIntroNormal }
HeredocIntroIndent =  { "<<-" }
HeredocIntroNormal =  { "<<" }

HeredocTemplate = ${
    (HeredocLiteral | TemplateInterpolation | TemplateDirective)*
}
HeredocLiteral    = @{ HeredocStringPart+ }
HeredocStringPart =  {
    "$${"
    | "%%{"
    | !("${" | "%{" | (NEWLINE ~ SpaceOrTab* ~ PEEK)) ~ ANY
}

// Quoted string templates
QuotedStringTemplate      = ${ "\"" ~ QuotedStringTemplateInner ~ "\"" }
QuotedStringTemplateInner = ${
    (QuotedStringTemplateLiteral | TemplateInterpolation | TemplateDirective)*
}
QuotedStringTemplateLiteral = @{ StringPart+ }

// String literals
StringLit  = ${ "\"" ~ String ~ "\"" }
String     = @{ StringPart* }
StringPart =  {
    "$${"
    | "%%{"
    | !("\"" | "\\" | "${" | "%{") ~ ANY
    | "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
    | "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}

// Functions and function calls
FunctionCall = { Identifier ~ Arguments }
Arguments    = { "(" ~ (Expression ~ ("," ~ Expression)* ~ ("," | ExpandFinal)?)? ~ ")" }
ExpandFinal  = { "..." }

// For expressions
ForExpr       = { ForTupleExpr | ForObjectExpr }
ForTupleExpr  = { "[" ~ ForIntro ~ Expression ~ ForCond? ~ "]" }
ForObjectExpr = { "{" ~ ForIntro ~ Expression ~ "=>" ~ Expression ~ ValueGrouping? ~ ForCond? ~ "}" }
ForIntro      = { "for" ~ Identifier ~ ("," ~ Identifier)? ~ "in" ~ Expression ~ ":" }
ForCond       = { "if" ~ Expression }
ValueGrouping = { "..." }

// Variables
Variable = @{ Identifier }

// Index operator
Index       =  { ("[" ~ Expression ~ "]") | LegacyIndex }
LegacyIndex = ${ "." ~ Int }

// Attribute access operator
GetAttr = ${ "." ~ Identifier }

// Splat operators
Splat     = _{ (AttrSplat ~ GetAttr*) | (FullSplat ~ (GetAttr | Index)*) }
AttrSplat =  { ".*" }
FullSplat =  { "[*]" }

// Unary and binary operators
UnaryOperator      = { "-" | "!" }
BinaryOperator     = { CompareOperator | ArithmeticOperator | LogicOperator }
CompareOperator    = { "==" | "!=" | "<=" | ">=" | "<" | ">" }
ArithmeticOperator = { "+" | "-" | "*" | "/" | "%" }
LogicOperator      = { "&&" | "||" }

// Comments
COMMENT         = _{ InlineComment | BlockComment }
InlineComment   = _{ ("#" | "//") ~ !(SpaceOrTab* ~ "@adnv") ~ (!EoInlineComment ~ ANY)* }
BlockComment    = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
EoInlineComment = _{ NEWLINE | EOI }

InlineHint       = ${ ("#" | "//") ~ SpaceOrTab* ~ "@adnv" ~ SpaceOrTab+ ~ (SourceInlineHint | InlineHintError) ~ SpaceOrTab* ~ NEWLINE }
SourceInlineHint = ${ "source" ~ SpaceOrTab+ ~ StringLit ~ SpaceOrTab+ ~ StringLit }
InlineHintError  = ${ (!NEWLINE ~ ANY)* }

// Whitespace
WHITESPACE = _{ SpaceOrTab | NEWLINE }
SpaceOrTab = _{ " " | "\t" }

// Top-level rule for the template sub-language
HclTemplate = ${ SOI ~ Template ~ EOI }

Template              = ${ (TemplateLiteral | TemplateInterpolation | TemplateDirective)* }
TemplateLiteral       = @{ ("$${" | "%%{" | (!("${" | "%{") ~ ANY))+ }
TemplateInterpolation = !{ TemplateIExprStart ~ Expression ~ TemplateExprEnd }
TemplateDirective     =  { TemplateIf | TemplateFor }

// Interpolation expression start
TemplateIExprStart       = _{ TemplateIExprStartStrip | TemplateIExprStartNormal }
TemplateIExprStartNormal =  { "${" }
TemplateIExprStartStrip  =  { "${~" }

// Directive expression start
TemplateDExprStart       = _{ TemplateDExprStartStrip | TemplateDExprStartNormal }
TemplateDExprStartNormal =  { "%{" }
TemplateDExprStartStrip  =  { "%{~" }

// Interpolation or directive expression end
TemplateExprEnd       = _{ TemplateExprEndNormal | TemplateExprEndStrip }
TemplateExprEndNormal =  { "}" }
TemplateExprEndStrip  =  { "~}" }

// If directive
TemplateIf        = ${ TemplateIfExpr ~ Template ~ (TemplateElseExpr ~ Template)? ~ TemplateEndIfExpr }
TemplateIfExpr    = !{ TemplateDExprStart ~ "if" ~ Expression ~ TemplateExprEnd }
TemplateElseExpr  = !{ TemplateDExprStart ~ "else" ~ TemplateExprEnd }
TemplateEndIfExpr = !{ TemplateDExprStart ~ "endif" ~ TemplateExprEnd }

// For directive
TemplateFor        = ${ TemplateForExpr ~ Template ~ TemplateEndForExpr }
TemplateForExpr    = !{ TemplateDExprStart ~ "for" ~ Identifier ~ ("," ~ Identifier)? ~ "in" ~ Expression ~ TemplateExprEnd }
TemplateEndForExpr = !{ TemplateDExprStart ~ "endfor" ~ TemplateExprEnd }