syncraft 0.1.26__py3-none-any.whl → 0.1.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of syncraft might be problematic. Click here for more details.

syncraft/algebra.py CHANGED
@@ -128,10 +128,7 @@ class Algebra(ABC, Generic[A, S]):
128
128
  def lazy_run(input: S, use_cache:bool) -> Either[Any, Tuple[A, S]]:
129
129
  return thunk().run(input, use_cache)
130
130
  return cls(lazy_run, name=cls.__name__ + '.lazy')
131
-
132
-
133
-
134
-
131
+
135
132
  @classmethod
136
133
  def fail(cls, error: Any) -> Algebra[Any, S]:
137
134
  def fail_run(input: S, use_cache:bool) -> Either[Any, Tuple[Any, S]]:
@@ -141,6 +138,7 @@ class Algebra(ABC, Generic[A, S]):
141
138
  state=input
142
139
  ))
143
140
  return cls(fail_run, name=cls.__name__ + '.fail')
141
+
144
142
  @classmethod
145
143
  def success(cls, value: Any) -> Algebra[Any, S]:
146
144
  def success_run(input: S, use_cache:bool) -> Either[Any, Tuple[Any, S]]:
@@ -234,7 +232,35 @@ class Algebra(ABC, Generic[A, S]):
234
232
  lazy_self = self.__class__(debug_run, name=label)
235
233
  return lazy_self
236
234
 
235
+ ######################################################## map on state ###########################################
236
+ def post_state(self, f: Callable[[S], S]) -> Algebra[A, S]:
237
+ def post_state_run(input: S, use_cache:bool) -> Either[Any, Tuple[A, S]]:
238
+ match self.run(input, use_cache):
239
+ case Right((value, state)):
240
+ return Right((value, f(state)))
241
+ case Left(err):
242
+ return Left(err)
243
+ case x:
244
+ raise ValueError(f"Unexpected result from self.run {x}")
245
+ return self.__class__(post_state_run, name=self.name)
246
+
247
+ def pre_state(self, f: Callable[[S], S]) -> Algebra[A, S]:
248
+ def pre_state_run(state: S, use_cache:bool) -> Either[Any, Tuple[A, S]]:
249
+ return self.run(f(state), use_cache)
250
+ return self.__class__(pre_state_run, name=self.name)
251
+
237
252
 
253
+ def map_all(self, f: Callable[[A, S], Tuple[B, S]]) -> Algebra[B, S]:
254
+ def map_all_run(input: S, use_cache:bool) -> Either[Any, Tuple[B, S]]:
255
+ match self.run(input, use_cache):
256
+ case Right((value, state)):
257
+ new_value, new_state = f(value, state)
258
+ return Right((new_value, new_state))
259
+ case Left(err):
260
+ return Left(err)
261
+ case x:
262
+ raise ValueError(f"Unexpected result from self.run {x}")
263
+ return self.__class__(map_all_run, name=self.name) # type: ignore
238
264
  ######################################################## fundamental combinators ############################################
239
265
  def fmap(self, f: Callable[[A], B]) -> Algebra[B, S]:
240
266
  def fmap_run(input: S, use_cache:bool) -> Either[Any, Tuple[B, S]]:
@@ -245,20 +271,12 @@ class Algebra(ABC, Generic[A, S]):
245
271
  return cast(Either[Any, Tuple[B, S]], parsed)
246
272
  return self.__class__(fmap_run, name=self.name) # type: ignore
247
273
 
248
- def imap(self, f: Callable[[B], A]) -> Algebra[A, S]:
249
- return self.map_state(lambda s: s.map(f))
250
274
 
251
275
  def map(self, f: Callable[[A], B]) -> Algebra[B, S]:
252
276
  return self.fmap(f)
253
277
 
254
- def bimap(self, f: Callable[[A], B], i: Callable[[B], A]) -> Algebra[A, S]:
255
- return self.fmap(f).as_(Algebra[A, S]).imap(i)
256
-
257
- def map_all(self, f: Callable[[Either[Any, Tuple[A, S]]], Either[Any, Tuple[B, S]]])->Algebra[B, S]:
258
- def map_all_run(input: S, use_cache:bool) -> Either[Any, Tuple[B, S]]:
259
- parsed = self.run(input, use_cache)
260
- return f(parsed)
261
- return self.__class__(map_all_run, name=self.name) # type: ignore
278
+ def bimap(self, f: Callable[[A], B], i: Callable[[B], A]) -> Algebra[B, S]:
279
+ return self.fmap(f).pre_state(lambda s: s.map(i))
262
280
 
263
281
  def map_error(self, f: Callable[[Optional[Any]], Any]) -> Algebra[A, S]:
264
282
  def map_error_run(input: S, use_cache:bool) -> Either[Any, Tuple[A, S]]:
@@ -268,12 +286,6 @@ class Algebra(ABC, Generic[A, S]):
268
286
  return parsed
269
287
  return self.__class__(map_error_run, name=self.name)
270
288
 
271
- def map_state(self, f: Callable[[S], S]) -> Algebra[A, S]:
272
- def map_state_run(state: S, use_cache:bool) -> Either[Any, Tuple[A, S]]:
273
- return self.run(f(state), use_cache)
274
- return self.__class__(map_state_run, name=self.name)
275
-
276
-
277
289
  def flat_map(self, f: Callable[[A], Algebra[B, S]]) -> Algebra[B, S]:
278
290
  def flat_map_run(input: S, use_cache:bool) -> Either[Any, Tuple[B, S]]:
279
291
  parsed = self.run(input, use_cache)
@@ -288,34 +300,34 @@ class Algebra(ABC, Generic[A, S]):
288
300
  def or_else_run(input: S, use_cache:bool) -> Either[Any, Tuple[Choice[A, B], S]]:
289
301
  match self.run(input, use_cache):
290
302
  case Right((value, state)):
291
- return Right((Choice(kind=ChoiceKind.LEFT, left=value, right=None), state))
303
+ return Right((Choice(kind=ChoiceKind.LEFT, value=value), state))
292
304
  case Left(err):
293
305
  if isinstance(err, Error) and err.committed:
294
- return Left(err)
306
+ return Left(replace(err, committed=False))
295
307
  match other.run(input, use_cache):
296
308
  case Right((other_value, other_state)):
297
- return Right((Choice(kind=ChoiceKind.RIGHT, left=None, right=other_value), other_state))
309
+ return Right((Choice(kind=ChoiceKind.RIGHT, value=other_value), other_state))
298
310
  case Left(other_err):
299
311
  return Left(other_err)
300
312
  raise TypeError(f"Unexpected result type from {other}")
301
313
  raise TypeError(f"Unexpected result type from {self}")
302
314
  return self.__class__(or_else_run, name=f'{self.name} | {other.name}') # type: ignore
303
315
 
304
- def then_both(self, other: 'Algebra[B, S]') -> 'Algebra[Then[A, B], S]':
316
+ def then_both(self, other: Algebra[B, S]) -> Algebra[Then[A, B], S]:
305
317
  def then_both_f(a: A) -> Algebra[Then[A, B], S]:
306
318
  def combine(b: B) -> Then[A, B]:
307
319
  return Then(left=a, right=b, kind=ThenKind.BOTH)
308
320
  return other.fmap(combine)
309
321
  return self.flat_map(then_both_f).named(f'{self.name} + {other.name}')
310
322
 
311
- def then_left(self, other: Algebra[B, S]) -> 'Algebra[Then[A, B], S]':
323
+ def then_left(self, other: Algebra[B, S]) -> Algebra[Then[A, B], S]:
312
324
  def then_left_f(a: A) -> Algebra[Then[A, B], S]:
313
325
  def combine(b: B) -> Then[A, B]:
314
326
  return Then(left=a, right=b, kind=ThenKind.LEFT)
315
327
  return other.fmap(combine)
316
328
  return self.flat_map(then_left_f).named(f'{self.name} // {other.name}')
317
329
 
318
- def then_right(self, other: Algebra[B, S]) -> 'Algebra[Then[A, B], S]':
330
+ def then_right(self, other: Algebra[B, S]) -> Algebra[Then[A, B], S]:
319
331
  def then_right_f(a: A) -> Algebra[Then[A, B], S]:
320
332
  def combine(b: B) -> Then[A, B]:
321
333
  return Then(left=a, right=b, kind=ThenKind.RIGHT)
syncraft/ast.py CHANGED
@@ -3,23 +3,82 @@
3
3
  from __future__ import annotations
4
4
  import re
5
5
  from typing import (
6
- Optional, Any, TypeVar, Tuple, runtime_checkable,
7
- Dict, Generic, Callable, Union, cast, List, Protocol, Type
6
+ Optional, Any, TypeVar, Tuple, runtime_checkable, Self,
7
+ Dict, Generic, Callable, Union, Protocol, Type
8
8
  )
9
9
 
10
10
 
11
- from dataclasses import dataclass, replace, is_dataclass, asdict
11
+ from dataclasses import dataclass
12
12
  from enum import Enum
13
-
14
- from syncraft.constraint import Binding, Variable, Bindable
13
+ from syncraft.constraint import Bindable
15
14
 
16
15
 
17
16
 
18
17
  A = TypeVar('A')
19
18
  B = TypeVar('B')
20
19
  C = TypeVar('C')
20
+ D = TypeVar('D')
21
21
  S = TypeVar('S', bound=Bindable)
22
22
 
23
+ @dataclass(frozen=True)
24
+ class Biarrow(Generic[A, B]):
25
+ forward: Callable[[A], B]
26
+ inverse: Callable[[B], A]
27
+ def __rshift__(self, other: Biarrow[B, C]) -> Biarrow[A, C]:
28
+ def fwd(a: A) -> C:
29
+ b = self.forward(a)
30
+ return other.forward(b)
31
+ def inv(c: C) -> A:
32
+ b = other.inverse(c)
33
+ return self.inverse(b)
34
+ return Biarrow(
35
+ forward=fwd,
36
+ inverse=inv
37
+ )
38
+ @staticmethod
39
+ def identity()->Biarrow[A, A]:
40
+ return Biarrow(
41
+ forward=lambda x: x,
42
+ inverse=lambda y: y
43
+ )
44
+
45
+ @staticmethod
46
+ def when(condition: Callable[..., bool],
47
+ then: Biarrow[A, B],
48
+ otherwise: Optional[Biarrow[A, B]] = None) -> Callable[..., Biarrow[A, B]]:
49
+ def _when(*args:Any, **kwargs:Any) -> Biarrow[A, B]:
50
+ return then if condition(*args, **kwargs) else (otherwise or Biarrow.identity())
51
+ return _when
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class Lens(Generic[C, A]):
56
+ get: Callable[[C], A]
57
+ set: Callable[[C, A], C]
58
+
59
+ def modify(self, source: C, f: Callable[[A], A]) -> C:
60
+ return self.set(source, f(self.get(source)))
61
+
62
+ def bimap(self, ff: Callable[[A], B], bf: Callable[[B], A]) -> Lens[C, B]:
63
+ def getf(data: C) -> B:
64
+ return ff(self.get(data))
65
+
66
+ def setf(data: C, value: B) -> C:
67
+ return self.set(data, bf(value))
68
+
69
+ return Lens(get=getf, set=setf)
70
+
71
+ def __truediv__(self, other: Lens[A, B]) -> Lens[C, B]:
72
+ def get_composed(obj: C) -> B:
73
+ return other.get(self.get(obj))
74
+ def set_composed(obj: C, value: B) -> C:
75
+ return self.set(obj, other.set(self.get(obj), value))
76
+ return Lens(get=get_composed, set=set_composed)
77
+
78
+ def __rtruediv__(self, other: Lens[B, C])->Lens[B, A]:
79
+ return other.__truediv__(self)
80
+
81
+
23
82
  @dataclass(frozen=True)
24
83
  class Reducer(Generic[A, S]):
25
84
  run_f: Callable[[A, S], S]
@@ -31,27 +90,63 @@ class Reducer(Generic[A, S]):
31
90
  return self(f(b), s)
32
91
  return Reducer(map_run)
33
92
 
34
-
93
+ def __rshift__(self, other: Reducer[A, S]) -> Reducer[A, S]:
94
+ return Reducer(lambda a, s: other(a, self(a, s)))
35
95
 
36
96
  @dataclass(frozen=True)
37
97
  class Bimap(Generic[A, B]):
38
98
  run_f: Callable[[A], Tuple[B, Callable[[B], A]]]
39
99
  def __call__(self, a: A) -> Tuple[B, Callable[[B], A]]:
40
100
  return self.run_f(a)
41
- def __rshift__(self, other: Bimap[B, C]) -> Bimap[A, C]:
42
- def then_run(a: A) -> Tuple[C, Callable[[C], A]]:
43
- b, inv1 = self(a)
44
- c, inv2 = other(b)
45
- def inv(c2: C) -> A:
46
- return inv1(inv2(c2))
47
- return c, inv
48
- return Bimap(then_run)
101
+ def __rshift__(self, other: Bimap[B, C] | Biarrow[B, C]) -> Bimap[A, C]:
102
+ if isinstance(other, Biarrow):
103
+ def biarrow_then_run(a: A) -> Tuple[C, Callable[[C], A]]:
104
+ b, inv1 = self(a)
105
+ c = other.forward(b)
106
+ def inv(c2: C) -> A:
107
+ b2 = other.inverse(c2)
108
+ return inv1(b2)
109
+ return c, inv
110
+ return Bimap(biarrow_then_run)
111
+ elif isinstance(other, Bimap):
112
+ def bimap_then_run(a: A) -> Tuple[C, Callable[[C], A]]:
113
+ b, inv1 = self(a)
114
+ c, inv2 = other(b)
115
+ def inv(c2: C) -> A:
116
+ return inv1(inv2(c2))
117
+ return c, inv
118
+ return Bimap(bimap_then_run)
119
+ else:
120
+ raise TypeError(f"Unsupported type for Bimap >>: {type(other)}")
121
+ def __rrshift__(self, other: Bimap[C, A] | Biarrow[C, A]) -> Bimap[C, B]:
122
+ if isinstance(other, Biarrow):
123
+ def biarrow_then_run(c: C) -> Tuple[B, Callable[[B], C]]:
124
+ a = other.forward(c)
125
+ b2, inv1 = self(a)
126
+ def inv(a2: B) -> C:
127
+ a3 = inv1(a2)
128
+ return other.inverse(a3)
129
+ return b2, inv
130
+ return Bimap(biarrow_then_run)
131
+ elif isinstance(other, Bimap):
132
+ def bimap_then_run(c: C)->Tuple[B, Callable[[B], C]]:
133
+ a, a2c = other(c)
134
+ b2, b2a = self(a)
135
+ def inv(b3: B) -> C:
136
+ a2 = b2a(b3)
137
+ return a2c(a2)
138
+ return b2, inv
139
+ return Bimap(bimap_then_run)
140
+ else:
141
+ raise TypeError(f"Unsupported type for Bimap <<: {type(other)}")
142
+
143
+
49
144
  @staticmethod
50
145
  def const(a: B)->Bimap[B, B]:
51
146
  return Bimap(lambda _: (a, lambda b: b))
52
147
 
53
148
  @staticmethod
54
- def identity()->Bimap[Any, Any]:
149
+ def identity()->Bimap[A, A]:
55
150
  return Bimap(lambda a: (a, lambda b: b))
56
151
 
57
152
  @staticmethod
@@ -68,59 +163,65 @@ class Bimap(Generic[A, B]):
68
163
 
69
164
 
70
165
 
71
- @dataclass(frozen=True)
72
- class Biarrow(Generic[S, A, B]):
73
- forward: Callable[[S, A], Tuple[S, B]]
74
- inverse: Callable[[S, B], Tuple[S, A]]
75
- def __rshift__(self, other: Biarrow[S, B, C]) -> Biarrow[S, A, C]:
76
- def fwd(s: S, a: A) -> Tuple[S, C]:
77
- s1, b = self.forward(s, a)
78
- return other.forward(s1, b)
79
- def inv(s: S, c: C) -> Tuple[S, A]:
80
- s1, b = other.inverse(s, c)
81
- return self.inverse(s1, b)
82
- return Biarrow(
83
- forward=fwd,
84
- inverse=inv
85
- )
86
- @staticmethod
87
- def identity()->Biarrow[S, A, A]:
88
- return Biarrow(
89
- forward=lambda s, x: (s, x),
90
- inverse=lambda s, y: (s, y)
91
- )
92
-
93
- @staticmethod
94
- def when(condition: Callable[..., bool],
95
- then: Biarrow[S, A, B],
96
- otherwise: Optional[Biarrow[S, A, B]] = None) -> Callable[..., Biarrow[S, A, B]]:
97
- def _when(*args:Any, **kwargs:Any) -> Biarrow[S, A, B]:
98
- return then if condition(*args, **kwargs) else (otherwise or Biarrow.identity())
99
- return _when
100
166
 
101
167
 
102
168
  @dataclass(frozen=True)
103
169
  class AST:
104
- pass
170
+ def walk(self, r: Reducer[Any, S], s: S) -> S:
171
+ return s
172
+
173
+ @dataclass(frozen=True)
174
+ class Nothing(AST):
175
+ def __str__(self)->str:
176
+ return self.__class__.__name__
177
+ def __repr__(self)->str:
178
+ return self.__str__()
179
+
180
+
181
+ @dataclass(frozen=True)
182
+ class Marked(Generic[A], AST):
183
+ name: str
184
+ value: A
185
+ def walk(self, r: Reducer[A, S], s: S) -> S:
186
+ return self.value.walk(r, s) if isinstance(self.value, AST) else r(self.value, s)
187
+
188
+
189
+ class DataclassProtocol(Protocol):
190
+ __dataclass_fields__: dict
191
+
192
+ E = TypeVar("E")
193
+ @dataclass(frozen=True)
194
+ class Collect(Generic[A, E], AST):
195
+ collector: Type[E]
196
+ value: A
105
197
 
106
198
  class ChoiceKind(Enum):
107
199
  LEFT = 'left'
108
200
  RIGHT = 'right'
201
+
109
202
  @dataclass(frozen=True)
110
203
  class Choice(Generic[A, B], AST):
111
- kind: ChoiceKind
112
- left: Optional[A]
113
- right: Optional[B]
114
-
204
+ kind: Optional[ChoiceKind]
205
+ value: Optional[A | B] = None
206
+ def walk(self, r: Reducer[A | B, S], s: S) -> S:
207
+ if self.value is not None:
208
+ if isinstance(self.value, AST):
209
+ return self.value.walk(r, s)
210
+ else:
211
+ return r(self.value, s)
212
+ return s
115
213
 
116
214
  @dataclass(frozen=True)
117
215
  class Many(Generic[A], AST):
118
216
  value: Tuple[A, ...]
217
+ def walk(self, r: Reducer[A, S], s: S) -> S:
218
+ for item in self.value:
219
+ if isinstance(item, AST):
220
+ s = item.walk(r, s)
221
+ else:
222
+ s = r(item, s)
223
+ return s
119
224
 
120
- @dataclass(frozen=True)
121
- class Marked(Generic[A], AST):
122
- name: str
123
- value: A
124
225
  class ThenKind(Enum):
125
226
  BOTH = '+'
126
227
  LEFT = '//'
@@ -132,19 +233,21 @@ MarkedThen = Tuple[Dict[str, Any] | Any, FlatThen]
132
233
  @dataclass(eq=True, frozen=True)
133
234
  class Then(Generic[A, B], AST):
134
235
  kind: ThenKind
135
- left: Optional[A]
136
- right: Optional[B]
137
-
138
- @runtime_checkable
139
- class TokenProtocol(Protocol):
140
- @property
141
- def token_type(self) -> Enum: ...
142
- @property
143
- def text(self) -> str: ...
144
-
236
+ left: A
237
+ right: B
238
+ def walk(self, r: Reducer[A | B, S], s: S) -> S:
239
+ if isinstance(self.left, AST):
240
+ s = self.left.walk(r, s)
241
+ else:
242
+ s = r(self.left, s)
243
+ if isinstance(self.right, AST):
244
+ s = self.right.walk(r, s)
245
+ else:
246
+ s = r(self.right, s)
247
+ return s
145
248
 
146
249
  @dataclass(frozen=True)
147
- class Token:
250
+ class Token(AST):
148
251
  token_type: Enum
149
252
  text: str
150
253
  def __str__(self) -> str:
@@ -152,8 +255,20 @@ class Token:
152
255
 
153
256
  def __repr__(self) -> str:
154
257
  return self.__str__()
155
-
156
258
 
259
+ def walk(self, r: Reducer['Token', S], s: S) -> S:
260
+ return r(self, s)
261
+
262
+
263
+ @runtime_checkable
264
+ class TokenProtocol(Protocol):
265
+ @property
266
+ def token_type(self) -> Enum: ...
267
+ @property
268
+ def text(self) -> str: ...
269
+
270
+ T = TypeVar('T', bound=TokenProtocol)
271
+
157
272
 
158
273
  @dataclass(frozen=True)
159
274
  class TokenSpec:
@@ -170,18 +285,94 @@ class TokenSpec:
170
285
  return type_match and value_match
171
286
 
172
287
 
173
-
174
-
175
- T = TypeVar('T', bound=TokenProtocol)
176
-
177
-
178
288
  ParseResult = Union[
179
289
  Then['ParseResult[T]', 'ParseResult[T]'],
180
290
  Marked['ParseResult[T]'],
181
291
  Choice['ParseResult[T]', 'ParseResult[T]'],
182
292
  Many['ParseResult[T]'],
293
+ Nothing,
183
294
  T,
184
295
  ]
185
296
 
186
297
 
187
298
 
299
+ """
300
+ @staticmethod
301
+ def collect_marked(a: FlatThen, f: Optional[Callable[..., Any]] = None)->Tuple[MarkedThen, Callable[[MarkedThen], FlatThen]]:
302
+ index: List[str | int] = []
303
+ named_count = 0
304
+ for i, v in enumerate(a):
305
+ if isinstance(v, Marked):
306
+ index.append(v.name)
307
+ named_count += 1
308
+ else:
309
+ index.append(i - named_count)
310
+ named = {v.name: v.value for v in a if isinstance(v, Marked)}
311
+ unnamed = [v for v in a if not isinstance(v, Marked)]
312
+ if f is None:
313
+ ret = (named, tuple(unnamed))
314
+ else:
315
+ ret = (f(**named), tuple(unnamed))
316
+ def invf(b: MarkedThen) -> Tuple[Any, ...]:
317
+ named_value, unnamed_value = b
318
+ assert isinstance(named_value, dict) or is_dataclass(named_value), f"Expected dict or dataclass for named values, got {type(named_value)}"
319
+ if is_dataclass(named_value):
320
+ named_dict = named | asdict(cast(Any, named_value))
321
+ else:
322
+ named_dict = named | named_value
323
+ ret = []
324
+ for x in index:
325
+ if isinstance(x, str):
326
+ assert x in named_dict, f"Missing named value: {x}"
327
+ ret.append(named_dict[x])
328
+ else:
329
+ assert 0 <= x < len(unnamed_value), f"Missing unnamed value at index: {x}"
330
+ ret.append(unnamed_value[x])
331
+ return tuple(ret)
332
+ return ret, invf
333
+
334
+ def bimap(self, f: Bimap[Any, Any]=Bimap.identity()) -> Tuple[FlatThen, Callable[[FlatThen], Then[A, B]]]:
335
+ match self.kind:
336
+ case ThenKind.LEFT:
337
+ lb, linv = self.left.bimap(f) if isinstance(self.left, AST) else f(self.left)
338
+ return lb, lambda b: replace(self, left=linv(b))
339
+ case ThenKind.RIGHT:
340
+ rb, rinv = self.right.bimap(f) if isinstance(self.right, AST) else f(self.right)
341
+ return rb, lambda b: replace(self, right=rinv(b))
342
+ case ThenKind.BOTH:
343
+ lb, linv = self.left.bimap(f) if isinstance(self.left, AST) else f(self.left)
344
+ rb, rinv = self.right.bimap(f) if isinstance(self.right, AST) else f(self.right)
345
+ left_v = (lb,) if not isinstance(self.left, Then) else lb
346
+ right_v = (rb,) if not isinstance(self.right, Then) else rb
347
+ def invf(b: Tuple[Any, ...]) -> Then[A, B]:
348
+ left_size = self.left.arity() if isinstance(self.left, Then) else 1
349
+ right_size = self.right.arity() if isinstance(self.right, Then) else 1
350
+ lraw = b[:left_size]
351
+ rraw = b[left_size:left_size + right_size]
352
+ lraw = lraw[0] if left_size == 1 else lraw
353
+ rraw = rraw[0] if right_size == 1 else rraw
354
+ la = linv(lraw)
355
+ ra = rinv(rraw)
356
+ return replace(self, left=la, right=ra)
357
+ return left_v + right_v, invf
358
+
359
+ def bimap_collected(self, f: Bimap[Any, Any]=Bimap.identity()) -> Tuple[MarkedThen, Callable[[MarkedThen], Then[A, B]]]:
360
+ data, invf = self.bimap(f)
361
+ data, func = Then.collect_marked(data)
362
+ return data, lambda d: invf(func(d))
363
+
364
+
365
+ def arity(self)->int:
366
+ if self.kind == ThenKind.LEFT:
367
+ return self.left.arity() if isinstance(self.left, Then) else 1
368
+ elif self.kind == ThenKind.RIGHT:
369
+ return self.right.arity() if isinstance(self.right, Then) else 1
370
+ elif self.kind == ThenKind.BOTH:
371
+ left_arity = self.left.arity() if isinstance(self.left, Then) else 1
372
+ right_arity = self.right.arity() if isinstance(self.right, Then) else 1
373
+ return left_arity + right_arity
374
+ else:
375
+ return 1
376
+
377
+
378
+ """
syncraft/finder.py CHANGED
@@ -1,18 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from typing import (
4
- Any, Tuple, Optional, Generator as YieldGen
4
+ Any, Tuple, Generator as YieldGen
5
5
  )
6
- from dataclasses import dataclass, replace
6
+ from dataclasses import dataclass
7
7
  from syncraft.algebra import (
8
8
  Algebra, Either, Right,
9
9
  )
10
10
  from syncraft.ast import T, ParseResult, Choice, Many, Then, Marked
11
11
 
12
12
  from syncraft.generator import GenState, Generator
13
- from sqlglot import TokenType
13
+
14
14
  from syncraft.syntax import Syntax
15
- import re
15
+
16
16
 
17
17
 
18
18
  @dataclass(frozen=True)
syncraft/generator.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from typing import (
4
- Any, TypeVar, Tuple, Optional, Callable, Generic, cast,
4
+ Any, TypeVar, Tuple, Optional, Callable, Generic,
5
5
  List,
6
6
  )
7
7
  from functools import cached_property
@@ -11,8 +11,8 @@ from syncraft.algebra import (
11
11
  )
12
12
 
13
13
  from syncraft.ast import (
14
- T, ParseResult, AST, Token, TokenSpec, Binding, Variable,
15
- Bindable,
14
+ T, ParseResult, AST, Token, TokenSpec,
15
+ Bindable, Nothing,
16
16
  Choice, Many, ChoiceKind,
17
17
  Then, ThenKind, Marked
18
18
  )
@@ -23,7 +23,7 @@ import re
23
23
  import rstr
24
24
  from functools import lru_cache
25
25
  import random
26
-
26
+ from rich import print
27
27
  B = TypeVar('B')
28
28
 
29
29
 
@@ -136,7 +136,7 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
136
136
  def flat_map(self, f: Callable[[ParseResult[T]], Algebra[B, GenState[T]]]) -> Algebra[B, GenState[T]]:
137
137
  def flat_map_run(input: GenState[T], use_cache:bool) -> Either[Any, Tuple[B, GenState[T]]]:
138
138
  try:
139
- if not isinstance(input.ast, Then):
139
+ if not isinstance(input.ast, Then) or isinstance(input.ast, Nothing):
140
140
  return Left(Error(this=self,
141
141
  message=f"Expect Then got {input.ast}",
142
142
  state=input))
@@ -179,7 +179,7 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
179
179
  pass
180
180
  return Right((Many(value=tuple(ret)), input))
181
181
  else:
182
- if not isinstance(input.ast, Many):
182
+ if not isinstance(input.ast, Many) or isinstance(input.ast, Nothing):
183
183
  return Left(Error(this=self,
184
184
  message=f"Expect Many got {input.ast}",
185
185
  state=input))
@@ -194,7 +194,7 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
194
194
  this=self,
195
195
  state=input.inject(x)
196
196
  ))
197
- case Left(_):
197
+ case Left(e):
198
198
  pass
199
199
  if len(ret) < at_least:
200
200
  return Left(Error(
@@ -210,22 +210,34 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
210
210
  other: Algebra[ParseResult[T], GenState[T]]
211
211
  ) -> Algebra[Choice[ParseResult[T], ParseResult[T]], GenState[T]]:
212
212
  def or_else_run(input: GenState[T], use_cache:bool) -> Either[Any, Tuple[Choice[ParseResult[T], ParseResult[T]], GenState[T]]]:
213
- def exec(kind: ChoiceKind,
213
+ def exec(kind: ChoiceKind | None,
214
214
  left: GenState[T],
215
215
  right: GenState[T])->Either[Any, Tuple[Choice[ParseResult[T], ParseResult[T]], GenState[T]]]:
216
216
  match kind:
217
217
  case ChoiceKind.LEFT:
218
218
  match self.run(left, use_cache):
219
219
  case Right((value, next_input)):
220
- return Right((Choice(kind=ChoiceKind.LEFT, left=value, right=None), next_input))
220
+ return Right((Choice(kind=ChoiceKind.LEFT, value=value), next_input))
221
221
  case Left(error):
222
222
  return Left(error)
223
223
  case ChoiceKind.RIGHT:
224
224
  match other.run(right, use_cache):
225
225
  case Right((value, next_input)):
226
- return Right((Choice(kind=ChoiceKind.RIGHT, left=None, right=value), next_input))
226
+ return Right((Choice(kind=ChoiceKind.RIGHT, value=value), next_input))
227
227
  case Left(error):
228
228
  return Left(error)
229
+ case None:
230
+ match self.run(left, use_cache):
231
+ case Right((value, next_input)):
232
+ return Right((Choice(kind=ChoiceKind.LEFT, value=value), next_input))
233
+ case Left(error):
234
+ if isinstance(error, Error) and error.committed:
235
+ return Left(replace(error, committed=False))
236
+ match other.run(left, use_cache):
237
+ case Right((value, next_input)):
238
+ return Right((Choice(kind=ChoiceKind.RIGHT, value=value), next_input))
239
+ case Left(error):
240
+ return Left(error)
229
241
  raise ValueError(f"Invalid ChoiceKind: {kind}")
230
242
 
231
243
  if input.pruned:
@@ -233,14 +245,14 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
233
245
  which = forked_input.rng("or_else").choice((ChoiceKind.LEFT, ChoiceKind.RIGHT))
234
246
  return exec(which, forked_input, forked_input)
235
247
  else:
236
- if isinstance(input.ast, Choice):
237
- return exec(input.ast.kind,
238
- input.inject(input.ast.left),
239
- input.inject(input.ast.right))
240
- else:
248
+ if not isinstance(input.ast, Choice) or isinstance(input.ast, Nothing):
241
249
  return Left(Error(this=self,
242
250
  message=f"Expect Choice got {input.ast}",
243
251
  state=input))
252
+ else:
253
+ return exec(input.ast.kind,
254
+ input.inject(input.ast.value),
255
+ input.inject(input.ast.value))
244
256
  return self.__class__(or_else_run, name=f"or_else({self.name} | {other.name})") # type: ignore
245
257
 
246
258
  @classmethod
@@ -259,7 +271,7 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
259
271
  current = input.ast
260
272
  if not isinstance(current, Token) or not gen.is_valid(current):
261
273
  return Left(Error(None,
262
- message=f"Expected a Token, but got {type(current)}.",
274
+ message=f"Expected a Token({gen.text}), but got {current}.",
263
275
  state=input))
264
276
  return Right((current, input))
265
277
  lazy_self = cls(token_run, name=cls.__name__ + f'.token({token_type or text or regex})') # type: ignore
syncraft/syntax.py CHANGED
@@ -1,27 +1,29 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from typing import (
4
- Optional, List, Any, TypeVar, Generic, Callable, Tuple, cast,
4
+ Optional, Any, TypeVar, Generic, Callable, Tuple, cast,
5
5
  Type, Literal
6
6
  )
7
7
  from dataclasses import dataclass, field, replace
8
8
  from functools import reduce
9
9
  from syncraft.algebra import Algebra, Error, Either, Right
10
10
  from syncraft.constraint import Variable, Bindable
11
- from syncraft.ast import Then, ThenKind, Marked
11
+ from syncraft.ast import Then, ThenKind, Marked, Choice, Many, ChoiceKind, Nothing, Collect, E
12
12
  from types import MethodType, FunctionType
13
13
 
14
-
14
+ from rich import print
15
15
 
16
16
 
17
17
  A = TypeVar('A') # Result type
18
18
  B = TypeVar('B') # Result type for mapping
19
19
  C = TypeVar('C') # Result type for else branch
20
+ D = TypeVar('D') # Result type for else branch
20
21
  S = TypeVar('S', bound=Bindable) # State type
21
22
 
22
23
 
23
24
 
24
25
 
26
+
25
27
  @dataclass(frozen=True)
26
28
  class Description:
27
29
  name: Optional[str] = None
@@ -134,49 +136,50 @@ class Syntax(Generic[A, S]):
134
136
  ######################################################## value transformation ########################################################
135
137
  def map(self, f: Callable[[A], B]) -> Syntax[B, S]:
136
138
  return self.__class__(lambda cls: self.alg(cls).map(f), meta = self.meta) # type: ignore
137
-
138
- def imap(self, f: Callable[[B], A]) -> Syntax[A, S]:
139
- return self.__class__(lambda cls: self.alg(cls).imap(f), meta=self.meta)
140
-
141
- def bimap(self, f: Callable[[A], B], i: Callable[[B], A]) -> Syntax[A, S]:
142
- return self.__class__(lambda cls: self.alg(cls).bimap(f, i), meta=self.meta)
139
+
140
+ def bimap(self, f: Callable[[A], B], i: Callable[[B], A]) -> Syntax[B, S]:
141
+ return self.__class__(lambda cls: self.alg(cls).bimap(f, i), meta=self.meta) # type: ignore
143
142
 
144
- def map_all(self, f: Callable[[Either[Any, Tuple[A, S]]], Either[Any, Tuple[B, S]]]) -> Syntax[B, S]:
143
+ def map_all(self, f: Callable[[A, S], Tuple[B, S]]) -> Syntax[B, S]:
145
144
  return self.__class__(lambda cls: self.alg(cls).map_all(f), meta=self.meta) # type: ignore
146
-
145
+
147
146
  def map_error(self, f: Callable[[Optional[Any]], Any]) -> Syntax[A, S]:
148
147
  return self.__class__(lambda cls: self.alg(cls).map_error(f), meta=self.meta)
149
148
 
150
- def map_state(self, f: Callable[[S], S]) -> Syntax[A, S]:
151
- return self.__class__(lambda cls: self.alg(cls).map_state(f), meta=self.meta)
149
+ def pre_state(self, f: Callable[[S], S]) -> Syntax[A, S]:
150
+ return self.__class__(lambda cls: self.alg(cls).pre_state(f), meta=self.meta)
152
151
 
152
+ def post_state(self, f: Callable[[S], S]) -> Syntax[A, S]:
153
+ return self.__class__(lambda cls: self.alg(cls).post_state(f), meta=self.meta)
153
154
 
154
155
  def flat_map(self, f: Callable[[A], Algebra[B, S]]) -> Syntax[B, S]:
155
156
  return self.__class__(lambda cls: self.alg(cls).flat_map(f)) # type: ignore
156
157
 
157
- def many(self, *, at_least: int = 1, at_most: Optional[int] = None) -> Syntax[Tuple[A, ...], S]:
158
+ def many(self, *, at_least: int = 1, at_most: Optional[int] = None) -> Syntax[Many[A], S]:
158
159
  return self.__class__(lambda cls:self.alg(cls).many(at_least=at_least, at_most=at_most)).describe(name='*', # type: ignore
159
160
  fixity='prefix',
160
161
  parameter=(self,))
161
162
 
162
163
  ################################################ facility combinators ############################################################
163
164
 
164
-
165
-
166
- def between(self, left: Syntax[Any, S], right: Syntax[Any, S]) -> Syntax[Then[Any, Then[A, Any]], S]:
165
+ def between(self, left: Syntax[B, S], right: Syntax[C, S]) -> Syntax[Then[B, Then[A, C]], S]:
167
166
  return left >> self // right
168
167
 
169
- def sep_by(self, sep: Syntax[Any, S]) -> Syntax[Tuple[A, ...], S]:
170
- return (self + (sep >> self).many().optional()).describe( # type: ignore
168
+ def sep_by(self, sep: Syntax[B, S]) -> Syntax[Then[A, Choice[Many[Then[B, A]], Optional[Nothing]]], S]:
169
+ ret: Syntax[Then[A, Choice[Many[Then[B, A]], Optional[Nothing]]], S] = (self + (sep >> self).many().optional())
170
+ return ret.describe(
171
171
  name='sep_by',
172
172
  fixity='prefix',
173
173
  parameter=(self, sep))
174
-
175
- def parens(self, sep: Syntax[Any, S], open: Syntax[Any, S], close: Syntax[Any, S]) -> Syntax[Any, S]:
174
+
175
+ def parens(self,
176
+ sep: Syntax[C, S],
177
+ open: Syntax[B, S],
178
+ close: Syntax[D, S]) -> Syntax[Then[B, Then[Then[A, Choice[Many[Then[C, A]], Optional[Nothing]]], D]], S]:
176
179
  return self.sep_by(sep=sep).between(left=open, right=close)
177
180
 
178
- def optional(self, default: Optional[B] = None) -> Syntax[Optional[A | B], S]:
179
- return (self | success(default)).describe(name='~', fixity='prefix', parameter=(self,))
181
+ def optional(self) -> Syntax[Choice[A, Optional[Nothing]], S]:
182
+ return (self | success(Nothing())).describe(name='~', fixity='prefix', parameter=(self,))
180
183
 
181
184
 
182
185
  def cut(self) -> Syntax[A, S]:
@@ -184,63 +187,80 @@ class Syntax(Generic[A, S]):
184
187
 
185
188
 
186
189
  ####################################################### operator overloading #############################################
187
- def __floordiv__(self, other: Syntax[B, S]) -> Syntax[Then[A, None], S]:
190
+ def __floordiv__(self, other: Syntax[B, S]) -> Syntax[Then[A, B], S]:
188
191
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
189
- return self.__class__(
190
- lambda cls: self.alg(cls).then_left(other.alg(cls)) # type: ignore
191
- ).describe(name=ThenKind.LEFT.value, fixity='infix', parameter=(self, other)).as_(Syntax[Then[A, None], S])
192
+ ret: Syntax[Then[A, B], S] = self.__class__(lambda cls: self.alg(cls).then_left(other.alg(cls))) # type: ignore
193
+ return ret.describe(name=ThenKind.LEFT.value, fixity='infix', parameter=(self, other)).as_(Syntax[Then[A, B], S])
194
+
195
+ def __lshift__(self, other: Syntax[B, S]) -> Syntax[Then[A, B], S]:
196
+ return self.__floordiv__(other)
192
197
 
193
- def __rfloordiv__(self, other: Syntax[B, S]) -> Syntax[Then[B, None], S]:
198
+ def __rfloordiv__(self, other: Syntax[B, S]) -> Syntax[Then[B, A], S]:
194
199
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
195
200
  return other.__floordiv__(self)
201
+
202
+ def __rlshift__(self, other: Syntax[B, S]) -> Syntax[Then[B, A], S]:
203
+ return self.__rfloordiv__(other)
196
204
 
197
- def __invert__(self) -> Syntax[A | None, S]:
198
- return self.optional()
205
+ def __add__(self, other: Syntax[B, S]) -> Syntax[Then[A, B], S]:
206
+ other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
207
+ ret: Syntax[Then[A, B], S] = self.__class__(lambda cls: self.alg(cls).then_both(other.alg(cls))) # type: ignore
208
+ return ret.describe(name=ThenKind.BOTH.value, fixity='infix', parameter=(self, other)).as_(Syntax[Then[A, B], S])
199
209
 
200
210
  def __radd__(self, other: Syntax[B, S]) -> Syntax[Then[B, A], S]:
201
211
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
202
212
  return other.__add__(self)
203
213
 
204
- def __add__(self, other: Syntax[B, S]) -> Syntax[Then[A, B], S]:
205
- other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
206
- return self.__class__(
207
- lambda cls: self.alg(cls).then_both(other.alg(cls)) # type: ignore
208
- ).describe(name=ThenKind.BOTH.value, fixity='infix', parameter=(self, other))
209
-
210
- def __rshift__(self, other: Syntax[B, S]) -> Syntax[Then[None, B], S]:
214
+ def __rshift__(self, other: Syntax[B, S]) -> Syntax[Then[A, B], S]:
211
215
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
212
- return self.__class__(
213
- lambda cls: self.alg(cls).then_right(other.alg(cls)) # type: ignore
214
- ).describe(name=ThenKind.RIGHT.value, fixity='infix', parameter=(self, other)).as_(Syntax[Then[None, B], S])
215
-
216
+ ret: Syntax[Then[A, B], S] = self.__class__(lambda cls: self.alg(cls).then_right(other.alg(cls))) # type: ignore
217
+ return ret.describe(name=ThenKind.RIGHT.value, fixity='infix', parameter=(self, other)).as_(Syntax[Then[A, B], S])
216
218
 
217
- def __rrshift__(self, other: Syntax[B, S]) -> Syntax[Then[None, A], S]:
219
+ def __rrshift__(self, other: Syntax[B, S]) -> Syntax[Then[B, A], S]:
218
220
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
219
221
  return other.__rshift__(self)
220
-
221
-
222
- def __or__(self, other: Syntax[B, S]) -> Syntax[A | B, S]:
222
+
223
+ def __or__(self, other: Syntax[B, S]) -> Syntax[Choice[A, B], S]:
223
224
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
224
- return self.__class__(lambda cls: self.alg(cls).or_else(other.alg(cls))).describe(name='|', fixity='infix', parameter=[self, other]) # type: ignore
225
-
225
+ ret: Syntax[Choice[A, B], S] = self.__class__(lambda cls: self.alg(cls).or_else(other.alg(cls))) # type: ignore
226
+ return ret.describe(name='|', fixity='infix', parameter=(self, other))
226
227
 
227
- def __ror__(self, other: Syntax[B, S]) -> Syntax[A | B, S]:
228
+ def __ror__(self, other: Syntax[B, S]) -> Syntax[Choice[B, A], S]:
228
229
  other = other if isinstance(other, Syntax) else self.lift(other).as_(Syntax[B, S])
229
- return other.__or__(self).as_(Syntax[A | B, S])
230
+ return other.__or__(self)
231
+
232
+ def __invert__(self) -> Syntax[Choice[A, Optional[Nothing]], S]:
233
+ return self.optional()
230
234
 
231
235
 
232
236
  ######################################################################## data processing combinators #########################################################
233
- def bind(self, var: Variable) -> Syntax[A, S]:
234
- def bind_v(result: Either[Any, Tuple[A, S]])->Either[Any, Tuple[A, S]]:
235
- if isinstance(result, Right):
236
- value, state = result.value
237
- return Right((value, state.bind(var, value)))
238
- return result
239
-
240
- ret = self.mark(var.name).map_all(bind_v) if var.name else self.map_all(bind_v) # type: ignore
237
+ def bind(self,
238
+ var: Variable,
239
+ collector: Optional[Type[E]]=None) -> Syntax[A |
240
+ Marked[A] |
241
+ Marked[Collect[A, E]] |
242
+ Collect[A, E], S]:
243
+ def bind_v(v: A | Marked[A] | Marked[Collect[A, E]] | Collect[A, E],
244
+ s: S)->Tuple[A | Marked[A] | Marked[Collect[A, E]] | Collect[A, E], S]:
245
+ return v, s.bind(var, v)
246
+ if callable(collector):
247
+ ret = self.to(collector).mark(var.name).map_all(bind_v) if var.name else self.to(collector).map_all(bind_v)
248
+ else:
249
+ ret = self.mark(var.name).map_all(bind_v) if var.name else self.map_all(bind_v)
241
250
  return ret.describe(name=f'bind({var.name})', fixity='postfix', parameter=(self,))
242
251
 
243
- def mark(self, var: str) -> Syntax[A, S]:
252
+ def to(self, f: Type[E])-> Syntax[Collect[A, E], S]:
253
+ def to_f(v: A) -> Collect[A, E]:
254
+ if isinstance(v, Collect):
255
+ return replace(v, collector=f)
256
+ else:
257
+ return Collect(collector=f, value=v)
258
+ def ito_f(c: Collect[A, E]) -> A:
259
+ return c.value if isinstance(c, Collect) else c
260
+ return self.bimap(to_f, ito_f).describe(name=f'to({f})', fixity='postfix', parameter=(self,))
261
+
262
+
263
+ def mark(self, var: str) -> Syntax[Marked[A], S]:
244
264
  def bind_s(value: A) -> Marked[A]:
245
265
  if isinstance(value, Marked):
246
266
  return replace(value, name=var)
@@ -278,17 +298,17 @@ def success(value: Any) -> Syntax[Any, Any]:
278
298
  return Syntax(lambda alg: alg.success(value)).describe(name=f'success({value})', fixity='prefix')
279
299
 
280
300
  def choice(*parsers: Syntax[Any, S]) -> Syntax[Any, S]:
281
- return reduce(lambda a, b: a | b, parsers) if len(parsers) > 0 else success(None)
301
+ return reduce(lambda a, b: a | b, parsers) if len(parsers) > 0 else success(Nothing())
282
302
 
283
303
 
284
304
  def all(*parsers: Syntax[Any, S]) -> Syntax[Then[Any, Any], S]:
285
- return reduce(lambda a, b: a + b, parsers) if len(parsers) > 0 else success(None)
305
+ return reduce(lambda a, b: a + b, parsers) if len(parsers) > 0 else success(Nothing())
286
306
 
287
307
  def first(*parsers: Syntax[Any, S]) -> Syntax[Any, S]:
288
- return reduce(lambda a, b: a // b, parsers) if len(parsers) > 0 else success(None)
308
+ return reduce(lambda a, b: a // b, parsers) if len(parsers) > 0 else success(Nothing())
289
309
 
290
310
  def last(*parsers: Syntax[Any, S]) -> Syntax[Any, S]:
291
- return reduce(lambda a, b: a >> b, parsers) if len(parsers) > 0 else success(None)
311
+ return reduce(lambda a, b: a >> b, parsers) if len(parsers) > 0 else success(Nothing())
292
312
 
293
313
  def bound(* parsers: Syntax[Any, S] | Tuple[str|Variable, Syntax[Any, S]]) -> Syntax[Any, S]:
294
314
  def is_named_parser(x: Any) -> bool:
@@ -325,5 +345,5 @@ def bound(* parsers: Syntax[Any, S] | Tuple[str|Variable, Syntax[Any, S]]) -> Sy
325
345
  else:
326
346
  ret = ret >> just_parser
327
347
 
328
- return ret if ret is not None else success(None)
348
+ return ret if ret is not None else success(Nothing())
329
349
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syncraft
3
- Version: 0.1.26
3
+ Version: 0.1.28
4
4
  Summary: Parser combinator library
5
5
  Author-email: Michael Afmokt <michael@esacca.com>
6
6
  License-Expression: MIT
@@ -19,8 +19,6 @@ Syncraft is a parser/generator combinator library with full round-trip support:
19
19
 
20
20
  - Parse source code into AST or dataclasses
21
21
  - Generate source code from dataclasses
22
- - Bidirectional transformations via lenses
23
- - Convenience combinators: `all`, `first`, `last`, `named`
24
22
  - SQLite syntax support included
25
23
 
26
24
  ## Installation
@@ -33,5 +31,7 @@ pip install syncraft
33
31
  ## TODO
34
32
  - [ ] simplify the result of then_left and then_right by bimap the result in syntax.
35
33
  - [ ] simplify the result of sep_by and between by bimap the result in syntax
34
+ - [ ] convert to dict/dataclass via bimap in syntax
35
+ - [ ] define DSL over Variable to construct predicates
36
36
  - [ ] Try the parsing, generation, and data processing machinery on SQLite3 syntax. So that I can have direct feedback on the usability of this library and a fully functional SQLite3 library.
37
37
  - [ ] Make the library as fast as possible and feasible.
@@ -0,0 +1,16 @@
1
+ syncraft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ syncraft/algebra.py,sha256=5WyH_ngUuj42nUm9Ag3lmDh-2kMRFahTin2uX1Cm3ys,15590
3
+ syncraft/ast.py,sha256=X3rvxxEEdf0y62FNfvSE-D2bnzjZNzNVcf21q5NQHGA,12776
4
+ syncraft/constraint.py,sha256=uT-ELzvv8J-s-Y1VYkXePUezseqCLhqzYUzFBYs0HsE,6418
5
+ syncraft/diagnostic.py,sha256=cgwcQnCcgrCRX3h-oGTDb5rcJAtitPV3LfH9eLvO93E,2837
6
+ syncraft/finder.py,sha256=GJYnUyBlteMb9gblVKkwy_vVxOMxTwP5P80tWA3kM2Q,1813
7
+ syncraft/generator.py,sha256=6K2zEAHLA9z6UPhIUDQl8w7077iS9UKIACxJRLjrYCM,12697
8
+ syncraft/parser.py,sha256=UpNtTckygIwWG8cX2ZvdEcUi3Il8gpC7aZAzPKx2crg,11289
9
+ syncraft/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ syncraft/sqlite3.py,sha256=Pq09IHZOwuWg5W82l9D1flzd36QV0TOHQpTJ5U02V8g,34701
11
+ syncraft/syntax.py,sha256=xHzhtN06hymRTBHcMpqFpgekB0P0PSLO1nOGXCgnvnA,16558
12
+ syncraft-0.1.28.dist-info/licenses/LICENSE,sha256=wHSV424U5csa3339dy1AZbsz2xsd0hrkMx2QK48CcUk,1062
13
+ syncraft-0.1.28.dist-info/METADATA,sha256=2pB3y5cw_ivWVniHSydwhv8NszC02xwOTk57Rqni8-g,1204
14
+ syncraft-0.1.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ syncraft-0.1.28.dist-info/top_level.txt,sha256=Kq3t8ESXB2xW1Xt3uPmkENFc-c4f2pamNmaURBk7zc8,9
16
+ syncraft-0.1.28.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- syncraft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- syncraft/algebra.py,sha256=FBy0cCl4RGnsi1uxoIIZPRcHgfHxWwUal9iLV_Mtc6I,14791
3
- syncraft/ast.py,sha256=WwkA02H00BUNrotsMbvypzqHzJb8HiWROVb3qBDSR-8,5113
4
- syncraft/constraint.py,sha256=uT-ELzvv8J-s-Y1VYkXePUezseqCLhqzYUzFBYs0HsE,6418
5
- syncraft/diagnostic.py,sha256=cgwcQnCcgrCRX3h-oGTDb5rcJAtitPV3LfH9eLvO93E,2837
6
- syncraft/finder.py,sha256=qrBlPzQ3hK0rsLIfTD0QdypbrPegDKKCMZriWu-qHBA,1870
7
- syncraft/generator.py,sha256=BiwwFTjPkk7itXK1wAbB7SJhHi8npd0Wx_3bxR6t1Ww,11775
8
- syncraft/parser.py,sha256=UpNtTckygIwWG8cX2ZvdEcUi3Il8gpC7aZAzPKx2crg,11289
9
- syncraft/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- syncraft/sqlite3.py,sha256=Pq09IHZOwuWg5W82l9D1flzd36QV0TOHQpTJ5U02V8g,34701
11
- syncraft/syntax.py,sha256=aMXnAuGD12_WQxv0TIEvVw-7EO8Bupv0AD1hy6nMJMw,15011
12
- syncraft-0.1.26.dist-info/licenses/LICENSE,sha256=wHSV424U5csa3339dy1AZbsz2xsd0hrkMx2QK48CcUk,1062
13
- syncraft-0.1.26.dist-info/METADATA,sha256=h5K3SkaNZtfxw3hD5uc7Ac3D92XJMYCll8cMigf8rvs,1199
14
- syncraft-0.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- syncraft-0.1.26.dist-info/top_level.txt,sha256=Kq3t8ESXB2xW1Xt3uPmkENFc-c4f2pamNmaURBk7zc8,9
16
- syncraft-0.1.26.dist-info/RECORD,,