commit
62ab651250
@ -0,0 +1,11 @@
|
|||||||
|
Cargo.toml
|
||||||
|
Cargo.lock
|
||||||
|
node_modules
|
||||||
|
build
|
||||||
|
package-lock.json
|
||||||
|
pnpm-lock.yaml
|
||||||
|
/bindings/
|
||||||
|
/src/
|
||||||
|
/target/
|
||||||
|
.build/
|
||||||
|
binding.gyp
|
@ -0,0 +1,3 @@
|
|||||||
|
# tree-sitter-moshell
|
||||||
|
|
||||||
|
Moshell grammar subset for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
|
@ -0,0 +1,112 @@
|
|||||||
|
===============================
|
||||||
|
Command
|
||||||
|
===============================
|
||||||
|
|
||||||
|
whoami
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(command (command_name (identifier))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Command without trailing new line
|
||||||
|
===============================
|
||||||
|
|
||||||
|
echo hello
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file (command (command_name (identifier)) (word)))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Variable expansion
|
||||||
|
===============================
|
||||||
|
|
||||||
|
cat $FOO
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(command
|
||||||
|
(command_name (identifier))
|
||||||
|
(expansion (variable (identifier)))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Redirection
|
||||||
|
===============================
|
||||||
|
|
||||||
|
cat file 2> /dev/null
|
||||||
|
echo message >&2
|
||||||
|
python <<< 'print("hello")'
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)
|
||||||
|
(word)
|
||||||
|
(redirection
|
||||||
|
(word)))
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)
|
||||||
|
(redirection
|
||||||
|
(word)))
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(redirection
|
||||||
|
(raw_string))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Pipeline
|
||||||
|
===============================
|
||||||
|
|
||||||
|
cat path/to/file.txt | wc -l
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(pipeline
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word))
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
String interpolation
|
||||||
|
===============================
|
||||||
|
|
||||||
|
echo "The result is $result"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(template_string
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier))))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Negated command
|
||||||
|
===============================
|
||||||
|
|
||||||
|
! grep foo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)))
|
@ -0,0 +1,138 @@
|
|||||||
|
===============================
|
||||||
|
If expression
|
||||||
|
===============================
|
||||||
|
|
||||||
|
if grep found file {
|
||||||
|
echo present
|
||||||
|
} else {
|
||||||
|
echo absent
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)
|
||||||
|
(word))
|
||||||
|
(block
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)))
|
||||||
|
(block
|
||||||
|
(command
|
||||||
|
(command_name
|
||||||
|
(identifier))
|
||||||
|
(word)))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
While statement
|
||||||
|
===============================
|
||||||
|
|
||||||
|
val i = 0
|
||||||
|
while $i < 10 {
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(variable_declaration
|
||||||
|
(identifier)
|
||||||
|
(primary
|
||||||
|
(number)))
|
||||||
|
(while
|
||||||
|
(infix_expression
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier)))
|
||||||
|
(primary
|
||||||
|
(number)))
|
||||||
|
(block
|
||||||
|
(assignation
|
||||||
|
(identifier)
|
||||||
|
(primary
|
||||||
|
(number))))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Function declaration
|
||||||
|
===============================
|
||||||
|
|
||||||
|
fun square(n: Int) -> Int = $n * $n
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(identifier)
|
||||||
|
(parameter_list
|
||||||
|
(function_parameter
|
||||||
|
(identifier)
|
||||||
|
(type_identifier
|
||||||
|
(identifier))))
|
||||||
|
(type_identifier
|
||||||
|
(identifier))
|
||||||
|
(infix_expression
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier)))
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier))))))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Implicit return
|
||||||
|
===============================
|
||||||
|
|
||||||
|
fun fibonacci(n: Int) -> Int =
|
||||||
|
if $n <= 1 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
fibonacci($n - 1) + fibonacci($n - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(identifier)
|
||||||
|
(parameter_list
|
||||||
|
(function_parameter
|
||||||
|
(identifier)
|
||||||
|
(type_identifier
|
||||||
|
(identifier))))
|
||||||
|
(type_identifier
|
||||||
|
(identifier))
|
||||||
|
(if
|
||||||
|
(infix_expression
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier)))
|
||||||
|
(primary
|
||||||
|
(number)))
|
||||||
|
(block
|
||||||
|
(primary
|
||||||
|
(number)))
|
||||||
|
(block
|
||||||
|
(infix_expression
|
||||||
|
(call_expression
|
||||||
|
(identifier)
|
||||||
|
(argument_list
|
||||||
|
(infix_expression
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier)))
|
||||||
|
(primary
|
||||||
|
(number)))))
|
||||||
|
(call_expression
|
||||||
|
(identifier)
|
||||||
|
(argument_list
|
||||||
|
(infix_expression
|
||||||
|
(expansion
|
||||||
|
(variable
|
||||||
|
(identifier)))
|
||||||
|
(primary
|
||||||
|
(number))))))))))
|
@ -0,0 +1,194 @@
|
|||||||
|
const commaSep = (rule) => seq(rule, repeat(seq(',', rule)));
|
||||||
|
|
||||||
|
module.exports = grammar({
|
||||||
|
name: 'moshell',
|
||||||
|
extras: $ => [
|
||||||
|
/\s/,
|
||||||
|
/\\\r?\n/,
|
||||||
|
$.line_comment,
|
||||||
|
$.block_comment,
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
source_file: $ => optional($._declarations),
|
||||||
|
|
||||||
|
_declarations: $ => seq(
|
||||||
|
repeat(seq(
|
||||||
|
$._declaration,
|
||||||
|
$._terminator
|
||||||
|
)),
|
||||||
|
$._declaration,
|
||||||
|
optional($._terminator)
|
||||||
|
),
|
||||||
|
_declaration: $ => choice(
|
||||||
|
$.function_declaration,
|
||||||
|
$.use_declaration,
|
||||||
|
$.variable_declaration,
|
||||||
|
$._statement,
|
||||||
|
$.return,
|
||||||
|
$.while,
|
||||||
|
'break',
|
||||||
|
'continue',
|
||||||
|
),
|
||||||
|
function_declaration: $ => seq(
|
||||||
|
'fun',
|
||||||
|
field('name', $.identifier),
|
||||||
|
field('parameters', $.parameter_list),
|
||||||
|
optional(seq(
|
||||||
|
'->',
|
||||||
|
field('return_type', $.type_identifier)
|
||||||
|
)),
|
||||||
|
'=',
|
||||||
|
$._expression
|
||||||
|
),
|
||||||
|
parameter_list: $ => seq(
|
||||||
|
'(',
|
||||||
|
optional(commaSep($.function_parameter)),
|
||||||
|
')'
|
||||||
|
),
|
||||||
|
function_parameter: $ => seq(
|
||||||
|
$.identifier,
|
||||||
|
':',
|
||||||
|
$.type_identifier
|
||||||
|
),
|
||||||
|
use_declaration: $ => seq(
|
||||||
|
'use',
|
||||||
|
$._use_clause,
|
||||||
|
),
|
||||||
|
_use_clause: $ => seq(
|
||||||
|
$.identifier,
|
||||||
|
repeat(seq('::', $.identifier)),
|
||||||
|
optional(seq('as', $.identifier)),
|
||||||
|
),
|
||||||
|
variable_declaration: $ => seq(
|
||||||
|
choice('var', 'val'),
|
||||||
|
$.identifier,
|
||||||
|
optional(seq(':', $.type_identifier)),
|
||||||
|
optional(seq('=', $._expression))
|
||||||
|
),
|
||||||
|
command: $ => seq(
|
||||||
|
$.command_name,
|
||||||
|
repeat($._argument),
|
||||||
|
repeat($.redirection),
|
||||||
|
),
|
||||||
|
|
||||||
|
_statement: $ => choice(
|
||||||
|
$.command,
|
||||||
|
$.pipeline,
|
||||||
|
seq('!', $.command),
|
||||||
|
$._expression,
|
||||||
|
),
|
||||||
|
while: $ => seq(
|
||||||
|
'while',
|
||||||
|
$._statement,
|
||||||
|
$.block
|
||||||
|
),
|
||||||
|
return: $ => seq(
|
||||||
|
'return',
|
||||||
|
optional($._expression)
|
||||||
|
),
|
||||||
|
|
||||||
|
_expression: $ => choice(
|
||||||
|
$.block,
|
||||||
|
$.if,
|
||||||
|
$.call_expression,
|
||||||
|
$.assignation,
|
||||||
|
$.infix_expression,
|
||||||
|
$.prefix_expression,
|
||||||
|
$.expansion,
|
||||||
|
$.primary
|
||||||
|
),
|
||||||
|
block: $ => seq(
|
||||||
|
'{',
|
||||||
|
optional($._declarations),
|
||||||
|
'}'
|
||||||
|
),
|
||||||
|
if: $ => seq(
|
||||||
|
'if',
|
||||||
|
field('condition', $._statement),
|
||||||
|
field('then', $.block),
|
||||||
|
optional(seq(
|
||||||
|
'else',
|
||||||
|
field('else', $.block)
|
||||||
|
))
|
||||||
|
),
|
||||||
|
call_expression: $ => seq(
|
||||||
|
field('name', $.identifier),
|
||||||
|
field('arguments', $.argument_list),
|
||||||
|
),
|
||||||
|
argument_list: $ => seq(
|
||||||
|
'(',
|
||||||
|
optional($._expression),
|
||||||
|
repeat(seq(',', $._expression)),
|
||||||
|
')'
|
||||||
|
),
|
||||||
|
assignation: $ => prec.right(seq(
|
||||||
|
choice($.identifier, $._expression),
|
||||||
|
choice('=', '+=', '-=', '*=', '/=', '%='),
|
||||||
|
$._expression
|
||||||
|
)),
|
||||||
|
cast_expression: $ => prec.left(seq(
|
||||||
|
field('value', $._expression),
|
||||||
|
'as',
|
||||||
|
field('type', $.type_identifier)
|
||||||
|
)),
|
||||||
|
infix_expression: $ => prec.left(seq(
|
||||||
|
$._expression,
|
||||||
|
choice('+', '-', '*', '/', '%', '==', '!=', '<', '>', '<=', '>=', '&&', '||', 'in'),
|
||||||
|
$._expression
|
||||||
|
)),
|
||||||
|
prefix_expression: $ => prec.right(seq(
|
||||||
|
choice('!', '-'),
|
||||||
|
$._expression
|
||||||
|
)),
|
||||||
|
|
||||||
|
expansion: $ => choice(
|
||||||
|
$.variable,
|
||||||
|
$.command_substitution
|
||||||
|
),
|
||||||
|
pipeline: $ => prec.left(seq(
|
||||||
|
$._statement,
|
||||||
|
'|',
|
||||||
|
$._statement
|
||||||
|
)),
|
||||||
|
redirection: $ => seq(
|
||||||
|
field('descriptor', optional($.number)),
|
||||||
|
choice('<', '>', '>>', '<<<', '&>', '&>>', '<&', '>&'),
|
||||||
|
field('destination', $._argument)
|
||||||
|
),
|
||||||
|
command_substitution: $ => seq('$(', $._declaration, ')'),
|
||||||
|
|
||||||
|
command_name: $ => $.identifier,
|
||||||
|
_argument: $ => choice(
|
||||||
|
$.raw_string,
|
||||||
|
$.template_string,
|
||||||
|
$.expansion,
|
||||||
|
$.word
|
||||||
|
),
|
||||||
|
|
||||||
|
primary: $ => choice(
|
||||||
|
$.number,
|
||||||
|
$.boolean,
|
||||||
|
$.raw_string,
|
||||||
|
$.template_string,
|
||||||
|
),
|
||||||
|
line_comment: $ => token(seq('//', /.*/)),
|
||||||
|
block_comment: $ => token(seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/')),
|
||||||
|
identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
|
||||||
|
word: $ => /[^#'"\\\s$<>{}&;]+/,
|
||||||
|
number: $ => /\d+/,
|
||||||
|
boolean: $ => choice('true', 'false'),
|
||||||
|
template_string: $ => seq(
|
||||||
|
'"',
|
||||||
|
repeat(choice($._string_content, $.expansion)),
|
||||||
|
'"'
|
||||||
|
),
|
||||||
|
raw_string: $ => /'[^']*'/,
|
||||||
|
_string_content: $ => token(prec(-1, /([^"`$\\]|\\(.|\r?\n))+/)),
|
||||||
|
_terminator: $ => choice(';', '\n'),
|
||||||
|
type_identifier: $ => $.identifier,
|
||||||
|
variable: $ => seq(
|
||||||
|
'$',
|
||||||
|
$.identifier
|
||||||
|
),
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "tree-sitter-moshell",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "C grammar for node-tree-sitter",
|
||||||
|
"main": "bindings/node",
|
||||||
|
"keywords": [
|
||||||
|
"parser",
|
||||||
|
"lexer"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/moshell-lang/tree-sitter-moshell.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "tree-sitter test"
|
||||||
|
},
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.17.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tree-sitter-cli": "^0.20.8"
|
||||||
|
},
|
||||||
|
"tree-sitter": [
|
||||||
|
{
|
||||||
|
"scope": "source.moshell",
|
||||||
|
"file-types": [
|
||||||
|
"msh"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
; Literals
|
||||||
|
|
||||||
|
(raw_string) @string
|
||||||
|
(template_string) @string
|
||||||
|
(number) @number
|
||||||
|
(command_name) @function.macro
|
||||||
|
(expansion) @embedded
|
||||||
|
|
||||||
|
; Functions
|
||||||
|
|
||||||
|
(function_declaration
|
||||||
|
name: (identifier) @function)
|
||||||
|
(function_parameter (identifier) @variable.parameter)
|
||||||
|
(call_expression
|
||||||
|
name: (identifier) @function)
|
||||||
|
|
||||||
|
(line_comment) @comment
|
||||||
|
(block_comment) @comment
|
||||||
|
|
||||||
|
; Punctuation and operators
|
||||||
|
|
||||||
|
"(" @punctuation.bracket
|
||||||
|
")" @punctuation.bracket
|
||||||
|
"{" @punctuation.bracket
|
||||||
|
"}" @punctuation.bracket
|
||||||
|
":" @punctuation.delimiter
|
||||||
|
"::" @punctuation.delimiter
|
||||||
|
"," @punctuation.delimiter
|
||||||
|
";" @punctuation.delimiter
|
||||||
|
|
||||||
|
[
|
||||||
|
"+"
|
||||||
|
"-"
|
||||||
|
"*"
|
||||||
|
"/"
|
||||||
|
"%"
|
||||||
|
"="
|
||||||
|
"+="
|
||||||
|
"-="
|
||||||
|
"*="
|
||||||
|
"/="
|
||||||
|
"%="
|
||||||
|
"<"
|
||||||
|
"<="
|
||||||
|
">"
|
||||||
|
">="
|
||||||
|
"&&"
|
||||||
|
"||"
|
||||||
|
"!"
|
||||||
|
"|"
|
||||||
|
] @operator
|
||||||
|
|
||||||
|
; Identifiers
|
||||||
|
|
||||||
|
(type_identifier) @type
|
||||||
|
[
|
||||||
|
"as"
|
||||||
|
"break"
|
||||||
|
"continue"
|
||||||
|
"else"
|
||||||
|
"fun"
|
||||||
|
"if"
|
||||||
|
"in"
|
||||||
|
"return"
|
||||||
|
"use"
|
||||||
|
"val"
|
||||||
|
"var"
|
||||||
|
"while"
|
||||||
|
] @keyword
|
||||||
|
[
|
||||||
|
"true"
|
||||||
|
"false"
|
||||||
|
] @constant.builtin
|
Loading…
Reference in new issue