6 |
6 |
7 signature ANTIQUOTE = |
7 signature ANTIQUOTE = |
8 sig |
8 sig |
9 datatype 'a antiquote = |
9 datatype 'a antiquote = |
10 Text of 'a | |
10 Text of 'a | |
11 Antiq of Symbol_Pos.T list * Position.range | |
11 Antiq of Symbol_Pos.T list * Position.range |
12 Open of Position.T | |
|
13 Close of Position.T |
|
14 val is_text: 'a antiquote -> bool |
12 val is_text: 'a antiquote -> bool |
15 val reports_of: ('a -> Position.report_text list) -> |
13 val reports_of: ('a -> Position.report_text list) -> |
16 'a antiquote list -> Position.report_text list |
14 'a antiquote list -> Position.report_text list |
17 val check_nesting: 'a antiquote list -> unit |
|
18 val scan_antiq: Symbol_Pos.T list -> (Symbol_Pos.T list * Position.range) * Symbol_Pos.T list |
15 val scan_antiq: Symbol_Pos.T list -> (Symbol_Pos.T list * Position.range) * Symbol_Pos.T list |
19 val scan: Symbol_Pos.T list -> 'a antiquote * Symbol_Pos.T list |
|
20 val scan_text: Symbol_Pos.T list -> Symbol_Pos.T list antiquote * Symbol_Pos.T list |
16 val scan_text: Symbol_Pos.T list -> Symbol_Pos.T list antiquote * Symbol_Pos.T list |
21 val read: Symbol_Pos.T list * Position.T -> Symbol_Pos.T list antiquote list |
17 val read: Symbol_Pos.T list * Position.T -> Symbol_Pos.T list antiquote list |
22 end; |
18 end; |
23 |
19 |
24 structure Antiquote: ANTIQUOTE = |
20 structure Antiquote: ANTIQUOTE = |
26 |
22 |
27 (* datatype antiquote *) |
23 (* datatype antiquote *) |
28 |
24 |
29 datatype 'a antiquote = |
25 datatype 'a antiquote = |
30 Text of 'a | |
26 Text of 'a | |
31 Antiq of Symbol_Pos.T list * Position.range | |
27 Antiq of Symbol_Pos.T list * Position.range; |
32 Open of Position.T | |
|
33 Close of Position.T; |
|
34 |
28 |
35 fun is_text (Text _) = true |
29 fun is_text (Text _) = true |
36 | is_text _ = false; |
30 | is_text _ = false; |
37 |
31 |
38 |
32 |
39 (* reports *) |
33 (* reports *) |
40 |
34 |
41 fun reports_of text = |
35 fun reports_of text = |
42 maps |
36 maps (fn Text x => text x | Antiq (_, (pos, _)) => [((pos, Markup.antiq), "")]); |
43 (fn Text x => text x |
|
44 | Antiq (_, (pos, _)) => [((pos, Markup.antiq), "")] |
|
45 | Open pos => [((pos, Markup.antiq), "")] |
|
46 | Close pos => [((pos, Markup.antiq), "")]); |
|
47 |
|
48 |
|
49 (* check_nesting *) |
|
50 |
|
51 fun err_unbalanced pos = |
|
52 error ("Unbalanced antiquotation block parentheses" ^ Position.here pos); |
|
53 |
|
54 fun check_nesting antiqs = |
|
55 let |
|
56 fun check [] [] = () |
|
57 | check [] (pos :: _) = err_unbalanced pos |
|
58 | check (Open pos :: ants) ps = check ants (pos :: ps) |
|
59 | check (Close pos :: _) [] = err_unbalanced pos |
|
60 | check (Close _ :: ants) (_ :: ps) = check ants ps |
|
61 | check (_ :: ants) ps = check ants ps; |
|
62 in check antiqs [] end; |
|
63 |
37 |
64 |
38 |
65 (* scan *) |
39 (* scan *) |
66 |
40 |
67 open Basic_Symbol_Pos; |
41 open Basic_Symbol_Pos; |
70 |
44 |
71 val err_prefix = "Antiquotation lexical error: "; |
45 val err_prefix = "Antiquotation lexical error: "; |
72 |
46 |
73 val scan_txt = |
47 val scan_txt = |
74 $$$ "@" --| Scan.ahead (~$$$ "{") || |
48 $$$ "@" --| Scan.ahead (~$$$ "{") || |
75 Scan.one (fn (s, _) => s <> "@" andalso s <> "\\<lbrace>" andalso s <> "\\<rbrace>" |
49 Scan.one (fn (s, _) => s <> "@" andalso Symbol.is_regular s) >> single; |
76 andalso Symbol.is_regular s) >> single; |
|
77 |
50 |
78 val scan_ant = |
51 val scan_ant = |
79 Scan.trace (Symbol_Pos.scan_string_qq err_prefix || Symbol_Pos.scan_string_bq err_prefix) >> #2 || |
52 Scan.trace (Symbol_Pos.scan_string_qq err_prefix || Symbol_Pos.scan_string_bq err_prefix) >> #2 || |
80 Scan.one (fn (s, _) => s <> "}" andalso Symbol.is_regular s) >> single; |
53 Scan.one (fn (s, _) => s <> "}" andalso Symbol.is_regular s) >> single; |
81 |
|
82 val scan_open = Symbol_Pos.scan_pos --| $$$ "\\<lbrace>"; |
|
83 val scan_close = Symbol_Pos.scan_pos --| $$$ "\\<rbrace>"; |
|
84 |
54 |
85 in |
55 in |
86 |
56 |
87 val scan_antiq = |
57 val scan_antiq = |
88 Symbol_Pos.scan_pos -- ($$$ "@" |-- $$$ "{" |-- |
58 Symbol_Pos.scan_pos -- ($$$ "@" |-- $$$ "{" |-- |
89 Symbol_Pos.!!! (fn () => err_prefix ^ "missing closing brace") |
59 Symbol_Pos.!!! (fn () => err_prefix ^ "missing closing brace") |
90 (Scan.repeat scan_ant -- ($$$ "}" |-- Symbol_Pos.scan_pos))) |
60 (Scan.repeat scan_ant -- ($$$ "}" |-- Symbol_Pos.scan_pos))) |
91 >> (fn (pos1, (body, pos2)) => (flat body, Position.range pos1 pos2)); |
61 >> (fn (pos1, (body, pos2)) => (flat body, Position.range pos1 pos2)); |
92 |
62 |
93 fun scan x = (scan_antiq >> Antiq || scan_open >> Open || scan_close >> Close) x; |
63 val scan_text = scan_antiq >> Antiq || Scan.repeat1 scan_txt >> (Text o flat); |
94 val scan_text = scan || Scan.repeat1 scan_txt >> (Text o flat); |
|
95 |
64 |
96 end; |
65 end; |
97 |
66 |
98 |
67 |
99 (* read *) |
68 (* read *) |
100 |
69 |
101 fun read (syms, pos) = |
70 fun read (syms, pos) = |
102 (case Scan.read Symbol_Pos.stopper (Scan.repeat scan_text) syms of |
71 (case Scan.read Symbol_Pos.stopper (Scan.repeat scan_text) syms of |
103 SOME xs => (Position.reports_text (reports_of (K []) xs); check_nesting xs; xs) |
72 SOME xs => (Position.reports_text (reports_of (K []) xs); xs) |
104 | NONE => error ("Malformed quotation/antiquotation source" ^ Position.here pos)); |
73 | NONE => error ("Malformed quotation/antiquotation source" ^ Position.here pos)); |
105 |
74 |
106 end; |
75 end; |