module.exports = grammar({ name: 'lila', word: $ => $.identifier, rules: { source_file: $ => repeat($._definition), _definition: $ => choice( $.function_definition ), function_definition: $ => seq( 'func', field('name', $.identifier), field('parameters', $.parameters), field('return_type', optional($._type)), field('body', $.block), ), parameters: $ => seq( '(', optional(seq( repeat(seq($.parameter, ',')), seq($.parameter, optional(',')), )), ')', ), parameter: $ => seq( $.identifier, ' ', $._type, ), block: $ => seq( '{', repeat($._statement), optional($._expression), '}', ), _statement: $ => choice( $.return_statement, $.assign_statement, $.if_statement, ), if_statement: $ => seq( 'if', field('condition', $._expression), field('body', $.block), ';' ), if_expression: $ => seq( 'if', field('condition', $._expression), field('body', $.block), field('else', seq('else', choice( $._expression, $.block, )) ), ), return_statement: $ => seq( 'return', optional($._expression), ';', ), assign_statement: $ => seq( $.identifier, '=', $._expression, ';', ), _expression: $ => choice( $.unary_expression, $.binary_expression, $.if_expression, $.boolean_literal, $.integer_literal, $.identifier, ), unary_expression: $ => prec(10, choice( seq('-', $._expression), seq('!', $._expression), )), binary_expression: $ => choice( prec.left(4, seq($._expression, '*', $._expression)), prec.left(3, seq($._expression, '+', $._expression)), prec.left(2, seq($._expression, '||', $._expression)), prec.left(1, seq($._expression, '&&', $._expression)), ), identifier: $ => /[a-z_]+[a-zA-Z0-9_]*/, integer_literal: $ => /\d+/, boolean_literal: $ => choice('true', 'false'), //string_literal: $ => /"[]"/, _type: $ => choice( $.primitive_type, ), primitive_type: $ => choice( 'bool', 'int', 'uint', ), } });