Files
pgn_to_tex/lib/lexer.ml
T
owenrees 79155255f6 Transfer code (#1)
* copy project root files

* import previously created code and rename where needed

* fix license and lint

* main is now just a JS wrapper

* minified main.cjs rather than copying to a newly named file
2026-05-28 12:35:03 +02:00

104 lines
3.2 KiB
OCaml

open Sedlexing
open Parser
let digit = [%sedlex.regexp? '0' .. '9']
let letter = [%sedlex.regexp? 'a' .. 'z' | 'A' .. 'Z']
let alphabetic = [%sedlex.regexp? letter]
let move_char = [%sedlex.regexp? letter | digit | '+' | '#' | '=' | '-' | 'x']
let piece_square_char =
[%sedlex.regexp? 'K' | 'Q' | 'R' | 'B' | 'N' | 'O' | 'a' .. 'h']
let clock_val = [%sedlex.regexp? Plus (digit | ':'), Opt ('.', Plus digit)]
let rec tokenize_header buf =
match%sedlex buf with
| Plus white_space -> tokenize_header buf
| ']' -> TAG_CLOSE
| '"' -> read_string (Buffer.create 16) buf
| letter, Star (letter | digit | '_') -> HEADER (Utf8.lexeme buf)
| eof -> EOF
| _ -> failwith "Unexpected character in header"
and tokenize_game buf =
match%sedlex buf with
| Plus white_space -> tokenize_game buf
| "[%clk " -> read_inline_clock buf
| '[' -> TAG_OPEN
| '{' -> read_comment (Buffer.create 32) buf
| '(' -> LPAREN
| ')' -> RPAREN
| '$', Plus digit -> NAG (Utf8.lexeme buf)
| Plus digit, Plus '.' -> NUMBER (Utf8.lexeme buf)
| "1-0" | "0-1" | "1/2-1/2" | "*" -> RESULT (Utf8.lexeme buf)
| "O-O" | "O-O-O" -> MOVE (Utf8.lexeme buf)
| ('K' | 'Q' | 'R' | 'B' | 'N' | 'a' .. 'h'), Star move_char ->
MOVE (Utf8.lexeme buf)
| eof -> EOF
| any -> tokenize_game buf
| _ -> failwith "Unexpected character in game"
and read_string b buf =
match%sedlex buf with
| '"' -> STRING (Buffer.contents b)
| '\\', '"' ->
Buffer.add_char b '"';
read_string b buf
| any ->
Buffer.add_string b (Utf8.lexeme buf);
read_string b buf
| _ -> failwith "Unterminated string"
and read_inline_clock buf =
match%sedlex buf with
| clock_val ->
let time = Utf8.lexeme buf in
begin match%sedlex buf with
| ']' -> CLOCK time
| _ -> failwith "Malformed inline clock: expected closing ']'"
end
| _ -> failwith "Malformed inline clock value"
and read_comment b buf =
match%sedlex buf with
| Plus white_space -> read_comment b buf
| "[%clk " -> read_comment_clock buf
| "[%" -> skip_bracket_tag buf b
| '}' -> COMMENT (Buffer.contents b)
| eof -> failwith "Unterminated comment"
| any ->
Buffer.add_string b (Utf8.lexeme buf);
read_comment_content b buf
| _ -> failwith "Malformed comment"
and read_comment_clock buf =
match%sedlex buf with
| clock_val ->
let time = Utf8.lexeme buf in
begin match%sedlex buf with
| ']' -> begin
match%sedlex buf with
| Star white_space, '}' -> CLOCK time
| _ -> failwith "Expected closing '}' after clock comment"
end
| _ -> failwith "Malformed clock in comment: expected ']'"
end
| _ -> failwith "Malformed clock value"
and read_comment_content b buf =
match%sedlex buf with
| "[%" -> skip_bracket_tag buf b
| '}' -> COMMENT (String.trim (Buffer.contents b))
| eof -> failwith "Unterminated comment"
| any ->
Buffer.add_string b (Utf8.lexeme buf);
read_comment_content b buf
| _ -> failwith "Malformed comment"
and skip_bracket_tag buf b =
match%sedlex buf with
| ']' -> read_comment_content b buf
| eof -> failwith "Unterminated [% tag inside comment"
| any -> skip_bracket_tag buf b
| _ -> failwith "Malformed comment"