Initial commit: Add README and LICENSE

This commit is contained in:
2025-11-25 11:43:36 +01:00
commit b2c5d94cb5
22 changed files with 27116 additions and 0 deletions

338
grammar.js Normal file
View File

@@ -0,0 +1,338 @@
module.exports = grammar({
name: 'stonescript',
rules: {
source_file: $ => repeat($._statement),
_statement: $ => choice(
// Comments first
$.comment,
$.block_comment,
// Keyword-based statements (must come before generic command)
$.variable_declaration, // 'var'
$.function_declaration, // 'func'
$.for_loop, // 'for'
$.return_statement, // 'return'
$.break_statement, // 'break'
$.continue_statement, // 'continue'
$.import_statement, // 'import'
$.new_expression, // 'new'
// Control flow
$.conditional, // '?'
$.else_if_clause, // ':?'
$.else_clause, // ':'
// Commands (after keywords!)
$.command_statement,
// Fallback
$.expression_statement
),
// Comments
comment: $ => token(seq('//', /.*/)),
block_comment: $ => token(seq(
'/*',
/[^*]*\*+(?:[^/*][^*]*\*+)*/,
'/'
)),
// Variable declaration
variable_declaration: $ => seq(
'var',
field('name', $.identifier),
optional(seq('=', field('value', $._expression)))
),
// Function declaration
function_declaration: $ => seq(
'func',
field('name', $.identifier),
'(',
optional($.parameter_list),
')',
optional($.function_body)
),
function_body: $ => seq(
$._indent,
repeat1($._statement),
$._dedent
),
parameter_list: $ => seq(
$.identifier,
repeat(seq(',', $.identifier))
),
// Loops
for_loop: $ => choice(
seq(
'for',
$.identifier,
'=',
$._expression,
'..',
$._expression,
optional($.block)
),
seq(
'for',
$.identifier,
':',
$._expression,
optional($.block)
)
),
// Import
import_statement: $ => seq(
'import',
$.module_path
),
new_expression: $ => seq(
'new',
$.module_path
),
module_path: $ => /[a-zA-Z_][a-zA-Z0-9_\/]*/,
// Control flow
return_statement: $ => prec.right(seq(
'return',
optional($._expression)
)),
break_statement: $ => 'break',
continue_statement: $ => 'continue',
// Conditionals
conditional: $ => seq(
'?',
$._expression,
optional($.block)
),
else_if_clause: $ => seq(
':?',
$._expression,
optional($.block)
),
else_clause: $ => seq(
':',
optional($.block)
),
block: $ => seq(
$._indent,
repeat1($._statement),
$._dedent
),
// Commands - specific patterns
command_statement: $ => choice(
$.equip_command,
$.activate_command,
$.loadout_command,
$.brew_command,
$.disable_enable_command,
$.play_command,
$.print_command
),
equip_command: $ => prec.left(seq(
choice('equip', 'equipL', 'equipR'),
repeat1($.item_criteria)
)),
item_criteria: $ => prec.left(choice(
$.identifier,
$.star_level,
$.enchantment_level
)),
star_level: $ => seq('*', $.number),
enchantment_level: $ => seq('+', $.number),
activate_command: $ => seq(
'activate',
choice(
$.identifier,
'P', 'L', 'R'
)
),
loadout_command: $ => seq(
'loadout',
$.number
),
brew_command: $ => seq(
'brew',
$.identifier,
repeat(seq('+', $.identifier))
),
disable_enable_command: $ => prec.left(seq(
choice('disable', 'enable'),
choice(
'abilities', 'hud', 'banner',
'loadout', 'npcDialog', 'pause', 'player'
)
)),
play_command: $ => prec.left(seq(
'play',
$.identifier,
optional($.number)
)),
print_command: $ => prec.right(seq(
choice('>', '>o', '>h', '>`', '>c', '>f'),
repeat(choice(
$.identifier,
$.string,
$.number,
$.color_code,
','
))
)),
color_code: $ => /#[a-zA-Z0-9]+/,
// Expressions
expression_statement: $ => $._expression,
_expression: $ => choice(
$.identifier,
$.number,
$.float,
$.string,
$.boolean,
$.null,
$.array,
$.member_expression,
$.call_expression,
$.index_expression,
$.unary_expression,
$.binary_expression,
$.update_expression,
$.assignment_expression,
$.parenthesized_expression,
$.new_expression
),
member_expression: $ => prec.left(15, seq(
field('object', $._expression),
'.',
field('property', $.identifier)
)),
call_expression: $ => prec.left(14, seq(
field('function', $._expression),
'(',
optional($.argument_list),
')'
)),
argument_list: $ => sep1($.comma_sep, $._expression),
comma_sep: $ => ',',
index_expression: $ => prec.left(13, seq(
$._expression,
'[',
$._expression,
']'
)),
unary_expression: $ => prec.right(12, seq(
choice('!', '-'),
$._expression
)),
// Binary operators with proper precedence
binary_expression: $ => choice(
prec.left(4, seq($._expression, '|', $._expression)),
prec.left(5, seq($._expression, '&', $._expression)),
prec.left(7, seq($._expression, '!', $._expression)),
prec.left(7, seq($._expression, '=', $._expression)),
prec.left(8, seq($._expression, '<', $._expression)),
prec.left(8, seq($._expression, '>', $._expression)),
prec.left(8, seq($._expression, '<=', $._expression)),
prec.left(8, seq($._expression, '>=', $._expression)),
prec.left(9, seq($._expression, '+', $._expression)),
prec.left(9, seq($._expression, '-', $._expression)),
prec.left(10, seq($._expression, '*', $._expression)),
prec.left(10, seq($._expression, '/', $._expression)),
prec.left(11, seq($._expression, '%', $._expression))
),
update_expression: $ => choice(
prec.left(12, seq($._expression, choice('++', '--'))),
prec.right(12, seq(choice('++', '--'), $._expression))
),
assignment_expression: $ => prec.right(2, seq(
$._expression,
choice('=', '+=', '-=', '*=', '/='),
$._expression
)),
parenthesized_expression: $ => seq(
'(',
$._expression,
')'
),
// Arrays
array: $ => seq(
'[',
optional(sep1($.comma_sep, $._expression)),
optional(','),
']'
),
// Primitives
identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
number: $ => /\d+/,
float: $ => /\d+\.\d+/,
string: $ => seq('"', repeat(choice(/[^"\\]/, /\\./)), '"'),
boolean: $ => choice('true', 'false'),
null: $ => 'null'
},
extras: $ => [
/\s/
],
externals: $ => [
$._newline,
$._indent,
$._dedent
],
word: $ => $.identifier,
conflicts: $ => [
[$.identifier, $.string],
[$._expression],
[$.command_statement],
[$._statement, $._expression], // new_expression can be both
[$.equip_command], // handle repeat ambiguity
[$.binary_expression, $.assignment_expression] // = operator ambiguity
]
});
// Helper to create comma-separated lists
function sep1(separator, rule) {
return seq(rule, repeat(seq(separator, rule)));
}