{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "tree-sitter grammar specification",
  "type": "object",

  "required": ["name", "rules"],

  "additionalProperties": false,

  "properties": {
    "name": {
      "description": "the name of the grammar",
      "type": "string",
      "pattern": "^[a-zA-Z_]\\w*"
    },

    "rules": {
      "type": "object",
      "patternProperties": {
        "^[a-zA-Z_]\\w*$": {
          "$ref": "#/definitions/rule"
        }
      },
      "additionalProperties": false
    },

    "extras": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/rule"
      }
    },

    "externals": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/rule"
      }
    },

    "inline": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[a-zA-Z_]\\w*$"
      }
    },

    "conflicts": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {
          "type": "string",
          "pattern": "^[a-zA-Z_]\\w*$"
        }
      }
    },

    "word": {
      "type": "string",
      "pattern": "^[a-zA-Z_]\\w*"
    },

    "supertypes": {
      "description": "A list of hidden rule names that should be considered supertypes in the generated node types file. See https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types.",
      "type": "array",
      "items": {
        "description": "the name of a rule in `rules` or `extras`",
        "type": "string"
      }
    }
  },

  "definitions": {
    "blank-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^BLANK$"
        }
      },
      "required": ["type"]
    },

    "string-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^STRING$"
        },
        "value": {
          "type": "string"
        }
      },
      "required": ["type", "value"]
    },

    "pattern-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^PATTERN$"
        },
        "value": { "type": "string" }
      },
      "required": ["type", "value"]
    },

    "symbol-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^SYMBOL$"
        },
        "name": { "type": "string" }
      },
      "required": ["type", "name"]
    },

    "seq-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^SEQ$"
        },
        "members": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/rule"
          }
        }
      },
      "required": ["type", "members"]
    },

    "choice-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^CHOICE$"
        },
        "members": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/rule"
          }
        }
      },
      "required": ["type", "members"]
    },

    "alias-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^ALIAS$"
        },
        "value": {
          "type": "string"
        },
        "named": {
          "type": "boolean"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["type", "named", "content", "value"]
    },

    "repeat-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^REPEAT$"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["type", "content"]
    },

    "repeat1-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^REPEAT1$"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["type", "content"]
    },

    "token-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^(TOKEN|IMMEDIATE_TOKEN)$"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["type", "content"]
    },

    "field-rule": {
      "properties": {
        "name": { "type": "string" },
        "type": {
          "type": "string",
          "pattern": "^FIELD$"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["name", "type", "content"]
    },

    "prec-rule": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "pattern": "^(PREC|PREC_LEFT|PREC_RIGHT|PREC_DYNAMIC)$"
        },
        "value": {
          "type": "integer"
        },
        "content": {
          "$ref": "#/definitions/rule"
        }
      },
      "required": ["type", "content", "value"]
    },

    "rule": {
      "oneOf": [
        { "$ref": "#/definitions/alias-rule" },
        { "$ref": "#/definitions/blank-rule" },
        { "$ref": "#/definitions/string-rule" },
        { "$ref": "#/definitions/pattern-rule" },
        { "$ref": "#/definitions/symbol-rule" },
        { "$ref": "#/definitions/seq-rule" },
        { "$ref": "#/definitions/choice-rule" },
        { "$ref": "#/definitions/repeat1-rule" },
        { "$ref": "#/definitions/repeat-rule" },
        { "$ref": "#/definitions/token-rule" },
        { "$ref": "#/definitions/field-rule" },
        { "$ref": "#/definitions/prec-rule" }
      ]
    }
  }
}
