LaunchPlatform / beancount-black

Opinionated code formatter, just like Python's black code formatter but for Beancount
MIT License
37 stars 6 forks source link

bean-black fails to parse expressions in a transaction amount #6

Closed 0x0013 closed 1 year ago

0x0013 commented 2 years ago

Program errors when a transaction contains an expression for the amount.

Example transaction:

2022-07-25 * "Food Place" "Meal for Two"
  Expenses:Food:Restaurants              (38.00 / 2) EUR
  Assets:Receivable                      (38.00 / 2) EUR
  Assets:Current:Cash

Output:

❯ bean-check start.beancount
❯ bean-black start.beancount
INFO:beancount_black.main:Processing file start.beancount
Traceback (most recent call last):
  File "/home/user/.local/lib/python3.10/site-packages/lark/lexer.py", line 536, in lex
    token = self.root_lexer.next_token(lexer_state, parser_state)
  File "/home/user/.local/lib/python3.10/site-packages/lark/lexer.py", line 466, in next_token
    raise UnexpectedCharacters(lex_state.text, line_ctr.char_pos, line_ctr.line, line_ctr.column,
lark.exceptions.UnexpectedCharacters: No terminal matches '(' in the current parser context, at line 236 col 42

 Expenses:Food:Restaurants              (38.00 / 2) EUR
                                        ^
Expected one of: 
    * FLAG
    * COMMA
    * METADATA_KEY
    * RBRACE
    * COMMENT
    * BOOLEAN
    * "@@"
    * ACCOUNT
    * DATE
    * _NL
    * SECTION_HEADER
    * "{{"
    * LBRACE
    * ESCAPED_STRING
    * SIGNED_NUMBER
    * "}}"
    * COLON
    * AT
    * HASH
    * LINK
    * CURRENCY
    * TAG
    * _EMPTY_LINE
    * TAGS

Previous tokens: Token('ACCOUNT', 'Expenses:Food:Restaurants')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/.local/bin/bean-black", line 8, in <module>
    sys.exit(main())
  File "/usr/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/user/.local/lib/python3.10/site-packages/beancount_black/main.py", line 47, in main
    tree = parser.parse(input_content)
  File "/home/user/.local/lib/python3.10/site-packages/lark/lark.py", line 625, in parse
    return self.parser.parse(text, start=start, on_error=on_error)
  File "/home/user/.local/lib/python3.10/site-packages/lark/parser_frontends.py", line 96, in parse
    return self.parser.parse(stream, chosen_start, **kw)
  File "/home/user/.local/lib/python3.10/site-packages/lark/parsers/lalr_parser.py", line 41, in parse
    return self.parser.parse(lexer, start)
  File "/home/user/.local/lib/python3.10/site-packages/lark/parsers/lalr_parser.py", line 171, in parse
    return self.parse_from_state(parser_state)
  File "/home/user/.local/lib/python3.10/site-packages/lark/parsers/lalr_parser.py", line 188, in parse_from_state
    raise e
  File "/home/user/.local/lib/python3.10/site-packages/lark/parsers/lalr_parser.py", line 178, in parse_from_state
    for token in state.lexer.lex(state):
  File "/home/user/.local/lib/python3.10/site-packages/lark/lexer.py", line 539, in lex
    raise e  # Raise the original UnexpectedCharacters. The root lexer raises it with the wrong expected set.
  File "/home/user/.local/lib/python3.10/site-packages/lark/lexer.py", line 528, in lex
    yield lexer.next_token(lexer_state, parser_state)
  File "/home/user/.local/lib/python3.10/site-packages/lark/lexer.py", line 466, in next_token
    raise UnexpectedCharacters(lex_state.text, line_ctr.char_pos, line_ctr.line, line_ctr.column,
lark.exceptions.UnexpectedCharacters: No terminal matches '(' in the current parser context, at line 236 col 42

 Expenses:Food:Restaurants              (38.00 / 2) EUR
                                        ^
Expected one of: 
    * SIGNED_NUMBER
    * _NL
    * COMMENT

Previous tokens: Token('ACCOUNT', 'Expenses:Food:Restaurants')

Similar result when removing the parenthesis - then program does not recognize / symbol.

fangpenlin commented 1 year ago

this has been addressed, now the latest beancount black can process number expression.

I added a test case for it

https://github.com/LaunchPlatform/beancount-black/blob/cd3793439f76e5f14c7f77c07f443fa2c80f6044/tests/fixtures/input/number_expr.bean https://github.com/LaunchPlatform/beancount-black/blob/cd3793439f76e5f14c7f77c07f443fa2c80f6044/tests/fixtures/expected_output/number_expr.bean

If you see any corner case we cannot processing it correctly, please let me know or feel free to open a PR