{
  "name": "readme_grammar",

  // Things that can appear anywhere in the language, like comments
  // and whitespace, are expressed as 'extras'.
  "extras": [
    {"type": "PATTERN", "value": "\\s"},
    {"type": "SYMBOL", "name": "comment"}
  ],

  "rules": {

    // The first rule listed in the grammar becomes the 'start rule'.
    "expression": {
      "type": "CHOICE",
      "members": [
        {"type": "SYMBOL", "name": "sum"},
        {"type": "SYMBOL", "name": "product"},
        {"type": "SYMBOL", "name": "number"},
        {"type": "SYMBOL", "name": "variable"},
        {
          "type": "SEQ",
          "members": [
            {"type": "STRING", "value": "("},
            {"type": "SYMBOL", "name": "expression"},
            {"type": "STRING", "value": ")"}
          ]
        }
      ]
    },

    // Tokens like '+' and '*' are described directly within the
    // grammar's rules, as opposed to in a separate lexer description.
    "sum": {
      "type": "PREC_LEFT",
      "value": 1,
      "content": {
        "type": "SEQ",
        "members": [
          {"type": "SYMBOL", "name": "expression"},
          {"type": "STRING", "value": "+"},
          {"type": "SYMBOL", "name": "expression"}
        ]
      }
    },

    // Ambiguities can be resolved at compile time by assigning precedence
    // values to rule subtrees.
    "product": {
      "type": "PREC_LEFT",
      "value": 2,
      "content": {
        "type": "SEQ",
        "members": [
          {"type": "SYMBOL", "name": "expression"},
          {"type": "STRING", "value": "*"},
          {"type": "SYMBOL", "name": "expression"}
        ]
      }
    },

    // Tokens can be specified using ECMAScript regexps.
    "number": {"type": "PATTERN", "value": "\\d+"},
    "comment": {"type": "PATTERN", "value": "#.*"},
    "variable": {"type": "PATTERN", "value": "[a-zA-Z]\\w*"}
  }
}