  Checktestdata language specification
  by the DOMjudge team



  11..  CChheecckktteessttddaattaa llaanngguuaaggee ssppeecciiffiiccaattiioonn

  This specification is dedicated to the public domain. Its authors
  waive all rights to the work worldwide under copyright law, including
  all related and neighboring rights, as specified in the Creative
  Commons Public Domain Dedication (CC0 1.0)
  <http://creativecommons.org/publicdomain/zero/1.0/>.

  Grammar and command syntax below. A valid checktestdata program
  consists of a list of commands. All commands are uppercase, while
  variables are lowercase with non-leading digits. Lines starting with
  '#' are comments and ignored.

  The following grammar sub-elements are defined:

  ______________________________________________________________________
  integer := 0|-?[1-9][0-9]*
  float := -?[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)?
  string := ".*"
  varname := [a-z][a-z0-9]*
  variable := <varname> | <varname> '[' <expr> [',' <expr> ...] ']'
  value := <integer> | <float> | <string> | <variable>
  compare := '<' | '>' | '<=' | '>=' | '==' | '!='
  logical := '&&' | '||'
  expr := <term> | <expr> [+-] <term>
  term := <term> [*%/] <factor> | <factor>
  factor := <value> | '-' <term> | '(' <expr> ')' | <factor> '^' <factor>
  test := '!' <test> | <test> <logical> <test> | '(' <test> ')' |
   <expr> <compare> <expr> | <testcommand>
  ______________________________________________________________________



  That is, variables can take integer, floating point as well as string
  values. No dynamic casting is performed, except that integers can be
  cast into floats. Integers and floats of arbitrary size and precision
  are supported, as well as the arithmetic operators +-*%/^ with the
  usual rules of precedence. An expression is integer if all its sub-
  expressions are integer. Integer division is used on integers.  The
  exponentiation operator ^ only allows non-negative integer exponents
  that fit in an unsigned long. String-valued variables can only be
  compared (lexicographically), no operators are supported.

  Within a string, the backslash acts as escape character for the
  following expressions:

  +o  \[0-7]{1,3} denotes an octal escape for a character

  +o  \n, \t, \r, \b denote linefeed, tab, carriage return and backspace

  +o  \" and \\ denote " and \

  +o  an escaped newline is ignored (line continuation)

     A backslash preceding any other character is treated as a literal
     backslash.

  Tests can be built from comparison operators, the usual logical
  operators ! && || (not, and, or) and a number of test commands that
  return a boolean value. These are:

     MATCH(<string> str)
        Returns whether the next character matches any of the characters
        in 'str'.

     ISEOF
        Returns whether end-of-file has been reached.

     UNIQUE(<varname> a [,<varname> b ...])
        Checks for uniqueness of tuples of values in the combined
        (array) variables a, b, ... That is, it is checked that firstly
        all arguments have precisely the same set of indices defined,
        and secondly that the tuples formed by evaluating (a,b,...) at
        these indices are unique. For example, if x,y are 1D arrays
        containing coordinates, then UNIQUE(x,y) checks that the points
        (x[i],y[i]) in the plane are unique.

     INARRAY(<value> val, <varname> array)
        Checks if val occurs in one of the indices of array.

  The following commands are available:

     SPACE / NEWLINE
        No-argument commands matching a single space (0x20) or newline
        respectively.

     EOF
        Matches end-of-file. This is implicitly added at the end of each
        program and must match exactly: no extra data may be present.

     INT(<expr> min, <expr> max [, <variable> name])
        Match an arbitrary sized integer value in the interval [min,max]
        and optionally assign the value read to variable 'name'.

     FLOAT(<expr> min, <expr> max [, <variable> name [, option]])
        Match a floating point number in the range [min,max] and
        optionally assign the value read to the variable 'name'. When
        the option 'FIXED' or 'SCIENTIFIC' is set, only accept floating
        point numbers in fixed point or scientific notation,
        respectively.

     STRING(<value> str)
        Match the string (variable) 'str'.

     REGEX(<string> str [, <variable> name])
        Match the extended regular expression 'str'. Matching is
        performed greedily. Optionally assign the matched string to
        variable 'name'.

     ASSERT(<test> condition)
        Assert that 'condition' is true, fail otherwise.

     UNSET(<varname> a [,<varname> b ...])
        Unset all values for variables a, b, ... This includes all
        values for array indexed variables with these names. This
        command should typically be inserted at the end of a loop after
        using UNIQUE or INARRAY, to make sure that no old variables are
        present anymore during the next iteration.

     REP(<expr> count [,<command> separator]) [<command>...] END

     REPI(<variable> i, <expr> count [,<command> separator]) [<com-
        mand>...] END
        Repeat the commands between the 'REP() ... END' statements count
        times and optionally match 'separator' command (count-1) times
        in between. The value of count must fit in an unsigned 32 bit
        int.  The second command 'REPI' does the same, but also stores
        the current iteration (counting from zero) in the variable 'i'.

     WHILE(<test> condition [,<command> separator]) [<command>...] END

     WHILEI(<variable> i, <test> condition [,<command> separator])
        [<command>...] END
        Repeat the commands as long as 'condition' is true. Optionally
        match 'separator' command between two consecutive iterations.
        The second command 'WHILEI' does the same, but also stores the
        current iteration (counting from zero) in the variable 'i'.

     IF(<test> cond) [<command> cmds1...] [ELSE [<command> cmds2...]]
        END
        Executes cmds1 if cond is true. Otherwise, executes cmds2 if the
        else statement is available.



