module.exports = grammar({ name: 'dust', word: $ => $.identifier, rules: { root: $ => repeat1($.item), item: $ => choice( $.comment, field('source', $.statement), ), comment: $ => seq(token('#'), /.*/), statement: $ => prec.right(choice( $.expression, $.yield, )), yield: $ => prec.left( seq( $.expression, '->', $.expression, repeat(prec.left(seq('->', $.expression))) ) ), expression: $ => choice( $._expression_kind, seq('(', $._expression_kind, ')') ), _expression_kind: $ => prec.right(choice( $.value, $.identifier, $.control_flow, $.select, $.insert, $.function_call, $.assignment, $.math, $.logic, $.loop, $.match, )), identifier: $ => /[a-z|_|.]+[0-9]?/, value: $ => choice( $.integer, $.float, $.string, $.list, $.boolean, $.function, $.table, $.map, ), float: $ => /[-]*[0-9]*[.]{1}[0-9]+/, integer: $ => /[-]*[0-9]+[.]{0}/, string: $ => /(".*?")|('.*?')|(`.*?`)/, boolean: $ => choice( 'true', 'false', ), list: $ => seq( '[', repeat1(seq(field('item', $.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(field('key_value_pair', seq($.identifier, "=", $.value))), '}', ), math: $ => prec.right(seq( $.expression, $.math_operator, $.expression, )), math_operator: $ => choice( '+', '-', '*', '/', '%', ), logic: $ => prec.right(seq( $.expression, $.logic_operator, $.expression, )), logic_operator: $ => choice( '==', '&&', '||', 'and', 'or', ), assignment: $ => prec.right(seq( $.identifier, choice("=", "+=", "-="), $.statement, )), select: $ => prec.right(seq( 'select', $.identifier, 'from', $.identifier, optional( seq('where', $.expression) ), )), insert: $ => prec.right(seq( 'insert', repeat1($.list), 'into', $.identifier, optional( seq('where', $.expression) ), )), control_flow: $ => prec.right(seq( 'if', field('if_expression', $.expression), 'then', field('then_statement', $.statement), optional( seq('else', field('else_statement', $.statement), ), ), )), function_call: $ => prec.right(seq( $.identifier, '<', repeat(seq($.expression, optional(','))), '>', )), loop: $ => choice( $.break_loop, $.while_loop, ), while_loop: $ => seq( 'while', $.expression, '{', $.statement, '}', ), break_loop: $ => seq( 'loop', '{', $.statement, '}', ), match: $ => seq( 'match', $.expression, '{', repeat1(seq($.expression, '=>', $.statement)), '}', ), } });