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
  ]
});
