intuicio_parser/
extendable.rs1use crate::{
2 alternation::AlternationParser, ParseResult, Parser, ParserExt, ParserHandle, ParserRegistry,
3};
4use std::sync::RwLock;
5
6pub mod shorthand {
7 use super::*;
8
9 pub fn ext_exchange(parser: ParserHandle) -> ParserHandle {
10 ExtendableParser::exchange(parser).into_handle()
11 }
12
13 pub fn ext_depth(parser: ParserHandle) -> ParserHandle {
14 ExtendableParser::depth(parser).into_handle()
15 }
16
17 pub fn ext_variants() -> ParserHandle {
18 ExtendableParser::variants().into_handle()
19 }
20
21 pub fn ext_wrap(parser: ParserHandle, extendable: ParserHandle) -> ParserHandle {
22 ExtendableWrapperParser::new(parser, extendable).into_handle()
23 }
24}
25
26#[derive(Clone)]
27enum ExtendableParserInner {
28 Exchange(ParserHandle),
29 Depth(ParserHandle),
30 Variants(AlternationParser),
31}
32
33pub struct ExtendableParser {
34 inner: RwLock<ExtendableParserInner>,
35}
36
37impl ExtendableParser {
38 pub fn exchange(parser: ParserHandle) -> Self {
39 Self {
40 inner: RwLock::new(ExtendableParserInner::Exchange(parser)),
41 }
42 }
43
44 pub fn depth(parser: ParserHandle) -> Self {
45 Self {
46 inner: RwLock::new(ExtendableParserInner::Depth(parser)),
47 }
48 }
49
50 pub fn variants() -> Self {
51 Self {
52 inner: RwLock::new(ExtendableParserInner::Variants(Default::default())),
53 }
54 }
55}
56
57impl Parser for ExtendableParser {
58 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
59 if let Ok(inner) = self.inner.read() {
60 match &*inner {
61 ExtendableParserInner::Exchange(parser) => parser.parse(registry, input),
62 ExtendableParserInner::Depth(parser) => parser.parse(registry, input),
63 ExtendableParserInner::Variants(parser) => parser.parse(registry, input),
64 }
65 } else {
66 Err("ExtendableParser cannot be read".into())
67 }
68 }
69
70 fn extend(&self, parser: ParserHandle) {
71 if let Ok(mut inner) = self.inner.write() {
72 match &mut *inner {
73 ExtendableParserInner::Exchange(inner) => {
74 *inner = parser;
75 }
76 ExtendableParserInner::Depth(inner) => {
77 parser.extend(inner.clone());
78 *inner = parser;
79 }
80 ExtendableParserInner::Variants(inner) => {
81 inner.prepend(parser);
82 }
83 }
84 }
85 }
86}
87
88#[derive(Clone)]
89pub struct ExtendableWrapperParser {
90 parser: ParserHandle,
91 extendable: ParserHandle,
92}
93
94impl ExtendableWrapperParser {
95 pub fn new(parser: ParserHandle, extendable: ParserHandle) -> Self {
96 Self { parser, extendable }
97 }
98}
99
100impl Parser for ExtendableWrapperParser {
101 fn parse<'a>(&self, registry: &ParserRegistry, input: &'a str) -> ParseResult<'a> {
102 self.parser.parse(registry, input)
103 }
104
105 fn extend(&self, parser: ParserHandle) {
106 self.extendable.extend(parser);
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use crate::{
113 extendable::{ExtendableParser, ExtendableWrapperParser},
114 shorthand::{
115 ext_depth, ext_exchange, ext_variants, ext_wrap, lit, oc, seq, slot_empty, ws,
116 },
117 ParserRegistry,
118 };
119
120 fn is_async<T: Send + Sync>() {}
121
122 #[test]
123 fn test_extendable() {
124 is_async::<ExtendableParser>();
125 is_async::<ExtendableWrapperParser>();
126
127 let registry = ParserRegistry::default();
128 let keyword_foo = lit("foo");
129 let keyword_bar = lit("bar");
130 let keyword_zee = lit("zee");
131
132 let exchange = ext_exchange(keyword_foo.clone());
133 assert!(exchange.parse(®istry, "foo").is_ok());
134 assert!(exchange.parse(®istry, "bar").is_err());
135 assert!(exchange.parse(®istry, "zee").is_err());
136 exchange.extend(keyword_bar.clone());
137 assert!(exchange.parse(®istry, "foo").is_err());
138 assert!(exchange.parse(®istry, "bar").is_ok());
139 assert!(exchange.parse(®istry, "zee").is_err());
140 exchange.extend(keyword_zee.clone());
141 assert!(exchange.parse(®istry, "foo").is_err());
142 assert!(exchange.parse(®istry, "bar").is_err());
143 assert!(exchange.parse(®istry, "zee").is_ok());
144
145 let variants = ext_variants();
146 assert!(variants.parse(®istry, "foo").is_err());
147 assert!(variants.parse(®istry, "bar").is_err());
148 assert!(variants.parse(®istry, "zee").is_err());
149 variants.extend(keyword_foo);
150 assert!(variants.parse(®istry, "foo").is_ok());
151 assert!(variants.parse(®istry, "bar").is_err());
152 assert!(variants.parse(®istry, "zee").is_err());
153 variants.extend(keyword_bar);
154 assert!(variants.parse(®istry, "foo").is_ok());
155 assert!(variants.parse(®istry, "bar").is_ok());
156 assert!(variants.parse(®istry, "zee").is_err());
157 variants.extend(keyword_zee);
158 assert!(variants.parse(®istry, "foo").is_ok());
159 assert!(variants.parse(®istry, "bar").is_ok());
160 assert!(variants.parse(®istry, "zee").is_ok());
161
162 let signature = seq([lit("fn"), ws(), lit("foo"), lit("("), lit(")")]);
163 let depth = ext_depth(signature);
164 depth.parse(®istry, "fn foo()").unwrap();
165 let async_signature = {
166 let slot = slot_empty();
167 ext_wrap(seq([lit("async"), ws(), slot.clone()]), slot)
168 };
169 async_signature.parse(®istry, "async ").unwrap();
170 depth.extend(async_signature);
171 depth.parse(®istry, "async fn foo()").unwrap();
172
173 let signature = {
174 let slot = slot_empty();
175 ext_wrap(oc(slot.clone(), lit("("), lit(")")), slot)
176 };
177 assert!(signature.parse(®istry, "(foo)").is_err());
178 signature.extend(lit("foo"));
179 assert!(signature
180 .parse(®istry, "(foo)")
181 .unwrap()
182 .1
183 .is::<String>());
184 }
185}