summaryrefslogtreecommitdiff
path: root/lib/parsing/parser.ml
blob: e56411b98809475c42f4f02b004b8b15729cf97b (plain)
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
open Types
open Headers
open Utils

let my_productions : production list = (* currently not in use *)
  [
    (S, [Nt E; Tm (LIT "$")]);    (* S ::= E $ *)
    (E, [Nt F; Nt E']);
    (E', [Tm IFF; Nt F; Nt E']);
    (E', []);
    (F, [Nt G; Nt F']);
    (F', [Tm IMPLIES; Nt G; Nt F']);
    (F', []);
    (G, [Nt H; Nt G']);
    (G', [Tm OR; Nt H; Nt G']);
    (G', []);
    (H, [Nt I; Nt H']);
    (H', [Tm AND; Nt I; Nt H']);
    (H', []);
    (I, [Tm NOT; Nt I]);
    (I, [Tm LEFT_PAREN; Nt E; Tm RIGHT_PAREN]);
    (I, [Tm TRUE]);
    (I, [Tm FALSE]);
    (I, [Tm (LIT "any string")])
  ]


let my_action_table (sym : symbol) (tk : tok) : action =
  let predict_if_in_first tk prod =
    match tk with
    | TRUE -> PREDICT prod
    | FALSE -> PREDICT prod
    | LIT _ -> PREDICT prod
    | NOT -> PREDICT prod
    | LEFT_PAREN -> PREDICT prod
    | _ -> REJECT
  in

  let predict_if_in_follow tk follow prod =
    if List.mem tk follow then
      PREDICT prod
    else
      REJECT
  in

  match sym, tk with
  | Tm (LIT "$"), LIT "$" -> ACCEPT
  | Tm t, tk -> if t = tk then MATCH t else REJECT
  | Nt S, tk -> predict_if_in_first tk (S, [Nt E; Tm (LIT "$")])
  | Nt E, tk -> predict_if_in_first tk (E, [Nt F; Nt E'])
  | Nt E', IFF -> PREDICT (E', [Tm IFF; Nt F; Nt E'])
  | Nt E', tk -> predict_if_in_follow tk [LIT "$"; RIGHT_PAREN] (E', [])
  | Nt F, tk -> predict_if_in_first tk (F, [Nt G; Nt F'])
  | Nt F', IMPLIES -> PREDICT (F', [Tm IMPLIES; Nt G; Nt F'])
  | Nt F', tk -> predict_if_in_follow tk [IFF; LIT "$"; RIGHT_PAREN] (F', [])
  | Nt G, tk -> predict_if_in_first tk (G, [Nt H; Nt G'])
  | Nt G', OR -> PREDICT (G', [Tm OR; Nt H; Nt G'])
  | Nt G', tk -> predict_if_in_follow tk [IMPLIES; IFF; LIT "$"; RIGHT_PAREN] (G', [])
  | Nt H, tk -> predict_if_in_first tk (H, [Nt I; Nt H'])
  | Nt H', AND -> PREDICT (H', [Tm AND; Nt I; Nt H'])
  | Nt H', tk -> predict_if_in_follow tk [OR; IMPLIES; IFF; LIT "$"; RIGHT_PAREN] (H', [])
  | Nt I, NOT -> PREDICT (I, [Tm NOT; Nt I]);
  | Nt I, LEFT_PAREN -> PREDICT (I, [Tm LEFT_PAREN; Nt E; Tm RIGHT_PAREN]);
  | Nt I, TRUE -> PREDICT (I, [Tm TRUE]);
  | Nt I, FALSE -> PREDICT (I, [Tm FALSE]);
  | Nt I, LIT s when s <> "$" -> PREDICT (I, [Tm (LIT s)])
  | _ -> REJECT


let parse (input : tok list) =
  let root = ref (Lf (Nt S)) in
  let initial_parse_state = {
    stack = [Nt S];
    ast_stack = [root]; (* list of ast refs corresponding to symbols on the stack *)
    input = input @ [LIT "$"];
    finished = false;
    accepted = false
  } in
  driver initial_parse_state my_action_table;
  (* print_endline (string_of_ast (!root)); *)
  prop_of_ast !root