grammar.y 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * @file grammar.y
  3. * @version 3.0
  4. * @author John Wiegley
  5. *
  6. * @brief Canonical BNF grammar for Ledger data files
  7. *
  8. * Extensions are permitted if: they are not required, and they are
  9. * backwards-compatible with this grammar.
  10. */
  11. /*
  12. * There are three special terminals in this grammar, which violate its
  13. * context free nature:
  14. *
  15. * TEXT -- consumes all characters until the next terminal
  16. * or EOL (end of line)
  17. * WHITESPACE -- any amount of whitespace, not including EOL
  18. * STRING -- characters up to the next WHITESPACE or EOL
  19. *
  20. * BIGINT -- a number of any width, matching [0-9]+
  21. * INT4 -- a four digit wide number
  22. * INT2 -- a two digit wide number
  23. * INT1 -- a one digit wide number
  24. *
  25. * Except for 1) the 'spacer' production (see below), 2) EOL, and 3) the
  26. * WHITESPACE required to begin a posting, whitespace is otherwise
  27. * ignored.
  28. *
  29. * Yes, this grammar is confusing and not so happy for machine readers,
  30. * but it was designed for the human author and reader. Once parsed,
  31. * the contents must be unambiguous, which means they can be output to
  32. * more rigorous formats for other programs to consume.
  33. */
  34. /*
  35. * Journals
  36. *
  37. * A journal is a file which primarily contains xacts, among other elements.
  38. */
  39. journal:
  40. journal_item journal |
  41. /* epsilon */
  42. ;
  43. journal_item:
  44. whitespace
  45. directive |
  46. xact |
  47. ;
  48. whitespace:
  49. EOL |
  50. WHITESPACE EOL |
  51. ';' TEXT EOL | /* these next four are all ignored */
  52. '*' TEXT EOL |
  53. ;
  54. directive:
  55. '@' word_directive EOL |
  56. '!' word_directive EOL |
  57. word_directive EOL |
  58. char_directive EOL
  59. ;
  60. word_directive:
  61. "include" TEXT |
  62. "account" TEXT |
  63. "end" |
  64. "alias" STRING '=' TEXT |
  65. "def" TEXT |
  66. TEXT WHITESPACE TEXT /* looked up in session (aka maybe Python) */
  67. ;
  68. char_directive:
  69. 'i' date time TEXT | /* a timeclock.el "check in" */
  70. 'I' date time TEXT |
  71. 'o' date time TEXT | /* a timeclock.el "check out" */
  72. 'O' date time TEXT |
  73. 'h' TEXT EOL |
  74. 'b' TEXT EOL |
  75. 'D' amount | /* sets display parameters for a commodity */
  76. 'A' TEXT | /* sets the "default balancing account" */
  77. 'C' commodity '=' amount | /* specifies a commodity conversion */
  78. 'P' date time commodity amount | /* a pricing history xact */
  79. 'N' commodity | /* commodity's price is never downloaded */
  80. 'Y' INT4 | /* sets the default year for date parsing */
  81. '-' '-' STRING TEXT | /* specify command-line options in the file */
  82. ;
  83. date: INT4 date_sep INT2 date_sep INT2 ;
  84. date_opt: '=' date | /* epsilon */ ;
  85. date_sep: '/' | '-' | '.' ;
  86. time: INT2 ':' INT2 ':' INT2 ;
  87. commodity:
  88. '"' TEXT '"' |
  89. STRING ;
  90. /*
  91. * Xacts
  92. *
  93. * Xacts are the atomic units of accounting, which are composed of
  94. * multiple postings between accounts, so long as it all balances in
  95. * the end.
  96. */
  97. xact: plain_xact |
  98. periodic_xact |
  99. automated_xact ;
  100. plain_xact:
  101. date date_opt status_opt code_opt FULLSTRING note_opt EOL
  102. postings ;
  103. status_opt: status | /* epsilon */ ;
  104. status: '*' | '!' | /* epsilon */ ;
  105. code_opt: code | /* epsilon */ ;
  106. code: '(' TEXT ')' ;
  107. spacer: ' ' ' ' | '\t' | ' ' '\t' ;
  108. note_opt: spacer note | /* epsilon */ ;
  109. note: ';' TEXT ;
  110. /* ---------------------------------------------------------------------- */
  111. periodic_xact:
  112. '~' period_expr note_opt EOL
  113. posting postings ;
  114. /*
  115. * A period expression has its own sub-grammar, which I don't quite have
  116. * the time to exhaustively describe now. See datetime.cc. It allows
  117. * for lots and lots of things, and is probably horribly ambiguous.
  118. */
  119. period_expr: FULLSTRING ;
  120. /* ---------------------------------------------------------------------- */
  121. automated_xact:
  122. '=' value_expr note_opt EOL
  123. posting postings ;
  124. /*
  125. * Value expressions are a algebraic math expressions very similar to
  126. * XPath (minus the path traversal items). This grammar needs fleshing
  127. * out also, since it's allowed in many places.
  128. */
  129. value_expr: FULLSTRING ;
  130. /*
  131. * There is a serious ambiguity here which the parser resolves as
  132. * follows: if an amount_expr can be parsed as an amount, it's an
  133. * amount; otherwise, it's a value expression.
  134. */
  135. quantity: neg_opt BIGINT decimal_opt ;
  136. neg_opt: '-' | /* epsilon */ ;
  137. decimal_opt: '.' BIGINT | /* epsilon */ ;
  138. annotation: lot_price_opt lot_date_opt lot_note_opt ;
  139. lot_date_opt: date | /* epsilon */ ;
  140. lot_date: '[' date ']' ;
  141. lot_price_opt: price | /* epsilon */ ;
  142. lot_price: '{' amount '}' ;
  143. lot_note_opt: note | /* epsilon */ ;
  144. lot_note: '(' string ')' ;
  145. amount:
  146. neg_opt commodity quantity annotation |
  147. quantity commodity annotation ;
  148. amount_expr: amount | value_expr ;
  149. /*
  150. * Postings
  151. *
  152. * Postings are the fundamental unit of accounting, and represent
  153. * the movement of commodities to or from an account. Thus, paying off
  154. * your credit card consists of two balancing postings: one that
  155. * withdraws money from your checking account, and another which pays
  156. * money to your credit institution.
  157. */
  158. postings:
  159. posting postings |
  160. /* epsilon */
  161. ;
  162. posting:
  163. WHITESPACE status_opt account values_opt note_opt EOL;
  164. account_name: FULLSTRING ;
  165. values_opt:
  166. spacer amount_expr price_opt |
  167. /* epsilon */
  168. ;
  169. price_opt: price | /* epsilon */ ;
  170. price:
  171. '@' amount_expr |
  172. '@@' amount_expr /* in this case, it's the whole price */
  173. ;
  174. account:
  175. account_name |
  176. '(' account_name ')' |
  177. '[' account_name ']' ;
  178. /* grammar.y ends here */