on 19052d8 help sign in
haskell.nix/lib/spdx/parser.nix
115 lines 3.8 kB history raw
1let String = { mempty = ""; mappend = a: b: a + b; };
2 List = { singleton = x: [x]; };
3 pair = a: b: { _1 = a; _2 = b; };
4 Pair = { pure = s: pair String.mempty s;
5 mappend = a: b: pair (String.mappend a._1 b._1) b._2;
6 map = f: p: pair (f p._1) p._2;
7 };
8 compose = f: g: x: f (g x);
9in with builtins; rec {
10 # Parser a = String -> [(a, String)]
11 string = str: s:
12 let strL = stringLength str;
13 sL = stringLength s;
14 in if str == substring 0 strL s
15 then [ (pair str (substring strL sL s)) ]
16 else [];
18 regex = capture_groups: re: s:
19 let result = match "(${re})(.*)" s;
20 in if result == null
21 then []
22 else [ (pair (elemAt result 0) (elemAt result (1 + capture_groups))) ];
24 # Left-biased choice
25 choice = cs: s:
26 if cs == []
27 then []
28 else let c = head cs;
29 cs' = tail cs;
30 result = c s;
31 in if result == []
32 then choice cs' s
33 else result;
35 optional = p: s:
36 let result = p s;
37 in if result == []
38 then [ (Pair.pure s) ]
39 else result;
41 chain = ps: s:
42 if ps == []
43 then [ (Pair.pure s) ]
44 else let p = head ps;
45 ps' = tail ps;
46 result = p s;
47 in if result == []
48 then []
49 else let r = head result;
50 rest = chain ps' r._2;
51 in if rest == []
52 then []
53 else let r' = head rest;
54 in [ (Pair.mappend r r') ];
56 idstring = regex 0 "[-\.0-9a-zA-Z]+";
58 license-ref = let documentref = chain [ (string "DocumentRef-")
59 idstring
60 (string ":")
61 ];
62 in chain [
63 (optional documentref)
64 (string "LicenseRef-")
65 idstring
66 ];
68 simple-expression = choice [ license-ref
69 (chain [ idstring (string "+") ])
70 idstring
71 ];
73 compound-expression = let wrap = compose (map (Pair.map List.singleton));
74 in choice [
75 (s: let result = simple-expression s;
76 in if result == []
77 then []
78 else let r = head result;
79 rest = chain [(string " WITH ") idstring ] r._2;
80 in if rest == []
81 then []
82 else [(pair r._1 (head rest)._2)]
83 )
84 (s: let result = simple-expression s;
85 in if result == []
86 then []
87 else let r = head result;
88 firstLicense = r._1;
89 operator = choice [ (string " AND ")
90 (string " OR ")
91 ]
92 r._2;
93 in if operator == []
94 then []
95 else let s' = (head operator)._2;
96 licenses = compound-expression s';
97 in if licenses == []
98 then []
99 else let ls = head licenses;
100 in [(pair ([firstLicense] ++ ls._1) ls._2)]
101 )
102 (wrap simple-expression)
103 (s: let openParen = string "(" s;
104 in if openParen == []
105 then []
106 else let result = compound-expression (head openParen)._2;
107 in if result == []
108 then []
109 else let r = head result;
110 closeParen = string ")" r._2;
111 in if closeParen == []
112 then []
113 else [(pair r._1 (head closeParen)._2)])
114 ];