~coder_kalyan/tree-sitter-scfg

b3aa103ac61ebaf110cabcabec2dcebc1f54f4b0 — Kalyan Sriram 2 years ago
initial commit
A  => .gitignore +6 -0
@@ 1,6 @@
node_modules
build
target
*.log
package-lock.json
Cargo.lock

A  => Cargo.toml +26 -0
@@ 1,26 @@
[package]
name = "tree-sitter-scfg"
description = "scfg grammar for the tree-sitter parsing library"
version = "0.0.1"
keywords = ["incremental", "parsing", "scfg"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-scfg"
edition = "2018"
license = "MIT"

build = "bindings/rust/build.rs"
include = [
  "bindings/rust/*",
  "grammar.js",
  "queries/*",
  "src/*",
]

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

[dependencies]
tree-sitter = "~0.20"

[build-dependencies]
cc = "1.0"

A  => binding.gyp +19 -0
@@ 1,19 @@
{
  "targets": [
    {
      "target_name": "tree_sitter_scfg_binding",
      "include_dirs": [
        "<!(node -e \"require('nan')\")",
        "src"
      ],
      "sources": [
        "bindings/node/binding.cc",
        "src/parser.c",
        # If your language uses an external scanner, add it here.
      ],
      "cflags_c": [
        "-std=c99",
      ]
    }
  ]
}

A  => bindings/node/binding.cc +28 -0
@@ 1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"

using namespace v8;

extern "C" TSLanguage * tree_sitter_scfg();

namespace {

NAN_METHOD(New) {}

void Init(Local<Object> exports, Local<Object> module) {
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("Language").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
  Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
  Nan::SetInternalFieldPointer(instance, 0, tree_sitter_scfg());

  Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("scfg").ToLocalChecked());
  Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}

NODE_MODULE(tree_sitter_scfg_binding, Init)

}  // namespace

A  => bindings/node/index.js +19 -0
@@ 1,19 @@
try {
  module.exports = require("../../build/Release/tree_sitter_scfg_binding");
} catch (error1) {
  if (error1.code !== 'MODULE_NOT_FOUND') {
    throw error1;
  }
  try {
    module.exports = require("../../build/Debug/tree_sitter_scfg_binding");
  } catch (error2) {
    if (error2.code !== 'MODULE_NOT_FOUND') {
      throw error2;
    }
    throw error1
  }
}

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

A  => bindings/rust/build.rs +40 -0
@@ 1,40 @@
fn main() {
    let src_dir = std::path::Path::new("src");

    let mut c_config = cc::Build::new();
    c_config.include(&src_dir);
    c_config
        .flag_if_supported("-Wno-unused-parameter")
        .flag_if_supported("-Wno-unused-but-set-variable")
        .flag_if_supported("-Wno-trigraphs");
    let parser_path = src_dir.join("parser.c");
    c_config.file(&parser_path);

    // If your language uses an external scanner written in C,
    // then include this block of code:

    /*
    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("parser");
    println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());

    // If your language uses an external scanner written in C++,
    // then include this block of code:

    /*
    let mut cpp_config = cc::Build::new();
    cpp_config.cpp(true);
    cpp_config.include(&src_dir);
    cpp_config
        .flag_if_supported("-Wno-unused-parameter")
        .flag_if_supported("-Wno-unused-but-set-variable");
    let scanner_path = src_dir.join("scanner.cc");
    cpp_config.file(&scanner_path);
    cpp_config.compile("scanner");
    println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
    */
}

A  => bindings/rust/lib.rs +52 -0
@@ 1,52 @@
//! This crate provides scfg language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! let code = "";
//! let mut parser = tree_sitter::Parser::new();
//! parser.set_language(tree_sitter_scfg::language()).expect("Error loading scfg grammar");
//! let tree = parser.parse(code, None).unwrap();
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/

use tree_sitter::Language;

extern "C" {
    fn tree_sitter_scfg() -> Language;
}

/// Get the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
    unsafe { tree_sitter_scfg() }
}

/// 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: &'static str = include_str!("../../src/node-types.json");

// Uncomment these to include any queries that this grammar contains

// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");

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

A  => examples/hello.scfg +8 -0
@@ 1,8 @@
username coder_kalyan
realname "Kalyan Sriram"

colors {
	red "#FF0000"
	green "#00FF00"
	blue "#0000FF"
}

A  => grammar.js +59 -0
@@ 1,59 @@
module.exports = grammar({
	name: 'scfg',

	rules: {
		source_file: $ => repeat($.directive),

		directive: $ => prec.left(2,
			seq(
				$.name,
				optional($.params),
				optional($.block),
				$._newline,
			),
		),

		name: $ => $._word,
		params: $ => prec.left(repeat1($._word)),

		block: $ => seq(
			$.bracket_open,
			$._newline,
			repeat($.directive),
			$.bracket_close,
		),

		_word: $ => choice(
			$.integer_scalar,
			$.float_scalar,
			$.true,
			$.false,
			$.atom,
			$.dquote_word,
			$.squote_word,
		),

		true: $ => choice(
			"true",
			"True",
		),
		false: $ => choice(
			"false",
			"False",
		),

		integer_scalar: $ => choice(
			/[+-]?[0-9]+/,
			/0x[0-9A-Fa-f]+/,
			/0b[01]+/,
		),
		float_scalar: $ => /[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)/,

		atom: $ => /[^"\r\n'{}\s]+/,
		dquote_word: $ => /"[^"\\\r\n]+"/,
		squote_word: $ => /'[^'\r\n]+'/,
		_newline: $ => /\r?\n/,
		bracket_open: $ => "{",
		bracket_close: $ => "}",
	}
});

A  => package.json +25 -0
@@ 1,25 @@
{
  "name": "tree-sitter-scfg",
  "version": "1.0.0",
  "description": "Tree sitter grammer for the scfg configuration language",
  "main": "bindings/node",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "nan": "^2.15.0"
  },
  "devDependencies": {
    "tree-sitter-cli": "^0.20.6"
  },
  "tree-sitter": [
	  {
		  "scope": "source.scfg",
		  "file-types": [
			  "scfg"
		  ]
	  }
  ]
}

A  => queries/highlights.scm +5 -0
@@ 1,5 @@
(atom) @identifier
(squote_word) @string
(dquote_word) @string
(bracket_open) @punctuation.bracket
(bracket_close) @punctuation.bracket

A  => src/grammar.json +145 -0
@@ 1,145 @@
{
  "name": "scfg",
  "rules": {
    "source_file": {
      "type": "REPEAT",
      "content": {
        "type": "SYMBOL",
        "name": "directive"
      }
    },
    "directive": {
      "type": "PREC_LEFT",
      "value": 2,
      "content": {
        "type": "SEQ",
        "members": [
          {
            "type": "SYMBOL",
            "name": "name"
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "params"
              },
              {
                "type": "BLANK"
              }
            ]
          },
          {
            "type": "CHOICE",
            "members": [
              {
                "type": "SYMBOL",
                "name": "block"
              },
              {
                "type": "BLANK"
              }
            ]
          },
          {
            "type": "SYMBOL",
            "name": "_newline"
          }
        ]
      }
    },
    "name": {
      "type": "SYMBOL",
      "name": "_word"
    },
    "params": {
      "type": "PREC_LEFT",
      "value": 0,
      "content": {
        "type": "REPEAT1",
        "content": {
          "type": "SYMBOL",
          "name": "_word"
        }
      }
    },
    "block": {
      "type": "SEQ",
      "members": [
        {
          "type": "SYMBOL",
          "name": "bracket_open"
        },
        {
          "type": "SYMBOL",
          "name": "_newline"
        },
        {
          "type": "REPEAT",
          "content": {
            "type": "SYMBOL",
            "name": "directive"
          }
        },
        {
          "type": "SYMBOL",
          "name": "bracket_close"
        }
      ]
    },
    "_word": {
      "type": "CHOICE",
      "members": [
        {
          "type": "SYMBOL",
          "name": "atom"
        },
        {
          "type": "SYMBOL",
          "name": "dquote_word"
        },
        {
          "type": "SYMBOL",
          "name": "squote_word"
        }
      ]
    },
    "atom": {
      "type": "PATTERN",
      "value": "[^\"\\r\\n'{}\\s]+"
    },
    "dquote_word": {
      "type": "PATTERN",
      "value": "\"[^\"\\\\\\r\\n]+\""
    },
    "squote_word": {
      "type": "PATTERN",
      "value": "'[^'\\r\\n]+'"
    },
    "_newline": {
      "type": "PATTERN",
      "value": "\\r?\\n"
    },
    "bracket_open": {
      "type": "STRING",
      "value": "{"
    },
    "bracket_close": {
      "type": "STRING",
      "value": "}"
    }
  },
  "extras": [
    {
      "type": "PATTERN",
      "value": "\\s"
    }
  ],
  "conflicts": [],
  "precedences": [],
  "externals": [],
  "inline": [],
  "supertypes": []
}


A  => src/node-types.json +129 -0
@@ 1,129 @@
[
  {
    "type": "block",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "bracket_close",
          "named": true
        },
        {
          "type": "bracket_open",
          "named": true
        },
        {
          "type": "directive",
          "named": true
        }
      ]
    }
  },
  {
    "type": "directive",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "block",
          "named": true
        },
        {
          "type": "name",
          "named": true
        },
        {
          "type": "params",
          "named": true
        }
      ]
    }
  },
  {
    "type": "name",
    "named": true,
    "fields": {},
    "children": {
      "multiple": false,
      "required": true,
      "types": [
        {
          "type": "atom",
          "named": true
        },
        {
          "type": "dquote_word",
          "named": true
        },
        {
          "type": "squote_word",
          "named": true
        }
      ]
    }
  },
  {
    "type": "params",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": true,
      "types": [
        {
          "type": "atom",
          "named": true
        },
        {
          "type": "dquote_word",
          "named": true
        },
        {
          "type": "squote_word",
          "named": true
        }
      ]
    }
  },
  {
    "type": "source_file",
    "named": true,
    "fields": {},
    "children": {
      "multiple": true,
      "required": false,
      "types": [
        {
          "type": "directive",
          "named": true
        }
      ]
    }
  },
  {
    "type": "atom",
    "named": true
  },
  {
    "type": "bracket_close",
    "named": true
  },
  {
    "type": "bracket_open",
    "named": true
  },
  {
    "type": "dquote_word",
    "named": true
  },
  {
    "type": "squote_word",
    "named": true
  }
]
\ No newline at end of file

A  => src/parser.c +494 -0
@@ 1,494 @@
#include <tree_sitter/parser.h>

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif

#define LANGUAGE_VERSION 13
#define STATE_COUNT 20
#define LARGE_STATE_COUNT 7
#define SYMBOL_COUNT 15
#define ALIAS_COUNT 0
#define TOKEN_COUNT 7
#define EXTERNAL_TOKEN_COUNT 0
#define FIELD_COUNT 0
#define MAX_ALIAS_SEQUENCE_LENGTH 4
#define PRODUCTION_ID_COUNT 1

enum {
  sym_atom = 1,
  sym_dquote_word = 2,
  sym_squote_word = 3,
  sym__newline = 4,
  sym_bracket_open = 5,
  sym_bracket_close = 6,
  sym_source_file = 7,
  sym_directive = 8,
  sym_name = 9,
  sym_params = 10,
  sym_block = 11,
  sym__word = 12,
  aux_sym_source_file_repeat1 = 13,
  aux_sym_params_repeat1 = 14,
};

static const char * const ts_symbol_names[] = {
  [ts_builtin_sym_end] = "end",
  [sym_atom] = "atom",
  [sym_dquote_word] = "dquote_word",
  [sym_squote_word] = "squote_word",
  [sym__newline] = "_newline",
  [sym_bracket_open] = "bracket_open",
  [sym_bracket_close] = "bracket_close",
  [sym_source_file] = "source_file",
  [sym_directive] = "directive",
  [sym_name] = "name",
  [sym_params] = "params",
  [sym_block] = "block",
  [sym__word] = "_word",
  [aux_sym_source_file_repeat1] = "source_file_repeat1",
  [aux_sym_params_repeat1] = "params_repeat1",
};

static const TSSymbol ts_symbol_map[] = {
  [ts_builtin_sym_end] = ts_builtin_sym_end,
  [sym_atom] = sym_atom,
  [sym_dquote_word] = sym_dquote_word,
  [sym_squote_word] = sym_squote_word,
  [sym__newline] = sym__newline,
  [sym_bracket_open] = sym_bracket_open,
  [sym_bracket_close] = sym_bracket_close,
  [sym_source_file] = sym_source_file,
  [sym_directive] = sym_directive,
  [sym_name] = sym_name,
  [sym_params] = sym_params,
  [sym_block] = sym_block,
  [sym__word] = sym__word,
  [aux_sym_source_file_repeat1] = aux_sym_source_file_repeat1,
  [aux_sym_params_repeat1] = aux_sym_params_repeat1,
};

static const TSSymbolMetadata ts_symbol_metadata[] = {
  [ts_builtin_sym_end] = {
    .visible = false,
    .named = true,
  },
  [sym_atom] = {
    .visible = true,
    .named = true,
  },
  [sym_dquote_word] = {
    .visible = true,
    .named = true,
  },
  [sym_squote_word] = {
    .visible = true,
    .named = true,
  },
  [sym__newline] = {
    .visible = false,
    .named = true,
  },
  [sym_bracket_open] = {
    .visible = true,
    .named = true,
  },
  [sym_bracket_close] = {
    .visible = true,
    .named = true,
  },
  [sym_source_file] = {
    .visible = true,
    .named = true,
  },
  [sym_directive] = {
    .visible = true,
    .named = true,
  },
  [sym_name] = {
    .visible = true,
    .named = true,
  },
  [sym_params] = {
    .visible = true,
    .named = true,
  },
  [sym_block] = {
    .visible = true,
    .named = true,
  },
  [sym__word] = {
    .visible = false,
    .named = true,
  },
  [aux_sym_source_file_repeat1] = {
    .visible = false,
    .named = false,
  },
  [aux_sym_params_repeat1] = {
    .visible = false,
    .named = false,
  },
};

static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = {
  [0] = {0},
};

static const uint16_t ts_non_terminal_alias_map[] = {
  0,
};

static bool ts_lex(TSLexer *lexer, TSStateId state) {
  START_LEXER();
  eof = lexer->eof(lexer);
  switch (state) {
    case 0:
      if (eof) ADVANCE(6);
      if (lookahead == '"') ADVANCE(4);
      if (lookahead == '\'') ADVANCE(5);
      if (lookahead == '{') ADVANCE(11);
      if (lookahead == '}') ADVANCE(12);
      if (lookahead == '\t' ||
          lookahead == '\n' ||
          lookahead == '\r' ||
          lookahead == ' ') SKIP(0)
      if (lookahead != 0) ADVANCE(7);
      END_STATE();
    case 1:
      if (lookahead == '\n') ADVANCE(10);
      if (lookahead == '\r') ADVANCE(1);
      if (lookahead == '"') ADVANCE(4);
      if (lookahead == '\'') ADVANCE(5);
      if (lookahead == '{') ADVANCE(11);
      if (lookahead == '\t' ||
          lookahead == ' ') SKIP(1)
      if (lookahead != 0 &&
          lookahead != '}') ADVANCE(7);
      END_STATE();
    case 2:
      if (lookahead == '"') ADVANCE(8);
      if (lookahead != 0 &&
          lookahead != '\n' &&
          lookahead != '\r' &&
          lookahead != '\\') ADVANCE(2);
      END_STATE();
    case 3:
      if (lookahead == '\'') ADVANCE(9);
      if (lookahead != 0 &&
          lookahead != '\n' &&
          lookahead != '\r') ADVANCE(3);
      END_STATE();
    case 4:
      if (lookahead != 0 &&
          lookahead != '\n' &&
          lookahead != '\r' &&
          lookahead != '"' &&
          lookahead != '\\') ADVANCE(2);
      END_STATE();
    case 5:
      if (lookahead != 0 &&
          lookahead != '\n' &&
          lookahead != '\r' &&
          lookahead != '\'') ADVANCE(3);
      END_STATE();
    case 6:
      ACCEPT_TOKEN(ts_builtin_sym_end);
      END_STATE();
    case 7:
      ACCEPT_TOKEN(sym_atom);
      if (lookahead != 0 &&
          lookahead != '\t' &&
          lookahead != '\n' &&
          lookahead != '\r' &&
          lookahead != ' ' &&
          lookahead != '"' &&
          lookahead != '\'' &&
          lookahead != '{' &&
          lookahead != '}') ADVANCE(7);
      END_STATE();
    case 8:
      ACCEPT_TOKEN(sym_dquote_word);
      END_STATE();
    case 9:
      ACCEPT_TOKEN(sym_squote_word);
      END_STATE();
    case 10:
      ACCEPT_TOKEN(sym__newline);
      if (lookahead == '\n') ADVANCE(10);
      if (lookahead == '\r') ADVANCE(1);
      END_STATE();
    case 11:
      ACCEPT_TOKEN(sym_bracket_open);
      END_STATE();
    case 12:
      ACCEPT_TOKEN(sym_bracket_close);
      END_STATE();
    default:
      return false;
  }
}

static const TSLexMode ts_lex_modes[STATE_COUNT] = {
  [0] = {.lex_state = 0},
  [1] = {.lex_state = 0},
  [2] = {.lex_state = 1},
  [3] = {.lex_state = 0},
  [4] = {.lex_state = 0},
  [5] = {.lex_state = 0},
  [6] = {.lex_state = 0},
  [7] = {.lex_state = 1},
  [8] = {.lex_state = 1},
  [9] = {.lex_state = 1},
  [10] = {.lex_state = 0},
  [11] = {.lex_state = 0},
  [12] = {.lex_state = 0},
  [13] = {.lex_state = 1},
  [14] = {.lex_state = 0},
  [15] = {.lex_state = 1},
  [16] = {.lex_state = 1},
  [17] = {.lex_state = 1},
  [18] = {.lex_state = 1},
  [19] = {.lex_state = 1},
};

static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
  [0] = {
    [ts_builtin_sym_end] = ACTIONS(1),
    [sym_atom] = ACTIONS(1),
    [sym_dquote_word] = ACTIONS(1),
    [sym_squote_word] = ACTIONS(1),
    [sym_bracket_open] = ACTIONS(1),
    [sym_bracket_close] = ACTIONS(1),
  },
  [1] = {
    [sym_source_file] = STATE(14),
    [sym_directive] = STATE(4),
    [sym_name] = STATE(2),
    [sym__word] = STATE(9),
    [aux_sym_source_file_repeat1] = STATE(4),
    [ts_builtin_sym_end] = ACTIONS(3),
    [sym_atom] = ACTIONS(5),
    [sym_dquote_word] = ACTIONS(5),
    [sym_squote_word] = ACTIONS(5),
  },
  [2] = {
    [sym_params] = STATE(13),
    [sym_block] = STATE(16),
    [sym__word] = STATE(7),
    [aux_sym_params_repeat1] = STATE(7),
    [sym_atom] = ACTIONS(7),
    [sym_dquote_word] = ACTIONS(7),
    [sym_squote_word] = ACTIONS(7),
    [sym__newline] = ACTIONS(9),
    [sym_bracket_open] = ACTIONS(11),
  },
  [3] = {
    [sym_directive] = STATE(3),
    [sym_name] = STATE(2),
    [sym__word] = STATE(9),
    [aux_sym_source_file_repeat1] = STATE(3),
    [ts_builtin_sym_end] = ACTIONS(13),
    [sym_atom] = ACTIONS(15),
    [sym_dquote_word] = ACTIONS(15),
    [sym_squote_word] = ACTIONS(15),
    [sym_bracket_close] = ACTIONS(13),
  },
  [4] = {
    [sym_directive] = STATE(3),
    [sym_name] = STATE(2),
    [sym__word] = STATE(9),
    [aux_sym_source_file_repeat1] = STATE(3),
    [ts_builtin_sym_end] = ACTIONS(18),
    [sym_atom] = ACTIONS(5),
    [sym_dquote_word] = ACTIONS(5),
    [sym_squote_word] = ACTIONS(5),
  },
  [5] = {
    [sym_directive] = STATE(6),
    [sym_name] = STATE(2),
    [sym__word] = STATE(9),
    [aux_sym_source_file_repeat1] = STATE(6),
    [sym_atom] = ACTIONS(5),
    [sym_dquote_word] = ACTIONS(5),
    [sym_squote_word] = ACTIONS(5),
    [sym_bracket_close] = ACTIONS(20),
  },
  [6] = {
    [sym_directive] = STATE(3),
    [sym_name] = STATE(2),
    [sym__word] = STATE(9),
    [aux_sym_source_file_repeat1] = STATE(3),
    [sym_atom] = ACTIONS(5),
    [sym_dquote_word] = ACTIONS(5),
    [sym_squote_word] = ACTIONS(5),
    [sym_bracket_close] = ACTIONS(22),
  },
};

static const uint16_t ts_small_parse_table[] = {
  [0] = 4,
    ACTIONS(26), 1,
      sym__newline,
    ACTIONS(28), 1,
      sym_bracket_open,
    STATE(8), 2,
      sym__word,
      aux_sym_params_repeat1,
    ACTIONS(24), 3,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
  [16] = 4,
    ACTIONS(33), 1,
      sym__newline,
    ACTIONS(35), 1,
      sym_bracket_open,
    STATE(8), 2,
      sym__word,
      aux_sym_params_repeat1,
    ACTIONS(30), 3,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
  [32] = 2,
    ACTIONS(39), 1,
      sym__newline,
    ACTIONS(37), 4,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
      sym_bracket_open,
  [42] = 1,
    ACTIONS(41), 5,
      ts_builtin_sym_end,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
      sym_bracket_close,
  [50] = 1,
    ACTIONS(43), 5,
      ts_builtin_sym_end,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
      sym_bracket_close,
  [58] = 1,
    ACTIONS(45), 5,
      ts_builtin_sym_end,
      sym_atom,
      sym_dquote_word,
      sym_squote_word,
      sym_bracket_close,
  [66] = 3,
    ACTIONS(11), 1,
      sym_bracket_open,
    ACTIONS(47), 1,
      sym__newline,
    STATE(17), 1,
      sym_block,
  [76] = 1,
    ACTIONS(49), 1,
      ts_builtin_sym_end,
  [80] = 1,
    ACTIONS(51), 1,
      sym__newline,
  [84] = 1,
    ACTIONS(47), 1,
      sym__newline,
  [88] = 1,
    ACTIONS(53), 1,
      sym__newline,
  [92] = 1,
    ACTIONS(55), 1,
      sym__newline,
  [96] = 1,
    ACTIONS(57), 1,
      sym__newline,
};

static const uint32_t ts_small_parse_table_map[] = {
  [SMALL_STATE(7)] = 0,
  [SMALL_STATE(8)] = 16,
  [SMALL_STATE(9)] = 32,
  [SMALL_STATE(10)] = 42,
  [SMALL_STATE(11)] = 50,
  [SMALL_STATE(12)] = 58,
  [SMALL_STATE(13)] = 66,
  [SMALL_STATE(14)] = 76,
  [SMALL_STATE(15)] = 80,
  [SMALL_STATE(16)] = 84,
  [SMALL_STATE(17)] = 88,
  [SMALL_STATE(18)] = 92,
  [SMALL_STATE(19)] = 96,
};

static const TSParseActionEntry ts_parse_actions[] = {
  [0] = {.entry = {.count = 0, .reusable = false}},
  [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(),
  [3] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 0),
  [5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9),
  [7] = {.entry = {.count = 1, .reusable = false}}, SHIFT(7),
  [9] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10),
  [11] = {.entry = {.count = 1, .reusable = false}}, SHIFT(15),
  [13] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2),
  [15] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2), SHIFT_REPEAT(9),
  [18] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1),
  [20] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18),
  [22] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19),
  [24] = {.entry = {.count = 1, .reusable = false}}, SHIFT(8),
  [26] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_params, 1),
  [28] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_params, 1),
  [30] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_params_repeat1, 2), SHIFT_REPEAT(8),
  [33] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_params_repeat1, 2),
  [35] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_params_repeat1, 2),
  [37] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_name, 1),
  [39] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_name, 1),
  [41] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_directive, 2),
  [43] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_directive, 3),
  [45] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_directive, 4),
  [47] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11),
  [49] = {.entry = {.count = 1, .reusable = true}},  ACCEPT_INPUT(),
  [51] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5),
  [53] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12),
  [55] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 3),
  [57] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 4),
};

#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#define extern __declspec(dllexport)
#endif

extern const TSLanguage *tree_sitter_scfg(void) {
  static const TSLanguage language = {
    .version = LANGUAGE_VERSION,
    .symbol_count = SYMBOL_COUNT,
    .alias_count = ALIAS_COUNT,
    .token_count = TOKEN_COUNT,
    .external_token_count = EXTERNAL_TOKEN_COUNT,
    .state_count = STATE_COUNT,
    .large_state_count = LARGE_STATE_COUNT,
    .production_id_count = PRODUCTION_ID_COUNT,
    .field_count = FIELD_COUNT,
    .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH,
    .parse_table = &ts_parse_table[0][0],
    .small_parse_table = ts_small_parse_table,
    .small_parse_table_map = ts_small_parse_table_map,
    .parse_actions = ts_parse_actions,
    .symbol_names = ts_symbol_names,
    .symbol_metadata = ts_symbol_metadata,
    .public_symbol_map = ts_symbol_map,
    .alias_map = ts_non_terminal_alias_map,
    .alias_sequences = &ts_alias_sequences[0][0],
    .lex_modes = ts_lex_modes,
    .lex_fn = ts_lex,
  };
  return &language;
}
#ifdef __cplusplus
}
#endif

A  => src/tree_sitter/parser.h +224 -0
@@ 1,224 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024

typedef uint16_t TSStateId;

#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif

typedef struct {
  TSFieldId field_id;
  uint8_t child_index;
  bool inherited;
} TSFieldMapEntry;

typedef struct {
  uint16_t index;
  uint16_t length;
} TSFieldMapSlice;

typedef struct {
  bool visible;
  bool named;
  bool supertype;
} TSSymbolMetadata;

typedef struct TSLexer TSLexer;

struct TSLexer {
  int32_t lookahead;
  TSSymbol result_symbol;
  void (*advance)(TSLexer *, bool);
  void (*mark_end)(TSLexer *);
  uint32_t (*get_column)(TSLexer *);
  bool (*is_at_included_range_start)(const TSLexer *);
  bool (*eof)(const TSLexer *);
};

typedef enum {
  TSParseActionTypeShift,
  TSParseActionTypeReduce,
  TSParseActionTypeAccept,
  TSParseActionTypeRecover,
} TSParseActionType;

typedef union {
  struct {
    uint8_t type;
    TSStateId state;
    bool extra;
    bool repetition;
  } shift;
  struct {
    uint8_t type;
    uint8_t child_count;
    TSSymbol symbol;
    int16_t dynamic_precedence;
    uint16_t production_id;
  } reduce;
  uint8_t type;
} TSParseAction;

typedef struct {
  uint16_t lex_state;
  uint16_t external_lex_state;
} TSLexMode;

typedef union {
  TSParseAction action;
  struct {
    uint8_t count;
    bool reusable;
  } entry;
} TSParseActionEntry;

struct TSLanguage {
  uint32_t version;
  uint32_t symbol_count;
  uint32_t alias_count;
  uint32_t token_count;
  uint32_t external_token_count;
  uint32_t state_count;
  uint32_t large_state_count;
  uint32_t production_id_count;
  uint32_t field_count;
  uint16_t max_alias_sequence_length;
  const uint16_t *parse_table;
  const uint16_t *small_parse_table;
  const uint32_t *small_parse_table_map;
  const TSParseActionEntry *parse_actions;
  const char * const *symbol_names;
  const char * const *field_names;
  const TSFieldMapSlice *field_map_slices;
  const TSFieldMapEntry *field_map_entries;
  const TSSymbolMetadata *symbol_metadata;
  const TSSymbol *public_symbol_map;
  const uint16_t *alias_map;
  const TSSymbol *alias_sequences;
  const TSLexMode *lex_modes;
  bool (*lex_fn)(TSLexer *, TSStateId);
  bool (*keyword_lex_fn)(TSLexer *, TSStateId);
  TSSymbol keyword_capture_token;
  struct {
    const bool *states;
    const TSSymbol *symbol_map;
    void *(*create)(void);
    void (*destroy)(void *);
    bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
    unsigned (*serialize)(void *, char *);
    void (*deserialize)(void *, const char *, unsigned);
  } external_scanner;
  const TSStateId *primary_state_ids;
};

/*
 *  Lexer Macros
 */

#define START_LEXER()           \
  bool result = false;          \
  bool skip = false;            \
  bool eof = false;             \
  int32_t lookahead;            \
  goto start;                   \
  next_state:                   \
  lexer->advance(lexer, skip);  \
  start:                        \
  skip = false;                 \
  lookahead = lexer->lookahead;

#define ADVANCE(state_value) \
  {                          \
    state = state_value;     \
    goto next_state;         \
  }

#define SKIP(state_value) \
  {                       \
    skip = true;          \
    state = state_value;  \
    goto next_state;      \
  }

#define ACCEPT_TOKEN(symbol_value)     \
  result = true;                       \
  lexer->result_symbol = symbol_value; \
  lexer->mark_end(lexer);

#define END_STATE() return result;

/*
 *  Parse Table Macros
 */

#define SMALL_STATE(id) id - LARGE_STATE_COUNT

#define STATE(id) id

#define ACTIONS(id) id

#define SHIFT(state_value)            \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .state = state_value            \
    }                                 \
  }}

#define SHIFT_REPEAT(state_value)     \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .state = state_value,           \
      .repetition = true              \
    }                                 \
  }}

#define SHIFT_EXTRA()                 \
  {{                                  \
    .shift = {                        \
      .type = TSParseActionTypeShift, \
      .extra = true                   \
    }                                 \
  }}

#define REDUCE(symbol_val, child_count_val, ...) \
  {{                                             \
    .reduce = {                                  \
      .type = TSParseActionTypeReduce,           \
      .symbol = symbol_val,                      \
      .child_count = child_count_val,            \
      __VA_ARGS__                                \
    },                                           \
  }}

#define RECOVER()                    \
  {{                                 \
    .type = TSParseActionTypeRecover \
  }}

#define ACCEPT_INPUT()              \
  {{                                \
    .type = TSParseActionTypeAccept \
  }}

#ifdef __cplusplus
}
#endif

#endif  // TREE_SITTER_PARSER_H_