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