syncraft 0.1.31__tar.gz → 0.1.32__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.

Files changed (25) hide show
  1. {syncraft-0.1.31 → syncraft-0.1.32}/PKG-INFO +1 -1
  2. {syncraft-0.1.31 → syncraft-0.1.32}/pyproject.toml +1 -1
  3. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/ast.py +7 -2
  4. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/syntax.py +18 -12
  5. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft.egg-info/PKG-INFO +1 -1
  6. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft.egg-info/SOURCES.txt +1 -0
  7. syncraft-0.1.32/tests/test_to.py +51 -0
  8. {syncraft-0.1.31 → syncraft-0.1.32}/LICENSE +0 -0
  9. {syncraft-0.1.31 → syncraft-0.1.32}/README.md +0 -0
  10. {syncraft-0.1.31 → syncraft-0.1.32}/setup.cfg +0 -0
  11. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/__init__.py +0 -0
  12. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/algebra.py +0 -0
  13. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/constraint.py +0 -0
  14. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/diagnostic.py +0 -0
  15. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/finder.py +0 -0
  16. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/generator.py +0 -0
  17. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/parser.py +0 -0
  18. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/py.typed +0 -0
  19. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft/sqlite3.py +0 -0
  20. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft.egg-info/dependency_links.txt +0 -0
  21. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft.egg-info/requires.txt +0 -0
  22. {syncraft-0.1.31 → syncraft-0.1.32}/syncraft.egg-info/top_level.txt +0 -0
  23. {syncraft-0.1.31 → syncraft-0.1.32}/tests/test_bimap.py +0 -0
  24. {syncraft-0.1.31 → syncraft-0.1.32}/tests/test_parse.py +0 -0
  25. {syncraft-0.1.31 → syncraft-0.1.32}/tests/test_until.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syncraft
3
- Version: 0.1.31
3
+ Version: 0.1.32
4
4
  Summary: Parser combinator library
5
5
  Author-email: Michael Afmokt <michael@esacca.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "syncraft"
3
- version = "0.1.31"
3
+ version = "0.1.32"
4
4
  description = "Parser combinator library"
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE"]
@@ -188,6 +188,11 @@ class AST:
188
188
 
189
189
  @dataclass(frozen=True)
190
190
  class Nothing(AST):
191
+ _instance = None
192
+ def __new__(cls):
193
+ if cls._instance is None:
194
+ cls._instance = super(Nothing, cls).__new__(cls)
195
+ return cls._instance
191
196
  def __str__(self)->str:
192
197
  return self.__class__.__name__
193
198
  def __repr__(self)->str:
@@ -226,8 +231,8 @@ class Many(Generic[A], AST):
226
231
  if len(bs) <= len(ret):
227
232
  return Many(value = tuple(ret[i][1](bs[i]) for i in range(len(bs))))
228
233
  else:
229
- half = [ret[i][1](bs[i]) for i in range(len(bs))]
230
- tmp = [ret[-1][1](bs[i]) for i in range(len(ret)-1, len(bs))]
234
+ half = [ret[i][1](bs[i]) for i in range(len(ret))]
235
+ tmp = [ret[-1][1](bs[i]) for i in range(len(ret), len(bs))]
231
236
  return Many(value = tuple(half + tmp))
232
237
  return [v[0] for v in ret], inv
233
238
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import (
4
4
  Optional, Any, TypeVar, Generic, Callable, Tuple, cast,
5
- Type, Literal
5
+ Type, Literal, List
6
6
  )
7
7
  from dataclasses import dataclass, field, replace
8
8
  from functools import reduce
@@ -168,21 +168,27 @@ class Syntax(Generic[A, S]):
168
168
  def sep_by(self,
169
169
  sep: Syntax[B, S]) -> Syntax[Then[A, Choice[Many[Then[B, A]], Optional[Nothing]]], S]:
170
170
  ret: Syntax[Then[A, Choice[Many[Then[B, A]], Optional[Nothing]]], S] = (self + (sep >> self).many().optional())
171
- def f(a: Then[A, Choice[Many[A], Optional[Nothing]]]) -> Many[A]:
172
- if a.right.kind == ChoiceKind.LEFT and isinstance(a.right.value, Many):
173
- if len(a.right.value.value) == 0:
174
- return Many(value = (a.left,))
175
- else:
176
- return Many(value = (a.left,) + a.right.value.value)
177
- else:
178
- return Many(value = (a.left,))
179
- def i(a: Many[A]) -> Then[A, Choice[Many[A], Optional[Nothing]]]:
171
+ def f(a: Then[A, Choice[Many[Then[B, A]], Optional[Nothing]]]) -> Many[A]:
172
+ match a:
173
+ case Then(kind=ThenKind.BOTH, left=left, right=Choice(kind=ChoiceKind.RIGHT, value=Nothing())):
174
+ return Many(value = (left,))
175
+ case Then(kind=ThenKind.BOTH, left=left, right=Choice(kind=ChoiceKind.LEFT, value=Many(value=bs))):
176
+ return Many(value = (left,) + tuple([b.right for b in bs]))
177
+ case _:
178
+ raise ValueError(f"Bad data shape {a}")
179
+
180
+ def i(a: Many[A]) -> Then[A, Choice[Many[Then[B|None, A]], Optional[Nothing]]]:
180
181
  assert len(a.value) >= 1, f"sep_by expect at least one element, got {len(a.value)}. {a}"
181
182
  if len(a.value) == 1:
182
183
  return Then(kind=ThenKind.BOTH, left=a.value[0], right=Choice(kind=ChoiceKind.RIGHT, value=Nothing()))
183
184
  else:
184
- return Then(kind= ThenKind.BOTH, left=a.value[0], right=Choice(kind=ChoiceKind.LEFT, value=Many(value=a.value[1:])))
185
- return ret.bimap(f,i).describe( # type: ignore
185
+ v: List[Then[B|None, A]] = [Then(kind=ThenKind.RIGHT, right=x, left=None) for x in a.value[1:]]
186
+ return Then(kind= ThenKind.BOTH,
187
+ left=a.value[0],
188
+ right=Choice(kind=ChoiceKind.LEFT,
189
+ value=Many(value=tuple(v))))
190
+ ret = ret.bimap(f,i) # type: ignore
191
+ return ret.describe(
186
192
  name='sep_by',
187
193
  fixity='prefix',
188
194
  parameter=(self, sep))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: syncraft
3
- Version: 0.1.31
3
+ Version: 0.1.32
4
4
  Summary: Parser combinator library
5
5
  Author-email: Michael Afmokt <michael@esacca.com>
6
6
  License-Expression: MIT
@@ -19,4 +19,5 @@ syncraft.egg-info/requires.txt
19
19
  syncraft.egg-info/top_level.txt
20
20
  tests/test_bimap.py
21
21
  tests/test_parse.py
22
+ tests/test_to.py
22
23
  tests/test_until.py
@@ -0,0 +1,51 @@
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
+
11
+
12
+ def test_to() -> 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,c,c 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
+ g = gen.generate(syntax, ast, restore_pruned=True)
48
+ assert ast == g
49
+ x, f = g.bimap()
50
+ print(x)
51
+ assert gen.generate(syntax, f(x), restore_pruned=True) == 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