/* Parses nuclear coordinates in xyz format */ %{ exception InputError of string %} %token EOL %token SPACE %token WORD %token INTEGER %token FLOAT %token EOF %start input %type <(Element.t * Coordinate.t) array> input %% /* Grammar rules and actions follow */ input: | integer title atoms_xyz { let len = List.length $3 in if len <> $1 then let error_msg = Printf.sprintf "%d atoms entered, expected %d" len $1 in raise (InputError error_msg) else Array.of_list $3 } integer: | INTEGER EOL { $1 } | INTEGER SPACE EOL { $1 } title: | title_list EOL { $1 } text: | WORD { $1 } | SPACE { $1 } | FLOAT { (string_of_float $1)} | INTEGER { (string_of_int $1)} title_list: | { "" } | title_list text { ($1 ^ $2) } atoms_xyz: | atoms_list EOL { List.rev $1 } | atoms_list EOF { List.rev $1 } atoms_list: | { [] } | atoms_list WORD SPACE FLOAT SPACE FLOAT SPACE FLOAT EOL { (Element.of_string $2, Coordinate.of_3_floats $4 $6 $8 `Angstrom ) :: $1 } | atoms_list WORD SPACE FLOAT SPACE FLOAT SPACE FLOAT SPACE EOL { (Element.of_string $2, Coordinate.of_3_floats $4 $6 $8 `Angstrom ) :: $1 } | atoms_list INTEGER SPACE FLOAT SPACE FLOAT SPACE FLOAT EOL { (Element.of_int $2, Coordinate.of_3_floats $4 $6 $8 `Angstrom ) :: $1 } | atoms_list INTEGER SPACE FLOAT SPACE FLOAT SPACE FLOAT SPACE EOL { (Element.of_int $2, Coordinate.of_3_floats $4 $6 $8 `Angstrom ) :: $1 }