module.exports = grammar({ name: 'OpenScenarioNext', extras: $ => [ /\s/, $.comment ], word: $ => $.identifier, rules: { // The production rules of the context-free grammar source_file: $ => $.scenario, scenario: $ => seq( 'Scenario', $.identifier, ':', repeat($.act), optional($.prototypes), optional($.resources)), act: $ => seq( 'Act', $.identifier, ':', repeat1($.rule)), rule: $ => prec.left(seq( '@', $.condition, optional( $.modifier), ':', repeat1($.action))), modifier: $ => seq( '%', $.identifier), condition: $ => choice( $.predicate, $.relation_expr, $.binary_expr ), relation_expr: $ => seq( $.scalar_expr, $.relation_op, $.scalar_expr ), relation_op: $ => choice( '<', '>', '<=', '>=', '==', '!=' ), binary_expr: $ => choice( $.and_expr, $.or_expr), and_expr: $ => prec.left(2, seq( $.condition, 'and', $.condition )), or_expr: $ => prec.left(1, seq( $.condition, 'or', $.condition )), predicate: $ => choice( $.atomic_predicate, $.function_application ), atomic_predicate: $ => choice( $.init_predicate, $.start_predicate, $.stop_predicate), init_predicate: $ => 'init', start_predicate: $ => 'start', stop_predicate: $ => 'stop', action: $ => $.function_application, function_application: $ => seq( $.identifier, '(', optional( seq( $.argument, repeat(seq(',',$.argument)))) , ')' ), argument: $ => choice( $.arg_expr, $.named_arg ), arg_expr: $ => choice( $.scalar_expr, $.coordinate_expr ), scalar_expr: $ => choice( $.identifier, $.record_expr, $.literal, $.function_application, $.arithmetic_expr ), named_arg: $ => seq( $.identifier, '=', $.arg_expr ), record_expr: $ => prec.left(seq( $.identifier, '.', $.identifier )), arithmetic_expr: $ => choice( $.product_expr, $.sum_expr), product_expr: $ => prec.left(2, seq( $.scalar_expr, choice('*','/'), $.scalar_expr )), sum_expr: $ => prec.left(1, seq( $.scalar_expr, choice('+','-'), $.scalar_expr )), coordinate_expr: $ => seq( $.scalar_expr, '|', $.scalar_expr, '|', $.scalar_expr ), prototypes: $ => seq( 'Prototypes', ':', repeat($.prototype)), prototype: $ => seq( $.identifier, ':', $.function_application), resources: $ => seq( 'Resources', ':', repeat($.resource)), resource: $ => seq( $.identifier, ':', $.function_application), literal: $ => choice ( $.numeric_literal, $.unit_literal, $.string_literal ), numeric_literal: $ => /[-+]?[0-9]+([.][0-9]+)?([eE][-+]?[0-9]+)?/, unit_literal: $ => seq( $.numeric_literal, $.unit ), unit: $ => choice( 'm', 'km', 'cm', 'mm', 'km/h', 'm/s', 'min', 'h', 's' ), string_literal: $ => token(seq('"', /[^"]*/, '"')), identifier: $ => /[A-Za-z][A-Za-z0-9_]*/, comment: $ => token(choice(seq('//', /.*/), seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/'))) } });