module.exports = grammar({ name: 'dust', word: $ => $.identifier, rules: { root: $ => repeat1($.item), item: $ => choice( $.comment, $.statement, ), comment: $ => prec.left(seq(token('#'), /.*/)), statement: $ => prec.right(choice( $.open_statement, $.yield_statement, )), open_statement: $ => prec.left($.expression), yield_statement: $ => seq($.open_statement, '->', $.open_statement), expression: $ => choice( $.value, $.identifier, $.operation, $.control_flow, $.tool, $.select, ), identifier: $ => /[a-z|_|.]+[0-9]?/, value: $ => choice( $.integer, $.float, $.string, $.list, $.empty, $.boolean, $.function, $.table, $.map, ), float: $ => /\d+\.\d*/, integer: $ => /\d+/, string: $ => /("|'|`)(.*?)("|'|`)/, empty: $ => '()', boolean: $ => choice( 'true', 'false', ), list: $ => seq( '[', repeat1(seq($.value, optional(','))), ']' ), function: $ => seq( 'function', optional(seq('<', repeat(seq($.identifier, optional(','))), '>')), '{', repeat1($.statement), '}', ), table: $ => seq( 'table', seq('<', repeat1(seq($.identifier, optional(','))), '>'), '{', repeat($.list), '}', ), map: $ => seq( 'map', '{', repeat(seq($.identifier, "=", $.value)), '}', ), operator: $ => choice( '=', '+', '-', '*', '/', '%', '==', '+=', '-=', '&&', '||', 'and', 'or', 'insert', 'into', 'select', 'from', 'where', ), operation: $ => prec.right(seq( $.expression, $.operator, $.expression, )), select: $ => prec.right(seq( 'select', $.identifier, 'from', $.identifier, optional( seq('where', $.expression) ), )), control_flow: $ => prec.right(seq( 'if', $.expression, 'then', $.statement, optional(seq('else', $.statement)) )), tool: $ => choice( "output", ), } });