llparse 0.1.2__tar.gz → 0.1.3__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.
Files changed (40) hide show
  1. {llparse-0.1.2 → llparse-0.1.3}/PKG-INFO +7 -4
  2. {llparse-0.1.2 → llparse-0.1.3}/README.md +6 -3
  3. {llparse-0.1.2 → llparse-0.1.3}/llparse/compilator.py +1 -1
  4. {llparse-0.1.2 → llparse-0.1.3}/llparse/debug.py +0 -3
  5. {llparse-0.1.2 → llparse-0.1.3}/llparse/frontend.py +45 -49
  6. {llparse-0.1.2 → llparse-0.1.3}/llparse/llparse.py +12 -2
  7. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/nodes.py +13 -18
  8. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/peephole.py +1 -1
  9. {llparse-0.1.2 → llparse-0.1.3}/llparse/trie.py +10 -8
  10. {llparse-0.1.2 → llparse-0.1.3}/llparse.egg-info/PKG-INFO +7 -4
  11. {llparse-0.1.2 → llparse-0.1.3}/llparse.egg-info/SOURCES.txt +1 -0
  12. {llparse-0.1.2 → llparse-0.1.3}/pyproject.toml +1 -1
  13. llparse-0.1.3/tests/test_frontend.py +25 -0
  14. {llparse-0.1.2 → llparse-0.1.3}/LICENSE +0 -0
  15. {llparse-0.1.2 → llparse-0.1.3}/llparse/C_compiler.py +0 -0
  16. {llparse-0.1.2 → llparse-0.1.3}/llparse/__init__.py +0 -0
  17. {llparse-0.1.2 → llparse-0.1.3}/llparse/constants.py +0 -0
  18. {llparse-0.1.2 → llparse-0.1.3}/llparse/cython_builder.py +0 -0
  19. {llparse-0.1.2 → llparse-0.1.3}/llparse/dot.py +0 -0
  20. {llparse-0.1.2 → llparse-0.1.3}/llparse/enumerator.py +0 -0
  21. {llparse-0.1.2 → llparse-0.1.3}/llparse/errors.py +0 -0
  22. {llparse-0.1.2 → llparse-0.1.3}/llparse/header.py +0 -0
  23. {llparse-0.1.2 → llparse-0.1.3}/llparse/pybuilder/__init__.py +0 -0
  24. {llparse-0.1.2 → llparse-0.1.3}/llparse/pybuilder/builder.py +0 -0
  25. {llparse-0.1.2 → llparse-0.1.3}/llparse/pybuilder/loopchecker.py +0 -0
  26. {llparse-0.1.2 → llparse-0.1.3}/llparse/pybuilder/main_code.py +0 -0
  27. {llparse-0.1.2 → llparse-0.1.3}/llparse/pybuilder/parsemap.py +0 -0
  28. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/containers.py +0 -0
  29. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/front.py +0 -0
  30. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/implementation.py +0 -0
  31. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/namespace.py +0 -0
  32. {llparse-0.1.2 → llparse-0.1.3}/llparse/pyfront/transform.py +0 -0
  33. {llparse-0.1.2 → llparse-0.1.3}/llparse/settings.py +0 -0
  34. {llparse-0.1.2 → llparse-0.1.3}/llparse/spanalloc.py +0 -0
  35. {llparse-0.1.2 → llparse-0.1.3}/llparse/test.py +0 -0
  36. {llparse-0.1.2 → llparse-0.1.3}/llparse.egg-info/dependency_links.txt +0 -0
  37. {llparse-0.1.2 → llparse-0.1.3}/llparse.egg-info/top_level.txt +0 -0
  38. {llparse-0.1.2 → llparse-0.1.3}/setup.cfg +0 -0
  39. {llparse-0.1.2 → llparse-0.1.3}/tests/test_loop_checker.py +0 -0
  40. {llparse-0.1.2 → llparse-0.1.3}/tests/test_span_allocator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llparse
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: A Parody of llparse written for writing C Parsers with Python
5
5
  Author-email: Vizonex <VizonexBusiness@gmail.com>
6
6
  Requires-Python: >=3.9
@@ -15,7 +15,7 @@ Dynamic: license-file
15
15
 
16
16
  A python parody of the typescript library llparse.
17
17
 
18
- I take no credit for the orginal work done by indutny and I was originally very nervous about making
18
+ I take no credit for the orginal work done by indutny and the other node-js contributors involved and I was originally very nervous about making
19
19
  this python library that I made public...
20
20
 
21
21
  Links to the original library
@@ -49,7 +49,7 @@ do it at your own risk. They maybe incompleted or not throughly stress-tested.
49
49
 
50
50
  ## New Features
51
51
  - Throw me an issue if typescript llparse introduces something new that you want for me or another contributor to try and implement
52
- just seeing llparse add new features is nothing but exciting to me.
52
+ just seeing llparse add new features is exciting to me.
53
53
 
54
54
  - If you want a feature that typescript llparse doesn't have, be sure to try making a pull request over there as well and not just here,
55
55
  there's a good chance they will appericate you for helping over there too and your helping make llhttp better by doing so. :)
@@ -62,7 +62,7 @@ there's a good chance they will appericate you for helping over there too and yo
62
62
  - Make it easy for me or someone else to find a problem and solve it in typescript after testing it in python
63
63
  - Typescript takes 2 commands to run a script with node-js it while python only takes one cutting the time required tremendously...
64
64
  - The orginal project was MIT licensed.
65
- - I wanted to write my own C Parsering tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
65
+ - I wanted to write my own C Parser tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
66
66
  - I didn't like __Lemon Parser__ or __Yacc__ all that much and a good ide for handling them in Visual Studio Code with error checking to my knowlegde does not exist.
67
67
  - The closest thing I got to what I wanted was a project named __NMFU__ shorthand for no memory for you and even I had problems with writing things using that library...
68
68
 
@@ -131,3 +131,6 @@ print(c.c)
131
131
  open("http_parser.c", "w").write(c.c)
132
132
  open("http_parser.h", "w").write(c.header)
133
133
  ```
134
+
135
+ ## Video Showcasing this library
136
+ - https://youtu.be/YQOzJ2BghQw
@@ -5,7 +5,7 @@
5
5
 
6
6
  A python parody of the typescript library llparse.
7
7
 
8
- I take no credit for the orginal work done by indutny and I was originally very nervous about making
8
+ I take no credit for the orginal work done by indutny and the other node-js contributors involved and I was originally very nervous about making
9
9
  this python library that I made public...
10
10
 
11
11
  Links to the original library
@@ -39,7 +39,7 @@ do it at your own risk. They maybe incompleted or not throughly stress-tested.
39
39
 
40
40
  ## New Features
41
41
  - Throw me an issue if typescript llparse introduces something new that you want for me or another contributor to try and implement
42
- just seeing llparse add new features is nothing but exciting to me.
42
+ just seeing llparse add new features is exciting to me.
43
43
 
44
44
  - If you want a feature that typescript llparse doesn't have, be sure to try making a pull request over there as well and not just here,
45
45
  there's a good chance they will appericate you for helping over there too and your helping make llhttp better by doing so. :)
@@ -52,7 +52,7 @@ there's a good chance they will appericate you for helping over there too and yo
52
52
  - Make it easy for me or someone else to find a problem and solve it in typescript after testing it in python
53
53
  - Typescript takes 2 commands to run a script with node-js it while python only takes one cutting the time required tremendously...
54
54
  - The orginal project was MIT licensed.
55
- - I wanted to write my own C Parsering tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
55
+ - I wanted to write my own C Parser tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
56
56
  - I didn't like __Lemon Parser__ or __Yacc__ all that much and a good ide for handling them in Visual Studio Code with error checking to my knowlegde does not exist.
57
57
  - The closest thing I got to what I wanted was a project named __NMFU__ shorthand for no memory for you and even I had problems with writing things using that library...
58
58
 
@@ -121,3 +121,6 @@ print(c.c)
121
121
  open("http_parser.c", "w").write(c.c)
122
122
  open("http_parser.h", "w").write(c.header)
123
123
  ```
124
+
125
+ ## Video Showcasing this library
126
+ - https://youtu.be/YQOzJ2BghQw
@@ -572,7 +572,7 @@ class Single(Node):
572
572
  else:
573
573
  ch = f"'{chr(e.key)}'"
574
574
 
575
- out.append(f" case {ch}:" + "{")
575
+ out.append(f" case {ch}: " + "{")
576
576
  tmp: list[str] = []
577
577
 
578
578
  # For now debug everything....
@@ -9,9 +9,6 @@ class Debugger:
9
9
 
10
10
  while queue:
11
11
  node = queue.pop()
12
- print(node.name)
13
- if node.name == "nmethods":
14
- print(node.getEdges())
15
12
  if edges := node.getEdges():
16
13
  for slot in edges:
17
14
  if slot.node in nodes:
@@ -12,11 +12,15 @@ from .pyfront.implementation import IImplementation
12
12
  from .pyfront.nodes import ITableEdge
13
13
  from .pyfront.peephole import Peephole
14
14
  from .spanalloc import SpanAllocator
15
- from .trie import Trie, TrieEmpty, TrieNode, TrieSequence, TrieSingle
15
+ from .trie import Trie, TrieEmpty, TrieNode, TrieSequence, TrieSingle, ITrieSingleChild
16
16
 
17
17
  DEFAULT_MIN_TABLE_SIZE = 32
18
18
  DEFAULT_MAX_TABLE_WIDTH = 4
19
19
 
20
+ from logging import getLogger
21
+
22
+ log = getLogger("llparse.frontend")
23
+
20
24
 
21
25
  WrappedNode = IWrap[_frontend.node.Node]
22
26
  WrappedCode = IWrap[_frontend.code.Code]
@@ -166,7 +170,7 @@ class Frontend:
166
170
  trieNode = trie.build(list(node))
167
171
 
168
172
  if not trieNode:
169
- # print("[DEBUG]", "TrieNode was nonexistant")
173
+ log.debug("TrieNode was nonexistant")
170
174
  return self.implementation.node.Empty(
171
175
  _frontend.node.Empty(self.Id.id(node.name))
172
176
  )
@@ -178,7 +182,7 @@ class Frontend:
178
182
 
179
183
  return children
180
184
 
181
- def registerNode(self, node: WrappedNode):
185
+ def registerNode(self, node: WrappedNode) -> None:
182
186
  # NOTE NO Implementations required here since this is python!
183
187
  if isinstance(
184
188
  node.ref,
@@ -287,7 +291,6 @@ class Frontend:
287
291
 
288
292
  if isinstance(single.ref, _frontend.node.Invoke):
289
293
  for edge in node:
290
- # print(edge.key)
291
294
  single.ref.addEdge(
292
295
  ord(edge.key) if isinstance(edge.key, str) else edge.key,
293
296
  self.translate(edge.node),
@@ -304,52 +307,48 @@ class Frontend:
304
307
  return None
305
308
 
306
309
  targets: dict[source.code.Node, ITableLookupTarget] = {}
307
- bailout = False
308
- for child in trie.children:
309
- if isinstance(child.node, TrieEmpty):
310
- # print(
311
- # 'non-leaf trie child of "%s" prevents table allocation' % node.name
312
- # )
313
- bailout = False
314
- continue
315
-
316
- empty: TrieEmpty = child.node
317
- if getattr(empty, "value", None) is None:
318
- # print(
319
- # 'value passing trie leaf of "%s" prevents table allocation'
320
- # % node.name
321
- # )
322
- bailout = False
323
- continue
310
+
311
+ def check_child(child: ITrieSingleChild):
312
+ nonlocal targets
313
+ if not isinstance(child.node, TrieEmpty):
314
+ log.debug(
315
+ 'non-leaf trie child of "%s" prevents table allocation' % node.name
316
+ )
317
+ return False
318
+ empty = child.node
319
+ if empty.value is not None:
320
+ log.debug(
321
+ 'value passing trie leaf of "%s" prevents table allocation'
322
+ % node.name
323
+ )
324
+ return False
324
325
 
325
326
  target = empty.node
326
- if not targets.get(target):
327
+ if target not in targets:
327
328
  targets[target] = ITableLookupTarget(
328
329
  keys=[child.key], noAdvance=child.noAdvance, trie=empty
329
330
  )
330
- bailout = True
331
- break
331
+ return True
332
332
 
333
333
  existing = targets[target]
334
-
335
334
  if existing.noAdvance != child.noAdvance:
336
- # print('noAdvance mismatch in a trie leaf of "%s" prevents table allocation' % node.name)
337
- bailout = False
338
- break
339
-
335
+ log.debug(
336
+ f'noAdvance mismatch in a trie leaf of "{node.name}" prevents '
337
+ "table allocation"
338
+ )
339
+ return False
340
340
  existing.keys.append(child.key)
341
+ return True
341
342
 
342
- # TODO: see if breaking or continue block after out is breakout has been determined is good ot not...
343
- bailout = True
344
- break
345
-
346
- # assert len(trie.children) == len(targets), "Something went wrong"
347
- if bailout:
343
+ if not all([check_child(child) for child in trie.children]):
348
344
  return
349
345
 
350
346
  # Weave width limit for optimization...
351
- if len(targets.keys()) >= (1 << self.options["maxTableElemWidth"]):
352
- # print('too many different trie targets of "%s" for a table allocation' % node.name)
347
+ if len(targets) >= (1 << self.options["maxTableElemWidth"]):
348
+ log.debug(
349
+ 'too many different trie targets of "%s" for a table allocation'
350
+ % node.name
351
+ )
353
352
  return
354
353
 
355
354
  table = self.implementation.node.TableLookup(
@@ -358,11 +357,11 @@ class Frontend:
358
357
  children.append(table)
359
358
 
360
359
  # Break Loop
361
- if self.Map.get(node):
360
+ if not self.Map.get(node):
362
361
  self.Map[node] = table
363
362
 
364
363
  for target in targets.values():
365
- _next = self.translateTrie(node, target, children)
364
+ _next = self.translateTrie(node, target.trie, children)
366
365
  table.ref.addEdge(
367
366
  ITableEdge(keys=target.keys, noAdvance=target.noAdvance, node=_next)
368
367
  )
@@ -408,9 +407,7 @@ class Frontend:
408
407
  self, node: source.code.Match, trie: TrieSingle, children: MatchChildren
409
408
  ):
410
409
  # Check if Tablelookup could be a valid option to Optimze our code up...
411
- maybeTable = self.maybeTableLookup(node, trie, children)
412
-
413
- if maybeTable:
410
+ if maybeTable := self.maybeTableLookup(node, trie, children):
414
411
  return maybeTable
415
412
 
416
413
  single = self.implementation.node.Single(
@@ -432,8 +429,7 @@ class Frontend:
432
429
  value=child.node.value if isinstance(child.node, TrieEmpty) else None,
433
430
  )
434
431
 
435
- otherwise = trie.otherwise
436
- if otherwise:
432
+ if otherwise := trie.otherwise:
437
433
  single.ref.setOtherwise(
438
434
  self.translateTrie(node, otherwise, children), True, otherwise.value
439
435
  )
@@ -442,8 +438,9 @@ class Frontend:
442
438
  def translateSpanCode(self, code: source.code._Span):
443
439
  return self.translateCode(code)
444
440
 
445
- # TODO Vizonex Maybe better typehining can be used in this function alone....
446
- def translateCode(self, code: source.code.Code):
441
+ def translateCode(
442
+ self, code: source.code.Code
443
+ ):
447
444
  """Translates Builder Classes to Frontend Classes..."""
448
445
 
449
446
  prefixed = self.codeId.id(code.name).name
@@ -499,9 +496,8 @@ class Frontend:
499
496
  else:
500
497
  raise Exception(f'UnSupported code:"{code.name}" type: "{type(code)}"')
501
498
 
502
- if self.codeCache.get(res.ref.cacheKey):
503
- return self.codeCache[res.ref.cacheKey]
504
-
499
+ if _res := self.codeCache.get(res.ref.cacheKey):
500
+ return _res
505
501
  self.codeCache[res.ref.cacheKey] = res
506
502
  return res
507
503
 
@@ -67,12 +67,20 @@ class Compiler:
67
67
  properties: list[source.Property],
68
68
  header_name: Optional[str] = None,
69
69
  Impl: Optional[IImplementation] = IImplementation(),
70
+ override_llparse_name: bool = False
70
71
  ):
71
72
  """Creates the C and header file..."""
72
73
  info = self.to_frontend(root, properties, Impl)
73
74
  hb = HeaderBuilder(self.prefix, self.headerGuard, properties, info.spans)
75
+ cdata = CCompiler(header_name, self.debug).compile(info)
76
+ if override_llparse_name:
77
+ # sometimes users want to combine parsers together when compiling with C
78
+ # to make up for conflicts with other parsers example: llhttp
79
+ # there should be a fair way of compiling everything.
80
+ cdata = cdata.replace('llparse', self.prefix)
81
+
74
82
  return CompilerResult(
75
- CCompiler(header_name, self.debug).compile(info), hb.build()
83
+ cdata , hb.build()
76
84
  )
77
85
 
78
86
 
@@ -122,6 +130,7 @@ class LLParse(source.Builder):
122
130
  maxTableElemWidth: Optional[int] = None,
123
131
  minTableSize: Optional[int] = None,
124
132
  header_name: Optional[str] = None,
133
+ override_llparse_name:bool = False
125
134
  ):
126
135
  """Builds Graph and then compiles the data into C code , returns with the header and C file inside of a Dataclass"""
127
136
 
@@ -133,7 +142,8 @@ class LLParse(source.Builder):
133
142
  minTableSize if minTableSize else DEFAULT_MIN_TABLE_SIZE,
134
143
  )
135
144
 
136
- return compiler.compile(root, self.properties(), header_name=header_name)
145
+ return compiler.compile(root, self.properties(), header_name=header_name, override_llparse_name=override_llparse_name)
146
+
137
147
 
138
148
  def to_frontend(
139
149
  self,
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Any, Optional
2
+ from typing import Any, Optional, Callable
3
3
 
4
4
  from ..pyfront.front import Code, IWrap, Span, SpanField
5
5
  from ..pyfront.transform import Transform
@@ -8,7 +8,9 @@ from ..pyfront.transform import Transform
8
8
  class Slot:
9
9
  # ONLY NODE SHOULD BE ALLOWED TO BE SEEN
10
10
 
11
- def __init__(self, node: IWrap["Node"], value: Any) -> None:
11
+ def __init__(
12
+ self, node: IWrap["Node"], value: Callable[[IWrap["Node"]], None]
13
+ ) -> None:
12
14
  self.privNode = node
13
15
  """Same as calling it from get and setting the value etc..."""
14
16
  self.privUpdate = value
@@ -19,12 +21,17 @@ class Slot:
19
21
  # I spent 4 hours trying to figure this how this could be implemented
20
22
  # so this is my only ideal sloution
21
23
  def __hash__(self) -> int:
22
- return hash(self.privUpdate.ref.id.name)
24
+ return hash(self.privNode.ref.id.name)
23
25
 
24
26
  @property
25
27
  def node(self):
26
28
  return self.privNode
27
29
 
30
+ @node.setter
31
+ def node(self, value: IWrap["Node"]):
32
+ self.privNode = value
33
+ self.privUpdate(value)
34
+
28
35
 
29
36
  @dataclass(unsafe_hash=True)
30
37
  class IUniqueName:
@@ -121,9 +128,6 @@ class Invoke(Node):
121
128
 
122
129
 
123
130
  class Empty(Node):
124
- # def __init__(self, id: IUniqueName) -> None:
125
- # super().__init__(id)
126
-
127
131
  def __hash__(self):
128
132
  return hash(self.id)
129
133
 
@@ -237,16 +241,7 @@ class TableLookup(Match):
237
241
  self.privEdges.append(edge)
238
242
 
239
243
  def buildSlots(self):
240
- edge = self.privEdges
241
- for e in edge:
242
- yield Slot(e.node, e.node)
243
- for e in super().buildSlots():
244
- yield e
245
-
246
-
247
- # Ident = Identifier("llComment")
248
-
249
- # node = Node(Ident.id("__On_Pagesum"))
244
+ for e in self.privEdges:
245
+ yield Slot(e.node, lambda value: setattr(e, "node", value))
246
+ yield from super().buildSlots()
250
247
 
251
- # node2 = Invoke(Ident.id("Check_Flag"),IsEqual("Flag","Check_Flag",0))
252
- # node2.setOtherwise(IWrap(node),True,0)
@@ -11,7 +11,7 @@ class Peephole:
11
11
  def optimize(self, root: WrapNode, nodes: WrapList):
12
12
  changed = set(nodes)
13
13
 
14
- while len(changed) != 0:
14
+ while changed:
15
15
  previous = changed
16
16
  changed = set()
17
17
 
@@ -58,7 +58,7 @@ class Trie:
58
58
  internalEdges: list[IEdge] = []
59
59
 
60
60
  for edge in edges:
61
- key = str(edge.key) if isinstance(edge.key, int) else edge.key
61
+ key = chr(edge.key) if isinstance(edge.key, int) else edge.key
62
62
  internalEdges.append(
63
63
  IEdge(
64
64
  key=key.encode("utf-8") if isinstance(key, str) else key,
@@ -73,8 +73,8 @@ class Trie:
73
73
  def level(self, edges: list[IEdge], path: list[bytes] = []):
74
74
  first = edges[0].key
75
75
  last = edges[-1].key
76
- # print("level",edges, first)
77
- if len(edges) == 1 and len(edges[0].key) == 0:
76
+ # print("level", edges, first)
77
+ if len(edges) == 1 and (len(edges[0].key) == 0):
78
78
  return TrieEmpty(edges[0].node, edges[0].value)
79
79
 
80
80
  i = 0
@@ -112,17 +112,17 @@ class Trie:
112
112
  + (b", ".join(path).decode("utf-8"))
113
113
  + "]"
114
114
  )
115
-
115
+
116
116
  keys: dict[int, list[IEdge]] = {}
117
117
  otherwise = None
118
118
  for edge in edges:
119
- if not len(edge.key):
119
+ if not edge.key:
120
120
  otherwise = TrieEmpty(edge.node, edge.value)
121
121
  continue
122
122
 
123
123
  key = edge.key[0]
124
124
 
125
- if keys.get(key):
125
+ if key in keys:
126
126
  keys[key].append(edge)
127
127
  else:
128
128
  keys[key] = [edge]
@@ -146,7 +146,9 @@ class Trie:
146
146
  + "]"
147
147
  )
148
148
  raise TypeError(err)
149
- child = ITrieSingleChild(key, noAdvance, self.level(sliced, subPath))
150
- children.append(child)
149
+
150
+ children.append(
151
+ ITrieSingleChild(key, noAdvance, self.level(sliced, subPath))
152
+ )
151
153
 
152
154
  return TrieSingle(children, otherwise)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llparse
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: A Parody of llparse written for writing C Parsers with Python
5
5
  Author-email: Vizonex <VizonexBusiness@gmail.com>
6
6
  Requires-Python: >=3.9
@@ -15,7 +15,7 @@ Dynamic: license-file
15
15
 
16
16
  A python parody of the typescript library llparse.
17
17
 
18
- I take no credit for the orginal work done by indutny and I was originally very nervous about making
18
+ I take no credit for the orginal work done by indutny and the other node-js contributors involved and I was originally very nervous about making
19
19
  this python library that I made public...
20
20
 
21
21
  Links to the original library
@@ -49,7 +49,7 @@ do it at your own risk. They maybe incompleted or not throughly stress-tested.
49
49
 
50
50
  ## New Features
51
51
  - Throw me an issue if typescript llparse introduces something new that you want for me or another contributor to try and implement
52
- just seeing llparse add new features is nothing but exciting to me.
52
+ just seeing llparse add new features is exciting to me.
53
53
 
54
54
  - If you want a feature that typescript llparse doesn't have, be sure to try making a pull request over there as well and not just here,
55
55
  there's a good chance they will appericate you for helping over there too and your helping make llhttp better by doing so. :)
@@ -62,7 +62,7 @@ there's a good chance they will appericate you for helping over there too and yo
62
62
  - Make it easy for me or someone else to find a problem and solve it in typescript after testing it in python
63
63
  - Typescript takes 2 commands to run a script with node-js it while python only takes one cutting the time required tremendously...
64
64
  - The orginal project was MIT licensed.
65
- - I wanted to write my own C Parsering tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
65
+ - I wanted to write my own C Parser tool with llhttp styled callbacks of my own using a language I was the most comfortable with using.
66
66
  - I didn't like __Lemon Parser__ or __Yacc__ all that much and a good ide for handling them in Visual Studio Code with error checking to my knowlegde does not exist.
67
67
  - The closest thing I got to what I wanted was a project named __NMFU__ shorthand for no memory for you and even I had problems with writing things using that library...
68
68
 
@@ -131,3 +131,6 @@ print(c.c)
131
131
  open("http_parser.c", "w").write(c.c)
132
132
  open("http_parser.h", "w").write(c.header)
133
133
  ```
134
+
135
+ ## Video Showcasing this library
136
+ - https://youtu.be/YQOzJ2BghQw
@@ -33,5 +33,6 @@ llparse/pyfront/namespace.py
33
33
  llparse/pyfront/nodes.py
34
34
  llparse/pyfront/peephole.py
35
35
  llparse/pyfront/transform.py
36
+ tests/test_frontend.py
36
37
  tests/test_loop_checker.py
37
38
  tests/test_span_allocator.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "llparse"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  description = "A Parody of llparse written for writing C Parsers with Python"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -0,0 +1,25 @@
1
+
2
+ from llparse import LLParse
3
+
4
+
5
+
6
+ def test_build_tables():
7
+ # There was a bug with 1.2 of our version that doesn't affect the node-js one where
8
+ # it wouldn't building tables, this attempts to simulate the problem Currenlty this
9
+ # bug is patched now :)
10
+ p = LLParse("lltable")
11
+ start = p.node('start')
12
+ loop = p.node('loop')
13
+ loop.skipTo(start)
14
+ start.match(
15
+ [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
16
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 58,
17
+ 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126, 32, 9, 10, 13, 11, 12],
18
+ loop
19
+ ).otherwise(p.error(0, 'im a little teapot'))
20
+
21
+ # If there is not a lookup_table this then it has failed me ;-;
22
+ assert "lookup_table" in p.build(start).c
23
+
24
+
25
+
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