Full Code of tree-sitter/tree-sitter-bash for AI

master a06c2e4415e9 cached
64 files
9.9 MB
2.6M tokens
94 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (10,429K chars total). Download the full file to get everything.
Repository: tree-sitter/tree-sitter-bash
Branch: master
Commit: a06c2e4415e9
Files: 64
Total size: 9.9 MB

Directory structure:
gitextract_j8navkbf/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yml
│       ├── fuzz.yml
│       ├── lint.yml
│       └── publish.yml
├── .gitignore
├── CMakeLists.txt
├── Cargo.toml
├── LICENSE
├── Makefile
├── Package.swift
├── README.md
├── binding.gyp
├── bindings/
│   ├── c/
│   │   ├── tree-sitter-bash.pc.in
│   │   └── tree_sitter/
│   │       └── tree-sitter-bash.h
│   ├── go/
│   │   ├── binding.go
│   │   └── binding_test.go
│   ├── node/
│   │   ├── binding.cc
│   │   ├── binding_test.js
│   │   ├── index.d.ts
│   │   └── index.js
│   ├── python/
│   │   ├── tests/
│   │   │   └── test_binding.py
│   │   └── tree_sitter_bash/
│   │       ├── __init__.py
│   │       ├── __init__.pyi
│   │       ├── binding.c
│   │       └── py.typed
│   ├── rust/
│   │   ├── build.rs
│   │   └── lib.rs
│   └── swift/
│       ├── TreeSitterBash/
│       │   └── bash.h
│       └── TreeSitterBashTests/
│           └── TreeSitterBashTests.swift
├── eslint.config.mjs
├── examples/
│   ├── atom.sh
│   ├── clean-old.sh
│   ├── doc-build.sh
│   ├── install.sh
│   ├── release.sh
│   ├── relocate.sh
│   ├── test.sh
│   └── update-authors.sh
├── go.mod
├── go.sum
├── grammar.js
├── package.json
├── pyproject.toml
├── queries/
│   └── highlights.scm
├── script/
│   ├── known-failures.txt
│   └── parse-examples
├── setup.py
├── src/
│   ├── grammar.json
│   ├── node-types.json
│   ├── parser.c
│   ├── scanner.c
│   └── tree_sitter/
│       ├── alloc.h
│       ├── array.h
│       └── parser.h
├── test/
│   └── corpus/
│       ├── commands.txt
│       ├── crlf.txt
│       ├── literals.txt
│       ├── programs.txt
│       └── statements.txt
└── tree-sitter.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8

[*.{json,toml,yml,gyp}]
indent_style = space
indent_size = 2

[*.js]
indent_style = space
indent_size = 2

[*.scm]
indent_style = space
indent_size = 2

[*.{c,cc,h}]
indent_style = space
indent_size = 4

[*.rs]
indent_style = space
indent_size = 4

[*.{py,pyi}]
indent_style = space
indent_size = 4

[*.swift]
indent_style = space
indent_size = 4

[*.go]
indent_style = tab
indent_size = 8

[Makefile]
indent_style = tab
indent_size = 8

[parser.c]
indent_size = 2

[{alloc,array,parser}.h]
indent_size = 2


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

# Generated source files
src/*.json linguist-generated
src/parser.c linguist-generated
src/tree_sitter/* linguist-generated

# C bindings
bindings/c/** linguist-generated
CMakeLists.txt linguist-generated
Makefile linguist-generated

# Rust bindings
bindings/rust/* linguist-generated
Cargo.toml linguist-generated
Cargo.lock linguist-generated

# Node.js bindings
bindings/node/* linguist-generated
binding.gyp linguist-generated
package.json linguist-generated
package-lock.json linguist-generated

# Python bindings
bindings/python/** linguist-generated
setup.py linguist-generated
pyproject.toml linguist-generated

# Go bindings
bindings/go/* linguist-generated
go.mod linguist-generated
go.sum linguist-generated

# Swift bindings
bindings/swift/** linguist-generated
Package.swift linguist-generated
Package.resolved linguist-generated

# Zig bindings
build.zig linguist-generated
build.zig.zon linguist-generated


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: tree-sitter
patreon: # Replace with a single Patreon username
open_collective: tree-sitter # Replace with a single Open Collective username
ko_fi: amaanq
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "ci"


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [master]
    paths:
      - grammar.js
      - src/**
      - test/**
      - bindings/**
      - binding.gyp
  pull_request:
    paths:
      - grammar.js
      - src/**
      - test/**
      - bindings/**
      - binding.gyp

concurrency:
  group: ${{github.workflow}}-${{github.ref}}
  cancel-in-progress: true

jobs:
  test:
    name: Test parser
    runs-on: ${{matrix.os}}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-14]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      - name: Set up tree-sitter
        uses: tree-sitter/setup-action/cli@v2
      - name: Set up examples
        shell: bash
        run: |-
          git clone https://github.com/Bash-it/bash-it examples/bash-it -q --single-branch --depth=1
          git clone https://git.savannah.gnu.org/git/bash.git examples/bash -q --single-branch --depth=1
          git clone https://anongit.gentoo.org/git/repo/gentoo.git examples/gentoo -q --single-branch --depth=1
          if [[ $RUNNER_OS != Windows ]]; then
            git clone https://github.com/oilshell/wild-corpus examples/wild-corpus -q --single-branch --depth=1
          fi
      - name: Run tests
        uses: tree-sitter/parser-test-action@v3
        with:
          generate: false
          test-rust: true
          test-node: false
          test-python: true
          test-go: true
          test-swift: false
      - name: Parse examples
        uses: tree-sitter/parse-action@v4
        with:
          files: |-
            examples/*.sh
            examples/bash-it/**/*.sh
            examples/bash-it/**/*.bash
            examples/bash/**/*.sh
            examples/bash/**/*.tests
            examples/gentoo/**/*.sh
            examples/gentoo/**/*.eclass
            examples/wild-corpus/**/*.sh
            # examples/gentoo/**/*.ebuild
            !examples/gentoo/app-antivirus/fangfrisch/files/fangfrisch-has-news.sh
            !examples/gentoo/eclass/ruby-fakegem.eclass
          invalid-files-list: script/known-failures.txt


================================================
FILE: .github/workflows/fuzz.yml
================================================
name: Fuzz

on:
  push:
    paths:
      - src/scanner.c
  pull_request:
    paths:
      - src/scanner.c
  workflow_dispatch:

concurrency:
  group: ${{github.workflow}}-${{github.ref}}
  cancel-in-progress: true

jobs:
  test:
    name: Fuzz scanner
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      - name: Run fuzzer
        uses: tree-sitter/fuzz-action@v4
        with:
          corpus: examples


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint

on:
  push:
    branches: [master]
    paths:
      - grammar.js
  pull_request:
    paths:
      - grammar.js

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      - name: Set up Node.js
        uses: actions/setup-node@v5
        with:
          cache: npm
          node-version: ${{vars.NODE_VERSION}}
      - name: Install modules
        run: npm ci --legacy-peer-deps
      - name: Run ESLint
        run: npm run lint


================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish packages

on:
  push:
    tags: ["*"]

permissions:
  contents: write
  id-token: write
  attestations: write

jobs:
  github:
    uses: tree-sitter/workflows/.github/workflows/release.yml@main
    with:
      generate: true
      attestations: true
  npm:
    uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main
    secrets:
      NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
    with:
      generate: true
  crates:
    uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main
    secrets:
      CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}}
    with:
      generate: true
  pypi:
    uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main
    secrets:
      PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}}
    with:
      generate: true


================================================
FILE: .gitignore
================================================
# Rust artifacts
target/

# Node artifacts
build/
prebuilds/
node_modules/

# Swift artifacts
.build/
Package.resolved

# Go artifacts
_obj/

# Python artifacts
.venv/
dist/
*.egg-info
*.whl

# C artifacts
*.a
*.so
*.so.*
*.dylib
*.dll
*.pc
*.exp
*.lib

# Zig artifacts
.zig-cache/
zig-cache/
zig-out/

# Example dirs
/examples/*/

# Grammar volatiles
*.wasm
*.obj
*.o

# Archives
*.tar.gz
*.tgz
*.zip


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.13)

project(tree-sitter-bash
        VERSION "0.25.1"
        DESCRIPTION "Bash grammar for tree-sitter"
        HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-bash"
        LANGUAGES C)

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF)

set(TREE_SITTER_ABI_VERSION 14 CACHE STRING "Tree-sitter ABI version")
if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$")
    unset(TREE_SITTER_ABI_VERSION CACHE)
    message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer")
endif()

find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")

add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
                   DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
                   COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
                            --abi=${TREE_SITTER_ABI_VERSION}
                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                   COMMENT "Generating parser.c")

add_library(tree-sitter-bash src/parser.c)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
  target_sources(tree-sitter-bash PRIVATE src/scanner.c)
endif()
target_include_directories(tree-sitter-bash
                           PRIVATE src
                           INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bindings/c>
                                     $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)


target_compile_definitions(tree-sitter-bash PRIVATE
                           $<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
                           $<$<CONFIG:Debug>:TREE_SITTER_DEBUG>)

set_target_properties(tree-sitter-bash
                      PROPERTIES
                      C_STANDARD 11
                      POSITION_INDEPENDENT_CODE ON
                      SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
                      DEFINE_SYMBOL "")

configure_file(bindings/c/tree-sitter-bash.pc.in
               "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-bash.pc" @ONLY)

include(GNUInstallDirs)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter"
        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        FILES_MATCHING PATTERN "*.h")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-bash.pc"
        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
install(TARGETS tree-sitter-bash
        LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")

add_custom_target(ts-test "${TREE_SITTER_CLI}" test
                  WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
                  COMMENT "tree-sitter test")


================================================
FILE: Cargo.toml
================================================
[package]
name = "tree-sitter-bash"
description = "Bash grammar for tree-sitter"
version = "0.25.1"
authors = [
  "Max Brunsfeld <maxbrunsfeld@gmail.com>",
  "Amaan Qureshi <amaanq12@gmail.com>",
]
license = "MIT"
readme = "README.md"
keywords = ["incremental", "parsing", "tree-sitter", "bash"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-bash"
edition = "2021"
autoexamples = false

build = "bindings/rust/build.rs"
include = ["LICENSE", "bindings/rust/*", "grammar.js", "queries/*", "src/*", "tree-sitter.json"]

[lib]
path = "bindings/rust/lib.rs"

[dependencies]
tree-sitter-language = "0.1"

[build-dependencies]
cc = "1.1"

[dev-dependencies]
tree-sitter = "0.25"


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2017 Max Brunsfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
ifeq ($(OS),Windows_NT)
$(error Windows is not supported)
endif

LANGUAGE_NAME := tree-sitter-bash
HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-bash
VERSION := 0.25.1

# repository
SRC_DIR := src

TS ?= tree-sitter

# install directory layout
PREFIX ?= /usr/local
INCLUDEDIR ?= $(PREFIX)/include
LIBDIR ?= $(PREFIX)/lib
PCLIBDIR ?= $(LIBDIR)/pkgconfig

# source/object files
PARSER := $(SRC_DIR)/parser.c
EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))

# flags
ARFLAGS ?= rcs
override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC

# ABI versioning
SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER))
SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION)))

# OS-specific bits
ifeq ($(shell uname),Darwin)
	SOEXT = dylib
	SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
	SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
	LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks
else
	SOEXT = so
	SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
	SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
	LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER)
endif
ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
	PCLIBDIR := $(PREFIX)/libdata/pkgconfig
endif

all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc

lib$(LANGUAGE_NAME).a: $(OBJS)
	$(AR) $(ARFLAGS) $@ $^

lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
	$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
ifneq ($(STRIP),)
	$(STRIP) $@
endif

$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
	sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
		-e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
		-e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \
		-e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \
		-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
		-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@

$(PARSER): $(SRC_DIR)/grammar.json
	$(TS) generate $^

install: all
	install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
	install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
	install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
	install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
	install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
	ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)

uninstall:
	$(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
		'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
		'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
		'$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc

clean:
	$(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)

test:
	$(TS) test

.PHONY: all install uninstall clean test


================================================
FILE: Package.swift
================================================
// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "TreeSitterBash",
    products: [
        .library(name: "TreeSitterBash", targets: ["TreeSitterBash"])
    ],
    dependencies: [
        .package(
            name: "SwiftTreeSitter",
            url: "https://github.com/tree-sitter/swift-tree-sitter",
            from: "0.25.0"
        )
    ],
    targets: [
        .target(
            name: "TreeSitterBash",
            dependencies: [],
            path: ".",
            sources: [
                "src/parser.c",
                "src/scanner.c",
            ],
            resources: [
                .copy("queries")
            ],
            publicHeadersPath: "bindings/swift",
            cSettings: [.headerSearchPath("src")]
        ),
        .testTarget(
            name: "TreeSitterBashTests",
            dependencies: [
                "SwiftTreeSitter",
                "TreeSitterBash",
            ],
            path: "bindings/swift/TreeSitterBashTests"
        ),
    ],
    cLanguageStandard: .c11
)


================================================
FILE: README.md
================================================
# tree-sitter-bash

[![CI][ci]](https://github.com/tree-sitter/tree-sitter-bash/actions/workflows/ci.yml)
[![discord][discord]](https://discord.gg/w7nTvsVJhm)
[![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org)
[![crates][crates]](https://crates.io/crates/tree-sitter-bash)
[![npm][npm]](https://www.npmjs.com/package/tree-sitter-bash)
[![pypi][pypi]](https://pypi.org/project/tree-sitter-bash)

Bash grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).

## Development

Install the dependencies:

```sh
npm install
```

Build and run the tests:

```sh
npm run build
npm run test
```

Run the build and tests in watch mode:

```sh
npm run test:watch
```

### References

- [Bash man page](http://man7.org/linux/man-pages/man1/bash.1.html#SHELL_GRAMMAR)
- [Shell command language specification](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html)
- [mvdnan/sh - a shell parser in go](https://github.com/mvdan/sh)

[ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-bash/ci.yml?logo=github&label=CI
[discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord
[matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix
[npm]: https://img.shields.io/npm/v/tree-sitter-bash?logo=npm
[crates]: https://img.shields.io/crates/v/tree-sitter-bash?logo=rust
[pypi]: https://img.shields.io/pypi/v/tree-sitter-bash?logo=pypi&logoColor=ffd242


================================================
FILE: binding.gyp
================================================
{
  "targets": [
    {
      "target_name": "tree_sitter_bash_binding",
      "dependencies": [
        "<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
      ],
      "include_dirs": [
        "src",
      ],
      "sources": [
        "bindings/node/binding.cc",
        "src/parser.c",
        "src/scanner.c",
      ],
      "conditions": [
        ["OS!='win'", {
          "cflags_c": [
            "-std=c11",
          ],
        }, { # OS == "win"
          "cflags_c": [
            "/std:c11",
            "/utf-8",
          ],
        }],
      ],
    }
  ]
}


================================================
FILE: bindings/c/tree-sitter-bash.pc.in
================================================
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: tree-sitter-bash
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -ltree-sitter-bash
Cflags: -I${includedir}


================================================
FILE: bindings/c/tree_sitter/tree-sitter-bash.h
================================================
#ifndef TREE_SITTER_BASH_H_
#define TREE_SITTER_BASH_H_

typedef struct TSLanguage TSLanguage;

#ifdef __cplusplus
extern "C" {
#endif

const TSLanguage *tree_sitter_bash(void);

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_BASH_H_


================================================
FILE: bindings/go/binding.go
================================================
package tree_sitter_bash

// #cgo CFLAGS: -std=c11 -fPIC
// #include "../../src/parser.c"
// #include "../../src/scanner.c"
import "C"

import "unsafe"

// Get the tree-sitter Language for this grammar.
func Language() unsafe.Pointer {
	return unsafe.Pointer(C.tree_sitter_bash())
}


================================================
FILE: bindings/go/binding_test.go
================================================
package tree_sitter_bash_test

import (
	"testing"

	tree_sitter "github.com/tree-sitter/go-tree-sitter"
	tree_sitter_bash "github.com/tree-sitter/tree-sitter-bash/bindings/go"
)

func TestCanLoadGrammar(t *testing.T) {
	language := tree_sitter.NewLanguage(tree_sitter_bash.Language())
	if language == nil {
		t.Errorf("Error loading Bash grammar")
	}
}


================================================
FILE: bindings/node/binding.cc
================================================
#include <napi.h>

typedef struct TSLanguage TSLanguage;

extern "C" TSLanguage *tree_sitter_bash();

// "tree-sitter", "language" hashed with BLAKE2
const napi_type_tag LANGUAGE_TYPE_TAG = {
    0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
};

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports["name"] = Napi::String::New(env, "bash");
    auto language = Napi::External<TSLanguage>::New(env, tree_sitter_bash());
    language.TypeTag(&LANGUAGE_TYPE_TAG);
    exports["language"] = language;
    return exports;
}

NODE_API_MODULE(tree_sitter_bash_binding, Init)


================================================
FILE: bindings/node/binding_test.js
================================================
const assert = require("node:assert");
const { test } = require("node:test");

const Parser = require("tree-sitter");

test("can load grammar", () => {
  const parser = new Parser();
  assert.doesNotThrow(() => parser.setLanguage(require(".")));
});


================================================
FILE: bindings/node/index.d.ts
================================================
type BaseNode = {
  type: string;
  named: boolean;
};

type ChildNode = {
  multiple: boolean;
  required: boolean;
  types: BaseNode[];
};

type NodeInfo =
  | (BaseNode & {
      subtypes: BaseNode[];
    })
  | (BaseNode & {
      fields: { [name: string]: ChildNode };
      children: ChildNode[];
    });

type Language = {
  name: string;
  language: unknown;
  nodeTypeInfo: NodeInfo[];
};

declare const language: Language;
export = language;


================================================
FILE: bindings/node/index.js
================================================
const root = require("path").join(__dirname, "..", "..");

module.exports =
  typeof process.versions.bun === "string"
    // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
    ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-bash.node`)
    : require("node-gyp-build")(root);

try {
  module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}


================================================
FILE: bindings/python/tests/test_binding.py
================================================
from unittest import TestCase

import tree_sitter, tree_sitter_bash


class TestLanguage(TestCase):
    def test_can_load_grammar(self):
        try:
            tree_sitter.Language(tree_sitter_bash.language())
        except Exception:
            self.fail("Error loading Bash grammar")


================================================
FILE: bindings/python/tree_sitter_bash/__init__.py
================================================
"""Bash grammar for tree-sitter"""

from importlib.resources import files as _files

from ._binding import language


def _get_query(name, file):
    query = _files(f"{__package__}.queries") / file
    globals()[name] = query.read_text()
    return globals()[name]


def __getattr__(name):
    if name == "HIGHLIGHTS_QUERY":
        return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")

    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


__all__ = [
    "language",
    "HIGHLIGHTS_QUERY",
]


def __dir__():
    return sorted(__all__ + [
        "__all__", "__builtins__", "__cached__", "__doc__", "__file__",
        "__loader__", "__name__", "__package__", "__path__", "__spec__",
    ])


================================================
FILE: bindings/python/tree_sitter_bash/__init__.pyi
================================================
from typing import Final

HIGHLIGHTS_QUERY: Final[str]

def language() -> object: ...


================================================
FILE: bindings/python/tree_sitter_bash/binding.c
================================================
#include <Python.h>

typedef struct TSLanguage TSLanguage;

TSLanguage *tree_sitter_bash(void);

static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
    return PyCapsule_New(tree_sitter_bash(), "tree_sitter.Language", NULL);
}

static struct PyModuleDef_Slot slots[] = {
#ifdef Py_GIL_DISABLED
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
#endif
    {0, NULL}
};

static PyMethodDef methods[] = {
    {"language", _binding_language, METH_NOARGS,
     "Get the tree-sitter language for this grammar."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    .m_base = PyModuleDef_HEAD_INIT,
    .m_name = "_binding",
    .m_doc = NULL,
    .m_size = 0,
    .m_methods = methods,
    .m_slots = slots,
};

PyMODINIT_FUNC PyInit__binding(void) {
    return PyModuleDef_Init(&module);
}


================================================
FILE: bindings/python/tree_sitter_bash/py.typed
================================================


================================================
FILE: bindings/rust/build.rs
================================================
fn main() {
    let src_dir = std::path::Path::new("src");

    let mut c_config = cc::Build::new();
    c_config
        .std("c11")
        .include(src_dir)
        .flag_if_supported("-Wno-unused-value");

    #[cfg(target_env = "msvc")]
    c_config.flag("-utf-8");

    let parser_path = src_dir.join("parser.c");
    c_config.file(&parser_path);
    println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());

    let scanner_path = src_dir.join("scanner.c");
    c_config.file(&scanner_path);
    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());

    c_config.compile("tree-sitter-bash");
}


================================================
FILE: bindings/rust/lib.rs
================================================
//! This crate provides Bash language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [LANGUAGE][] constant to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! use tree_sitter::Parser;
//!
//! let code = r#"
//! echo "hello world!"
//! "#;
//! let mut parser = Parser::new();
//! let language = tree_sitter_bash::LANGUAGE;
//! parser
//!     .set_language(&language.into())
//!     .expect("Error loading Bash parser");
//! let tree = parser.parse(code, None).unwrap();
//! assert!(!tree.root_node().has_error());
//! ```
//!
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/

use tree_sitter_language::LanguageFn;

extern "C" {
    fn tree_sitter_bash() -> *const ();
}

/// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar.
///
/// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html
pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_bash) };

/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");

/// The syntax highlighting query for this grammar.
pub const HIGHLIGHT_QUERY: &str = include_str!("../../queries/highlights.scm");

#[cfg(test)]
mod tests {
    #[test]
    fn test_can_load_grammar() {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(&super::LANGUAGE.into())
            .expect("Error loading Bash parser");
    }
}


================================================
FILE: bindings/swift/TreeSitterBash/bash.h
================================================
#ifndef TREE_SITTER_BASH_H_
#define TREE_SITTER_BASH_H_

typedef struct TSLanguage TSLanguage;

#ifdef __cplusplus
extern "C" {
#endif

const TSLanguage *tree_sitter_bash(void);

#ifdef __cplusplus
}
#endif

#endif // TREE_SITTER_BASH_H_


================================================
FILE: bindings/swift/TreeSitterBashTests/TreeSitterBashTests.swift
================================================
import XCTest
import SwiftTreeSitter
import TreeSitterBash

final class TreeSitterBashTests: XCTestCase {
    func testCanLoadGrammar() throws {
        let parser = Parser()
        let language = Language(language: tree_sitter_bash())
        XCTAssertNoThrow(try parser.setLanguage(language),
                         "Error loading Bash grammar")
    }
}


================================================
FILE: eslint.config.mjs
================================================
import treesitter from 'eslint-config-treesitter';

export default [
  ...treesitter,
];


================================================
FILE: examples/atom.sh
================================================
#!/bin/bash

if [ "$(uname)" == 'Darwin' ]; then
  OS='Mac'
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
  OS='Linux'
else
  echo "Your platform ($(uname -a)) is not supported."
  exit 1
fi

if [ "$(basename $0)" == 'atom-beta' ]; then
  BETA_VERSION=true
else
  BETA_VERSION=
fi

export ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT=true

while getopts ":wtfvh-:" opt; do
  case "$opt" in
    -)
      case "${OPTARG}" in
        wait)
          WAIT=1
          ;;
        help|version)
          REDIRECT_STDERR=1
          EXPECT_OUTPUT=1
          ;;
        foreground|benchmark|benchmark-test|test)
          EXPECT_OUTPUT=1
          ;;
      esac
      ;;
    w)
      WAIT=1
      ;;
    h|v)
      REDIRECT_STDERR=1
      EXPECT_OUTPUT=1
      ;;
    f|t)
      EXPECT_OUTPUT=1
      ;;
  esac
done

if [ $REDIRECT_STDERR ]; then
  exec 2> /dev/null
fi

if [ $EXPECT_OUTPUT ]; then
  export ELECTRON_ENABLE_LOGGING=1
fi

if [ $OS == 'Mac' ]; then
  if [ -L "$0" ]; then
    SCRIPT="$(readlink "$0")"
  else
    SCRIPT="$0"
  fi
  ATOM_APP="$(dirname "$(dirname "$(dirname "$(dirname "$SCRIPT")")")")"
  if [ "$ATOM_APP" == . ]; then
    unset ATOM_APP
  else
    ATOM_PATH="$(dirname "$ATOM_APP")"
    ATOM_APP_NAME="$(basename "$ATOM_APP")"
  fi

  if [ -n "$BETA_VERSION" ]; then
    ATOM_EXECUTABLE_NAME="Atom Beta"
  else
    ATOM_EXECUTABLE_NAME="Atom"
  fi

  if [ -z "${ATOM_PATH}" ]; then
    # If ATOM_PATH isn't set, check /Applications and then ~/Applications for Atom.app
    if [ -x "/Applications/$ATOM_APP_NAME" ]; then
      ATOM_PATH="/Applications"
    elif [ -x "$HOME/Applications/$ATOM_APP_NAME" ]; then
      ATOM_PATH="$HOME/Applications"
    else
      # We haven't found an Atom.app, use spotlight to search for Atom
      ATOM_PATH="$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | grep -v ShipIt | head -1 | xargs -0 dirname)"

      # Exit if Atom can't be found
      if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
        echo "Cannot locate ${ATOM_APP_NAME}, it is usually located in /Applications. Set the ATOM_PATH environment variable to the directory containing ${ATOM_APP_NAME}."
        exit 1
      fi
    fi
  fi

  if [ $EXPECT_OUTPUT ]; then
    "$ATOM_PATH/$ATOM_APP_NAME/Contents/MacOS/$ATOM_EXECUTABLE_NAME" --executed-from="$(pwd)" --pid=$$ "$@"
    exit $?
  else
    open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ --path-environment="$PATH" "$@"
  fi
elif [ $OS == 'Linux' ]; then
  SCRIPT=$(readlink -f "$0")
  USR_DIRECTORY=$(readlink -f $(dirname $SCRIPT)/..)

  if [ -n "$BETA_VERSION" ]; then
    ATOM_PATH="$USR_DIRECTORY/share/atom-beta/atom"
  else
    ATOM_PATH="$USR_DIRECTORY/share/atom/atom"
  fi

  ATOM_HOME="${ATOM_HOME:-$HOME/.atom}"
  mkdir -p "$ATOM_HOME"

  : ${TMPDIR:=/tmp}

  [ -x "$ATOM_PATH" ] || ATOM_PATH="$TMPDIR/atom-build/Atom/atom"

  if [ $EXPECT_OUTPUT ]; then
    "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@"
    exit $?
  else
    (
    nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > "$ATOM_HOME/nohup.out" 2>&1
    if [ $? -ne 0 ]; then
      cat "$ATOM_HOME/nohup.out"
      exit $?
    fi
    ) &
  fi
fi

# Exits this process when Atom is used as $EDITOR
on_die() {
  exit 0
}
trap 'on_die' SIGQUIT SIGTERM

# If the wait flag is set, don't exit this process until Atom tells it to.
if [ $WAIT ]; then
  while true; do
    sleep 1
  done
fi


================================================
FILE: examples/clean-old.sh
================================================
#!/bin/bash

# look for old 0.x cruft, and get rid of it.
# Should already be sitting in the npm folder.

# This doesn't have to be quite as cross-platform as install.sh.
# There are some bash-isms, because maintaining *two*
# fully-portable posix/bourne sh scripts is too much for
# one project with a sane maintainer.

# If readlink isn't available, then this is just too tricky.
# However, greadlink is fine, so Solaris can join the party, too.
readlink="readlink"
which $readlink >/dev/null 2>/dev/null
if [ $? -ne 0 ]; then
  readlink="greadlink"
  which $readlink >/dev/null 2>/dev/null
  if [ $? -ne 0 ]; then
    echo "Can't find the readlink or greadlink command. Aborting."
    exit 1
  fi
fi

if [ "x$npm_config_prefix" != "x" ]; then
  PREFIXES=$npm_config_prefix
else
  node="$NODE"
  if [ "x$node" = "x" ]; then
    node=`which node`
  fi
  if [ "x$node" = "x" ]; then
    echo "Can't find node to determine prefix. Aborting."
    exit 1
  fi


  PREFIX=`dirname $node`
  PREFIX=`dirname $PREFIX`
  echo "cleanup prefix=$PREFIX"
  PREFIXES=$PREFIX

  altprefix=`"$node" -e process.installPrefix`
  if [ "x$altprefix" != "x" ] && [ "x$altprefix" != "x$PREFIX" ]; then
    echo "altprefix=$altprefix"
    PREFIXES="$PREFIX $altprefix"
  fi
fi

# now prefix is where npm would be rooted by default
# go hunting.

packages=
for prefix in $PREFIXES; do
  packages="$packages
    "`ls "$prefix"/lib/node/.npm 2>/dev/null | grep -v .cache`
done

packages=`echo $packages`

filelist=()
fid=0

for prefix in $PREFIXES; do
  # remove any links into the .npm dir, or links to
  # version-named shims/symlinks.
  for folder in share/man bin lib/node; do
    find $prefix/$folder -type l | while read file; do
      target=`$readlink $file | grep '/\.npm/'`
      if [ "x$target" != "x" ]; then
        # found one!
        filelist[$fid]="$file"
        let 'fid++'
        # also remove any symlinks to this file.
        base=`basename "$file"`
        base=`echo "$base" | awk -F@ '{print $1}'`
        if [ "x$base" != "x" ]; then
          find "`dirname $file`" -type l -name "$base"'*' \
          | while read l; do
              target=`$readlink "$l" | grep "$base"`
              if [ "x$target" != "x" ]; then
                filelist[$fid]="$1"
                let 'fid++'
              fi
            done
        fi
      fi
    done

    # Scour for shim files.  These are relics of 0.2 npm installs.
    # note: grep -r is not portable.
    find $prefix/$folder -type f \
      | xargs grep -sl '// generated by npm' \
      | while read file; do
          filelist[$fid]="$file"
          let 'fid++'
        done
  done

  # now remove the package modules, and the .npm folder itself.
  if [ "x$packages" != "x" ]; then
    for pkg in $packages; do
      filelist[$fid]="$prefix/lib/node/$pkg"
      let 'fid++'
      for i in $prefix/lib/node/$pkg\@*; do
        filelist[$fid]="$i"
        let 'fid++'
      done
    done
  fi

  for folder in lib/node/.npm lib/npm share/npm; do
    if [ -d $prefix/$folder ]; then
      filelist[$fid]="$prefix/$folder"
      let 'fid++'
    fi
  done
done

# now actually clean, but only if there's anything TO clean
if [ "${#filelist[@]}" -gt 0 ]; then
  echo ""
  echo "This script will find and eliminate any shims, symbolic"
  echo "links, and other cruft that was installed by npm 0.x."
  echo ""

  if [ "x$packages" != "x" ]; then
    echo "The following packages appear to have been installed with"
    echo "an old version of npm, and will be removed forcibly:"
    for pkg in $packages; do
      echo "    $pkg"
    done
    echo "Make a note of these. You may want to install them"
    echo "with npm 1.0 when this process is completed."
    echo ""
  fi

  OK=
  if [ "x$1" = "x-y" ]; then
    OK="yes"
  fi

  while [ "$OK" != "y" ] && [ "$OK" != "yes" ] && [ "$OK" != "no" ]; do
    echo "Is this OK?"
    echo "  enter 'yes' or 'no'"
    echo "  or 'show' to see a list of files "
    read OK
    if [ "x$OK" = "xshow" ] || [ "x$OK" = "xs" ]; then
      for i in "${filelist[@]}"; do
        echo "$i"
      done
    fi
  done
  if [ "$OK" = "no" ]; then
    echo "Aborting"
    exit 1
  fi
  for i in "${filelist[@]}"; do
    rm -rf "$i"
  done
fi

echo ""
echo 'All clean!'

exit 0


================================================
FILE: examples/doc-build.sh
================================================
#!/usr/bin/env bash

if [[ $DEBUG != "" ]]; then
  set -x
fi
set -o errexit
set -o pipefail

if ! [ -x node_modules/.bin/marked-man ]; then
  ps=0
  if [ -f .building_marked-man ]; then
    pid=$(cat .building_marked-man)
    ps=$(ps -p $pid | grep $pid | wc -l) || true
  fi

  if [ -f .building_marked-man ] && [ $ps != 0 ]; then
    while [ -f .building_marked-man ]; do
      sleep 1
    done
  else
    # a race to see which make process will be the one to install marked-man
    echo $$ > .building_marked-man
    sleep 1
    if [ $(cat .building_marked-man) == $$ ]; then
      make node_modules/.bin/marked-man
      rm .building_marked-man
    else
      while [ -f .building_marked-man ]; do
        sleep 1
      done
    fi
  fi
fi

if ! [ -x node_modules/.bin/marked ]; then
  ps=0
  if [ -f .building_marked ]; then
    pid=$(cat .building_marked)
    ps=$(ps -p $pid | grep $pid | wc -l) || true
  fi

  if [ -f .building_marked ] && [ $ps != 0 ]; then
    while [ -f .building_marked ]; do
      sleep 1
    done
  else
    # a race to see which make process will be the one to install marked
    echo $$ > .building_marked
    sleep 1
    if [ $(cat .building_marked) == $$ ]; then
      make node_modules/.bin/marked
      rm .building_marked
    else
      while [ -f .building_marked ]; do
        sleep 1
      done
    fi
  fi
fi

src=$1
dest=$2
name=$(basename ${src%.*})
date=$(date -u +'%Y-%m-%d %H:%M:%S')
version=$(node cli.js -v)

mkdir -p $(dirname $dest)

html_replace_tokens () {
	local url=$1
	sed "s|@NAME@|$name|g" \
	| sed "s|@DATE@|$date|g" \
	| sed "s|@URL@|$url|g" \
	| sed "s|@VERSION@|$version|g" \
	| perl -p -e 's/<h1([^>]*)>([^\(]*\([0-9]\)) -- (.*?)<\/h1>/<h1>\2<\/h1> <p>\3<\/p>/g' \
	| perl -p -e 's/npm-npm/npm/g' \
	| perl -p -e 's/([^"-])(npm-)?README(?!\.html)(\(1\))?/\1<a href="..\/..\/doc\/README.html">README<\/a>/g' \
	| perl -p -e 's/<title><a href="[^"]+README.html">README<\/a><\/title>/<title>README<\/title>/g' \
	| perl -p -e 's/([^"-])([^\(> ]+)(\(1\))/\1<a href="..\/cli\/\2.html">\2\3<\/a>/g' \
	| perl -p -e 's/([^"-])([^\(> ]+)(\(3\))/\1<a href="..\/api\/\2.html">\2\3<\/a>/g' \
	| perl -p -e 's/([^"-])([^\(> ]+)(\(5\))/\1<a href="..\/files\/\2.html">\2\3<\/a>/g' \
	| perl -p -e 's/([^"-])([^\(> ]+)(\(7\))/\1<a href="..\/misc\/\2.html">\2\3<\/a>/g' \
	| perl -p -e 's/\([1357]\)<\/a><\/h1>/<\/a><\/h1>/g' \
	| (if [ $(basename $(dirname $dest)) == "doc" ]; then
			perl -p -e 's/ href="\.\.\// href="/g'
		else
			cat
		fi)
}

man_replace_tokens () {
	sed "s|@VERSION@|$version|g" \
	| perl -p -e 's/(npm\\-)?([a-zA-Z\\\.\-]*)\(1\)/npm help \2/g' \
	| perl -p -e 's/(npm\\-)?([a-zA-Z\\\.\-]*)\(([57])\)/npm help \3 \2/g' \
	| perl -p -e 's/(npm\\-)?([a-zA-Z\\\.\-]*)\(3\)/npm apihelp \2/g' \
	| perl -p -e 's/npm\(1\)/npm help npm/g' \
	| perl -p -e 's/npm\(3\)/npm apihelp npm/g'
}

case $dest in
  *.[1357])
    ./node_modules/.bin/marked-man --roff $src \
    | man_replace_tokens > $dest
    exit $?
    ;;
  *.html)
    url=${dest/html\//}
    (cat html/dochead.html && \
     cat $src | ./node_modules/.bin/marked &&
     cat html/docfoot.html)\
    | html_replace_tokens $url \
    > $dest
    exit $?
    ;;
  *)
    echo "Invalid destination type: $dest" >&2
    exit 1
    ;;
esac


================================================
FILE: examples/install.sh
================================================
#!/bin/sh

# A word about this shell script:
#
# It must work everywhere, including on systems that lack
# a /bin/bash, map 'sh' to ksh, ksh97, bash, ash, or zsh,
# and potentially have either a posix shell or bourne
# shell living at /bin/sh.
#
# See this helpful document on writing portable shell scripts:
# http://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html
#
# The only shell it won't ever work on is cmd.exe.

if [ "x$0" = "xsh" ]; then
  # run as curl | sh
  # on some systems, you can just do cat>npm-install.sh
  # which is a bit cuter.  But on others, &1 is already closed,
  # so catting to another script file won't do anything.
  # Follow Location: headers, and fail on errors
  curl -f -L -s https://www.npmjs.org/install.sh > npm-install-$$.sh
  ret=$?
  if [ $ret -eq 0 ]; then
    (exit 0)
  else
    rm npm-install-$$.sh
    echo "Failed to download script" >&2
    exit $ret
  fi
  sh npm-install-$$.sh
  ret=$?
  rm npm-install-$$.sh
  exit $ret
fi

# See what "npm_config_*" things there are in the env,
# and make them permanent.
# If this fails, it's not such a big deal.
configures="`env | grep 'npm_config_' | sed -e 's|^npm_config_||g'`"

npm_config_loglevel="error"
if [ "x$npm_debug" = "x" ]; then
  (exit 0)
else
  echo "Running in debug mode."
  echo "Note that this requires bash or zsh."
  set -o xtrace
  set -o pipefail
  npm_config_loglevel="verbose"
fi
export npm_config_loglevel

# make sure that node exists
node=`which node 2>&1`
ret=$?
if [ $ret -eq 0 ] && [ -x "$node" ]; then
  (exit 0)
else
  echo "npm cannot be installed without node.js." >&2
  echo "Install node first, and then try again." >&2
  echo "" >&2
  echo "Maybe node is installed, but not in the PATH?" >&2
  echo "Note that running as sudo can change envs." >&2
  echo ""
  echo "PATH=$PATH" >&2
  exit $ret
fi

# set the temp dir
TMP="${TMPDIR}"
if [ "x$TMP" = "x" ]; then
  TMP="/tmp"
fi
TMP="${TMP}/npm.$$"
rm -rf "$TMP" || true
mkdir "$TMP"
if [ $? -ne 0 ]; then
  echo "failed to mkdir $TMP" >&2
  exit 1
fi

BACK="$PWD"

ret=0
tar="${TAR}"
if [ -z "$tar" ]; then
  tar="${npm_config_tar}"
fi
if [ -z "$tar" ]; then
  tar=`which tar 2>&1`
  ret=$?
fi

if [ $ret -eq 0 ] && [ -x "$tar" ]; then
  echo "tar=$tar"
  echo "version:"
  $tar --version
  ret=$?
fi

if [ $ret -eq 0 ]; then
  (exit 0)
else
  echo "No suitable tar program found."
  exit 1
fi



# Try to find a suitable make
# If the MAKE environment var is set, use that.
# otherwise, try to find gmake, and then make.
# If no make is found, then just execute the necessary commands.

# XXX For some reason, make is building all the docs every time.  This
# is an annoying source of bugs. Figure out why this happens.
MAKE=NOMAKE

if [ "x$MAKE" = "x" ]; then
  make=`which gmake 2>&1`
  if [ $? -eq 0 ] && [ -x "$make" ]; then
    (exit 0)
  else
    make=`which make 2>&1`
    if [ $? -eq 0 ] && [ -x "$make" ]; then
      (exit 0)
    else
      make=NOMAKE
    fi
  fi
else
  make="$MAKE"
fi

if [ -x "$make" ]; then
  (exit 0)
else
  # echo "Installing without make. This may fail." >&2
  make=NOMAKE
fi

# If there's no bash, then don't even try to clean
if [ -x "/bin/bash" ]; then
  (exit 0)
else
  clean="no"
fi

node_version=`"$node" --version 2>&1`
ret=$?
if [ $ret -ne 0 ]; then
  echo "You need node to run this program." >&2
  echo "node --version reports: $node_version" >&2
  echo "with exit code = $ret" >&2
  echo "Please install node before continuing." >&2
  exit $ret
fi

t="${npm_install}"
if [ -z "$t" ]; then
  # switch based on node version.
  # note that we can only use strict sh-compatible patterns here.
  case $node_version in
    0.[01234567].* | v0.[01234567].*)
      echo "You are using an outdated and unsupported version of" >&2
      echo "node ($node_version).  Please update node and try again." >&2
      exit 99
      ;;
    *)
      echo "install npm@latest"
      t="latest"
      ;;
  esac
fi

# need to echo "" after, because Posix sed doesn't treat EOF
# as an implied end of line.
url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \
     | sed -e 's/^.*tarball":"//' \
     | sed -e 's/".*$//'`

ret=$?
if [ "x$url" = "x" ]; then
  ret=125
  # try without the -e arg to sed.
  url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \
       | sed 's/^.*tarball":"//' \
       | sed 's/".*$//'`
  ret=$?
  if [ "x$url" = "x" ]; then
    ret=125
  fi
fi
if [ $ret -ne 0 ]; then
  echo "Failed to get tarball url for npm/$t" >&2
  exit $ret
fi


echo "fetching: $url" >&2

cd "$TMP" \
  && curl -SsL "$url" \
     | $tar -xzf - \
  && cd "$TMP"/* \
  && (ver=`"$node" bin/read-package-json.js package.json version`
      isnpm10=0
      if [ $ret -eq 0 ]; then
        if [ -d node_modules ]; then
          if "$node" node_modules/semver/bin/semver -v "$ver" -r "1"
          then
            isnpm10=1
          fi
        else
          if "$node" bin/semver -v "$ver" -r ">=1.0"; then
            isnpm10=1
          fi
        fi
      fi

      ret=0
      if [ $isnpm10 -eq 1 ] && [ -f "scripts/clean-old.sh" ]; then
        if [ "x$skipclean" = "x" ]; then
          (exit 0)
        else
          clean=no
        fi
        if [ "x$clean" = "xno" ] \
            || [ "x$clean" = "xn" ]; then
          echo "Skipping 0.x cruft clean" >&2
          ret=0
        elif [ "x$clean" = "xy" ] || [ "x$clean" = "xyes" ]; then
          NODE="$node" /bin/bash "scripts/clean-old.sh" "-y"
          ret=$?
        else
          NODE="$node" /bin/bash "scripts/clean-old.sh" </dev/tty
          ret=$?
        fi
      fi

      if [ $ret -ne 0 ]; then
        echo "Aborted 0.x cleanup.  Exiting." >&2
        exit $ret
      fi) \
  && (if [ "x$configures" = "x" ]; then
        (exit 0)
      else
        echo "./configure $configures"
        echo "$configures" > npmrc
      fi) \
  && (if [ "$make" = "NOMAKE" ]; then
        (exit 0)
      elif "$make" uninstall install; then
        (exit 0)
      else
        make="NOMAKE"
      fi
      if [ "$make" = "NOMAKE" ]; then
        "$node" cli.js rm npm -gf
        "$node" cli.js install -gf
      fi) \
  && cd "$BACK" \
  && rm -rf "$TMP" \
  && echo "It worked"

ret=$?
if [ $ret -ne 0 ]; then
  echo "It failed" >&2
fi
exit $ret


================================================
FILE: examples/release.sh
================================================
#!/bin/bash

# script for creating a zip and tarball for inclusion in node

unset CDPATH

set -e

rm -rf release *.tgz || true
mkdir release
node ./cli.js pack --loglevel error >/dev/null
mv *.tgz release
cd release
tar xzf *.tgz

mkdir node_modules
mv package node_modules/npm

# make the zip for windows users
cp node_modules/npm/bin/*.cmd .
zipname=npm-$(node ../cli.js -v).zip
zip -q -9 -r -X "$zipname" *.cmd node_modules

# make the tar for node's deps
cd node_modules
tarname=npm-$(node ../../cli.js -v).tgz
tar czf "$tarname" npm

cd ..
mv "node_modules/$tarname" .

rm -rf *.cmd
rm -rf node_modules

echo "release/$tarname"
echo "release/$zipname"


================================================
FILE: examples/relocate.sh
================================================
#!/bin/bash

# Change the cli shebang to point at the specified node
# Useful for when the program is moved around after install.
# Also used by the default 'make install' in node to point
# npm at the newly installed node, rather than the first one
# in the PATH, which would be the default otherwise.

# bash /path/to/npm/scripts/relocate.sh $nodepath
# If $nodepath is blank, then it'll use /usr/bin/env

dir="$(dirname "$(dirname "$0")")"
cli="$dir"/bin/npm-cli.js
tmp="$cli".tmp

node="$1"
if [ "x$node" = "x" ]; then
  node="/usr/bin/env node"
fi
node="#!$node"

sed -e 1d "$cli" > "$tmp"
echo "$node" > "$cli"
cat "$tmp" >> "$cli"
rm "$tmp"
chmod ogu+x $cli


================================================
FILE: examples/test.sh
================================================
#!/usr/bin/env bash

set -e

function usage {
  cat <<-EOF
USAGE

  $0  [-dgGhv] [-f focus-string] [-s seed]

OPTIONS

  -h  print this message

  -b  run make under scan-build static analyzer

  -d  run tests in a debugger (either lldb or gdb)

  -g  run tests with valgrind's memcheck tool

  -G  run tests with valgrind's memcheck tool, including a full leak check

  -v  run tests with verbose output

  -f  run only tests whose description contain the given string

  -s  set the seed used to control random behavior

  -z  pipe tests' stderr to \`dot(1)\` to render an SVG log


EOF
}

profile=
leak_check=no
mode=normal
verbose=
args=()
target=tests
export BUILDTYPE=Test
cmd="out/${BUILDTYPE}/${target}"
run_scan_build=

if [ "$(uname -s)" == "Darwin" ]; then
  export LINK="clang++ -fsanitize=address"
fi

while getopts "bdf:s:gGhpvS" option; do
  case ${option} in
    h)
      usage
      exit
      ;;
    d)
      mode=debug
      ;;
    g)
      mode=valgrind
      ;;
    G)
      mode=valgrind
      leak_check=full
      ;;
    p)
      profile=true
      ;;
    f)
      args+=("--only=${OPTARG}")
      ;;
    v)
      verbose=true
      ;;
    s)
      export TREE_SITTER_SEED=${OPTARG}
      ;;
    S)
      mode=SVG
      ;;
    b)
      run_scan_build=true
      ;;
  esac
done

if [[ -n $verbose ]]; then
  args+=("--reporter=spec")
else
  args+=("--reporter=singleline")
fi

if [[ -n "$run_scan_build" ]]; then
  . script/util/scan-build.sh
  scan_build make -j2 $target
else
  make -j2 $target
fi
args=${args:-""}

if [[ -n $profile ]]; then
  export CPUPROFILE=/tmp/${target}-$(date '+%s').prof
fi

case ${mode} in
  valgrind)
    valgrind                                     \
      --suppressions=./script/util/valgrind.supp \
      --dsymutil=yes                             \
      --leak-check=${leak_check}                 \
      $cmd "${args[@]}" 2>&1 |                   \
      grep --color -E '\w+_tests?.cc:\d+|$'
    ;;

  debug)
    if which -s lldb; then
      lldb $cmd -- "${args[@]}"
    elif which -s gdb; then
      gdb $cmd -- "${args[@]}"
    else
      echo "No debugger found"
      exit 1
    fi
    ;;

  SVG)
    echo "<!DOCTYPE html><style>svg { width: 100%; margin-bottom: 20px; }</style>" > index.html
    $cmd "${args[@]}" 2> >(grep -v 'Assertion failed' | dot -Tsvg >> index.html)
    echo "Wrote index.html"
    ;;

  normal)
    time $cmd "${args[@]}"
    ;;
esac

if [[ -n $profile ]]; then
  pprof $cmd $CPUPROFILE
fi


================================================
FILE: examples/update-authors.sh
================================================
#!/bin/sh

git log --reverse --format='%aN <%aE>' | perl -wnE '
BEGIN {
  say "# Authors sorted by whether or not they\x27re me";
}

print $seen{$_} = $_ unless $seen{$_}
' > AUTHORS


================================================
FILE: go.mod
================================================
module github.com/tree-sitter/tree-sitter-bash

go 1.22

require github.com/tree-sitter/go-tree-sitter v0.24.0

require github.com/mattn/go-pointer v0.0.1 // indirect


================================================
FILE: go.sum
================================================
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ=
github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk=
github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs=
github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA=
github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc=
github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s=
github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4=
github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4=
github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo=
github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY=
github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo=
github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU=
github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA=
github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc=
github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg=
github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU=
github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4=
github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk=
github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g=
github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs=
github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw=
github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g=
github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI=
github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg=
github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc=
github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=


================================================
FILE: grammar.js
================================================
/**
 * @file Bash grammar for tree-sitter
 * @author Max Brunsfeld <maxbrunsfeld@gmail.com>
 * @author Amaan Qureshi <amaanq12@gmail.com>
 * @license MIT
 */

/// <reference types="tree-sitter-cli/dsl" />
// @ts-check

const SPECIAL_CHARACTERS = [
  '\'', '"',
  '<', '>',
  '{', '}',
  '\\[', '\\]',
  '(', ')',
  '`', '$',
  '|', '&', ';',
  '\\',
  '\\s',
];

const PREC = {
  UPDATE: 0,
  ASSIGN: 1,
  TERNARY: 2,
  LOGICAL_OR: 3,
  LOGICAL_AND: 4,
  BITWISE_OR: 5,
  BITWISE_XOR: 6,
  BITWISE_AND: 7,
  EQUALITY: 8,
  COMPARE: 9,
  TEST: 10,
  UNARY: 11,
  SHIFT: 12,
  ADD: 13,
  MULTIPLY: 14,
  EXPONENT: 15,
  NEGATE: 16,
  PREFIX: 17,
  POSTFIX: 18,
};

module.exports = grammar({
  name: 'bash',

  conflicts: $ => [
    [$._expression, $.command_name],
    [$.command, $.variable_assignments],
    [$.redirected_statement, $.command],
    [$.redirected_statement, $.command_substitution],
    [$.function_definition, $.command_name],
    [$.pipeline],
  ],

  inline: $ => [
    $._statement,
    $._terminator,
    $._literal,
    $._terminated_statement,
    $._primary_expression,
    $._simple_variable_name,
    $._multiline_variable_name,
    $._special_variable_name,
    $._c_word,
    $._statement_not_subshell,
    $._redirect,
  ],

  externals: $ => [
    $.heredoc_start,
    $.simple_heredoc_body,
    $._heredoc_body_beginning,
    $.heredoc_content,
    $.heredoc_end,
    $.file_descriptor,
    $._empty_value,
    $._concat,
    $.variable_name, // Variable name followed by an operator like '=' or '+='
    $.test_operator,
    $.regex,
    $._regex_no_slash,
    $._regex_no_space,
    $._expansion_word,
    $.extglob_pattern,
    $._bare_dollar,
    $._brace_start,
    $._immediate_double_hash,
    $._external_expansion_sym_hash,
    $._external_expansion_sym_bang,
    $._external_expansion_sym_equal,
    '}',
    ']',
    '<<',
    '<<-',
    /\n/,
    '(',
    'esac',
    $.__error_recovery,
  ],

  extras: $ => [
    $.comment,
    /\s/,
    /\\\r?\n/,
    /\\( |\t|\v|\f)/,
  ],

  supertypes: $ => [
    $._statement,
    $._expression,
    $._primary_expression,
  ],

  word: $ => $.word,

  rules: {
    program: $ => optional($._statements),

    _statements: $ => prec(1, seq(
      repeat(seq(
        $._statement,
        $._terminator,
      )),
      $._statement,
      optional($._terminator),
    )),

    _terminated_statement: $ => repeat1(seq(
      $._statement,
      $._terminator,
    )),

    // Statements

    _statement: $ => choice(
      $._statement_not_subshell,
      $.subshell,
    ),

    _statement_not_subshell: $ => choice(
      $.redirected_statement,
      $.variable_assignment,
      $.variable_assignments,
      $.command,
      $.declaration_command,
      $.unset_command,
      $.test_command,
      $.negated_command,
      $.for_statement,
      $.c_style_for_statement,
      $.while_statement,
      $.if_statement,
      $.case_statement,
      $.pipeline,
      $.list,
      $.compound_statement,
      $.function_definition,
    ),

    _statement_not_pipeline: $ => prec(1, choice(
      $.redirected_statement,
      $.variable_assignment,
      $.variable_assignments,
      $.command,
      $.declaration_command,
      $.unset_command,
      $.test_command,
      $.negated_command,
      $.for_statement,
      $.c_style_for_statement,
      $.while_statement,
      $.if_statement,
      $.case_statement,
      $.list,
      $.compound_statement,
      $.function_definition,
      $.subshell,
    )),

    redirected_statement: $ => prec.dynamic(-1, prec.right(-1, choice(
      seq(
        field('body', $._statement),
        field('redirect', choice(
          repeat1(choice(
            $.file_redirect,
            $.heredoc_redirect,
          )),
        )),
      ),
      seq(
        field('body', choice($.if_statement, $.while_statement)),
        $.herestring_redirect,
      ),
      field('redirect', repeat1($._redirect)),
      $.herestring_redirect,
    ))),

    for_statement: $ => seq(
      choice('for', 'select'),
      field('variable', $._simple_variable_name),
      optional(seq(
        'in',
        field('value', repeat1($._literal)),
      )),
      $._terminator,
      field('body', $.do_group),
    ),

    c_style_for_statement: $ => seq(
      'for',
      '((',
      choice($._for_body),
      '))',
      optional(';'),
      field('body', choice(
        $.do_group,
        $.compound_statement,
      )),
    ),
    _for_body: $ => seq(
      field('initializer', commaSep($._c_expression)),
      $._c_terminator,
      field('condition', commaSep($._c_expression)),
      $._c_terminator,
      field('update', commaSep($._c_expression)),
    ),

    _c_expression: $ => choice(
      $._c_expression_not_assignment,
      alias($._c_variable_assignment, $.variable_assignment),
    ),
    _c_expression_not_assignment: $ => choice(
      $._c_word,
      $.simple_expansion,
      $.expansion,
      $.number,
      $.string,
      alias($._c_unary_expression, $.unary_expression),
      alias($._c_binary_expression, $.binary_expression),
      alias($._c_postfix_expression, $.postfix_expression),
      alias($._c_parenthesized_expression, $.parenthesized_expression),
      $.command_substitution,
    ),

    _c_variable_assignment: $ => seq(
      field('name', alias($._c_word, $.variable_name)),
      '=',
      field('value', $._c_expression),
    ),
    _c_unary_expression: $ => prec(PREC.PREFIX, seq(
      field('operator', choice('++', '--')),
      $._c_expression_not_assignment,
    )),
    _c_binary_expression: $ => {
      const table = [
        [choice('+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '&=', '^=', '|='), PREC.UPDATE],
        [choice('||', '-o'), PREC.LOGICAL_OR],
        [choice('&&', '-a'), PREC.LOGICAL_AND],
        ['|', PREC.BITWISE_OR],
        ['^', PREC.BITWISE_XOR],
        ['&', PREC.BITWISE_AND],
        [choice('==', '!='), PREC.EQUALITY],
        [choice('<', '>', '<=', '>='), PREC.COMPARE],
        [choice('<<', '>>'), PREC.SHIFT],
        [choice('+', '-'), PREC.ADD],
        [choice('*', '/', '%'), PREC.MULTIPLY],
        ['**', PREC.EXPONENT],
      ];

      return choice(...table.map(([operator, precedence]) => {
        // @ts-ignore
        return prec[operator === '**' ? 'right' : 'left'](precedence, seq(
          field('left', $._c_expression_not_assignment),
          // @ts-ignore
          field('operator', operator),
          field('right', $._c_expression_not_assignment),
        ));
      }));
    },
    _c_postfix_expression: $ => prec(PREC.POSTFIX, seq(
      $._c_expression_not_assignment,
      field('operator', choice('++', '--')),
    )),
    _c_parenthesized_expression: $ => seq(
      '(',
      commaSep1($._c_expression),
      ')',
    ),
    _c_word: $ => alias(/[a-zA-Z_][a-zA-Z0-9_]*/, $.word),

    while_statement: $ => seq(
      choice('while', 'until'),
      field('condition', $._terminated_statement),
      field('body', $.do_group),
    ),

    do_group: $ => seq(
      'do',
      optional($._terminated_statement),
      'done',
    ),

    if_statement: $ => seq(
      'if',
      field('condition', $._terminated_statement),
      'then',
      optional($._terminated_statement),
      repeat($.elif_clause),
      optional($.else_clause),
      'fi',
    ),

    elif_clause: $ => seq(
      'elif',
      $._terminated_statement,
      'then',
      optional($._terminated_statement),
    ),

    else_clause: $ => seq(
      'else',
      optional($._terminated_statement),
    ),

    case_statement: $ => seq(
      'case',
      field('value', $._literal),
      optional($._terminator),
      'in',
      optional($._terminator),
      optional(seq(
        repeat($.case_item),
        alias($.last_case_item, $.case_item),
      )),
      'esac',
    ),

    case_item: $ => seq(
      choice(
        seq(
          optional('('),
          field('value', choice($._literal, $._extglob_blob)),
          repeat(seq('|', field('value', choice($._literal, $._extglob_blob)))),
          ')',
        ),
      ),
      optional($._statements),
      prec(1, choice(
        field('termination', ';;'),
        field('fallthrough', choice(';&', ';;&')),
      )),
    ),

    last_case_item: $ => seq(
      optional('('),
      field('value', choice($._literal, $._extglob_blob)),
      repeat(seq('|', field('value', choice($._literal, $._extglob_blob)))),
      ')',
      optional($._statements),
      optional(prec(1, ';;')),
    ),

    function_definition: $ => prec.right(seq(
      choice(
        seq(
          'function',
          field('name', $.word),
          optional(seq('(', ')')),
        ),
        seq(
          field('name', $.word),
          '(', ')',
        ),
      ),
      field(
        'body',
        choice(
          $.compound_statement,
          $.subshell,
          $.test_command,
          $.if_statement,
        ),
      ),
      field('redirect', optional($._redirect)),
    )),

    compound_statement: $ => choice(
      seq(
        '{',
        optional($._terminated_statement),
        token(prec(-1, '}')),
      ),
      seq(
        '((',
        repeat(
          seq(
            $._arithmetic_expression,
            ',',
          ),
        ),
        $._arithmetic_expression,
        '))'),
    ),

    subshell: $ => seq(
      '(',
      $._statements,
      ')',
    ),

    pipeline: $ => prec.right(seq(
      $._statement_not_pipeline,
      repeat1(seq(
        choice('|', '|&'),
        $._statement_not_pipeline,
      )),
    )),

    list: $ => prec.left(-1, seq(
      $._statement,
      choice('&&', '||'),
      $._statement,
    )),

    // Commands

    negated_command: $ => seq(
      '!',
      choice(
        prec(2, $.command),
        prec(1, $.variable_assignment),
        $.test_command,
        $.subshell,
      ),
    ),

    test_command: $ => seq(
      choice(
        seq('[', optional(choice($._expression, $.redirected_statement)), ']'),
        seq(
          '[[',
          choice(
            $._expression,
            alias($._test_command_binary_expression, $.binary_expression),
          ),
          ']]',
        ),
      ),
    ),

    _test_command_binary_expression: $ => prec(PREC.ASSIGN,
      seq(
        field('left', $._expression),
        field('operator', '='),
        field('right', alias($._regex_no_space, $.regex)),
      ),
    ),

    declaration_command: $ => prec.left(seq(
      choice('declare', 'typeset', 'export', 'readonly', 'local'),
      repeat(choice(
        $._literal,
        $._simple_variable_name,
        $.variable_assignment,
      )),
    )),

    unset_command: $ => prec.left(seq(
      choice('unset', 'unsetenv'),
      repeat(choice(
        $._literal,
        $._simple_variable_name,
      )),
    )),

    command: $ => prec.left(seq(
      repeat(choice(
        $.variable_assignment,
        field('redirect', $._redirect),
      )),
      field('name', $.command_name),
      choice(
        repeat(choice(
          field('argument', $._literal),
          field('argument', alias($._bare_dollar, '$')),
          field('argument', seq(
            choice('=~', '=='),
            choice($._literal, $.regex),
          )),
          field('redirect', $.herestring_redirect),
        )),
        $.subshell,
      ),
    )),

    command_name: $ => $._literal,

    variable_assignment: $ => seq(
      field('name', choice(
        $.variable_name,
        $.subscript,
      )),
      choice(
        '=',
        '+=',
      ),
      field('value', choice(
        $._literal,
        $.array,
        $._empty_value,
        alias($._comment_word, $.word),
      )),
    ),

    variable_assignments: $ => seq($.variable_assignment, repeat1($.variable_assignment)),

    subscript: $ => seq(
      field('name', $.variable_name),
      '[',
      field('index', choice($._literal, $.binary_expression, $.unary_expression, $.compound_statement, $.subshell)),
      optional($._concat),
      ']',
      optional($._concat),
    ),

    file_redirect: $ => prec.left(seq(
      field('descriptor', optional($.file_descriptor)),
      choice(
        seq(
          choice('<', '>', '>>', '&>', '&>>', '<&', '>&', '>|'),
          field('destination', repeat1($._literal)),
        ),
        seq(
          choice('<&-', '>&-'), // close file descriptor
          optional(field('destination', $._literal)),
        ),
      ),
    )),

    heredoc_redirect: $ => seq(
      field('descriptor', optional($.file_descriptor)),
      choice('<<', '<<-'),
      $.heredoc_start,
      optional(choice(
        alias($._heredoc_pipeline, $.pipeline),
        seq(
          field('redirect', repeat1($._redirect)),
          optional($._heredoc_expression),
        ),
        $._heredoc_expression,
        $._heredoc_command,
      )),
      /\n/,
      choice($._heredoc_body, $._simple_heredoc_body),
    ),

    _heredoc_pipeline: $ => seq(
      choice('|', '|&'),
      $._statement,
    ),

    _heredoc_expression: $ => seq(
      field('operator', choice('||', '&&')),
      field('right', $._statement),
    ),

    _heredoc_command: $ => repeat1(field('argument', $._literal)),

    _heredoc_body: $ => seq(
      $.heredoc_body,
      $.heredoc_end,
    ),

    heredoc_body: $ => seq(
      $._heredoc_body_beginning,
      repeat(choice(
        $.expansion,
        $.simple_expansion,
        $.command_substitution,
        $.heredoc_content,
      )),
    ),

    _simple_heredoc_body: $ => seq(
      alias($.simple_heredoc_body, $.heredoc_body),
      $.heredoc_end,
    ),

    herestring_redirect: $ => prec.left(seq(
      field('descriptor', optional($.file_descriptor)),
      '<<<',
      $._literal,
    )),

    _redirect: $ => choice($.file_redirect, $.herestring_redirect),

    // Expressions

    _expression: $ => choice(
      $._literal,
      $.unary_expression,
      $.ternary_expression,
      $.binary_expression,
      $.postfix_expression,
      $.parenthesized_expression,
    ),

    // https://tldp.org/LDP/abs/html/opprecedence.html
    binary_expression: $ => {
      const table = [
        [choice('+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '&=', '^=', '|='), PREC.UPDATE],
        [choice('=', '=~'), PREC.ASSIGN],
        ['||', PREC.LOGICAL_OR],
        ['&&', PREC.LOGICAL_AND],
        ['|', PREC.BITWISE_OR],
        ['^', PREC.BITWISE_XOR],
        ['&', PREC.BITWISE_AND],
        [choice('==', '!='), PREC.EQUALITY],
        [choice('<', '>', '<=', '>='), PREC.COMPARE],
        [$.test_operator, PREC.TEST],
        [choice('<<', '>>'), PREC.SHIFT],
        [choice('+', '-'), PREC.ADD],
        [choice('*', '/', '%'), PREC.MULTIPLY],
        ['**', PREC.EXPONENT],
      ];

      return choice(
        choice(...table.map(([operator, precedence]) => {
          // @ts-ignore
          return prec[operator === '**' ? 'right' : 'left'](precedence, seq(
            field('left', $._expression),
            // @ts-ignore
            field('operator', operator),
            field('right', $._expression),
          ));
        })),
        prec(PREC.ASSIGN, seq(
          field('left', $._expression),
          field('operator', '=~'),
          field('right', alias($._regex_no_space, $.regex)),
        )),
        prec(PREC.EQUALITY, seq(
          field('left', $._expression),
          field('operator', choice('==', '!=')),
          field('right', $._extglob_blob),
        )),
      );
    },

    ternary_expression: $ => prec.left(PREC.TERNARY, seq(
      field('condition', $._expression),
      '?',
      field('consequence', $._expression),
      ':',
      field('alternative', $._expression),
    )),

    unary_expression: $ => choice(
      prec(PREC.PREFIX, seq(
        field('operator', tokenLiterals(1, '++', '--')),
        $._expression,
      )),
      prec(PREC.UNARY, seq(
        field('operator', tokenLiterals(1, '-', '+', '~')),
        $._expression,
      )),
      prec.right(PREC.UNARY, seq(
        field('operator', '!'),
        $._expression,
      )),
      prec.right(PREC.TEST, seq(
        field('operator', $.test_operator),
        $._expression,
      )),
    ),

    postfix_expression: $ => prec(PREC.POSTFIX, seq(
      $._expression,
      field('operator', choice('++', '--')),
    )),

    parenthesized_expression: $ => seq(
      '(',
      $._expression,
      ')',
    ),

    // Literals

    _literal: $ => choice(
      $.concatenation,
      $._primary_expression,
      alias(prec(-2, repeat1($._special_character)), $.word),
    ),

    _primary_expression: $ => choice(
      $.word,
      alias($.test_operator, $.word),
      $.string,
      $.raw_string,
      $.translated_string,
      $.ansi_c_string,
      $.number,
      $.expansion,
      $.simple_expansion,
      $.command_substitution,
      $.process_substitution,
      $.arithmetic_expansion,
      $.brace_expression,
    ),

    arithmetic_expansion: $ => choice(
      seq('$((', commaSep1($._arithmetic_expression), '))'),
      seq('$[', $._arithmetic_expression, ']'),
    ),

    brace_expression: $ => seq(
      alias($._brace_start, '{'),
      alias(token.immediate(/\d+/), $.number),
      token.immediate('..'),
      alias(token.immediate(/\d+/), $.number),
      token.immediate('}'),
    ),

    _arithmetic_expression: $ => prec(1, choice(
      $._arithmetic_literal,
      alias($._arithmetic_unary_expression, $.unary_expression),
      alias($._arithmetic_ternary_expression, $.ternary_expression),
      alias($._arithmetic_binary_expression, $.binary_expression),
      alias($._arithmetic_postfix_expression, $.postfix_expression),
      alias($._arithmetic_parenthesized_expression, $.parenthesized_expression),
      $.command_substitution,
    )),

    _arithmetic_literal: $ => prec(1, choice(
      $.number,
      $.subscript,
      $.simple_expansion,
      $.expansion,
      $._simple_variable_name,
      $.variable_name,
      $.string,
      $.raw_string,
    )),

    _arithmetic_binary_expression: $ => {
      const table = [
        [choice('+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '&=', '^=', '|='), PREC.UPDATE],
        [choice('=', '=~'), PREC.ASSIGN],
        ['||', PREC.LOGICAL_OR],
        ['&&', PREC.LOGICAL_AND],
        ['|', PREC.BITWISE_OR],
        ['^', PREC.BITWISE_XOR],
        ['&', PREC.BITWISE_AND],
        [choice('==', '!='), PREC.EQUALITY],
        [choice('<', '>', '<=', '>='), PREC.COMPARE],
        [choice('<<', '>>'), PREC.SHIFT],
        [choice('+', '-'), PREC.ADD],
        [choice('*', '/', '%'), PREC.MULTIPLY],
        ['**', PREC.EXPONENT],
      ];

      return choice(...table.map(([operator, precedence]) => {
        // @ts-ignore
        return prec.left(precedence, seq(
          field('left', $._arithmetic_expression),
          // @ts-ignore
          field('operator', operator),
          field('right', $._arithmetic_expression),
        ));
      }));
    },

    _arithmetic_ternary_expression: $ => prec.left(PREC.TERNARY, seq(
      field('condition', $._arithmetic_expression),
      '?',
      field('consequence', $._arithmetic_expression),
      ':',
      field('alternative', $._arithmetic_expression),
    )),

    _arithmetic_unary_expression: $ => choice(
      prec(PREC.PREFIX, seq(
        field('operator', tokenLiterals(1, '++', '--')),
        $._arithmetic_expression,
      )),
      prec(PREC.UNARY, seq(
        field('operator', tokenLiterals(1, '-', '+', '~')),
        $._arithmetic_expression,
      )),
      prec.right(PREC.UNARY, seq(
        field('operator', '!'),
        $._arithmetic_expression,
      )),
    ),

    _arithmetic_postfix_expression: $ => prec(PREC.POSTFIX, seq(
      $._arithmetic_expression,
      field('operator', choice('++', '--')),
    )),

    _arithmetic_parenthesized_expression: $ => seq(
      '(',
      $._arithmetic_expression,
      ')',
    ),


    concatenation: $ => prec(-1, seq(
      choice(
        $._primary_expression,
        alias($._special_character, $.word),
      ),
      repeat1(seq(
        choice($._concat, alias(/`\s*`/, '``')),
        choice(
          $._primary_expression,
          alias($._special_character, $.word),
          alias($._comment_word, $.word),
          alias($._bare_dollar, '$'),
        ),
      )),
      optional(seq($._concat, '$')),
    )),

    _special_character: _ => token(prec(-1, choice('{', '}', '[', ']'))),

    string: $ => seq(
      '"',
      repeat(seq(
        choice(
          seq(optional('$'), $.string_content),
          $.expansion,
          $.simple_expansion,
          $.command_substitution,
          $.arithmetic_expansion,
        ),
        optional($._concat),
      )),
      optional('$'),
      '"',
    ),

    string_content: _ => token(prec(-1, /([^"`$\\\r\n]|\\(.|\r?\n))+/)),

    translated_string: $ => seq('$', $.string),

    array: $ => seq(
      '(',
      repeat($._literal),
      ')',
    ),

    raw_string: _ => /'[^']*'/,

    ansi_c_string: _ => /\$'([^']|\\')*'/,

    number: $ => choice(
      /-?(0x)?[0-9]+(#[0-9A-Za-z@_]+)?/,
      // the base can be an expansion or command substitution
      seq(/-?(0x)?[0-9]+#/, choice($.expansion, $.command_substitution)),
    ),

    simple_expansion: $ => seq(
      '$',
      choice(
        $._simple_variable_name,
        $._multiline_variable_name,
        $._special_variable_name,
        $.variable_name,
        alias('!', $.special_variable_name),
        alias('#', $.special_variable_name),
      ),
    ),

    string_expansion: $ => seq('$', $.string),

    expansion: $ => seq(
      '${',
      optional($._expansion_body),
      '}',
    ),
    _expansion_body: $ => choice(
      // ${!##} ${!#}
      repeat1(field(
        'operator',
        choice(
          alias($._external_expansion_sym_hash, '#'),
          alias($._external_expansion_sym_bang, '!'),
          alias($._external_expansion_sym_equal, '='),
        ),
      )),
      seq(
        optional(field('operator', token.immediate('!'))),
        choice($.variable_name, $._simple_variable_name, $._special_variable_name, $.subscript),
        choice(
          $._expansion_expression,
          $._expansion_regex,
          $._expansion_regex_replacement,
          $._expansion_regex_removal,
          $._expansion_max_length,
          $._expansion_operator,
        ),
      ),
      seq(
        field('operator', token.immediate('!')),
        choice($._simple_variable_name, $.variable_name),
        optional(field('operator', choice(
          token.immediate('@'),
          token.immediate('*'),
        ))),
      ),
      seq(
        optional(field('operator', immediateLiterals('#', '!', '='))),
        choice(
          $.subscript,
          $._simple_variable_name,
          $._special_variable_name,
          $.command_substitution,
        ),
        repeat(field(
          'operator',
          choice(
            alias($._external_expansion_sym_hash, '#'),
            alias($._external_expansion_sym_bang, '!'),
            alias($._external_expansion_sym_equal, '='),
          ),
        )),
      ),
    ),

    _expansion_expression: $ => prec(1, seq(
      field('operator', immediateLiterals('=', ':=', '-', ':-', '+', ':+', '?', ':?')),
      optional(seq(
        choice(
          alias($._concatenation_in_expansion, $.concatenation),
          $.command_substitution,
          $.word,
          $.expansion,
          $.simple_expansion,
          $.array,
          $.string,
          $.raw_string,
          $.ansi_c_string,
          alias($._expansion_word, $.word),
        ),
      )),
    )),

    _expansion_regex: $ => seq(
      field('operator', choice('#', alias($._immediate_double_hash, '##'), '%', '%%')),
      repeat(choice(
        $.regex,
        alias(')', $.regex),
        $.string,
        $.raw_string,
        alias(/\s+/, $.regex),
      )),
    ),

    _expansion_regex_replacement: $ => seq(
      field('operator', choice('/', '//', '/#', '/%')),
      optional(choice(
        alias($._regex_no_slash, $.regex),
        $.string,
        $.command_substitution,
        seq($.string, alias($._regex_no_slash, $.regex)),
      )),
      // This can be elided
      optional(seq(
        field('operator', '/'),
        optional(seq(
          choice(
            $._primary_expression,
            alias(prec(-2, repeat1($._special_character)), $.word),
            seq($.command_substitution, alias($._expansion_word, $.word)),
            alias($._expansion_word, $.word),
            alias($._concatenation_in_expansion, $.concatenation),
            $.array,
          ),
          field('operator', optional('/')),
        )),
      )),
    ),

    _expansion_regex_removal: $ => seq(
      field('operator', choice(',', ',,', '^', '^^')),
      optional($.regex),
    ),

    _expansion_max_length: $ => seq(
      field('operator', ':'),
      optional(choice(
        $._simple_variable_name,
        $.number,
        $.arithmetic_expansion,
        $.expansion,
        $.parenthesized_expression,
        $.command_substitution,
        alias($._expansion_max_length_binary_expression, $.binary_expression),
        /\n/,
      )),
      optional(seq(
        field('operator', ':'),
        optional($.simple_expansion),
        optional(choice(
          $._simple_variable_name,
          $.number,
          $.arithmetic_expansion,
          $.expansion,
          $.parenthesized_expression,
          $.command_substitution,
          alias($._expansion_max_length_binary_expression, $.binary_expression),
          /\n/,
        )),
      )),
    ),

    _expansion_max_length_expression: $ => choice(
      $._simple_variable_name,
      $.number,
      $.expansion,
      alias($._expansion_max_length_binary_expression, $.binary_expression),
    ),
    _expansion_max_length_binary_expression: $ => {
      const table = [
        [choice('+', '-'), PREC.ADD],
        [choice('*', '/', '%'), PREC.MULTIPLY],
      ];

      return choice(...table.map(([operator, precedence]) => {
        // @ts-ignore
        return prec.left(precedence, seq(
          $._expansion_max_length_expression,
          // @ts-ignore
          field('operator', operator),
          $._expansion_max_length_expression,
        ));
      }));
    },

    _expansion_operator: _ => seq(
      field('operator', token.immediate('@')),
      field('operator', immediateLiterals('U', 'u', 'L', 'Q', 'E', 'P', 'A', 'K', 'a', 'k')),
    ),

    _concatenation_in_expansion: $ => prec(-2, seq(
      choice(
        $.word,
        $.variable_name,
        $.simple_expansion,
        $.expansion,
        $.string,
        $.raw_string,
        $.ansi_c_string,
        $.command_substitution,
        alias($._expansion_word, $.word),
        $.array,
        $.process_substitution,
      ),
      repeat1(seq(
        choice($._concat, alias(/`\s*`/, '``')),
        choice(
          $.word,
          $.variable_name,
          $.simple_expansion,
          $.expansion,
          $.string,
          $.raw_string,
          $.ansi_c_string,
          $.command_substitution,
          alias($._expansion_word, $.word),
          $.array,
          $.process_substitution,
        ),
      )),
    )),

    command_substitution: $ => choice(
      seq('$(', $._statements, ')'),
      seq('$(', field('redirect', $.file_redirect), ')'),
      prec(1, seq('`', $._statements, '`')),
      seq('$`', $._statements, '`'),
    ),

    process_substitution: $ => seq(
      choice('<(', '>('),
      $._statements,
      ')',
    ),

    _extglob_blob: $ => choice(
      $.extglob_pattern,
      seq(
        $.extglob_pattern,
        choice($.string, $.expansion, $.command_substitution),
        optional($.extglob_pattern),
      ),
    ),

    comment: _ => token(prec(-10, /#.*/)),

    _comment_word: _ => token(prec(-8, seq(
      choice(
        noneOf(...SPECIAL_CHARACTERS),
        seq('\\', noneOf('\\s')),
      ),
      repeat(choice(
        noneOf(...SPECIAL_CHARACTERS),
        seq('\\', noneOf('\\s')),
        '\\ ',
      )),
    ))),

    _simple_variable_name: $ => alias(/\w+/, $.variable_name),
    _multiline_variable_name: $ => alias(
      token(prec(-1, /(\w|\\\r?\n)+/)),
      $.variable_name,
    ),

    _special_variable_name: $ => alias(choice('*', '@', '?', '!', '#', '-', '$', '_'), $.special_variable_name),

    word: _ => token(seq(
      choice(
        noneOf('#', ...SPECIAL_CHARACTERS),
        seq('\\', noneOf('\\s')),
      ),
      repeat(choice(
        noneOf(...SPECIAL_CHARACTERS),
        seq('\\', noneOf('\\s')),
        '\\ ',
      )),
    )),

    _c_terminator: _ => choice(';', /\n/, '&'),
    _terminator: _ => choice(';', ';;', /\n/, '&'),
  },
});

/**
 * Returns a regular expression that matches any character except the ones
 * provided.
 *
 * @param  {...string} characters
 *
 * @returns {RegExp}
 */
function noneOf(...characters) {
  const negatedString = characters.map(c => c == '\\' ? '\\\\' : c).join('');
  return new RegExp('[^' + negatedString + ']');
}

/**
 * Creates a rule to optionally match one or more of the rules separated by a comma
 *
 * @param {RuleOrLiteral} rule
 *
 * @returns {ChoiceRule}
 */
function commaSep(rule) {
  return optional(commaSep1(rule));
}

/**
 * Creates a rule to match one or more of the rules separated by a comma
 *
 * @param {RuleOrLiteral} rule
 *
 * @returns {SeqRule}
 */
function commaSep1(rule) {
  return seq(rule, repeat(seq(',', rule)));
}

/**
 *
 * Turns a list of rules into a choice of immediate rule
 *
 * @param {(RegExp | string)[]} literals
 *
 * @returns {ChoiceRule}
 */
function immediateLiterals(...literals) {
  return choice(...literals.map(l => token.immediate(l)));
}

/**
 *
 * Turns a list of rules into a choice of aliased token rules
 *
 * @param {number} precedence
 *
 * @param {(RegExp | string)[]} literals
 *
 * @returns {ChoiceRule}
 */
function tokenLiterals(precedence, ...literals) {
  return choice(...literals.map(l => token(prec(precedence, l))));
}


================================================
FILE: package.json
================================================
{
  "name": "tree-sitter-bash",
  "version": "0.25.1",
  "description": "Bash grammar for tree-sitter",
  "repository": "https://github.com/tree-sitter/tree-sitter-bash",
  "license": "MIT",
  "author": {
    "name": "Max Brunsfeld",
    "email": "maxbrunsfeld@gmail.com"
  },
  "maintainers": [
    {
      "name": "Amaan Qureshi",
      "email": "amaanq12@gmail.com"
    }
  ],
  "main": "bindings/node",
  "types": "bindings/node",
  "keywords": [
    "incremental",
    "parsing",
    "tree-sitter",
    "bash"
  ],
  "files": [
    "grammar.js",
    "tree-sitter.json",
    "binding.gyp",
    "prebuilds/**",
    "bindings/node/*",
    "queries/*",
    "src/**",
    "*.wasm"
  ],
  "dependencies": {
    "node-addon-api": "^8.2.1",
    "node-gyp-build": "^4.8.2"
  },
  "devDependencies": {
    "eslint": "^9.12.0",
    "eslint-config-treesitter": "^1.0.2",
    "tree-sitter-cli": "^0.25.6",
    "prebuildify": "^6.0.1"
  },
  "peerDependencies": {
    "tree-sitter": "^0.25.0"
  },
  "peerDependenciesMeta": {
    "tree-sitter": {
      "optional": true
    }
  },
  "scripts": {
    "install": "node-gyp-build",
    "lint": "eslint grammar.js",
    "prestart": "tree-sitter build --wasm",
    "start": "tree-sitter playground",
    "test": "node --test bindings/node/*_test.js"
  }
}


================================================
FILE: pyproject.toml
================================================
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "tree-sitter-bash"
description = "Bash grammar for tree-sitter"
version = "0.25.1"
keywords = ["incremental", "parsing", "tree-sitter", "bash"]
classifiers = [
  "Intended Audience :: Developers",
  "License :: OSI Approved :: MIT License",
  "Topic :: Software Development :: Compilers",
  "Topic :: Text Processing :: Linguistic",
  "Typing :: Typed",
]
authors = [
  { name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" },
  { name = "Amaan Qureshi", email = "amaanq12@gmail.com" },
]
requires-python = ">=3.10"
license.text = "MIT"
readme = "README.md"

[project.urls]
Homepage = "https://github.com/tree-sitter/tree-sitter-bash"

[project.optional-dependencies]
core = ["tree-sitter~=0.24"]

[tool.cibuildwheel]
build = "cp310-*"
build-frontend = "build"


================================================
FILE: queries/highlights.scm
================================================
[
  (string)
  (raw_string)
  (heredoc_body)
  (heredoc_start)
] @string

(command_name) @function

(variable_name) @property

[
  "case"
  "do"
  "done"
  "elif"
  "else"
  "esac"
  "export"
  "fi"
  "for"
  "function"
  "if"
  "in"
  "select"
  "then"
  "unset"
  "until"
  "while"
] @keyword

(comment) @comment

(function_definition name: (word) @function)

(file_descriptor) @number

[
  (command_substitution)
  (process_substitution)
  (expansion)
]@embedded

[
  "$"
  "&&"
  ">"
  ">>"
  "<"
  "|"
] @operator

(
  (command (_) @constant)
  (#match? @constant "^-")
)


================================================
FILE: script/known-failures.txt
================================================
examples/bash-it/completion/available/bundler.completion.bash
examples/bash-it/completion/available/sqlmap.completion.bash
examples/bash-it/plugins/available/colors.plugin.bash
examples/bash-it/plugins/available/history-eternal.plugin.bash
examples/bash-it/themes/hawaii50/hawaii50.theme.bash
examples/bash/examples/functions/notify.bash
examples/bash/examples/shellmath/shellmath.sh
examples/bash/tests/arith-for.tests
examples/bash/tests/arith.tests
examples/bash/tests/array.tests
examples/bash/tests/assoc.tests
examples/bash/tests/braces.tests
examples/bash/tests/case.tests
examples/bash/tests/casemod.tests
examples/bash/tests/comsub-posix.tests
examples/bash/tests/comsub.tests
examples/bash/tests/comsub2.tests
examples/bash/tests/cond.tests
examples/bash/tests/errors.tests
examples/bash/tests/extglob.tests
examples/bash/tests/glob.tests
examples/bash/tests/heredoc.tests
examples/bash/tests/histexp.tests
examples/bash/tests/misc/dev-tcp.tests
examples/bash/tests/more-exp.tests
examples/bash/tests/new-exp.tests
examples/bash/tests/parser.tests
examples/bash/tests/posixexp.tests
examples/bash/tests/posixexp2.tests
examples/bash/tests/printf.tests
examples/bash/tests/quote.tests
examples/bash/tests/quotearray.tests
examples/bash/tests/redir.tests
examples/bash/tests/test.tests
examples/gentoo/app-misc/editor-wrapper/files/editor-wrapper-4.sh
examples/gentoo/dev-lang/rust/rust-1.74.1-r101.ebuild
examples/gentoo/dev-libs/libffi/libffi-3.5.1.ebuild
examples/gentoo/dev-libs/libffi/libffi-3.5.2.ebuild
examples/gentoo/dev-libs/libffi/libffi-9999.ebuild
examples/gentoo/eclass/rust.eclass
examples/gentoo/eclass/tests/toolchain-funcs.sh
examples/gentoo/eclass/texlive-common.eclass
examples/gentoo/eclass/toolchain-funcs.eclass
examples/gentoo/mail-client/thunderbird-bin/files/thunderbird-bin-r1.sh
examples/gentoo/mail-client/thunderbird/files/thunderbird-r1.sh
examples/gentoo/net-misc/asterisk/asterisk-18.26.2.ebuild
examples/gentoo/net-misc/asterisk/asterisk-18.26.4.ebuild
examples/gentoo/net-misc/asterisk/asterisk-20.15.2.ebuild
examples/gentoo/net-misc/asterisk/asterisk-21.10.2.ebuild
examples/gentoo/net-misc/asterisk/asterisk-22.5.2.ebuild
examples/gentoo/sys-apps/dcfldd/dcfldd-1.9.2-r1.ebuild
examples/gentoo/sys-apps/dcfldd/dcfldd-1.9.3.ebuild
examples/gentoo/sys-apps/less/files/lesspipe-r3.sh
examples/gentoo/sys-apps/less/files/lesspipe-r4.sh
examples/gentoo/sys-apps/locale-gen/locale-gen-3.8.ebuild
examples/gentoo/sys-apps/locale-gen/locale-gen-3.9-r1.ebuild
examples/gentoo/sys-apps/locale-gen/locale-gen-9999.ebuild
examples/gentoo/sys-fs/bcachefs-tools/bcachefs-tools-1.25.3.ebuild
examples/gentoo/sys-fs/bcachefs-tools/bcachefs-tools-1.31.5.ebuild
examples/gentoo/www-client/firefox-bin/files/firefox-bin-r1.sh
examples/gentoo/www-client/firefox/files/firefox-r1.sh
examples/wild-corpus/cloud/chef-bcpc/legacy_scripts/make_databag.sh
examples/wild-corpus/cloud/docker/hack/make.sh
examples/wild-corpus/cloud/kubernetes/build/common.sh
examples/wild-corpus/cloud/kubernetes/cluster/gce/config-default.sh
examples/wild-corpus/cloud/kubernetes/cluster/gce/config-test.sh
examples/wild-corpus/cloud/kubernetes/hack/benchmark-go.sh
examples/wild-corpus/cloud/kubernetes/hack/generate-bindata.sh
examples/wild-corpus/cloud/kubernetes/hack/lib/golang.sh
examples/wild-corpus/cloud/kubernetes/hack/lib/test.sh
examples/wild-corpus/cloud/kubernetes/hack/make-rules/test-integration.sh
examples/wild-corpus/cloud/kubernetes/hack/make-rules/test.sh
examples/wild-corpus/cloud/kubernetes/hack/make-rules/verify.sh
examples/wild-corpus/cloud/kubernetes/hack/update-api-reference-docs.sh
examples/wild-corpus/cloud/kubernetes/hack/update-codegen.sh
examples/wild-corpus/cloud/kubernetes/hack/update-federation-api-reference-docs.sh
examples/wild-corpus/cloud/kubernetes/hack/update-federation-swagger-spec.sh
examples/wild-corpus/cloud/kubernetes/hack/update-swagger-spec.sh
examples/wild-corpus/cloud/kubernetes/test/e2e_node/gubernator.sh
examples/wild-corpus/cloud/kubernetes/vendor/github.com/ugorji/go/codec/prebuild.sh
examples/wild-corpus/cloud/sandstorm/install.sh
examples/wild-corpus/cloud/sandstorm/make-bundle.sh
examples/wild-corpus/cloud/sandstorm/shell/run-dev.sh
examples/wild-corpus/distro/DietPi/PREP_SYSTEM_FOR_DIETPI.sh
examples/wild-corpus/distro/portage/bin/misc-functions.sh
examples/wild-corpus/distro/portage/bin/phase-helpers.sh
examples/wild-corpus/distro/woof-CE/initrd-progs/build.sh
examples/wild-corpus/distro/woof-CE/woof-code/rootfs-packages/network_wizard/usr/sbin/wag-profiles.sh
examples/wild-corpus/distro/woof-CE/woof-code/rootfs-skeleton/usr/local/petget/installpkg.sh
examples/wild-corpus/distro/woof-CE/woof-code/rootfs-skeleton/usr/local/petget/pkg_chooser.sh
examples/wild-corpus/esoteric/CmdlineGL/share/examples/FlightSim.sh
examples/wild-corpus/esoteric/CmdlineGL/share/examples/Robot.sh
examples/wild-corpus/esoteric/make-a-lisp-bash/core.sh
examples/wild-corpus/esoteric/shasm/shasm.sh
examples/wild-corpus/exp/shootout/timing.sh
examples/wild-corpus/freebsd-11.1/contrib/binutils/ld/emulparams/elf64bmip.sh
examples/wild-corpus/freebsd-11.1/contrib/binutils/ld/genscripts.sh
examples/wild-corpus/freebsd-11.1/contrib/gcc/scan-types.sh
examples/wild-corpus/freebsd-11.1/contrib/groff/src/preproc/eqn/neqn.sh
examples/wild-corpus/freebsd-11.1/contrib/groff/src/roff/nroff/nroff.sh
examples/wild-corpus/freebsd-11.1/contrib/netbsd-tests/bin/sh/t_arith.sh
examples/wild-corpus/freebsd-11.1/contrib/netbsd-tests/bin/sh/t_here.sh
examples/wild-corpus/freebsd-11.1/contrib/ntp/scripts/stats/summary.sh
examples/wild-corpus/freebsd-11.1/contrib/ntp/scripts/update-leap/update-leap.sh
examples/wild-corpus/freebsd-11.1/crypto/openssl/util/bat.sh
examples/wild-corpus/freebsd-11.1/gnu/usr.bin/binutils/ld/genscripts.sh
examples/wild-corpus/freebsd-11.1/share/examples/drivers/make_device_driver.sh
examples/wild-corpus/freebsd-11.1/share/examples/drivers/make_pseudo_driver.sh
examples/wild-corpus/freebsd-11.1/tools/tools/mctest/mctest_run.sh
examples/wild-corpus/freebsd-11.1/tools/tools/nanobsd/fill_pkg.sh
examples/wild-corpus/freebsd-11.1/tools/tools/shlib-compat/test/regress.sh
examples/wild-corpus/freebsd-11.1/tools/tools/sysbuild/sysbuild.sh
examples/wild-corpus/freebsd-11.1/tools/tools/sysdoc/sysdoc.sh
examples/wild-corpus/freebsd-11.1/usr.bin/apply/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/calendar/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/comm/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/file2c/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/join/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/jot/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/m4/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/man/man.sh
examples/wild-corpus/freebsd-11.1/usr.bin/ncal/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/printf/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/sed/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/shar/shar.sh
examples/wild-corpus/freebsd-11.1/usr.bin/tr/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/uudecode/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/uuencode/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.bin/xargs/tests/regress.sh
examples/wild-corpus/freebsd-11.1/usr.sbin/adduser/adduser.sh
examples/wild-corpus/freebsd-11.1/usr.sbin/freebsd-update/freebsd-update.sh
examples/wild-corpus/freebsd-11.1/usr.sbin/manctl/manctl.sh
examples/wild-corpus/freebsd-11.1/usr.sbin/portsnap/portsnap/portsnap.sh
examples/wild-corpus/git/contrib/examples/git-ls-remote.sh
examples/wild-corpus/git/contrib/examples/git-merge.sh
examples/wild-corpus/git/contrib/examples/git-pull.sh
examples/wild-corpus/git/git-filter-branch.sh
examples/wild-corpus/git/git-merge-octopus.sh
examples/wild-corpus/git/git-merge-resolve.sh
examples/wild-corpus/git/git-rebase--interactive.sh
examples/wild-corpus/git/git-submodule.sh
examples/wild-corpus/git/t/lib-pack.sh
examples/wild-corpus/git/t/t9500-gitweb-standalone-no-errors.sh
examples/wild-corpus/gnu/binutils-2.26/ld/emulparams/elf64bmip.sh
examples/wild-corpus/gnu/binutils-2.26/ld/genscripts.sh
examples/wild-corpus/gnu/coreutils-8.22/gnulib-tests/init.sh
examples/wild-corpus/gnu/coreutils-8.22/tests/init.sh
examples/wild-corpus/gnu/coreutils-8.22/tests/ln/hard-to-sym.sh
examples/wild-corpus/gnu/glibc-2.23/posix/globtest.sh
examples/wild-corpus/gnu/glibc-2.23/posix/tst-getconf.sh
examples/wild-corpus/gnu/glibc-2.23/sysdeps/unix/make-syscalls.sh
examples/wild-corpus/gnu/grep-2.24/gnulib-tests/init.sh
examples/wild-corpus/gnu/grep-2.24/tests/init.sh
examples/wild-corpus/google/bazel/src/test/shell/bazel/remote_helpers.sh
examples/wild-corpus/google/kythe/.jenkins/nightly-release.sh
examples/wild-corpus/google/kythe/kythe/extractors/openjdk/extract.sh
examples/wild-corpus/hg-other/eigen/bench/perf_monitoring/gemm/run.sh
examples/wild-corpus/hg-other/pygments-main/tests/examplefiles/example.sh
examples/wild-corpus/hg-other/pygments-main/tests/examplefiles/ltmain.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/acct/prctmp.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/acct/prtacct.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/allocate/disk_clean.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/ast/msgcc/msgcc.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/avs/dscfg/dscfgadm.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/diff3/diff3.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/initpkg/umountall.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/ipf/examples/mkfilters.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/krb5/kadmin/kclient/kclient.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/svc/configd/restore_repository.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/svc/shell/ipf_include.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/tail/tests/sun_solaris_tail.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/tsol/misc/txzonemgr.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/ypcmd/multi.awk.sh
examples/wild-corpus/illumos-gate/usr/src/cmd/ypcmd/ypinit.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libast/common/comp/conf.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/data/bash_pre_rc.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/cpvprint.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/crawlsrccomments.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/filemutexdemo1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/filetree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/gnaw.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/mandelbrotset1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/multifollow.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/numtree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/primenumbers1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/rssread.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shcalc.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shircbot.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shlint.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shman.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shnote.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shpiano.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shtinyurl.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/shtwitter.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/simplefileattributetree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/simplefiletree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/svcproptree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/termclock.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/test_net_sctp.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/scripts/xmldocumenttree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/append.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/arith.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/arrays.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/arrays2.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/attributes.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/basic.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/bracket.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/builtins.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/comvar.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/coprocess.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/cubetype.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/enum.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/expand.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/functions.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/io.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/nameref.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/options.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/path.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/pointtype.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/quoting.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/quoting2.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/recttype.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sigchld.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/signal.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/statics.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/subshell.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/substring.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_array_default_datatype.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_builtin_poll.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_builtin_tail.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_command_substitution.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_compound_misc.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_compound_nameref.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_compoundvario.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6722134_background_CHLD_trap.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6789247_printf_hexfloat_rounding.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805792_varmovetest1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6805795_negative_zero.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6835835_builtin_cat_n_broken.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6855875_typeset_hexfloat_has_too_few_digits.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6881017_background_process_in_subshell_hangs_caller.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6904557_wc_no_longer_counts_number_of_bytes_correctly.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6904575_cut_-d_with_multibyte_character_no_longer_works.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6904878_join_-t_no_longer_works_with_multibyte_char_separator.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_cr_6907460_EXIT_trap_handlers_are_sometimes_executed_twice.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_locale_misc.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_staticvariables.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_vartree001.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_vartree002.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/sun_solaris_vartree003.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/tilde.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/timetype.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/treemove.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/types.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/variables.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/vartree1.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/common/tests/vartree2.sh
examples/wild-corpus/illumos-gate/usr/src/lib/libshell/misc/buildksh93.sh
examples/wild-corpus/illumos-gate/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh
examples/wild-corpus/illumos-gate/usr/src/tools/env/illumos.sh
examples/wild-corpus/illumos-gate/usr/src/tools/gk/cshrc.sh
examples/wild-corpus/illumos-gate/usr/src/tools/gk/gen_make.machines.sh
examples/wild-corpus/illumos-gate/usr/src/tools/gk/login.sh
examples/wild-corpus/illumos-gate/usr/src/tools/scripts/bldenv.sh
examples/wild-corpus/illumos-gate/usr/src/tools/scripts/nightly.sh
examples/wild-corpus/illumos-gate/usr/src/tools/scripts/webrev.sh
examples/wild-corpus/liballocs/tools/debug-funcs.sh
examples/wild-corpus/linux-4.8.7/scripts/decode_stacktrace.sh
examples/wild-corpus/linux-4.8.7/scripts/tags.sh
examples/wild-corpus/linux-4.8.7/tools/perf/perf-completion.sh
examples/wild-corpus/linux-4.8.7/tools/perf/perf-with-kcore.sh
examples/wild-corpus/linux-4.8.7/tools/vm/slabinfo-gnuplot.sh
examples/wild-corpus/minix/commands/scripts/DESCRIBE.sh
examples/wild-corpus/minix/commands/scripts/mkdist.sh
examples/wild-corpus/minix/lib/generate.sh
examples/wild-corpus/oil/test/gold.sh
examples/wild-corpus/oil/test/osh2oil.sh
examples/wild-corpus/oil/test/oshc-deps.sh
examples/wild-corpus/oil/test/smoke.sh
examples/wild-corpus/sdk/tools/clang/scripts/update.sh
examples/wild-corpus/shell/ast/src/cmd/3d/3d.sh
examples/wild-corpus/shell/ast/src/cmd/3d/features/syscall.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/ditto.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/hurl.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/iffe.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/mktest.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/package.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/regress.sh
examples/wild-corpus/shell/ast/src/cmd/INIT/rt.sh
examples/wild-corpus/shell/ast/src/cmd/html/mm2bb.sh
examples/wild-corpus/shell/ast/src/cmd/html/mm2html.sh
examples/wild-corpus/shell/ast/src/cmd/html/mm2twiki.sh
examples/wild-corpus/shell/ast/src/cmd/ie/ie.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/data/bash_pre_rc.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/append.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/arith.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/arrays.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/arrays2.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/attributes.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/basic.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/bracket.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/builtins.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/comvar.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/comvario.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/coprocess.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/cubetype.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/enum.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/expand.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/functions.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/heredoc.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/io.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/leaks.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/locale.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/math.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/nameref.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/namespace.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/options.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/path.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/pointtype.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/quoting.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/quoting2.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/recttype.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/sigchld.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/signal.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/statics.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/subshell.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/substring.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/tilde.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/timetype.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/treemove.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/types.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/variables.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/vartree1.sh
examples/wild-corpus/shell/ast/src/cmd/ksh93/tests/vartree2.sh
examples/wild-corpus/shell/ast/src/cmd/mam/mamold.sh
examples/wild-corpus/shell/ast/src/cmd/msgcc/msgadmin.sh
examples/wild-corpus/shell/ast/src/cmd/msgcc/msgcc.sh
examples/wild-corpus/shell/ast/src/cmd/pax/tar.sh
examples/wild-corpus/shell/ast/src/cmd/proto/changes.sh
examples/wild-corpus/shell/ast/src/cmd/std/seq.sh
examples/wild-corpus/shell/ast/src/cmd/warp/warp.sh
examples/wild-corpus/shell/ast/src/lib/libast/comp/conf.sh
examples/wild-corpus/shell/bashdb/command/backtrace.sh
examples/wild-corpus/shell/bashdb/command/set_sub/autoeval.sh
examples/wild-corpus/shell/bashdb/command/set_sub/autolist.sh
examples/wild-corpus/shell/bashdb/command/set_sub/basename.sh
examples/wild-corpus/shell/bashdb/command/set_sub/debug.sh
examples/wild-corpus/shell/bashdb/command/set_sub/debugging.sh
examples/wild-corpus/shell/bashdb/command/set_sub/editing.sh
examples/wild-corpus/shell/bashdb/command/set_sub/highlight.sh
examples/wild-corpus/shell/bashdb/command/set_sub/history.sh
examples/wild-corpus/shell/bashdb/command/set_sub/showcommand.sh
examples/wild-corpus/shell/bashdb/getopts_long.sh
examples/wild-corpus/shell/bashdb/lib/processor.sh
examples/wild-corpus/shell/bashdb/test/unit/test-file.sh
examples/wild-corpus/shell/mksh/Build.sh
examples/wild-corpus/shell/mksh/test.sh
examples/wild-corpus/shell/modernish/install.sh
examples/wild-corpus/shell/mwc-sh/shql.sh
examples/wild-corpus/shell/posixcube/test.sh


================================================
FILE: script/parse-examples
================================================
#!/usr/bin/env bash

set -euo pipefail

files=(
  examples/*.sh
  examples/bash-it/**/*.sh
  examples/bash-it/**/*.bash
  examples/bash/**/*.sh
  examples/bash/**/*.tests
  examples/gentoo/**/*.sh
  examples/gentoo/**/*.eclass
  examples/gentoo/**/*.ebuild
  examples/wild-corpus/**/*.sh
)

clone() {
  if [[ -d examples/$1 ]]; then
    git -C "examples/$1" fetch origin "$3:$3" -f -u --depth=1
  else
    git clone "$2" "examples/$1" -b "$3" --single-branch --depth=1
  fi
}

cd "${0%/script/parse-examples}"

clone bash-it https://github.com/Bash-it/bash-it master
clone bash https://git.savannah.gnu.org/git/bash.git master
clone gentoo https://anongit.gentoo.org/git/repo/gentoo.git master
clone wild-corpus https://github.com/oilshell/wild-corpus main

find examples \( -name '*.sh' -or -name '*.bash' -or -name '*.tests' -or \
  -name '*.eclass' -or -name '*.ebuild' \) -and -type f -print > script/example-files.txt

tree-sitter parse --scope source.bash -q -s --paths script/example-files.txt | \
  tee >(awk '/ERROR|MISSING/{print $1}' | sort > script/known-failures.txt)


================================================
FILE: setup.py
================================================
from os import path
from platform import system
from sysconfig import get_config_var

from setuptools import Extension, find_packages, setup
from setuptools.command.build import build
from setuptools.command.egg_info import egg_info
from wheel.bdist_wheel import bdist_wheel

sources = [
    "bindings/python/tree_sitter_bash/binding.c",
    "src/parser.c",
]
if path.exists("src/scanner.c"):
    sources.append("src/scanner.c")

macros: list[tuple[str, str | None]] = [
    ("PY_SSIZE_T_CLEAN", None),
    ("TREE_SITTER_HIDE_SYMBOLS", None),
]
if limited_api := not get_config_var("Py_GIL_DISABLED"):
    macros.append(("Py_LIMITED_API", "0x030A0000"))

if system() != "Windows":
    cflags = ["-std=c11", "-fvisibility=hidden"]
else:
    cflags = ["/std:c11", "/utf-8"]


class Build(build):
    def run(self):
        if path.isdir("queries"):
            dest = path.join(self.build_lib, "tree_sitter_bash", "queries")
            self.copy_tree("queries", dest)
        super().run()


class BdistWheel(bdist_wheel):
    def get_tag(self):
        python, abi, platform = super().get_tag()
        if python.startswith("cp"):
            python, abi = "cp310", "abi3"
        return python, abi, platform


class EggInfo(egg_info):
    def find_sources(self):
        super().find_sources()
        self.filelist.recursive_include("queries", "*.scm")
        self.filelist.include("src/tree_sitter/*.h")


setup(
    packages=find_packages("bindings/python"),
    package_dir={"": "bindings/python"},
    package_data={
        "tree_sitter_bash": ["*.pyi", "py.typed"],
        "tree_sitter_bash.queries": ["*.scm"],
    },
    ext_package="tree_sitter_bash",
    ext_modules=[
        Extension(
            name="_binding",
            sources=sources,
            extra_compile_args=cflags,
            define_macros=macros,
            include_dirs=["src"],
            py_limited_api=limited_api,
        )
    ],
    cmdclass={
        "build": Build,
        "bdist_wheel": BdistWheel,
        "egg_info": EggInfo,
    },
    zip_safe=False
)


================================================
FILE: src/grammar.json
================================================
{
  "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json",
  "name": "bash",
  "word": "word",
  "rules": {
    "program": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_statements"
        },
        {
          "type": "BLANK"
        }
      ]
    },
    "_statements": {
      "type": "PREC",
      "value": 1,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "REPEAT",
            "content": {
              "type": "SEQ",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "_statement"
                },
                {
                  "type": "SYMBOL",
                  "name": "_terminator"
                }
              ]
            }
          },
          {
            "type": "SYMBOL",
            "name": "_statement"
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "_terminator"
              },
              {
                "type": "BLANK"
              }
            ]
          }
        ]
      }
    },
    "_terminated_statement": {
      "type": "REPEAT1",
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "SYMBOL",
            "name": "_statement"
          },
          {
            "type": "SYMBOL",
            "name": "_terminator"
          }
        ]
      }
    },
    "_statement": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_statement_not_subshell"
        },
        {
          "type": "SYMBOL",
          "name": "subshell"
        }
      ]
    },
    "_statement_not_subshell": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "redirected_statement"
        },
        {
          "type": "SYMBOL",
          "name": "variable_assignment"
        },
        {
          "type": "SYMBOL",
          "name": "variable_assignments"
        },
        {
          "type": "SYMBOL",
          "name": "command"
        },
        {
          "type": "SYMBOL",
          "name": "declaration_command"
        },
        {
          "type": "SYMBOL",
          "name": "unset_command"
        },
        {
          "type": "SYMBOL",
          "name": "test_command"
        },
        {
          "type": "SYMBOL",
          "name": "negated_command"
        },
        {
          "type": "SYMBOL",
          "name": "for_statement"
        },
        {
          "type": "SYMBOL",
          "name": "c_style_for_statement"
        },
        {
          "type": "SYMBOL",
          "name": "while_statement"
        },
        {
          "type": "SYMBOL",
          "name": "if_statement"
        },
        {
          "type": "SYMBOL",
          "name": "case_statement"
        },
        {
          "type": "SYMBOL",
          "name": "pipeline"
        },
        {
          "type": "SYMBOL",
          "name": "list"
        },
        {
          "type": "SYMBOL",
          "name": "compound_statement"
        },
        {
          "type": "SYMBOL",
          "name": "function_definition"
        }
      ]
    },
    "_statement_not_pipeline": {
      "type": "PREC",
      "value": 1,
      "content": {
        "type": "CHOICE",
        "members": [
          {
            "type": "SYMBOL",
            "name": "redirected_statement"
          },
          {
            "type": "SYMBOL",
            "name": "variable_assignment"
          },
          {
            "type": "SYMBOL",
            "name": "variable_assignments"
          },
          {
            "type": "SYMBOL",
            "name": "command"
          },
          {
            "type": "SYMBOL",
            "name": "declaration_command"
          },
          {
            "type": "SYMBOL",
            "name": "unset_command"
          },
          {
            "type": "SYMBOL",
            "name": "test_command"
          },
          {
            "type": "SYMBOL",
            "name": "negated_command"
          },
          {
            "type": "SYMBOL",
            "name": "for_statement"
          },
          {
            "type": "SYMBOL",
            "name": "c_style_for_statement"
          },
          {
            "type": "SYMBOL",
            "name": "while_statement"
          },
          {
            "type": "SYMBOL",
            "name": "if_statement"
          },
          {
            "type": "SYMBOL",
            "name": "case_statement"
          },
          {
            "type": "SYMBOL",
            "name": "list"
          },
          {
            "type": "SYMBOL",
            "name": "compound_statement"
          },
          {
            "type": "SYMBOL",
            "name": "function_definition"
          },
          {
            "type": "SYMBOL",
            "name": "subshell"
          }
        ]
      }
    },
    "redirected_statement": {
      "type": "PREC_DYNAMIC",
      "value": -1,
      "content": {
        "type": "PREC_RIGHT",
        "value": -1,
        "content": {
          "type": "CHOICE",
          "members": [
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "FIELD",
                  "name": "body",
                  "content": {
                    "type": "SYMBOL",
                    "name": "_statement"
                  }
                },
                {
                  "type": "FIELD",
                  "name": "redirect",
                  "content": {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "REPEAT1",
                        "content": {
                          "type": "CHOICE",
                          "members": [
                            {
                              "type": "SYMBOL",
                              "name": "file_redirect"
                            },
                            {
                              "type": "SYMBOL",
                              "name": "heredoc_redirect"
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "FIELD",
                  "name": "body",
                  "content": {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "SYMBOL",
                        "name": "if_statement"
                      },
                      {
                        "type": "SYMBOL",
                        "name": "while_statement"
                      }
                    ]
                  }
                },
                {
                  "type": "SYMBOL",
                  "name": "herestring_redirect"
                }
              ]
            },
            {
              "type": "FIELD",
              "name": "redirect",
              "content": {
                "type": "REPEAT1",
                "content": {
                  "type": "SYMBOL",
                  "name": "_redirect"
                }
              }
            },
            {
              "type": "SYMBOL",
              "name": "herestring_redirect"
            }
          ]
        }
      }
    },
    "for_statement": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "for"
            },
            {
              "type": "STRING",
              "value": "select"
            }
          ]
        },
        {
          "type": "FIELD",
          "name": "variable",
          "content": {
            "type": "SYMBOL",
            "name": "_simple_variable_name"
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "STRING",
                  "value": "in"
                },
                {
                  "type": "FIELD",
                  "name": "value",
                  "content": {
                    "type": "REPEAT1",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_literal"
                    }
                  }
                }
              ]
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "SYMBOL",
          "name": "_terminator"
        },
        {
          "type": "FIELD",
          "name": "body",
          "content": {
            "type": "SYMBOL",
            "name": "do_group"
          }
        }
      ]
    },
    "c_style_for_statement": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "for"
        },
        {
          "type": "STRING",
          "value": "(("
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_for_body"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "))"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": ";"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "FIELD",
          "name": "body",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "do_group"
              },
              {
                "type": "SYMBOL",
                "name": "compound_statement"
              }
            ]
          }
        }
      ]
    },
    "_for_body": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "initializer",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "SYMBOL",
                    "name": "_c_expression"
                  },
                  {
                    "type": "REPEAT",
                    "content": {
                      "type": "SEQ",
                      "members": [
                        {
                          "type": "STRING",
                          "value": ","
                        },
                        {
                          "type": "SYMBOL",
                          "name": "_c_expression"
                        }
                      ]
                    }
                  }
                ]
              },
              {
                "type": "BLANK"
              }
            ]
          }
        },
        {
          "type": "SYMBOL",
          "name": "_c_terminator"
        },
        {
          "type": "FIELD",
          "name": "condition",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "SYMBOL",
                    "name": "_c_expression"
                  },
                  {
                    "type": "REPEAT",
                    "content": {
                      "type": "SEQ",
                      "members": [
                        {
                          "type": "STRING",
                          "value": ","
                        },
                        {
                          "type": "SYMBOL",
                          "name": "_c_expression"
                        }
                      ]
                    }
                  }
                ]
              },
              {
                "type": "BLANK"
              }
            ]
          }
        },
        {
          "type": "SYMBOL",
          "name": "_c_terminator"
        },
        {
          "type": "FIELD",
          "name": "update",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "SYMBOL",
                    "name": "_c_expression"
                  },
                  {
                    "type": "REPEAT",
                    "content": {
                      "type": "SEQ",
                      "members": [
                        {
                          "type": "STRING",
                          "value": ","
                        },
                        {
                          "type": "SYMBOL",
                          "name": "_c_expression"
                        }
                      ]
                    }
                  }
                ]
              },
              {
                "type": "BLANK"
              }
            ]
          }
        }
      ]
    },
    "_c_expression": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_c_expression_not_assignment"
        },
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "_c_variable_assignment"
          },
          "named": true,
          "value": "variable_assignment"
        }
      ]
    },
    "_c_expression_not_assignment": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_c_word"
        },
        {
          "type": "SYMBOL",
          "name": "simple_expansion"
        },
        {
          "type": "SYMBOL",
          "name": "expansion"
        },
        {
          "type": "SYMBOL",
          "name": "number"
        },
        {
          "type": "SYMBOL",
          "name": "string"
        },
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "_c_unary_expression"
          },
          "named": true,
          "value": "unary_expression"
        },
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "_c_binary_expression"
          },
          "named": true,
          "value": "binary_expression"
        },
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "_c_postfix_expression"
          },
          "named": true,
          "value": "postfix_expression"
        },
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "_c_parenthesized_expression"
          },
          "named": true,
          "value": "parenthesized_expression"
        },
        {
          "type": "SYMBOL",
          "name": "command_substitution"
        }
      ]
    },
    "_c_variable_assignment": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "name",
          "content": {
            "type": "ALIAS",
            "content": {
              "type": "SYMBOL",
              "name": "_c_word"
            },
            "named": true,
            "value": "variable_name"
          }
        },
        {
          "type": "STRING",
          "value": "="
        },
        {
          "type": "FIELD",
          "name": "value",
          "content": {
            "type": "SYMBOL",
            "name": "_c_expression"
          }
        }
      ]
    },
    "_c_unary_expression": {
      "type": "PREC",
      "value": 17,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "FIELD",
            "name": "operator",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "STRING",
                  "value": "++"
                },
                {
                  "type": "STRING",
                  "value": "--"
                }
              ]
            }
          },
          {
            "type": "SYMBOL",
            "name": "_c_expression_not_assignment"
          }
        ]
      }
    },
    "_c_binary_expression": {
      "type": "CHOICE",
      "members": [
        {
          "type": "PREC_LEFT",
          "value": 0,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "+="
                    },
                    {
                      "type": "STRING",
                      "value": "-="
                    },
                    {
                      "type": "STRING",
                      "value": "*="
                    },
                    {
                      "type": "STRING",
                      "value": "/="
                    },
                    {
                      "type": "STRING",
                      "value": "%="
                    },
                    {
                      "type": "STRING",
                      "value": "**="
                    },
                    {
                      "type": "STRING",
                      "value": "<<="
                    },
                    {
                      "type": "STRING",
                      "value": ">>="
                    },
                    {
                      "type": "STRING",
                      "value": "&="
                    },
                    {
                      "type": "STRING",
                      "value": "^="
                    },
                    {
                      "type": "STRING",
                      "value": "|="
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 3,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "||"
                    },
                    {
                      "type": "STRING",
                      "value": "-o"
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 4,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "&&"
                    },
                    {
                      "type": "STRING",
                      "value": "-a"
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 5,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "STRING",
                  "value": "|"
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 6,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "STRING",
                  "value": "^"
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 7,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "STRING",
                  "value": "&"
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 8,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "=="
                    },
                    {
                      "type": "STRING",
                      "value": "!="
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 9,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "<"
                    },
                    {
                      "type": "STRING",
                      "value": ">"
                    },
                    {
                      "type": "STRING",
                      "value": "<="
                    },
                    {
                      "type": "STRING",
                      "value": ">="
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 12,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "<<"
                    },
                    {
                      "type": "STRING",
                      "value": ">>"
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 13,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "+"
                    },
                    {
                      "type": "STRING",
                      "value": "-"
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_LEFT",
          "value": 14,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "*"
                    },
                    {
                      "type": "STRING",
                      "value": "/"
                    },
                    {
                      "type": "STRING",
                      "value": "%"
                    }
                  ]
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        },
        {
          "type": "PREC_RIGHT",
          "value": 15,
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "FIELD",
                "name": "left",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              },
              {
                "type": "FIELD",
                "name": "operator",
                "content": {
                  "type": "STRING",
                  "value": "**"
                }
              },
              {
                "type": "FIELD",
                "name": "right",
                "content": {
                  "type": "SYMBOL",
                  "name": "_c_expression_not_assignment"
                }
              }
            ]
          }
        }
      ]
    },
    "_c_postfix_expression": {
      "type": "PREC",
      "value": 18,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "SYMBOL",
            "name": "_c_expression_not_assignment"
          },
          {
            "type": "FIELD",
            "name": "operator",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "STRING",
                  "value": "++"
                },
                {
                  "type": "STRING",
                  "value": "--"
                }
              ]
            }
          }
        ]
      }
    },
    "_c_parenthesized_expression": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "("
        },
        {
          "type": "SEQ",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_c_expression"
            },
            {
              "type": "REPEAT",
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "STRING",
                    "value": ","
                  },
                  {
                    "type": "SYMBOL",
                    "name": "_c_expression"
                  }
                ]
              }
            }
          ]
        },
        {
          "type": "STRING",
          "value": ")"
        }
      ]
    },
    "_c_word": {
      "type": "ALIAS",
      "content": {
        "type": "PATTERN",
        "value": "[a-zA-Z_][a-zA-Z0-9_]*"
      },
      "named": true,
      "value": "word"
    },
    "while_statement": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "while"
            },
            {
              "type": "STRING",
              "value": "until"
            }
          ]
        },
        {
          "type": "FIELD",
          "name": "condition",
          "content": {
            "type": "SYMBOL",
            "name": "_terminated_statement"
          }
        },
        {
          "type": "FIELD",
          "name": "body",
          "content": {
            "type": "SYMBOL",
            "name": "do_group"
          }
        }
      ]
    },
    "do_group": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "do"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminated_statement"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "done"
        }
      ]
    },
    "if_statement": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "if"
        },
        {
          "type": "FIELD",
          "name": "condition",
          "content": {
            "type": "SYMBOL",
            "name": "_terminated_statement"
          }
        },
        {
          "type": "STRING",
          "value": "then"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminated_statement"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "REPEAT",
          "content": {
            "type": "SYMBOL",
            "name": "elif_clause"
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "else_clause"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "fi"
        }
      ]
    },
    "elif_clause": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "elif"
        },
        {
          "type": "SYMBOL",
          "name": "_terminated_statement"
        },
        {
          "type": "STRING",
          "value": "then"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminated_statement"
            },
            {
              "type": "BLANK"
            }
          ]
        }
      ]
    },
    "else_clause": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "else"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminated_statement"
            },
            {
              "type": "BLANK"
            }
          ]
        }
      ]
    },
    "case_statement": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "case"
        },
        {
          "type": "FIELD",
          "name": "value",
          "content": {
            "type": "SYMBOL",
            "name": "_literal"
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminator"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "in"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_terminator"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "REPEAT",
                  "content": {
                    "type": "SYMBOL",
                    "name": "case_item"
                  }
                },
                {
                  "type": "ALIAS",
                  "content": {
                    "type": "SYMBOL",
                    "name": "last_case_item"
                  },
                  "named": true,
                  "value": "case_item"
                }
              ]
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "esac"
        }
      ]
    },
    "case_item": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "("
                    },
                    {
                      "type": "BLANK"
                    }
                  ]
                },
                {
                  "type": "FIELD",
                  "name": "value",
                  "content": {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "SYMBOL",
                        "name": "_literal"
                      },
                      {
                        "type": "SYMBOL",
                        "name": "_extglob_blob"
                      }
                    ]
                  }
                },
                {
                  "type": "REPEAT",
                  "content": {
                    "type": "SEQ",
                    "members": [
                      {
                        "type": "STRING",
                        "value": "|"
                      },
                      {
                        "type": "FIELD",
                        "name": "value",
                        "content": {
                          "type": "CHOICE",
                          "members": [
                            {
                              "type": "SYMBOL",
                              "name": "_literal"
                            },
                            {
                              "type": "SYMBOL",
                              "name": "_extglob_blob"
                            }
                          ]
                        }
                      }
                    ]
                  }
                },
                {
                  "type": "STRING",
                  "value": ")"
                }
              ]
            }
          ]
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_statements"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "PREC",
          "value": 1,
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "FIELD",
                "name": "termination",
                "content": {
                  "type": "STRING",
                  "value": ";;"
                }
              },
              {
                "type": "FIELD",
                "name": "fallthrough",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": ";&"
                    },
                    {
                      "type": "STRING",
                      "value": ";;&"
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    },
    "last_case_item": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "("
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "FIELD",
          "name": "value",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "_literal"
              },
              {
                "type": "SYMBOL",
                "name": "_extglob_blob"
              }
            ]
          }
        },
        {
          "type": "REPEAT",
          "content": {
            "type": "SEQ",
            "members": [
              {
                "type": "STRING",
                "value": "|"
              },
              {
                "type": "FIELD",
                "name": "value",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "SYMBOL",
                      "name": "_literal"
                    },
                    {
                      "type": "SYMBOL",
                      "name": "_extglob_blob"
                    }
                  ]
                }
              }
            ]
          }
        },
        {
          "type": "STRING",
          "value": ")"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_statements"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "PREC",
              "value": 1,
              "content": {
                "type": "STRING",
                "value": ";;"
              }
            },
            {
              "type": "BLANK"
            }
          ]
        }
      ]
    },
    "function_definition": {
      "type": "PREC_RIGHT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "STRING",
                    "value": "function"
                  },
                  {
                    "type": "FIELD",
                    "name": "name",
                    "content": {
                      "type": "SYMBOL",
                      "name": "word"
                    }
                  },
                  {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "SEQ",
                        "members": [
                          {
                            "type": "STRING",
                            "value": "("
                          },
                          {
                            "type": "STRING",
                            "value": ")"
                          }
                        ]
                      },
                      {
                        "type": "BLANK"
                      }
                    ]
                  }
                ]
              },
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "name",
                    "content": {
                      "type": "SYMBOL",
                      "name": "word"
                    }
                  },
                  {
                    "type": "STRING",
                    "value": "("
                  },
                  {
                    "type": "STRING",
                    "value": ")"
                  }
                ]
              }
            ]
          },
          {
            "type": "FIELD",
            "name": "body",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "compound_statement"
                },
                {
                  "type": "SYMBOL",
                  "name": "subshell"
                },
                {
                  "type": "SYMBOL",
                  "name": "test_command"
                },
                {
                  "type": "SYMBOL",
                  "name": "if_statement"
                }
              ]
            }
          },
          {
            "type": "FIELD",
            "name": "redirect",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "_redirect"
                },
                {
                  "type": "BLANK"
                }
              ]
            }
          }
        ]
      }
    },
    "compound_statement": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SEQ",
          "members": [
            {
              "type": "STRING",
              "value": "{"
            },
            {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "_terminated_statement"
                },
                {
                  "type": "BLANK"
                }
              ]
            },
            {
              "type": "TOKEN",
              "content": {
                "type": "PREC",
                "value": -1,
                "content": {
                  "type": "STRING",
                  "value": "}"
                }
              }
            }
          ]
        },
        {
          "type": "SEQ",
          "members": [
            {
              "type": "STRING",
              "value": "(("
            },
            {
              "type": "REPEAT",
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "SYMBOL",
                    "name": "_arithmetic_expression"
                  },
                  {
                    "type": "STRING",
                    "value": ","
                  }
                ]
              }
            },
            {
              "type": "SYMBOL",
              "name": "_arithmetic_expression"
            },
            {
              "type": "STRING",
              "value": "))"
            }
          ]
        }
      ]
    },
    "subshell": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "("
        },
        {
          "type": "SYMBOL",
          "name": "_statements"
        },
        {
          "type": "STRING",
          "value": ")"
        }
      ]
    },
    "pipeline": {
      "type": "PREC_RIGHT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "SYMBOL",
            "name": "_statement_not_pipeline"
          },
          {
            "type": "REPEAT1",
            "content": {
              "type": "SEQ",
              "members": [
                {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "STRING",
                      "value": "|"
                    },
                    {
                      "type": "STRING",
                      "value": "|&"
                    }
                  ]
                },
                {
                  "type": "SYMBOL",
                  "name": "_statement_not_pipeline"
                }
              ]
            }
          }
        ]
      }
    },
    "list": {
      "type": "PREC_LEFT",
      "value": -1,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "SYMBOL",
            "name": "_statement"
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "STRING",
                "value": "&&"
              },
              {
                "type": "STRING",
                "value": "||"
              }
            ]
          },
          {
            "type": "SYMBOL",
            "name": "_statement"
          }
        ]
      }
    },
    "negated_command": {
      "type": "SEQ",
      "members": [
        {
          "type": "STRING",
          "value": "!"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "PREC",
              "value": 2,
              "content": {
                "type": "SYMBOL",
                "name": "command"
              }
            },
            {
              "type": "PREC",
              "value": 1,
              "content": {
                "type": "SYMBOL",
                "name": "variable_assignment"
              }
            },
            {
              "type": "SYMBOL",
              "name": "test_command"
            },
            {
              "type": "SYMBOL",
              "name": "subshell"
            }
          ]
        }
      ]
    },
    "test_command": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "STRING",
                  "value": "["
                },
                {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "CHOICE",
                      "members": [
                        {
                          "type": "SYMBOL",
                          "name": "_expression"
                        },
                        {
                          "type": "SYMBOL",
                          "name": "redirected_statement"
                        }
                      ]
                    },
                    {
                      "type": "BLANK"
                    }
                  ]
                },
                {
                  "type": "STRING",
                  "value": "]"
                }
              ]
            },
            {
              "type": "SEQ",
              "members": [
                {
                  "type": "STRING",
                  "value": "[["
                },
                {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "SYMBOL",
                      "name": "_expression"
                    },
                    {
                      "type": "ALIAS",
                      "content": {
                        "type": "SYMBOL",
                        "name": "_test_command_binary_expression"
                      },
                      "named": true,
                      "value": "binary_expression"
                    }
                  ]
                },
                {
                  "type": "STRING",
                  "value": "]]"
                }
              ]
            }
          ]
        }
      ]
    },
    "_test_command_binary_expression": {
      "type": "PREC",
      "value": 1,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "FIELD",
            "name": "left",
            "content": {
              "type": "SYMBOL",
              "name": "_expression"
            }
          },
          {
            "type": "FIELD",
            "name": "operator",
            "content": {
              "type": "STRING",
              "value": "="
            }
          },
          {
            "type": "FIELD",
            "name": "right",
            "content": {
              "type": "ALIAS",
              "content": {
                "type": "SYMBOL",
                "name": "_regex_no_space"
              },
              "named": true,
              "value": "regex"
            }
          }
        ]
      }
    },
    "declaration_command": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "STRING",
                "value": "declare"
              },
              {
                "type": "STRING",
                "value": "typeset"
              },
              {
                "type": "STRING",
                "value": "export"
              },
              {
                "type": "STRING",
                "value": "readonly"
              },
              {
                "type": "STRING",
                "value": "local"
              }
            ]
          },
          {
            "type": "REPEAT",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "_literal"
                },
                {
                  "type": "SYMBOL",
                  "name": "_simple_variable_name"
                },
                {
                  "type": "SYMBOL",
                  "name": "variable_assignment"
                }
              ]
            }
          }
        ]
      }
    },
    "unset_command": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "STRING",
                "value": "unset"
              },
              {
                "type": "STRING",
                "value": "unsetenv"
              }
            ]
          },
          {
            "type": "REPEAT",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "_literal"
                },
                {
                  "type": "SYMBOL",
                  "name": "_simple_variable_name"
                }
              ]
            }
          }
        ]
      }
    },
    "command": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "REPEAT",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "variable_assignment"
                },
                {
                  "type": "FIELD",
                  "name": "redirect",
                  "content": {
                    "type": "SYMBOL",
                    "name": "_redirect"
                  }
                }
              ]
            }
          },
          {
            "type": "FIELD",
            "name": "name",
            "content": {
              "type": "SYMBOL",
              "name": "command_name"
            }
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "REPEAT",
                "content": {
                  "type": "CHOICE",
                  "members": [
                    {
                      "type": "FIELD",
                      "name": "argument",
                      "content": {
                        "type": "SYMBOL",
                        "name": "_literal"
                      }
                    },
                    {
                      "type": "FIELD",
                      "name": "argument",
                      "content": {
                        "type": "ALIAS",
                        "content": {
                          "type": "SYMBOL",
                          "name": "_bare_dollar"
                        },
                        "named": false,
                        "value": "$"
                      }
                    },
                    {
                      "type": "FIELD",
                      "name": "argument",
                      "content": {
                        "type": "SEQ",
                        "members": [
                          {
                            "type": "CHOICE",
                            "members": [
                              {
                                "type": "STRING",
                                "value": "=~"
                              },
                              {
                                "type": "STRING",
                                "value": "=="
                              }
                            ]
                          },
                          {
                            "type": "CHOICE",
                            "members": [
                              {
                                "type": "SYMBOL",
                                "name": "_literal"
                              },
                              {
                                "type": "SYMBOL",
                                "name": "regex"
                              }
                            ]
                          }
                        ]
                      }
                    },
                    {
                      "type": "FIELD",
                      "name": "redirect",
                      "content": {
                        "type": "SYMBOL",
                        "name": "herestring_redirect"
                      }
                    }
                  ]
                }
              },
              {
                "type": "SYMBOL",
                "name": "subshell"
              }
            ]
          }
        ]
      }
    },
    "command_name": {
      "type": "SYMBOL",
      "name": "_literal"
    },
    "variable_assignment": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "name",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "variable_name"
              },
              {
                "type": "SYMBOL",
                "name": "subscript"
              }
            ]
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "="
            },
            {
              "type": "STRING",
              "value": "+="
            }
          ]
        },
        {
          "type": "FIELD",
          "name": "value",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "_literal"
              },
              {
                "type": "SYMBOL",
                "name": "array"
              },
              {
                "type": "SYMBOL",
                "name": "_empty_value"
              },
              {
                "type": "ALIAS",
                "content": {
                  "type": "SYMBOL",
                  "name": "_comment_word"
                },
                "named": true,
                "value": "word"
              }
            ]
          }
        }
      ]
    },
    "variable_assignments": {
      "type": "SEQ",
      "members": [
        {
          "type": "SYMBOL",
          "name": "variable_assignment"
        },
        {
          "type": "REPEAT1",
          "content": {
            "type": "SYMBOL",
            "name": "variable_assignment"
          }
        }
      ]
    },
    "subscript": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "name",
          "content": {
            "type": "SYMBOL",
            "name": "variable_name"
          }
        },
        {
          "type": "STRING",
          "value": "["
        },
        {
          "type": "FIELD",
          "name": "index",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "_literal"
              },
              {
                "type": "SYMBOL",
                "name": "binary_expression"
              },
              {
                "type": "SYMBOL",
                "name": "unary_expression"
              },
              {
                "type": "SYMBOL",
                "name": "compound_statement"
              },
              {
                "type": "SYMBOL",
                "name": "subshell"
              }
            ]
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_concat"
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "STRING",
          "value": "]"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_concat"
            },
            {
              "type": "BLANK"
            }
          ]
        }
      ]
    },
    "file_redirect": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "FIELD",
            "name": "descriptor",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "file_descriptor"
                },
                {
                  "type": "BLANK"
                }
              ]
            }
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "STRING",
                        "value": "<"
                      },
                      {
                        "type": "STRING",
                        "value": ">"
                      },
                      {
                        "type": "STRING",
                        "value": ">>"
                      },
                      {
                        "type": "STRING",
                        "value": "&>"
                      },
                      {
                        "type": "STRING",
                        "value": "&>>"
                      },
                      {
                        "type": "STRING",
                        "value": "<&"
                      },
                      {
                        "type": "STRING",
                        "value": ">&"
                      },
                      {
                        "type": "STRING",
                        "value": ">|"
                      }
                    ]
                  },
                  {
                    "type": "FIELD",
                    "name": "destination",
                    "content": {
                      "type": "REPEAT1",
                      "content": {
                        "type": "SYMBOL",
                        "name": "_literal"
                      }
                    }
                  }
                ]
              },
              {
                "type": "SEQ",
                "members": [
                  {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "STRING",
                        "value": "<&-"
                      },
                      {
                        "type": "STRING",
                        "value": ">&-"
                      }
                    ]
                  },
                  {
                    "type": "CHOICE",
                    "members": [
                      {
                        "type": "FIELD",
                        "name": "destination",
                        "content": {
                          "type": "SYMBOL",
                          "name": "_literal"
                        }
                      },
                      {
                        "type": "BLANK"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    },
    "heredoc_redirect": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "descriptor",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "file_descriptor"
              },
              {
                "type": "BLANK"
              }
            ]
          }
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "<<"
            },
            {
              "type": "STRING",
              "value": "<<-"
            }
          ]
        },
        {
          "type": "SYMBOL",
          "name": "heredoc_start"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "CHOICE",
              "members": [
                {
                  "type": "ALIAS",
                  "content": {
                    "type": "SYMBOL",
                    "name": "_heredoc_pipeline"
                  },
                  "named": true,
                  "value": "pipeline"
                },
                {
                  "type": "SEQ",
                  "members": [
                    {
                      "type": "FIELD",
                      "name": "redirect",
                      "content": {
                        "type": "REPEAT1",
                        "content": {
                          "type": "SYMBOL",
                          "name": "_redirect"
                        }
                      }
                    },
                    {
                      "type": "CHOICE",
                      "members": [
                        {
                          "type": "SYMBOL",
                          "name": "_heredoc_expression"
                        },
                        {
                          "type": "BLANK"
                        }
                      ]
                    }
                  ]
                },
                {
                  "type": "SYMBOL",
                  "name": "_heredoc_expression"
                },
                {
                  "type": "SYMBOL",
                  "name": "_heredoc_command"
                }
              ]
            },
            {
              "type": "BLANK"
            }
          ]
        },
        {
          "type": "PATTERN",
          "value": "\\n"
        },
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "SYMBOL",
              "name": "_heredoc_body"
            },
            {
              "type": "SYMBOL",
              "name": "_simple_heredoc_body"
            }
          ]
        }
      ]
    },
    "_heredoc_pipeline": {
      "type": "SEQ",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "STRING",
              "value": "|"
            },
            {
              "type": "STRING",
              "value": "|&"
            }
          ]
        },
        {
          "type": "SYMBOL",
          "name": "_statement"
        }
      ]
    },
    "_heredoc_expression": {
      "type": "SEQ",
      "members": [
        {
          "type": "FIELD",
          "name": "operator",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "STRING",
                "value": "||"
              },
              {
                "type": "STRING",
                "value": "&&"
              }
            ]
          }
        },
        {
          "type": "FIELD",
          "name": "right",
          "content": {
            "type": "SYMBOL",
            "name": "_statement"
          }
        }
      ]
    },
    "_heredoc_command": {
      "type": "REPEAT1",
      "content": {
        "type": "FIELD",
        "name": "argument",
        "content": {
          "type": "SYMBOL",
          "name": "_literal"
        }
      }
    },
    "_heredoc_body": {
      "type": "SEQ",
      "members": [
        {
          "type": "SYMBOL",
          "name": "heredoc_body"
        },
        {
          "type": "SYMBOL",
          "name": "heredoc_end"
        }
      ]
    },
    "heredoc_body": {
      "type": "SEQ",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_heredoc_body_beginning"
        },
        {
          "type": "REPEAT",
          "content": {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "expansion"
              },
              {
                "type": "SYMBOL",
                "name": "simple_expansion"
              },
              {
                "type": "SYMBOL",
                "name": "command_substitution"
              },
              {
                "type": "SYMBOL",
                "name": "heredoc_content"
              }
            ]
          }
        }
      ]
    },
    "_simple_heredoc_body": {
      "type": "SEQ",
      "members": [
        {
          "type": "ALIAS",
          "content": {
            "type": "SYMBOL",
            "name": "simple_heredoc_body"
          },
          "named": true,
          "value": "heredoc_body"
        },
        {
          "type": "SYMBOL",
          "name": "heredoc_end"
        }
      ]
    },
    "herestring_redirect": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "FIELD",
            "name": "descriptor",
            "content": {
              "type": "CHOICE",
              "members": [
                {
                  "type": "SYMBOL",
                  "name": "file_descriptor"
                },
                {
                  "type": "BLANK"
                }
              ]
            }
          },
          {
            "type": "STRING",
            "value": "<<<"
          },
          {
            "type": "SYMBOL",
            "name": "_literal"
          }
        ]
      }
    },
    "_redirect": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "file_redirect"
        },
        {
          "type": "SYMBOL",
          "name": "herestring_redirect"
        }
      ]
    },
    "_expression": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "_literal"
        },
        {
          "type": "SYMBOL",
          "name": "unary_expression"
        },
        {
          "type": "SYMBOL",
          "name": "ternary_expression"
        },
        {
          "type": "SYMBOL",
          "name": "binary_expression"
        },
        {
          "type": "SYMBOL",
          "name": "postfix_expression"
        },
        {
          "type": "SYMBOL",
          "name": "parenthesized_expression"
        }
      ]
    },
    "binary_expression": {
      "type": "CHOICE",
      "members": [
        {
          "type": "CHOICE",
          "members": [
            {
              "type": "PREC_LEFT",
              "value": 0,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "CHOICE",
                      "members": [
                        {
                          "type": "STRING",
                          "value": "+="
                        },
                        {
                          "type": "STRING",
                          "value": "-="
                        },
                        {
                          "type": "STRING",
                          "value": "*="
                        },
                        {
                          "type": "STRING",
                          "value": "/="
                        },
                        {
                          "type": "STRING",
                          "value": "%="
                        },
                        {
                          "type": "STRING",
                          "value": "**="
                        },
                        {
                          "type": "STRING",
                          "value": "<<="
                        },
                        {
                          "type": "STRING",
                          "value": ">>="
                        },
                        {
                          "type": "STRING",
                          "value": "&="
                        },
                        {
                          "type": "STRING",
                          "value": "^="
                        },
                        {
                          "type": "STRING",
                          "value": "|="
                        }
                      ]
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 1,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "CHOICE",
                      "members": [
                        {
                          "type": "STRING",
                          "value": "="
                        },
                        {
                          "type": "STRING",
                          "value": "=~"
                        }
                      ]
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 3,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "STRING",
                      "value": "||"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 4,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "STRING",
                      "value": "&&"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 5,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "STRING",
                      "value": "|"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 6,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "STRING",
                      "value": "^"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 7,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "STRING",
                      "value": "&"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 8,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
                    "name": "left",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "operator",
                    "content": {
                      "type": "CHOICE",
                      "members": [
                        {
                          "type": "STRING",
                          "value": "=="
                        },
                        {
                          "type": "STRING",
                          "value": "!="
                        }
                      ]
                    }
                  },
                  {
                    "type": "FIELD",
                    "name": "right",
                    "content": {
                      "type": "SYMBOL",
                      "name": "_expression"
                    }
                  }
                ]
              }
            },
            {
              "type": "PREC_LEFT",
              "value": 9,
              "content": {
                "type": "SEQ",
                "members": [
                  {
                    "type": "FIELD",
            
Download .txt
gitextract_j8navkbf/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yml
│       ├── fuzz.yml
│       ├── lint.yml
│       └── publish.yml
├── .gitignore
├── CMakeLists.txt
├── Cargo.toml
├── LICENSE
├── Makefile
├── Package.swift
├── README.md
├── binding.gyp
├── bindings/
│   ├── c/
│   │   ├── tree-sitter-bash.pc.in
│   │   └── tree_sitter/
│   │       └── tree-sitter-bash.h
│   ├── go/
│   │   ├── binding.go
│   │   └── binding_test.go
│   ├── node/
│   │   ├── binding.cc
│   │   ├── binding_test.js
│   │   ├── index.d.ts
│   │   └── index.js
│   ├── python/
│   │   ├── tests/
│   │   │   └── test_binding.py
│   │   └── tree_sitter_bash/
│   │       ├── __init__.py
│   │       ├── __init__.pyi
│   │       ├── binding.c
│   │       └── py.typed
│   ├── rust/
│   │   ├── build.rs
│   │   └── lib.rs
│   └── swift/
│       ├── TreeSitterBash/
│       │   └── bash.h
│       └── TreeSitterBashTests/
│           └── TreeSitterBashTests.swift
├── eslint.config.mjs
├── examples/
│   ├── atom.sh
│   ├── clean-old.sh
│   ├── doc-build.sh
│   ├── install.sh
│   ├── release.sh
│   ├── relocate.sh
│   ├── test.sh
│   └── update-authors.sh
├── go.mod
├── go.sum
├── grammar.js
├── package.json
├── pyproject.toml
├── queries/
│   └── highlights.scm
├── script/
│   ├── known-failures.txt
│   └── parse-examples
├── setup.py
├── src/
│   ├── grammar.json
│   ├── node-types.json
│   ├── parser.c
│   ├── scanner.c
│   └── tree_sitter/
│       ├── alloc.h
│       ├── array.h
│       └── parser.h
├── test/
│   └── corpus/
│       ├── commands.txt
│       ├── crlf.txt
│       ├── literals.txt
│       ├── programs.txt
│       └── statements.txt
└── tree-sitter.json
Download .txt
SYMBOL INDEX (94 symbols across 18 files)

FILE: bindings/c/tree_sitter/tree-sitter-bash.h
  type TSLanguage (line 4) | typedef struct TSLanguage TSLanguage;

FILE: bindings/go/binding.go
  function Language (line 11) | func Language() unsafe.Pointer {

FILE: bindings/go/binding_test.go
  function TestCanLoadGrammar (line 10) | func TestCanLoadGrammar(t *testing.T) {

FILE: bindings/node/binding.cc
  type TSLanguage (line 3) | struct TSLanguage
  function Init (line 12) | Napi::Object Init(Napi::Env env, Napi::Object exports) {

FILE: bindings/node/index.d.ts
  type BaseNode (line 1) | type BaseNode = {
  type ChildNode (line 6) | type ChildNode = {
  type NodeInfo (line 12) | type NodeInfo =
  type Language (line 21) | type Language = {

FILE: bindings/python/tests/test_binding.py
  class TestLanguage (line 6) | class TestLanguage(TestCase):
    method test_can_load_grammar (line 7) | def test_can_load_grammar(self):

FILE: bindings/python/tree_sitter_bash/__init__.py
  function _get_query (line 8) | def _get_query(name, file):
  function __getattr__ (line 14) | def __getattr__(name):
  function __dir__ (line 27) | def __dir__():

FILE: bindings/python/tree_sitter_bash/__init__.pyi
  function language (line 5) | def language() -> object: ...

FILE: bindings/python/tree_sitter_bash/binding.c
  type TSLanguage (line 3) | typedef struct TSLanguage TSLanguage;
  function PyObject (line 7) | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *...
  type PyModuleDef_Slot (line 11) | struct PyModuleDef_Slot
  type PyModuleDef (line 24) | struct PyModuleDef
  function PyMODINIT_FUNC (line 33) | PyMODINIT_FUNC PyInit__binding(void) {

FILE: bindings/rust/build.rs
  function main (line 1) | fn main() {

FILE: bindings/rust/lib.rs
  function tree_sitter_bash (line 27) | fn tree_sitter_bash() -> *const ();
  constant LANGUAGE (line 33) | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitt...
  constant NODE_TYPES (line 38) | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
  constant HIGHLIGHT_QUERY (line 41) | pub const HIGHLIGHT_QUERY: &str = include_str!("../../queries/highlights...
  function test_can_load_grammar (line 46) | fn test_can_load_grammar() {

FILE: bindings/swift/TreeSitterBash/bash.h
  type TSLanguage (line 4) | typedef struct TSLanguage TSLanguage;

FILE: grammar.js
  constant SPECIAL_CHARACTERS (line 11) | const SPECIAL_CHARACTERS = [
  constant PREC (line 23) | const PREC = {
  function noneOf (line 1150) | function noneOf(...characters) {
  function commaSep (line 1162) | function commaSep(rule) {
  function commaSep1 (line 1173) | function commaSep1(rule) {
  function immediateLiterals (line 1185) | function immediateLiterals(...literals) {
  function tokenLiterals (line 1199) | function tokenLiterals(precedence, ...literals) {

FILE: setup.py
  class Build (line 30) | class Build(build):
    method run (line 31) | def run(self):
  class BdistWheel (line 38) | class BdistWheel(bdist_wheel):
    method get_tag (line 39) | def get_tag(self):
  class EggInfo (line 46) | class EggInfo(egg_info):
    method find_sources (line 47) | def find_sources(self):

FILE: src/parser.c
  type ts_symbol_identifiers (line 30) | enum ts_symbol_identifiers {
  type ts_field_identifiers (line 2002) | enum ts_field_identifiers {
  function ts_lex (line 10359) | static bool ts_lex(TSLexer *lexer, TSStateId state) {
  function ts_lex_keywords (line 20765) | static bool ts_lex_keywords(TSLexer *lexer, TSStateId state) {
  type ts_external_scanner_symbol_identifiers (line 349604) | enum ts_external_scanner_symbol_identifiers {
  function TS_PUBLIC (line 350577) | TS_PUBLIC const TSLanguage *tree_sitter_bash(void) {

FILE: src/scanner.c
  type TokenType (line 9) | enum TokenType {
  type String (line 41) | typedef Array(char) String;
  type Heredoc (line 43) | typedef struct {
  type Scanner (line 60) | typedef struct {
  function advance (line 67) | static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false...
  function skip (line 69) | static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
  function in_error_recovery (line 71) | static inline bool in_error_recovery(const bool *valid_symbols) { return...
  function reset_string (line 73) | static inline void reset_string(String *string) {
  function reset_heredoc (line 80) | static inline void reset_heredoc(Heredoc *heredoc) {
  function reset (line 87) | static inline void reset(Scanner *scanner) {
  function serialize (line 93) | static unsigned serialize(Scanner *scanner, char *buffer) {
  function deserialize (line 121) | static void deserialize(Scanner *scanner, const char *buffer, unsigned l...
  function advance_word (line 164) | static bool advance_word(TSLexer *lexer, String *unquoted_word) {
  function scan_bare_dollar (line 195) | static inline bool scan_bare_dollar(TSLexer *lexer) {
  function scan_heredoc_start (line 210) | static bool scan_heredoc_start(Heredoc *heredoc, TSLexer *lexer) {
  function scan_heredoc_end_identifier (line 226) | static bool scan_heredoc_end_identifier(Heredoc *heredoc, TSLexer *lexer) {
  function scan_heredoc_content (line 246) | static bool scan_heredoc_content(Scanner *scanner, TSLexer *lexer, enum ...
  function scan (line 349) | static bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_sym...
  function tree_sitter_bash_external_scanner_scan (line 1193) | bool tree_sitter_bash_external_scanner_scan(void *payload, TSLexer *lexe...
  function tree_sitter_bash_external_scanner_serialize (line 1198) | unsigned tree_sitter_bash_external_scanner_serialize(void *payload, char...
  function tree_sitter_bash_external_scanner_deserialize (line 1203) | void tree_sitter_bash_external_scanner_deserialize(void *payload, const ...
  function tree_sitter_bash_external_scanner_destroy (line 1208) | void tree_sitter_bash_external_scanner_destroy(void *payload) {

FILE: src/tree_sitter/array.h
  type Array (line 160) | typedef Array(void) Array;
  function _array__delete (line 163) | static inline void _array__delete(Array *self) {
  function _array__erase (line 173) | static inline void _array__erase(Array *self, size_t element_size,
  function _array__reserve (line 183) | static inline void _array__reserve(Array *self, size_t element_size, uin...
  function _array__assign (line 195) | static inline void _array__assign(Array *self, const Array *other, size_...
  function _array__swap (line 202) | static inline void _array__swap(Array *self, Array *other) {
  function _array__grow (line 209) | static inline void _array__grow(Array *self, uint32_t count, size_t elem...
  function _array__splice (line 220) | static inline void _array__splice(Array *self, size_t element_size,

FILE: src/tree_sitter/parser.h
  type TSStateId (line 17) | typedef uint16_t TSStateId;
  type TSSymbol (line 18) | typedef uint16_t TSSymbol;
  type TSFieldId (line 19) | typedef uint16_t TSFieldId;
  type TSLanguage (line 20) | typedef struct TSLanguage TSLanguage;
  type TSLanguageMetadata (line 21) | typedef struct TSLanguageMetadata {
  type TSFieldMapEntry (line 28) | typedef struct {
  type TSMapSlice (line 35) | typedef struct {
  type TSSymbolMetadata (line 40) | typedef struct {
  type TSLexer (line 46) | typedef struct TSLexer TSLexer;
  type TSLexer (line 48) | struct TSLexer {
  type TSParseActionType (line 59) | typedef enum {
  type TSParseAction (line 66) | typedef union {
  type TSLexMode (line 83) | typedef struct {
  type TSLexerMode (line 88) | typedef struct {
  type TSParseActionEntry (line 94) | typedef union {
  type TSCharacterRange (line 102) | typedef struct {
  type TSLanguage (line 107) | struct TSLanguage {
  function set_contains (line 154) | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t...
Copy disabled (too large) Download .json
Condensed preview — 64 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,816K chars).
[
  {
    "path": ".editorconfig",
    "chars": 541,
    "preview": "root = true\n\n[*]\ncharset = utf-8\n\n[*.{json,toml,yml,gyp}]\nindent_style = space\nindent_size = 2\n\n[*.js]\nindent_style = sp"
  },
  {
    "path": ".gitattributes",
    "chars": 941,
    "preview": "* text=auto eol=lf\n\n# Generated source files\nsrc/*.json linguist-generated\nsrc/parser.c linguist-generated\nsrc/tree_sitt"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 835,
    "preview": "# These are supported funding model platforms\n\ngithub: tree-sitter\npatreon: # Replace with a single Patreon username\nope"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 157,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n  "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 2111,
    "preview": "name: CI\n\non:\n  push:\n    branches: [master]\n    paths:\n      - grammar.js\n      - src/**\n      - test/**\n      - bindin"
  },
  {
    "path": ".github/workflows/fuzz.yml",
    "chars": 465,
    "preview": "name: Fuzz\n\non:\n  push:\n    paths:\n      - src/scanner.c\n  pull_request:\n    paths:\n      - src/scanner.c\n  workflow_dis"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 511,
    "preview": "name: Lint\n\non:\n  push:\n    branches: [master]\n    paths:\n      - grammar.js\n  pull_request:\n    paths:\n      - grammar."
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 796,
    "preview": "name: Publish packages\n\non:\n  push:\n    tags: [\"*\"]\n\npermissions:\n  contents: write\n  id-token: write\n  attestations: wr"
  },
  {
    "path": ".gitignore",
    "chars": 402,
    "preview": "# Rust artifacts\ntarget/\n\n# Node artifacts\nbuild/\nprebuilds/\nnode_modules/\n\n# Swift artifacts\n.build/\nPackage.resolved\n\n"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 2683,
    "preview": "cmake_minimum_required(VERSION 3.13)\n\nproject(tree-sitter-bash\n        VERSION \"0.25.1\"\n        DESCRIPTION \"Bash gramma"
  },
  {
    "path": "Cargo.toml",
    "chars": 725,
    "preview": "[package]\nname = \"tree-sitter-bash\"\ndescription = \"Bash grammar for tree-sitter\"\nversion = \"0.25.1\"\nauthors = [\n  \"Max B"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2017 Max Brunsfeld\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "Makefile",
    "chars": 3191,
    "preview": "ifeq ($(OS),Windows_NT)\n$(error Windows is not supported)\nendif\n\nLANGUAGE_NAME := tree-sitter-bash\nHOMEPAGE_URL := https"
  },
  {
    "path": "Package.swift",
    "chars": 1070,
    "preview": "// swift-tools-version:5.3\nimport PackageDescription\n\nlet package = Package(\n    name: \"TreeSitterBash\",\n    products: ["
  },
  {
    "path": "README.md",
    "chars": 1485,
    "preview": "# tree-sitter-bash\n\n[![CI][ci]](https://github.com/tree-sitter/tree-sitter-bash/actions/workflows/ci.yml)\n[![discord][di"
  },
  {
    "path": "binding.gyp",
    "chars": 599,
    "preview": "{\n  \"targets\": [\n    {\n      \"target_name\": \"tree_sitter_bash_binding\",\n      \"dependencies\": [\n        \"<!(node -p \\\"re"
  },
  {
    "path": "bindings/c/tree-sitter-bash.pc.in",
    "chars": 293,
    "preview": "prefix=@CMAKE_INSTALL_PREFIX@\nlibdir=${prefix}/@CMAKE_INSTALL_LIBDIR@\nincludedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@\n\nN"
  },
  {
    "path": "bindings/c/tree_sitter/tree-sitter-bash.h",
    "chars": 238,
    "preview": "#ifndef TREE_SITTER_BASH_H_\n#define TREE_SITTER_BASH_H_\n\ntypedef struct TSLanguage TSLanguage;\n\n#ifdef __cplusplus\nexter"
  },
  {
    "path": "bindings/go/binding.go",
    "chars": 283,
    "preview": "package tree_sitter_bash\n\n// #cgo CFLAGS: -std=c11 -fPIC\n// #include \"../../src/parser.c\"\n// #include \"../../src/scanner"
  },
  {
    "path": "bindings/go/binding_test.go",
    "chars": 354,
    "preview": "package tree_sitter_bash_test\n\nimport (\n\t\"testing\"\n\n\ttree_sitter \"github.com/tree-sitter/go-tree-sitter\"\n\ttree_sitter_ba"
  },
  {
    "path": "bindings/node/binding.cc",
    "chars": 577,
    "preview": "#include <napi.h>\n\ntypedef struct TSLanguage TSLanguage;\n\nextern \"C\" TSLanguage *tree_sitter_bash();\n\n// \"tree-sitter\", "
  },
  {
    "path": "bindings/node/binding_test.js",
    "chars": 250,
    "preview": "const assert = require(\"node:assert\");\nconst { test } = require(\"node:test\");\n\nconst Parser = require(\"tree-sitter\");\n\nt"
  },
  {
    "path": "bindings/node/index.d.ts",
    "chars": 452,
    "preview": "type BaseNode = {\n  type: string;\n  named: boolean;\n};\n\ntype ChildNode = {\n  multiple: boolean;\n  required: boolean;\n  t"
  },
  {
    "path": "bindings/node/index.js",
    "chars": 453,
    "preview": "const root = require(\"path\").join(__dirname, \"..\", \"..\");\n\nmodule.exports =\n  typeof process.versions.bun === \"string\"\n "
  },
  {
    "path": "bindings/python/tests/test_binding.py",
    "chars": 290,
    "preview": "from unittest import TestCase\n\nimport tree_sitter, tree_sitter_bash\n\n\nclass TestLanguage(TestCase):\n    def test_can_loa"
  },
  {
    "path": "bindings/python/tree_sitter_bash/__init__.py",
    "chars": 720,
    "preview": "\"\"\"Bash grammar for tree-sitter\"\"\"\n\nfrom importlib.resources import files as _files\n\nfrom ._binding import language\n\n\nde"
  },
  {
    "path": "bindings/python/tree_sitter_bash/__init__.pyi",
    "chars": 86,
    "preview": "from typing import Final\n\nHIGHLIGHTS_QUERY: Final[str]\n\ndef language() -> object: ...\n"
  },
  {
    "path": "bindings/python/tree_sitter_bash/binding.c",
    "chars": 832,
    "preview": "#include <Python.h>\n\ntypedef struct TSLanguage TSLanguage;\n\nTSLanguage *tree_sitter_bash(void);\n\nstatic PyObject* _bindi"
  },
  {
    "path": "bindings/python/tree_sitter_bash/py.typed",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "bindings/rust/build.rs",
    "chars": 632,
    "preview": "fn main() {\n    let src_dir = std::path::Path::new(\"src\");\n\n    let mut c_config = cc::Build::new();\n    c_config\n      "
  },
  {
    "path": "bindings/rust/lib.rs",
    "chars": 1725,
    "preview": "//! This crate provides Bash language support for the [tree-sitter][] parsing library.\n//!\n//! Typically, you will use t"
  },
  {
    "path": "bindings/swift/TreeSitterBash/bash.h",
    "chars": 238,
    "preview": "#ifndef TREE_SITTER_BASH_H_\n#define TREE_SITTER_BASH_H_\n\ntypedef struct TSLanguage TSLanguage;\n\n#ifdef __cplusplus\nexter"
  },
  {
    "path": "bindings/swift/TreeSitterBashTests/TreeSitterBashTests.swift",
    "chars": 359,
    "preview": "import XCTest\nimport SwiftTreeSitter\nimport TreeSitterBash\n\nfinal class TreeSitterBashTests: XCTestCase {\n    func testC"
  },
  {
    "path": "eslint.config.mjs",
    "chars": 89,
    "preview": "import treesitter from 'eslint-config-treesitter';\n\nexport default [\n  ...treesitter,\n];\n"
  },
  {
    "path": "examples/atom.sh",
    "chars": 3410,
    "preview": "#!/bin/bash\n\nif [ \"$(uname)\" == 'Darwin' ]; then\n  OS='Mac'\nelif [ \"$(expr substr $(uname -s) 1 5)\" == 'Linux' ]; then\n "
  },
  {
    "path": "examples/clean-old.sh",
    "chars": 4258,
    "preview": "#!/bin/bash\n\n# look for old 0.x cruft, and get rid of it.\n# Should already be sitting in the npm folder.\n\n# This doesn't"
  },
  {
    "path": "examples/doc-build.sh",
    "chars": 3260,
    "preview": "#!/usr/bin/env bash\n\nif [[ $DEBUG != \"\" ]]; then\n  set -x\nfi\nset -o errexit\nset -o pipefail\n\nif ! [ -x node_modules/.bin"
  },
  {
    "path": "examples/install.sh",
    "chars": 6239,
    "preview": "#!/bin/sh\n\n# A word about this shell script:\n#\n# It must work everywhere, including on systems that lack\n# a /bin/bash, "
  },
  {
    "path": "examples/release.sh",
    "chars": 657,
    "preview": "#!/bin/bash\n\n# script for creating a zip and tarball for inclusion in node\n\nunset CDPATH\n\nset -e\n\nrm -rf release *.tgz |"
  },
  {
    "path": "examples/relocate.sh",
    "chars": 665,
    "preview": "#!/bin/bash\n\n# Change the cli shebang to point at the specified node\n# Useful for when the program is moved around after"
  },
  {
    "path": "examples/test.sh",
    "chars": 2481,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nfunction usage {\n  cat <<-EOF\nUSAGE\n\n  $0  [-dgGhv] [-f focus-string] [-s seed]\n\nOPTIONS\n\n "
  },
  {
    "path": "examples/update-authors.sh",
    "chars": 183,
    "preview": "#!/bin/sh\n\ngit log --reverse --format='%aN <%aE>' | perl -wnE '\nBEGIN {\n  say \"# Authors sorted by whether or not they\\x"
  },
  {
    "path": "go.mod",
    "chars": 167,
    "preview": "module github.com/tree-sitter/tree-sitter-bash\n\ngo 1.22\n\nrequire github.com/tree-sitter/go-tree-sitter v0.24.0\n\nrequire "
  },
  {
    "path": "go.sum",
    "chars": 4176,
    "preview": "github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.m"
  },
  {
    "path": "grammar.js",
    "chars": 30142,
    "preview": "/**\n * @file Bash grammar for tree-sitter\n * @author Max Brunsfeld <maxbrunsfeld@gmail.com>\n * @author Amaan Qureshi <am"
  },
  {
    "path": "package.json",
    "chars": 1292,
    "preview": "{\n  \"name\": \"tree-sitter-bash\",\n  \"version\": \"0.25.1\",\n  \"description\": \"Bash grammar for tree-sitter\",\n  \"repository\": "
  },
  {
    "path": "pyproject.toml",
    "chars": 878,
    "preview": "[build-system]\nrequires = [\"setuptools>=42\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"tree-si"
  },
  {
    "path": "queries/highlights.scm",
    "chars": 577,
    "preview": "[\n  (string)\n  (raw_string)\n  (heredoc_body)\n  (heredoc_start)\n] @string\n\n(command_name) @function\n\n(variable_name) @pro"
  },
  {
    "path": "script/known-failures.txt",
    "chars": 23847,
    "preview": "examples/bash-it/completion/available/bundler.completion.bash\nexamples/bash-it/completion/available/sqlmap.completion.ba"
  },
  {
    "path": "script/parse-examples",
    "chars": 1081,
    "preview": "#!/usr/bin/env bash\n\nset -euo pipefail\n\nfiles=(\n  examples/*.sh\n  examples/bash-it/**/*.sh\n  examples/bash-it/**/*.bash\n"
  },
  {
    "path": "setup.py",
    "chars": 2056,
    "preview": "from os import path\nfrom platform import system\nfrom sysconfig import get_config_var\n\nfrom setuptools import Extension, "
  },
  {
    "path": "src/grammar.json",
    "chars": 179629,
    "preview": "{\n  \"$schema\": \"https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json\",\n  \"name\": \"bash\",\n  \"word"
  },
  {
    "path": "src/node-types.json",
    "chars": 51167,
    "preview": "[\n  {\n    \"type\": \"_expression\",\n    \"named\": true,\n    \"subtypes\": [\n      {\n        \"type\": \"_primary_expression\",\n   "
  },
  {
    "path": "src/parser.c",
    "chars": 9912254,
    "preview": "/* Automatically @generated by tree-sitter v0.25.10 */\n\n#include \"tree_sitter/parser.h\"\n\n#if defined(__GNUC__) || define"
  },
  {
    "path": "src/scanner.c",
    "chars": 45602,
    "preview": "#include \"tree_sitter/array.h\"\n#include \"tree_sitter/parser.h\"\n\n#include <assert.h>\n#include <ctype.h>\n#include <string."
  },
  {
    "path": "src/tree_sitter/alloc.h",
    "chars": 985,
    "preview": "#ifndef TREE_SITTER_ALLOC_H_\n#define TREE_SITTER_ALLOC_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdbool.h>\n"
  },
  {
    "path": "src/tree_sitter/array.h",
    "chars": 10431,
    "preview": "#ifndef TREE_SITTER_ARRAY_H_\n#define TREE_SITTER_ARRAY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"./alloc.h\"\n"
  },
  {
    "path": "src/tree_sitter/parser.h",
    "chars": 7624,
    "preview": "#ifndef TREE_SITTER_PARSER_H_\n#define TREE_SITTER_PARSER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdbool.h"
  },
  {
    "path": "test/corpus/commands.txt",
    "chars": 17200,
    "preview": "===============================\nCommands\n===============================\n\nwhoami\n\n---\n\n(program\n  (command\n    (command_"
  },
  {
    "path": "test/corpus/crlf.txt",
    "chars": 239,
    "preview": "================================\nVariables with CRLF line endings\n================================\n\nA=one\n\nB=two\n\n---\n\n("
  },
  {
    "path": "test/corpus/literals.txt",
    "chars": 37509,
    "preview": "================================================================================\nLiteral words\n========================="
  },
  {
    "path": "test/corpus/programs.txt",
    "chars": 1311,
    "preview": "===============================\nComments\n===============================\n\n#!/bin/bash\n# hi\n\n---\n\n(program\n  (comment)\n  "
  },
  {
    "path": "test/corpus/statements.txt",
    "chars": 42290,
    "preview": "================================================================================\nPipelines\n============================="
  },
  {
    "path": "tree-sitter.json",
    "chars": 916,
    "preview": "{\n  \"grammars\": [\n    {\n      \"name\": \"bash\",\n      \"camelcase\": \"Bash\",\n      \"scope\": \"source.bash\",\n      \"path\": \".\""
  }
]

About this extraction

This page contains the full source code of the tree-sitter/tree-sitter-bash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 64 files (9.9 MB), approximately 2.6M tokens, and a symbol index with 94 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!