Initial commit

main
Clément FRÉVILLE 2 years ago
commit 62ab651250
Signed by: clement.freville2
GPG Key ID: 732E73BB80FA6076

11
.gitignore vendored

@ -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…
Cancel
Save