)]}'
{
  "commit": "b05c53fb01342873787b545359f443b5dbf2be7f",
  "tree": "fb628f9aa5e539abc5bd2e64240bb0211707be0b",
  "parents": [
    "ad74392541b9a72b521e56673cfdd013532fbd4a"
  ],
  "author": {
    "name": "Sketch🕴️",
    "email": "skallywag@sketch.dev",
    "time": "Sat Feb 28 19:13:36 2026 +0400"
  },
  "committer": {
    "name": "Sketch🕴️",
    "email": "skallywag@sketch.dev",
    "time": "Sat Feb 28 19:13:36 2026 +0400"
  },
  "message": "parser: implement recursive-descent parser with tests\n\n- Parse([]token.Token) (ast.Node, error) converts tokens to AST\n- Grammar: expr → term ((+|-) term)*, term → factor ((*|/) factor)*, factor → NUMBER | \u0027(\u0027 expr \u0027)\u0027\n- Correct operator precedence (* / before + -)\n- Left-associative operators\n- Error handling: empty input, missing/unexpected parens, trailing tokens, consecutive operators\n- 19 unit tests covering success and error cases\n",
  "tree_diff": [
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "c7be53b1b42097a027a2b381e34cec9498545f7a",
      "new_mode": 33188,
      "new_path": "parser/parser.go"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "521455ba8b2dd81b9db24893bd98d18902abc6ed",
      "new_mode": 33188,
      "new_path": "parser/parser_test.go"
    }
  ]
}
