aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lexer.mll
blob: 53ef04ac05ca400ddfd75595381f04a450aa6f52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
open Parser

exception Error of string

let unescape s =
  let buffer = Buffer.create (String.length s) in
  let rec go i =
    if i < String.length s then
      match s.[i] with
      | '\\' when i + 1 < String.length s ->
          (match s.[i + 1] with
           | 'n' -> Buffer.add_char buffer '\n'
           | 't' -> Buffer.add_char buffer '\t'
           | c -> Buffer.add_char buffer c);
          go (i + 2)
      | c ->
          Buffer.add_char buffer c;
          go (i + 1)
  in
  go 0;
  Buffer.contents buffer
}

let digit = ['0'-'9']
let ident = ['A'-'Z' 'a'-'z'] ['A'-'Z' 'a'-'z' '0'-'9' '_']*
let string_body = ([^ '"' '\\'] | '\\' _)*

rule token = parse
  | [' ' '\t' '\r' '\n']+     { token lexbuf }
  | '%' [^ '\n']*             { token lexbuf }
  | "#("                      { HASH_LPAREN }
  | '('                       { LPAREN }
  | ')'                       { RPAREN }
  | '['                       { LBRACKET }
  | ']'                       { RBRACKET }
  | '{'                       { LBRACE }
  | '}'                       { RBRACE }
  | '|'                       { BAR }
  | ":and"                    { AND }
  | ":or"                     { OR }
  | '-'? digit+ '/' digit+ as s
      { match String.index_opt s '/' with
        | Some i ->
            RAT
              ( Z.of_string (String.sub s 0 i),
                Z.of_string (String.sub s (i + 1) (String.length s - i - 1)) )
        | None -> assert false }
  | '-'? digit+ as s          { INT (Z.of_string s) }
  | (ident as name) ':'       { LABEL name }
  | ident as name             { NAME name }
  | '"' (string_body as s) '"' { STR (unescape s) }
  | eof                       { EOF }
  | _ as c                    { raise (Error (Printf.sprintf "unexpected character %C" c)) }