initial commit
Getty Ritter
9 years ago
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 |