Documentation
¶
Overview ¶
Package ast defines the Abstract Syntax Tree node types for CalcMark
Index ¶
- func ContainsScaleRef(node Node) bool
- type AsPercentOf
- type Assignment
- type BetweenExpr
- type BinaryOp
- type BooleanLiteral
- type ComparisonOp
- type CurrencyLiteral
- type DateLiteral
- type DirectiveRef
- type DurationLiteral
- type EndOfExpr
- type Expression
- type FractionLiteral
- type FunctionCall
- type Identifier
- type LengthOfExpr
- type NapkinConversion
- type Node
- type NumberLiteral
- type PercentageOf
- type Position
- type PreciseConversion
- type QuantityLiteral
- type Range
- type RateLiteral
- type RelativeDateLiteral
- type StartOfExpr
- type TimeLiteral
- type UTCOffset
- type UnaryOp
- type UnitConversion
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ContainsScaleRef ¶
ContainsScaleRef returns true if the AST node tree contains a DirectiveRef with Directive=="scale". Used by the scale transform to exempt statements that explicitly reference @scale.
Types ¶
type AsPercentOf ¶
type AsPercentOf struct {
Numerator Node // The value to express as a percentage
Denominator Node // The reference value (the "whole")
Range *Range
}
AsPercentOf represents "X as % of Y" — computes the ratio X/Y as a Percentage. This is the inverse of PercentageOf: "20% of 500" = 100, "100 as % of 500" = 20%.
func (*AsPercentOf) GetRange ¶
func (a *AsPercentOf) GetRange() *Range
func (*AsPercentOf) String ¶
func (a *AsPercentOf) String() string
type Assignment ¶
Assignment represents a variable assignment
func (*Assignment) GetRange ¶
func (a *Assignment) GetRange() *Range
func (*Assignment) String ¶
func (a *Assignment) String() string
type BetweenExpr ¶
type BetweenExpr struct {
// Start is the period's first day; End is its last (closed
// interval, day precision -- mirrors *types.Period).
Start Node
End Node
// SourceText is the original source slice for diagnostics +
// AST round-tripping.
SourceText string
Range *Range
}
BetweenExpr represents `between A and B` / `from A to B` -- a user-defined custom Period spanning two Date endpoints. Both endpoints are generic Node so any expression typing as Date is well-formed at the AST layer; semantic check (spec/semantic) is where Date typing + start <= end constraints are enforced. The runtime constructs a *types.Period (PeriodCustom kind) from the evaluated endpoints.
func (*BetweenExpr) GetRange ¶
func (b *BetweenExpr) GetRange() *Range
func (*BetweenExpr) String ¶
func (b *BetweenExpr) String() string
type BooleanLiteral ¶
BooleanLiteral represents a boolean literal
func (*BooleanLiteral) GetRange ¶
func (b *BooleanLiteral) GetRange() *Range
func (*BooleanLiteral) String ¶
func (b *BooleanLiteral) String() string
type ComparisonOp ¶
type ComparisonOp struct {
Operator string // ">", "<", ">=", "<=", "==", "!="
Left Node
Right Node
Range *Range
}
ComparisonOp represents a comparison operation (>, <, ==, etc.)
func (*ComparisonOp) GetRange ¶
func (c *ComparisonOp) GetRange() *Range
func (*ComparisonOp) String ¶
func (c *ComparisonOp) String() string
type CurrencyLiteral ¶
type CurrencyLiteral struct {
Symbol string // Currency symbol or code
Value string // Numeric value
SourceText string // Original text for debugging
Range *Range
}
CurrencyLiteral represents a currency value (e.g., "$100", "50 EUR").
func (*CurrencyLiteral) GetRange ¶
func (c *CurrencyLiteral) GetRange() *Range
func (*CurrencyLiteral) String ¶
func (c *CurrencyLiteral) String() string
type DateLiteral ¶
type DateLiteral struct {
Month string // "Dec", "December"
Day string // "25" — the literal day. When the user wrote no
// day number in source, Day is "1" (lexer default) AND
// HasExplicitDay is false.
Year *string // nil if not provided, "2024" if provided
// HasExplicitDay reports whether a day number was scanned from
// the source. Discriminates `April 1` (true: specific date) from
// `April` (false: bare month, semantically a Period). The parser
// uses this flag to route bare-month forms to RelativeDateLiteral
// instead of DateLiteral. Lexer-driven so the discriminator
// doesn't depend on substring inspection of SourceText (which
// drifts with whitespace / future lexer changes).
HasExplicitDay bool
SourceText string
Range *Range
}
DateLiteral represents a date literal: "Dec 25" or "Dec 25 2024"
func (*DateLiteral) GetRange ¶
func (d *DateLiteral) GetRange() *Range
func (*DateLiteral) String ¶
func (d *DateLiteral) String() string
type DirectiveRef ¶
type DirectiveRef struct {
Directive string // "scale" or "globals" (or any identifier — semantic checker validates)
Field string // "" for @scale, "tax_rate" for @globals.tax_rate
Range *Range
}
DirectiveRef represents a reference to a frontmatter directive (@scale, @globals.name).
func (*DirectiveRef) GetRange ¶
func (d *DirectiveRef) GetRange() *Range
func (*DirectiveRef) String ¶
func (d *DirectiveRef) String() string
type DurationLiteral ¶
type DurationLiteral struct {
Value string // Numeric value ("5", "3.5", etc.)
Unit string // Time unit ("days", "hours", "minutes", etc.)
SourceText string // Original text from source
Range *Range
}
DurationLiteral represents a duration literal: "5 days", "3 hours"
func (*DurationLiteral) GetRange ¶
func (d *DurationLiteral) GetRange() *Range
func (*DurationLiteral) String ¶
func (d *DurationLiteral) String() string
type EndOfExpr ¶
type EndOfExpr struct {
// Period is the inner expression. Must type as Period at semantic
// check time; runtime panics if non-Period flows through. Parser
// uses parsePrimary() so precedence is preserved
// (`end of Q1 + 1 day` parses as `(end of Q1) + 1 day`).
Period Node
// SourceText is the original source slice ("end of Q1") for
// diagnostics + AST round-tripping.
SourceText string
Range *Range
}
EndOfExpr represents `end of <period>` -- the operator that resolves a Period-typed inner expression to its last day. The inner is a generic Node so any expression that types as Period (literal, identifier-bound period, parenthesized period expression) parses uniformly. Type-check enforcement of "must be a Period" lives in spec/semantic; at the AST layer the constraint is unenforced -- a NumberLiteral here is well-formed but semantically rejected.
Replaces the previous string-flatten in spec/parser/primary.go which produced ast.RelativeDateLiteral{Keyword: "end of " + innerKeyword} -- losing the inner's structure, bounding the inner-token set to an enumeration, and forcing string-prefix dispatch in the interpreter.
type Expression ¶
Expression represents a standalone expression (no assignment)
func (*Expression) GetRange ¶
func (e *Expression) GetRange() *Range
func (*Expression) String ¶
func (e *Expression) String() string
type FractionLiteral ¶
type FractionLiteral struct {
Numerator int64 // The numerator value
Denominator int64 // The denominator value
Unit string // Optional unit (e.g., "cup" for "1/3 cup"), empty if dimensionless
SourceText string // Original text from source (e.g., "1/3")
Range *Range
}
FractionLiteral represents a fraction literal (e.g., "1/3", "7/8", "1/3 cup"). Numerator and Denominator are stored as int64, parsed once at parse time.
func (*FractionLiteral) GetRange ¶
func (f *FractionLiteral) GetRange() *Range
func (*FractionLiteral) String ¶
func (f *FractionLiteral) String() string
type FunctionCall ¶
type FunctionCall struct {
Name string // Canonical function name: "avg", "sqrt"
Arguments []Node
Range *Range
}
FunctionCall represents a function call (avg, sqrt, etc.)
func (*FunctionCall) GetRange ¶
func (f *FunctionCall) GetRange() *Range
func (*FunctionCall) String ¶
func (f *FunctionCall) String() string
type Identifier ¶
Identifier represents a variable identifier
func (*Identifier) GetRange ¶
func (i *Identifier) GetRange() *Range
func (*Identifier) String ¶
func (i *Identifier) String() string
type LengthOfExpr ¶
type LengthOfExpr struct {
// Period is the inner expression. Must type as Period at
// semantic check time. Parser uses parsePrimary() so precedence
// is preserved.
Period Node
// AsNumber discriminates the surface form: false = `length of`
// (returns Duration); true = `days in` (returns Number, integer
// day count).
AsNumber bool
// SourceText is the original source slice.
SourceText string
Range *Range
}
LengthOfExpr represents `length of <Period>` (returns Duration) and `days in <Period>` (returns Number). Both forms desugar to the same node; AsNumber discriminates the return shape.
AST layer doesn't enforce that Period types as Period -- semantic (spec/semantic) does. Period field is generic Node so any expression typing as Period (literal, variable-bound, parenthesized) parses uniformly.
func (*LengthOfExpr) GetRange ¶
func (l *LengthOfExpr) GetRange() *Range
func (*LengthOfExpr) String ¶
func (l *LengthOfExpr) String() string
type NapkinConversion ¶
NapkinConversion represents human-readable number formatting (e.g., "1234567 as napkin").
func (*NapkinConversion) GetRange ¶
func (n *NapkinConversion) GetRange() *Range
func (*NapkinConversion) String ¶
func (n *NapkinConversion) String() string
type NumberLiteral ¶
type NumberLiteral struct {
Value string // Normalized value (e.g., "1000" for both "1000" and "1,000")
SourceText string // Original text from source (e.g., "1,000", "1k", "10000")
Range *Range
}
NumberLiteral represents a numeric literal
func (*NumberLiteral) GetRange ¶
func (n *NumberLiteral) GetRange() *Range
func (*NumberLiteral) String ¶
func (n *NumberLiteral) String() string
type PercentageOf ¶
type PercentageOf struct {
Percentage Node // The percentage value (e.g., NumberLiteral for "10%")
Value Node // The value to take percentage of
Range *Range
}
PercentageOf represents percentage of a value (e.g., "10% of 200").
func (*PercentageOf) GetRange ¶
func (p *PercentageOf) GetRange() *Range
func (*PercentageOf) String ¶
func (p *PercentageOf) String() string
type PreciseConversion ¶
PreciseConversion represents full-precision display (e.g., "1 second as hour as precise").
func (*PreciseConversion) GetRange ¶
func (n *PreciseConversion) GetRange() *Range
func (*PreciseConversion) String ¶
func (n *PreciseConversion) String() string
type QuantityLiteral ¶
type QuantityLiteral struct {
Value string // The numeric value (used when Expr is nil)
Expr Node // Expression providing the value (e.g., DirectiveRef); nil for literal quantities
Unit string // The unit identifier
SourceText string // Original text
Range *Range
}
QuantityLiteral represents a number with a unit (e.g., "5 kg", "10 meters"). When Expr is non-nil, the quantity value comes from evaluating the expression (e.g., "@scale meters" uses a DirectiveRef as the value source).
func (*QuantityLiteral) GetRange ¶
func (q *QuantityLiteral) GetRange() *Range
func (*QuantityLiteral) String ¶
func (q *QuantityLiteral) String() string
type Range ¶
Range represents a range in source text
type RateLiteral ¶
type RateLiteral struct {
Amount Node // The quantity numerator (e.g., QuantityLiteral for "100 MB")
PerUnit string // The time unit denominator (e.g., "second", "hour", "day")
SourceText string //Original text
Range *Range
}
RateLiteral represents a rate expression (e.g., "100 MB/s", "5 GB per day", "$0.10 per hour"). Rates combine a quantity (amount) with a time period.
func (*RateLiteral) GetRange ¶
func (r *RateLiteral) GetRange() *Range
func (*RateLiteral) String ¶
func (r *RateLiteral) String() string
type RelativeDateLiteral ¶
type RelativeDateLiteral struct {
Keyword string // "today", "tomorrow", "yesterday", "now"
SourceText string
Range *Range
}
RelativeDateLiteral represents relative date keywords: today, tomorrow, yesterday, now
func (*RelativeDateLiteral) GetRange ¶
func (r *RelativeDateLiteral) GetRange() *Range
func (*RelativeDateLiteral) String ¶
func (r *RelativeDateLiteral) String() string
type StartOfExpr ¶
StartOfExpr is the symmetric partner of EndOfExpr -- resolves a Period to its first day. Parser-level identical to EndOfExpr; interpreter just returns Period.Start unchanged. Useful in expressions where intent matters (e.g. `forecast = start of next fiscal quarter` reads better than the implicit `next fiscal quarter` even though they evaluate the same).
func (*StartOfExpr) GetRange ¶
func (s *StartOfExpr) GetRange() *Range
func (*StartOfExpr) String ¶
func (s *StartOfExpr) String() string
type TimeLiteral ¶
type TimeLiteral struct {
Hour string // "10", "14"
Minute string // "30"
Second *string // nil or "45"
Period *string // nil, "AM", or "PM"
UTCOffset *UTCOffset // nil or offset spec
SourceText string
Range *Range
}
TimeLiteral represents a time literal: "10:30AM", "14:30", "10:30:45PM", "10:30AM UTC-7"
func (*TimeLiteral) GetRange ¶
func (t *TimeLiteral) GetRange() *Range
func (*TimeLiteral) String ¶
func (t *TimeLiteral) String() string
type UTCOffset ¶
type UTCOffset struct {
Sign string // "+" or "-"
Hours string // "7", "5"
Minutes *string // nil or "30" (for UTC+5:30)
}
UTCOffset represents a UTC timezone offset: UTC-7, UTC+5:30
type UnitConversion ¶
type UnitConversion struct {
Quantity Node // The quantity expression to convert
TargetUnit string // The target unit to convert to
TargetTimeUnit string // For rate conversions: the target time unit (e.g., "s" in "inch/s")
Range *Range
}
UnitConversion represents explicit unit conversion (e.g., "10 meters in feet"). For rate conversions (e.g., "10 m/s in inch/s"), TargetTimeUnit is set.
func (*UnitConversion) GetRange ¶
func (u *UnitConversion) GetRange() *Range
func (*UnitConversion) String ¶
func (u *UnitConversion) String() string