Skip to content

Lexical Specification

This document defines the lexical structure of Ledger files: characters, tokens, whitespace, and comments.

Character Set

Encoding

Ledger files MUST be encoded in UTF-8.

file = UTF-8 encoded text
BOM  = optional (U+FEFF at start)

Line Endings

Ledger accepts: - LF (Unix): \n - CRLF (Windows): \r\n - CR (legacy Mac): \r

Implementations SHOULD normalize to LF internally.

Whitespace

Horizontal Whitespace

SPACE = U+0020
TAB   = U+0009

Significant Whitespace

Context Whitespace Role
Line start Indicates posting (must be indented)
Account/amount separator Two spaces minimum
Token separator Single space sufficient

Indentation

Postings MUST be indented:

2024/01/15 Transaction
    Expenses:Food    $50    ; Indented with spaces
    Assets:Checking        ; Indented with tab

Minimum: 1 space or 1 tab.

Comments

Line Comments

Three comment styles:

; Semicolon comment (most common)
# Hash comment
* Asterisk comment (org-mode compatible)

End-of-Line Comments

2024/01/15 Transaction  ; Header comment
    Expenses:Food    $50  ; Posting comment
    Assets:Checking

Block Comments

comment
This is a block comment.
Multiple lines are allowed.
Anything until 'end comment'.
end comment

Metadata Comments

Special comment syntax for metadata:

    Expenses:Food    $50
        ; Key: Value
        ; :tag1:tag2:

Dates

Primary Format

date = year "/" month "/" day
     | year "-" month "-" day
     | year "." month "." day

year  = digit digit digit digit
month = digit digit
day   = digit digit

Examples

2024/01/15    ; Slash (most common)
2024-01-15    ; Dash
2024.01.15    ; Dot

Effective Dates

2024/01/15=2024/01/20    ; Primary=Effective

Numbers

Integer

integer = ["-"] digit+

Decimal

decimal = ["-"] digit* "." digit+
        | ["-"] digit+ ["." digit*]

Thousands Separator

$1,234,567.89    ; Comma separator
1.234.567,89 EUR ; European style

Commodities

Symbol Commodities

symbol = "$" | "€" | "£" | "¥" | ...

Alphabetic Commodities

commodity = letter (letter | digit | "_" | "-" | "'")*

Quoted Commodities

quoted_commodity = '"' (non-quote-char | '\"')* '"'

Examples

$100            ; Symbol
100 USD         ; Alphabetic
100 "ACME Inc"  ; Quoted

Accounts

Account Name

account = segment (":" segment)*
segment = (letter | digit | " " | "-" | "_")+

Virtual Accounts

virtual_account          = "(" account ")"
balanced_virtual_account = "[" account "]"

Examples

Assets:Bank:Checking
Expenses:Food & Dining
(Budget:Food)
[Savings:Goal]

Strings

Payee/Narration

Unquoted text from after status/code to end of line or comment:

2024/01/15 This is the payee text  ; Comment

Quoted Strings

string = '"' (char | escape)* '"'
escape = "\\" | '\"' | "\n" | "\t"

Status Markers

status = "*" | "!"
Marker Meaning
(none) Unmarked
! Pending
* Cleared

Transaction Codes

code = "(" text ")"
2024/01/15 * (#1234) Check payment

Tags

Inline Tags

tag_list = ":" tag (":" tag)* ":"
tag      = (letter | digit | "-" | "_")+
; :personal:reimbursable:

Metadata Tags

metadata = key ":" value
key      = (letter | digit | "-" | "_")+
value    = text
; Receipt: photo.jpg
; Project: Alpha

Operators

Arithmetic

+ - * / ( )

Comparison

== != < > <= >= =~ !~

Logical

and or not

Reserved Words

Directive Keywords

account commodity tag payee alias include
bucket assert check define apply end
year Y D P A

Expression Keywords

and or not expr true false

Function Names

abs round floor ceiling truncate
total amount commodity quantity
date today year month day
any all count sum min max average
has_tag tag format join

Token Examples

Complete Transaction

2024/01/15 * (#1234) Whole Foods  ; Weekly groceries
    ; :groceries:food:
    Expenses:Food:Groceries    $125.50
        ; Receipt: IMG_001.jpg
    Assets:Bank:Checking      $-125.50 = $1000.00

Tokens: 1. Date: 2024/01/15 2. Status: * 3. Code: (#1234) 4. Payee: Whole Foods 5. Comment: ; Weekly groceries 6. Tags: :groceries:food: 7. Account: Expenses:Food:Groceries 8. Amount: $125.50 9. Metadata: Receipt: IMG_001.jpg 10. Account: Assets:Bank:Checking 11. Amount: $-125.50 12. Balance assertion: = $1000.00

Error Recovery

Unterminated String

Error: Unterminated string at line 42
  "This string never ends
  ^

Invalid Character

Error: Invalid character at line 42
  2024/01/15 Purchase™
                     ^
  Unexpected character: ™

Invalid Date

Error: Invalid date at line 42
  2024/13/45 Transaction
  ^
  Month 13 and day 45 are invalid

See Also