gdritter repos shift-resolve / 7cc1bd2
initial commit Getty Ritter 9 years ago
1 changed file(s) with 110 addition(s) and 0 deletion(s). Collapse all Expand all
1 (* A given rule in a grammar is a list of either terminals or
2 * nonterminals... *)
3 type element =
4 | Nonterm of string
5 | Term of char
6 type rule = element list
7
8 (* and a grammar itself is a set---er, list, for us---that maps
9 * nonterminal names to one or more rules. *)
10 type grammar = (string * rule) list
11
12 (* We'll work with the same grammar that's described in the paper:
13 * S' ::= S
14 * S ::= ACa | BDd
15 * A ::= AD | a
16 * B ::= BC | b
17 * C ::= c
18 * D ::= d
19 *)
20
21 let test_grammar =
22 [ "S'", [ Nonterm "S" ]
23 ; "S", [ Nonterm "A"; Nonterm "C"; Term 'a' ]
24 ; "S", [ Nonterm "B"; Nonterm "D"; Term 'd' ]
25 ; "A", [ Nonterm "A"; Nonterm "D" ]
26 ; "A", [ Term 'a' ]
27 ; "B", [ Nonterm "B"; Nonterm "C" ]
28 ; "B", [ Term 'b' ]
29 ; "C", [ Term 'c' ]
30 ; "D", [ Term 'd' ]
31 ]
32
33 (* Every action in our generated table is going to be either a
34 * Shift, which will give us the new state as well, or a Resolve,
35 * which will produce a non-terminal and optionally pop some
36 * things from the stack.
37 *)
38 type state = int
39 type action =
40 | Shift of state
41 | Resolve of element * int
42
43 (* This is not the best data structure to put a table in. *)
44 type table = (int * element) -> action option
45 let empty : table = fun _ -> None
46 let lookup (t : table) (k : int * element) = t k
47 let insert (k : int * element) (v : action) (t : table) =
48 fun k' -> if k = k' then Some v else lookup t k'
49
50 let sample : table = (empty
51 |> insert (0, Term 'a') (Shift 4)
52 |> insert (0, Term 'b') (Shift 5)
53 |> insert (0, Nonterm "S") (Shift 1)
54 |> insert (0, Nonterm "A") (Shift 2)
55 |> insert (0, Nonterm "B") (Shift 3)
56 |> insert (1, Term '$') (Resolve (Nonterm "S'", 0))
57 |> insert (2, Term 'c') (Shift 8)
58 |> insert (2, Nonterm "C") (Shift 6)
59 |> insert (2, Nonterm "D") (Shift 7)
60 |> insert (3, Term 'c') (Shift 8)
61 |> insert (3, Nonterm "C") (Shift 9)
62 |> insert (3, Nonterm "D") (Shift 10)
63 |> insert (4, Term 'c') (Shift 8)
64 |> insert (4, Nonterm "C") (Resolve (Nonterm "A", 0))
65 |> insert (4, Nonterm "D") (Resolve (Nonterm "A", 0))
66 |> insert (5, Term 'c') (Shift 8)
67 |> insert (5, Nonterm "C") (Resolve (Nonterm "B", 0))
68 |> insert (5, Nonterm "D") (Resolve (Nonterm "B", 0))
69 |> insert (6, Term 'a') (Shift 11)
70 |> insert (6, Term 'c') (Shift 8)
71 |> insert (7, Term 'c') (Shift 8)
72 |> insert (7, Nonterm "C") (Resolve (Nonterm "A", 0))
73 |> insert (7, Nonterm "D") (Resolve (Nonterm "A", 0))
74 |> insert (8, Term 'a') (Resolve (Nonterm "C", 0))
75 |> insert (8, Term 'b') (Resolve (Nonterm "D", 0))
76 |> insert (8, Term 'c') (Shift 8)
77 |> insert (8, Nonterm "C") (Shift 12)
78 |> insert (8, Nonterm "D") (Shift 13)
79 |> insert (9, Term 'c') (Shift 8)
80 |> insert (9, Nonterm "C") (Resolve (Nonterm "B", 0))
81 |> insert (9, Nonterm "D") (Resolve (Nonterm "B", 0))
82 |> insert (10, Term 'b') (Shift 14)
83 |> insert (10, Term 'c') (Shift 8)
84 |> insert (11, Term '$') (Resolve (Nonterm "S", 0))
85 |> insert (12, Term 'a') (Resolve (Nonterm "D", 1))
86 |> insert (12, Term 'c') (Shift 8)
87 |> insert (12, Nonterm "C") (Resolve (Nonterm "C", 1))
88 |> insert (12, Nonterm "D") (Resolve (Nonterm "C", 1))
89 |> insert (13, Term 'b') (Resolve (Nonterm "C", 1))
90 |> insert (13, Term 'c') (Shift 8)
91 |> insert (13, Nonterm "C") (Resolve (Nonterm "D", 1))
92 |> insert (13, Nonterm "D") (Resolve (Nonterm "D", 1))
93 |> insert (14, Term '$') (Resolve (Nonterm "S", 0)))
94
95 let rec take n ls =
96 if n = 0 then [] else (List.hd ls :: take (n-1) (List.tl ls))
97
98 let rec drop n ls =
99 if n = 0 then ls else drop (n-1) (List.tl ls)
100
101 let runParser (t : table) (inp : char list) =
102 let rec helper (inS : element list) (stS : state list) (st : state) =
103 match inS with
104 | [] -> stS
105 | (i::is) -> match lookup t (st, i) with
106 | None -> raise (Failure "Unable to find rule")
107 | Some (Shift n) ->
108 helper is (n::stS) n
109 | Some (Resolve (s, i)) -> raise (Failure "..")
110 in helper (List.map (fun x -> Term x) inp) [] 0