module.exports = grammar({ name: 'test_script', rules: { source_file: $ => repeat($._item), _item: $ => choice( $.command, $.comment, $._whitespace ), // Test script commands command: $ => choice( $.load_command, $.output_file_command, $.compare_to_command, $.output_list_command, $.set_command, $.eval_command, $.output_command, $.tick_command, $.tock_command, $.ticktock_command, $.repeat_command, $.while_command, $.echo_command ), // File operations load_command: $ => seq( 'load', $.filename, ',' ), output_file_command: $ => seq( 'output-file', $.filename, ',' ), compare_to_command: $ => seq( 'compare-to', $.filename, ',' ), // Output commands output_list_command: $ => seq( 'output-list', repeat1($.output_spec), ';' ), output_command: $ => seq( 'output', ';' ), // Simulation control tick_command: $ => seq('tick', ','), tock_command: $ => seq('tock', ','), ticktock_command: $ => seq('ticktock', ';'), eval_command: $ => seq('eval', ','), // Variable assignment set_command: $ => seq( 'set', $.variable_reference, $.value, ',' ), // Control flow repeat_command: $ => seq( 'repeat', $.number, '{', repeat($._item), '}' ), while_command: $ => seq( 'while', $.condition, '{', repeat($._item), '}' ), // Echo command for debugging echo_command: $ => seq( 'echo', $.string, ';' ), // Variable references (RAM[index], register names, etc.) variable_reference: $ => choice( $.memory_reference, $.register_reference, $.pin_reference ), memory_reference: $ => seq( 'RAM', '[', $.index, ']' ), register_reference: $ => choice( 'DRegister[]', 'ARegister[]', 'PC[]', /[A-Z][a-zA-Z0-9_]*/ ), pin_reference: $ => /[a-zA-Z][a-zA-Z0-9_]*/, // Output format specifications output_spec: $ => seq( $.variable_reference, optional($.format_spec) ), format_spec: $ => /%[BDSX]\d+\.\d+\.\d+/, // Values value: $ => choice( $.number, $.binary_value, $.string ), binary_value: $ => /%B[01]+/, // Basic tokens number: $ => /\d+/, index: $ => /\d+/, filename: $ => /[a-zA-Z0-9_.-]+\.[a-zA-Z0-9]+/, string: $ => /"[^"]*"/, condition: $ => /[^{]+/, // Comments comment: $ => token(seq('//', /.*/)), // Whitespace _whitespace: $ => /\s+/ }, extras: $ => [ /\s/, $.comment ] });