update stuff

This commit is contained in:
Maix0 2024-06-01 20:48:52 +02:00
parent 9ded0ac536
commit 8338f82e2c
2 changed files with 130 additions and 0 deletions

View file

@ -34,6 +34,8 @@
llvmPackages.bintools
norminette
rust-bin.stable.latest.default
(tree-sitter.override {webUISupport = true;})
nodejs
];
VALGRIND_INC_OPT = "${pkgs.valgrind.dev}/include";
ASAN_OPTIONS = "strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1";

128
tree-sitter-sh/grammar.js Normal file
View file

@ -0,0 +1,128 @@
/// <reference types="tree-sitter-cli/dsl" />
// @ts-check
const SPECIAL_CHARACTERS = [
'\'', '"',
'<', '>',
'{', '}',
'\\[', '\\]',
'(', ')',
'`', '$',
'|', '&', ';',
'\\',
'\\s',
];
module.exports = grammar({
name: "sh",
rules: {
source_file: $ => repeat($.program),
program: $ => $.expansion,
expansion: $ => choice(
$.basic_expansion,
$.complex_expansion,
$.arithmetic_expansion,
$.command_substitution,
),
basic_expansion: $ => seq("$", field("varname", $.varname)),
complex_expansion: $ => seq(
"${",
optional(choice(
seq(
optional(field("prefix", $.complex_expansion_prefix)),
field("varname", choice($.varname, repeat1(/[0-9]/))),
),
seq(
field("varname", choice($.varname, repeat1(/[0-9]/))),
optional(field("suffix", $.complex_expansion_suffix)),
),
)),
"}",
),
complex_expansion_prefix: _ => prec(1, choice('#')),
complex_expansion_suffix: $ => choice(
...CESuffixRegex(['%', '%%', '#', '##'], $.suffix_matching),
...CESuffixWord(['+', '-', '=', '?'], $.suffix_word),
),
suffix_matching: _ => 'matching',
suffix_word: _ => 'word',
varname: $ => choice($._special_varname, seq(/[a-zA-Z]/, repeat(/[a-zA-Z0-9_]/))),
_special_varname: _ => choice("@", "*", "#", "?", "?", "-", "$", "!", "0", /[1-9]/),
command_substitution: $ => seq("$(", repeat($.program), ")"),
arithmetic_expansion: _ => seq("$((", "))"),
// word: _ => token(seq(
// choice(
// noneOf('#', ...SPECIAL_CHARACTERS),
// seq('\\', noneOf('\\s')),
// ),
// repeat(choice(
// noneOf(...SPECIAL_CHARACTERS),
// seq('\\', noneOf('\\s')),
// '\\ ',
// )),
// )),
}
});
/**
* Returns a regular expression that matches any character except the ones
* provided.
* @param {...string} characters
* @return {RegExp}
*/
function noneOf(...characters) {
const negatedString = characters.map(c => c == '\\' ? '\\\\' : c).join('');
return new RegExp('[^' + negatedString + ']');
}
/**
*
* Turns a list of rules into a choice of immediate rule
*
* @param {(RegExp|String)[]} literals
*
* @return {ImmediateTokenRule[]}
*/
function immediateLiterals(...literals) {
return 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
*
* @return {ChoiceRule}
*/
function tokenLiterals(precedence, ...literals) {
return choice(...literals.map(l => token(prec(precedence, l))));
}
/**
* @param {(string)[]} op
* @param {RuleOrLiteral} rule
* @return {RuleOrLiteral[]}
*/
function CESuffixRegex(op, rule) {
return (op.map(o => seq(o, rule)));
}
/**
* @param {(string)[]} op
* @param {RuleOrLiteral} rule
* @return {RuleOrLiteral[]}
*/
function CESuffixWord(op, rule) {
return (op.flatMap(o => [seq(token.immediate(`${o}`), rule), seq(token.immediate(`:${o}`), rule)]));
}