syncraft 0.1.34__tar.gz → 0.1.35__tar.gz
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-0.1.34 → syncraft-0.1.35}/PKG-INFO +1 -2
- {syncraft-0.1.34 → syncraft-0.1.35}/README.md +0 -1
- {syncraft-0.1.34 → syncraft-0.1.35}/pyproject.toml +1 -1
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/algebra.py +7 -5
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/ast.py +6 -3
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/constraint.py +2 -1
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/generator.py +2 -2
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/syntax.py +2 -1
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft.egg-info/PKG-INFO +1 -2
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft.egg-info/SOURCES.txt +1 -0
- syncraft-0.1.35/tests/test_find.py +47 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/LICENSE +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/setup.cfg +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/__init__.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/diagnostic.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/finder.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/parser.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/py.typed +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft/sqlite3.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft.egg-info/dependency_links.txt +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft.egg-info/requires.txt +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/syncraft.egg-info/top_level.txt +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/tests/test_bimap.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/tests/test_parse.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/tests/test_to.py +0 -0
- {syncraft-0.1.34 → syncraft-0.1.35}/tests/test_until.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: syncraft
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.35
|
|
4
4
|
Summary: Parser combinator library
|
|
5
5
|
Author-email: Michael Afmokt <michael@esacca.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -29,7 +29,6 @@ pip install syncraft
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
## TODO
|
|
32
|
-
- [ ] convert to dict/dataclass via bimap in syntax
|
|
33
32
|
- [ ] define DSL over Variable to construct predicates
|
|
34
33
|
- [ ] 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.
|
|
35
34
|
- [ ] Make the library as fast as possible and feasible.
|
|
@@ -14,7 +14,6 @@ pip install syncraft
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
## TODO
|
|
17
|
-
- [ ] convert to dict/dataclass via bimap in syntax
|
|
18
17
|
- [ ] define DSL over Variable to construct predicates
|
|
19
18
|
- [ ] 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.
|
|
20
19
|
- [ ] Make the library as fast as possible and feasible.
|
|
@@ -48,6 +48,7 @@ class Error:
|
|
|
48
48
|
error: Optional[Any] = None
|
|
49
49
|
state: Optional[Any] = None
|
|
50
50
|
committed: bool = False
|
|
51
|
+
stack: Optional[str] = None
|
|
51
52
|
previous: Optional[Error] = None
|
|
52
53
|
|
|
53
54
|
def attach( self,
|
|
@@ -115,14 +116,15 @@ class Algebra(ABC, Generic[A, S]):
|
|
|
115
116
|
result = Left(result.value.attach(this=self, state=input))
|
|
116
117
|
except Exception as e:
|
|
117
118
|
cache.pop(input, None) # Clear the cache entry on exception
|
|
118
|
-
traceback.print_exc()
|
|
119
|
-
print(f"Exception from self.run(S): {e}")
|
|
119
|
+
# traceback.print_exc()
|
|
120
|
+
# print(f"Exception from self.run(S): {e}")
|
|
120
121
|
return Left(
|
|
121
122
|
Error(
|
|
122
123
|
message="Exception from self.run(S): {e}",
|
|
123
124
|
this=self,
|
|
124
125
|
state=input,
|
|
125
|
-
error=e
|
|
126
|
+
error=e,
|
|
127
|
+
stack=traceback.format_exc()
|
|
126
128
|
))
|
|
127
129
|
return result
|
|
128
130
|
|
|
@@ -341,8 +343,8 @@ class Algebra(ABC, Generic[A, S]):
|
|
|
341
343
|
return self.flat_map(then_right_f).named(f'{self.name} >> {other.name}')
|
|
342
344
|
|
|
343
345
|
def many(self, *, at_least: int, at_most: Optional[int]) -> Algebra[Many[A], S]:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
+
if at_least <=0 or (at_most is not None and at_most < at_least):
|
|
347
|
+
raise ValueError(f"Invalid arguments for many: at_least={at_least}, at_most={at_most}")
|
|
346
348
|
def many_run(input: S, use_cache:bool) -> Either[Any, Tuple[Many[A], S]]:
|
|
347
349
|
ret: List[A] = []
|
|
348
350
|
current_input = input
|
|
@@ -14,7 +14,8 @@ from enum import Enum
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def shallow_dict(a: Any)->Dict[str, Any]:
|
|
17
|
-
|
|
17
|
+
if not is_dataclass(a):
|
|
18
|
+
raise ValueError(f"Expected dataclass instance for collector inverse, got {type(a)}")
|
|
18
19
|
return {f.name: getattr(a, f.name) for f in fields(a)}
|
|
19
20
|
|
|
20
21
|
|
|
@@ -300,7 +301,8 @@ class Collect(Generic[A, E], AST):
|
|
|
300
301
|
def bimap(self, r: Bimap[A, B]=Bimap.identity()) -> Tuple[B | E, Callable[[B | E], Collect[A, E]]]:
|
|
301
302
|
|
|
302
303
|
def inv_one_positional(e: E) -> B:
|
|
303
|
-
|
|
304
|
+
if not is_dataclass(e):
|
|
305
|
+
raise ValueError(f"Expected dataclass instance for collector inverse, got {type(e)}")
|
|
304
306
|
named_dict = shallow_dict(e)
|
|
305
307
|
return named_dict[fields(e)[0].name]
|
|
306
308
|
|
|
@@ -319,7 +321,8 @@ class Collect(Generic[A, E], AST):
|
|
|
319
321
|
unnamed = [v for v in b if not isinstance(v, Marked)]
|
|
320
322
|
ret: E = self.collector(*unnamed, **named)
|
|
321
323
|
def invf(e: E) -> Tuple[Any, ...]:
|
|
322
|
-
|
|
324
|
+
if not is_dataclass(e):
|
|
325
|
+
raise ValueError(f"Expected dataclass instance for collector inverse, got {type(e)}")
|
|
323
326
|
named_dict = shallow_dict(e)
|
|
324
327
|
unnamed = []
|
|
325
328
|
for f in fields(e):
|
|
@@ -55,7 +55,8 @@ class Variable:
|
|
|
55
55
|
object.__setattr__(self, '_root', self)
|
|
56
56
|
|
|
57
57
|
def raw(self, b:'BoundVar') -> Tuple[Any, ...]:
|
|
58
|
-
|
|
58
|
+
if self._root is None:
|
|
59
|
+
raise ValueError("_rawf can not be None")
|
|
59
60
|
return b.get(self._root, ())
|
|
60
61
|
|
|
61
62
|
|
|
@@ -174,8 +174,8 @@ class Generator(Algebra[ParseResult[T], GenState[T]]):
|
|
|
174
174
|
|
|
175
175
|
|
|
176
176
|
def many(self, *, at_least: int, at_most: Optional[int]) -> Algebra[Many[ParseResult[T]], GenState[T]]:
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
if at_least <=0 or (at_most is not None and at_most < at_least):
|
|
178
|
+
raise ValueError(f"Invalid arguments for many: at_least={at_least}, at_most={at_most}")
|
|
179
179
|
def many_run(input: GenState[T], use_cache:bool) -> Either[Any, Tuple[Many[ParseResult[T]], GenState[T]]]:
|
|
180
180
|
if input.pruned:
|
|
181
181
|
upper = at_most if at_most is not None else at_least + 2
|
|
@@ -178,7 +178,8 @@ class Syntax(Generic[A, S]):
|
|
|
178
178
|
raise ValueError(f"Bad data shape {a}")
|
|
179
179
|
|
|
180
180
|
def i(a: Many[A]) -> Then[A, Choice[Many[Then[B|None, A]], Optional[Nothing]]]:
|
|
181
|
-
|
|
181
|
+
if not isinstance(a, Many) or len(a.value) < 1:
|
|
182
|
+
raise ValueError(f"sep_by inverse expect Many with at least one element, got {a}")
|
|
182
183
|
if len(a.value) == 1:
|
|
183
184
|
return Then(kind=ThenKind.BOTH, left=a.value[0], right=Choice(kind=ChoiceKind.RIGHT, value=Nothing()))
|
|
184
185
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: syncraft
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.35
|
|
4
4
|
Summary: Parser combinator library
|
|
5
5
|
Author-email: Michael Afmokt <michael@esacca.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -29,7 +29,6 @@ pip install syncraft
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
## TODO
|
|
32
|
-
- [ ] convert to dict/dataclass via bimap in syntax
|
|
33
32
|
- [ ] define DSL over Variable to construct predicates
|
|
34
33
|
- [ ] 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.
|
|
35
34
|
- [ ] Make the library as fast as possible and feasible.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Any, List, Tuple
|
|
3
|
+
from syncraft.algebra import Either, Left, Right, Error
|
|
4
|
+
from syncraft.ast import Marked, Then, ThenKind, Many, Nothing
|
|
5
|
+
from syncraft.parser import literal, variable, parse, Parser, Token
|
|
6
|
+
from syncraft.generator import TokenGen
|
|
7
|
+
from rich import print
|
|
8
|
+
import syncraft.generator as gen
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from syncraft.finder import find, matches, anything
|
|
11
|
+
|
|
12
|
+
def test_find()->None:
|
|
13
|
+
@dataclass
|
|
14
|
+
class IfThenElse:
|
|
15
|
+
condition: Any
|
|
16
|
+
then: Any
|
|
17
|
+
otherwise: Any
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class While:
|
|
21
|
+
condition:Any
|
|
22
|
+
body:Any
|
|
23
|
+
|
|
24
|
+
WHILE = literal("while")
|
|
25
|
+
IF = literal("if")
|
|
26
|
+
ELSE = literal("else")
|
|
27
|
+
THEN = literal("then")
|
|
28
|
+
END = literal("end")
|
|
29
|
+
A = literal('a')
|
|
30
|
+
B = literal('b')
|
|
31
|
+
C = literal('c')
|
|
32
|
+
D = literal('d')
|
|
33
|
+
M = literal(',')
|
|
34
|
+
var = A | B | C | D
|
|
35
|
+
condition = var.sep_by(M).mark('condition')
|
|
36
|
+
ifthenelse = (IF >> condition
|
|
37
|
+
// THEN
|
|
38
|
+
+ var.sep_by(M).mark('then')
|
|
39
|
+
// ELSE
|
|
40
|
+
+ var.sep_by(M).mark('otherwise')
|
|
41
|
+
// END).to(IfThenElse).many()
|
|
42
|
+
syntax = (WHILE >> condition
|
|
43
|
+
+ ifthenelse.mark('body')
|
|
44
|
+
// ~END).to(While)
|
|
45
|
+
sql = 'while b if a,b then c,d else a,d end if a,b then c,d else a,d end'
|
|
46
|
+
ast = parse(syntax, sql, dialect='sqlite')
|
|
47
|
+
print(ast)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|