llparse 0.1.1__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 (41) hide show
  1. {llparse-0.1.1 → llparse-0.1.3}/PKG-INFO +7 -4
  2. {llparse-0.1.1 → llparse-0.1.3}/README.md +6 -3
  3. {llparse-0.1.1 → llparse-0.1.3}/llparse/C_compiler.py +28 -30
  4. {llparse-0.1.1 → llparse-0.1.3}/llparse/compilator.py +5 -9
  5. {llparse-0.1.1 → llparse-0.1.3}/llparse/cython_builder.py +1 -0
  6. {llparse-0.1.1 → llparse-0.1.3}/llparse/debug.py +0 -3
  7. {llparse-0.1.1 → llparse-0.1.3}/llparse/dot.py +0 -3
  8. llparse-0.1.3/llparse/errors.py +2 -0
  9. {llparse-0.1.1 → llparse-0.1.3}/llparse/frontend.py +45 -51
  10. {llparse-0.1.1 → llparse-0.1.3}/llparse/llparse.py +19 -4
  11. {llparse-0.1.1 → llparse-0.1.3}/llparse/pybuilder/loopchecker.py +80 -39
  12. {llparse-0.1.1 → llparse-0.1.3}/llparse/pybuilder/main_code.py +27 -10
  13. {llparse-0.1.1 → llparse-0.1.3}/llparse/pybuilder/parsemap.py +2 -6
  14. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/front.py +3 -1
  15. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/nodes.py +16 -19
  16. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/peephole.py +1 -1
  17. {llparse-0.1.1 → llparse-0.1.3}/llparse/settings.py +0 -1
  18. {llparse-0.1.1 → llparse-0.1.3}/llparse/spanalloc.py +12 -27
  19. {llparse-0.1.1 → llparse-0.1.3}/llparse/test.py +1 -0
  20. {llparse-0.1.1 → llparse-0.1.3}/llparse/trie.py +10 -21
  21. {llparse-0.1.1 → llparse-0.1.3}/llparse.egg-info/PKG-INFO +7 -4
  22. {llparse-0.1.1 → llparse-0.1.3}/llparse.egg-info/SOURCES.txt +5 -2
  23. {llparse-0.1.1 → llparse-0.1.3}/pyproject.toml +1 -1
  24. llparse-0.1.3/tests/test_frontend.py +25 -0
  25. llparse-0.1.3/tests/test_loop_checker.py +160 -0
  26. llparse-0.1.3/tests/test_span_allocator.py +121 -0
  27. llparse-0.1.1/llparse/tire.py +0 -158
  28. {llparse-0.1.1 → llparse-0.1.3}/LICENSE +0 -0
  29. {llparse-0.1.1 → llparse-0.1.3}/llparse/__init__.py +0 -0
  30. {llparse-0.1.1 → llparse-0.1.3}/llparse/constants.py +0 -0
  31. {llparse-0.1.1 → llparse-0.1.3}/llparse/enumerator.py +0 -0
  32. {llparse-0.1.1 → llparse-0.1.3}/llparse/header.py +0 -0
  33. {llparse-0.1.1 → llparse-0.1.3}/llparse/pybuilder/__init__.py +0 -0
  34. {llparse-0.1.1 → llparse-0.1.3}/llparse/pybuilder/builder.py +0 -0
  35. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/containers.py +0 -0
  36. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/implementation.py +0 -0
  37. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/namespace.py +2 -2
  38. {llparse-0.1.1 → llparse-0.1.3}/llparse/pyfront/transform.py +0 -0
  39. {llparse-0.1.1 → llparse-0.1.3}/llparse.egg-info/dependency_links.txt +0 -0
  40. {llparse-0.1.1 → llparse-0.1.3}/llparse.egg-info/top_level.txt +0 -0
  41. {llparse-0.1.1 → llparse-0.1.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llparse
3
- Version: 0.1.1
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
@@ -29,32 +29,32 @@ class CCompiler:
29
29
  out.append("#include <string.h>")
30
30
  out.append("")
31
31
  # Seems LLParse was updated from /* UNREACHABLE */ abort(); to a Macro, Intresting...
32
- out.append('#ifdef __SSE4_2__')
33
- out.append(' #ifdef _MSC_VER')
34
- out.append(' #include <nmmintrin.h>')
35
- out.append(' #else /* !_MSC_VER */')
36
- out.append(' #include <x86intrin.h>')
37
- out.append(' #endif /* _MSC_VER */')
38
- out.append('#endif /* __SSE4_2__ */')
39
- out.append('')
40
-
41
- out.append('#ifdef __ARM_NEON__')
42
- out.append(' #include <arm_neon.h>')
43
- out.append('#endif /* __ARM_NEON__ */')
44
- out.append('')
45
-
46
- out.append('#ifdef __wasm__')
47
- out.append(' #include <wasm_simd128.h>')
48
- out.append('#endif /* __wasm__ */')
49
- out.append('')
50
-
51
- out.append('#ifdef _MSC_VER')
52
- out.append(' #define ALIGN(n) _declspec(align(n))')
53
- out.append(' #define UNREACHABLE __assume(0)')
54
- out.append('#else /* !_MSC_VER */')
55
- out.append(' #define ALIGN(n) __attribute__((aligned(n)))')
56
- out.append(' #define UNREACHABLE __builtin_unreachable()')
57
- out.append('#endif /* _MSC_VER */')
32
+ out.append("#ifdef __SSE4_2__")
33
+ out.append(" #ifdef _MSC_VER")
34
+ out.append(" #include <nmmintrin.h>")
35
+ out.append(" #else /* !_MSC_VER */")
36
+ out.append(" #include <x86intrin.h>")
37
+ out.append(" #endif /* _MSC_VER */")
38
+ out.append("#endif /* __SSE4_2__ */")
39
+ out.append("")
40
+
41
+ out.append("#ifdef __ARM_NEON__")
42
+ out.append(" #include <arm_neon.h>")
43
+ out.append("#endif /* __ARM_NEON__ */")
44
+ out.append("")
45
+
46
+ out.append("#ifdef __wasm__")
47
+ out.append(" #include <wasm_simd128.h>")
48
+ out.append("#endif /* __wasm__ */")
49
+ out.append("")
50
+
51
+ out.append("#ifdef _MSC_VER")
52
+ out.append(" #define ALIGN(n) _declspec(align(n))")
53
+ out.append(" #define UNREACHABLE __assume(0)")
54
+ out.append("#else /* !_MSC_VER */")
55
+ out.append(" #define ALIGN(n) __attribute__((aligned(n)))")
56
+ out.append(" #define UNREACHABLE __builtin_unreachable()")
57
+ out.append("#endif /* _MSC_VER */")
58
58
 
59
59
  out.append("")
60
60
  out.append(
@@ -83,7 +83,7 @@ class CCompiler:
83
83
  out.append("}")
84
84
  out.append("")
85
85
 
86
- # TODO (Vizonex) Make llparse_state_t's Name Optional and alterable incase mixed with
86
+ # TODO (Vizonex) Make llparse_state_t's Name Optional and alterable incase mixed with
87
87
  # llhttp or another parser
88
88
  out.append(f"static llparse_state_t {info.prefix}__run(")
89
89
  out.append(f" {info.prefix}_t* {ARG_STATE},")
@@ -182,9 +182,7 @@ class CCompiler:
182
182
  else:
183
183
  # TODO (Vizonex) Merge lines 139 & 140 together in a future update
184
184
  callback = (
185
- f"(({info.prefix}__span_cb)"
186
- + ctx.spanCbField(span.index)
187
- + f")"
185
+ f"(({info.prefix}__span_cb)" + ctx.spanCbField(span.index) + f")"
188
186
  )
189
187
 
190
188
  args = [ctx.stateArg(), posField, f"(const char*) {ctx.endPosArg()}"]
@@ -170,7 +170,7 @@ class Load(Field):
170
170
  def doBuild(self, ctx: "Compilation", out: list[str]):
171
171
  out.append(f"return {self.field(ctx)};")
172
172
 
173
-
173
+
174
174
  # BIG ONE
175
175
 
176
176
 
@@ -374,7 +374,6 @@ class Consume(Node):
374
374
  index = ctx.stateField(self.ref.field)
375
375
  ty = ctx.getFieldType(self.ref.field)
376
376
 
377
-
378
377
  if ty == "i64":
379
378
  pass
380
379
  elif ty == "i32":
@@ -412,7 +411,6 @@ class Empty(Node):
412
411
  def __init__(self, ref: _frontend.node.Empty) -> None:
413
412
  self.ref = ref
414
413
  super().__init__(ref)
415
-
416
414
 
417
415
  def doBuild(self, out: list[str]):
418
416
  assert self.ref.otherwise
@@ -574,7 +572,7 @@ class Single(Node):
574
572
  else:
575
573
  ch = f"'{chr(e.key)}'"
576
574
 
577
- out.append(f" case {ch}:" + "{")
575
+ out.append(f" case {ch}: " + "{")
578
576
  tmp: list[str] = []
579
577
 
580
578
  # For now debug everything....
@@ -884,7 +882,7 @@ class Compilation:
884
882
  def buildStateEnum(self, out: list[str]):
885
883
  # TODO (Vizonex) Give out other names that you could pass as an enum statename
886
884
  # this is incase multiple llparse_state_e states are given to compile
887
- # example would be mixing llhttp with some other source...
885
+ # example would be mixing llhttp with some other source...
888
886
  out.append("enum llparse_state_e {")
889
887
  out.append(f" {STATE_ERROR},")
890
888
  for stateName in self.stateDict.keys():
@@ -992,8 +990,7 @@ class Compilation:
992
990
  out.append(f"{LABEL_PREFIX}{name} : " + "{")
993
991
  for line in lines:
994
992
  out.append(f" {line}")
995
- out.append(" /* UNREACHABLE */;")
996
- out.append(" abort();")
993
+ out.append(" UNREACHABLE;")
997
994
  out.append("}")
998
995
 
999
996
  def buildInternalStates(self, out: list[str]):
@@ -1004,8 +1001,7 @@ class Compilation:
1004
1001
  out.append(f"{LABEL_PREFIX}{name}: " + "{")
1005
1002
  for line in lines:
1006
1003
  out.append(f" {line}")
1007
- out.append(" /* UNREACHABLE */;")
1008
- out.append(" abort();")
1004
+ out.append(" UNREACHABLE;")
1009
1005
  out.append("}")
1010
1006
 
1011
1007
  def addState(self, state: str, lines: list[str]):
@@ -2,6 +2,7 @@
2
2
 
3
3
  from contextlib import contextmanager
4
4
  from typing import Optional
5
+
5
6
  from .frontend import IFrontendResult
6
7
  from .pyfront.front import Match
7
8
  from .pyfront.nodes import Invoke
@@ -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:
@@ -208,6 +208,3 @@ class Dot:
208
208
 
209
209
  def escape(self, value: str):
210
210
  return "'" + value.replace("\\", "\\$1").replace('"', "\\$1") + "'"
211
-
212
-
213
- # TODO FIX ALL BUFFERS BACK TO STRINGS!
@@ -0,0 +1,2 @@
1
+ class Error(Exception):
2
+ pass
@@ -4,6 +4,7 @@ from typing import Literal, Optional, Union
4
4
  from .enumerator import Enumerator
5
5
  from .pybuilder import LoopChecker
6
6
  from .pybuilder import builder as source
7
+
7
8
  # from pyfront.namespace import code, node , transform
8
9
  from .pyfront import namespace as _frontend
9
10
  from .pyfront.front import Identifier, IWrap, SpanField
@@ -11,19 +12,20 @@ from .pyfront.implementation import IImplementation
11
12
  from .pyfront.nodes import ITableEdge
12
13
  from .pyfront.peephole import Peephole
13
14
  from .spanalloc import SpanAllocator
14
- from .trie import Trie, TrieEmpty, TrieNode, TrieSequence, TrieSingle
15
+ from .trie import Trie, TrieEmpty, TrieNode, TrieSequence, TrieSingle, ITrieSingleChild
15
16
 
16
17
  DEFAULT_MIN_TABLE_SIZE = 32
17
18
  DEFAULT_MAX_TABLE_WIDTH = 4
18
19
 
20
+ from logging import getLogger
21
+
22
+ log = getLogger("llparse.frontend")
19
23
 
20
24
 
21
25
  WrappedNode = IWrap[_frontend.node.Node]
22
26
  WrappedCode = IWrap[_frontend.code.Code]
23
27
 
24
28
 
25
-
26
-
27
29
  @dataclass
28
30
  class ITableLookupTarget:
29
31
  trie: TrieEmpty
@@ -168,7 +170,7 @@ class Frontend:
168
170
  trieNode = trie.build(list(node))
169
171
 
170
172
  if not trieNode:
171
- # print("[DEBUG]", "TrieNode was nonexistant")
173
+ log.debug("TrieNode was nonexistant")
172
174
  return self.implementation.node.Empty(
173
175
  _frontend.node.Empty(self.Id.id(node.name))
174
176
  )
@@ -180,7 +182,7 @@ class Frontend:
180
182
 
181
183
  return children
182
184
 
183
- def registerNode(self, node: WrappedNode):
185
+ def registerNode(self, node: WrappedNode) -> None:
184
186
  # NOTE NO Implementations required here since this is python!
185
187
  if isinstance(
186
188
  node.ref,
@@ -289,7 +291,6 @@ class Frontend:
289
291
 
290
292
  if isinstance(single.ref, _frontend.node.Invoke):
291
293
  for edge in node:
292
- # print(edge.key)
293
294
  single.ref.addEdge(
294
295
  ord(edge.key) if isinstance(edge.key, str) else edge.key,
295
296
  self.translate(edge.node),
@@ -306,52 +307,48 @@ class Frontend:
306
307
  return None
307
308
 
308
309
  targets: dict[source.code.Node, ITableLookupTarget] = {}
309
- bailout = False
310
- for child in trie.children:
311
- if isinstance(child.node, TrieEmpty):
312
- # print(
313
- # 'non-leaf trie child of "%s" prevents table allocation' % node.name
314
- # )
315
- bailout = False
316
- continue
317
-
318
- empty: TrieEmpty = child.node
319
- if getattr(empty, "value", None) is None:
320
- # print(
321
- # 'value passing trie leaf of "%s" prevents table allocation'
322
- # % node.name
323
- # )
324
- bailout = False
325
- 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
326
325
 
327
326
  target = empty.node
328
- if not targets.get(target):
327
+ if target not in targets:
329
328
  targets[target] = ITableLookupTarget(
330
329
  keys=[child.key], noAdvance=child.noAdvance, trie=empty
331
330
  )
332
- bailout = True
333
- break
331
+ return True
334
332
 
335
333
  existing = targets[target]
336
-
337
334
  if existing.noAdvance != child.noAdvance:
338
- # print('noAdvance mismatch in a trie leaf of "%s" prevents table allocation' % node.name)
339
- bailout = False
340
- break
341
-
335
+ log.debug(
336
+ f'noAdvance mismatch in a trie leaf of "{node.name}" prevents '
337
+ "table allocation"
338
+ )
339
+ return False
342
340
  existing.keys.append(child.key)
341
+ return True
343
342
 
344
- # TODO: see if breaking or continue block after out is breakout has been determined is good ot not...
345
- bailout = True
346
- break
347
-
348
- # assert len(trie.children) == len(targets), "Something went wrong"
349
- if bailout:
343
+ if not all([check_child(child) for child in trie.children]):
350
344
  return
351
345
 
352
346
  # Weave width limit for optimization...
353
- if len(targets.keys()) >= (1 << self.options["maxTableElemWidth"]):
354
- # 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
+ )
355
352
  return
356
353
 
357
354
  table = self.implementation.node.TableLookup(
@@ -360,11 +357,11 @@ class Frontend:
360
357
  children.append(table)
361
358
 
362
359
  # Break Loop
363
- if self.Map.get(node):
360
+ if not self.Map.get(node):
364
361
  self.Map[node] = table
365
362
 
366
363
  for target in targets.values():
367
- _next = self.translateTrie(node, target, children)
364
+ _next = self.translateTrie(node, target.trie, children)
368
365
  table.ref.addEdge(
369
366
  ITableEdge(keys=target.keys, noAdvance=target.noAdvance, node=_next)
370
367
  )
@@ -410,9 +407,7 @@ class Frontend:
410
407
  self, node: source.code.Match, trie: TrieSingle, children: MatchChildren
411
408
  ):
412
409
  # Check if Tablelookup could be a valid option to Optimze our code up...
413
- maybeTable = self.maybeTableLookup(node, trie, children)
414
-
415
- if maybeTable:
410
+ if maybeTable := self.maybeTableLookup(node, trie, children):
416
411
  return maybeTable
417
412
 
418
413
  single = self.implementation.node.Single(
@@ -434,8 +429,7 @@ class Frontend:
434
429
  value=child.node.value if isinstance(child.node, TrieEmpty) else None,
435
430
  )
436
431
 
437
- otherwise = trie.otherwise
438
- if otherwise:
432
+ if otherwise := trie.otherwise:
439
433
  single.ref.setOtherwise(
440
434
  self.translateTrie(node, otherwise, children), True, otherwise.value
441
435
  )
@@ -444,8 +438,9 @@ class Frontend:
444
438
  def translateSpanCode(self, code: source.code._Span):
445
439
  return self.translateCode(code)
446
440
 
447
- # TODO Vizonex Maybe better typehining can be used in this function alone....
448
- def translateCode(self, code: source.code.Code):
441
+ def translateCode(
442
+ self, code: source.code.Code
443
+ ):
449
444
  """Translates Builder Classes to Frontend Classes..."""
450
445
 
451
446
  prefixed = self.codeId.id(code.name).name
@@ -501,9 +496,8 @@ class Frontend:
501
496
  else:
502
497
  raise Exception(f'UnSupported code:"{code.name}" type: "{type(code)}"')
503
498
 
504
- if self.codeCache.get(res.ref.cacheKey):
505
- return self.codeCache[res.ref.cacheKey]
506
-
499
+ if _res := self.codeCache.get(res.ref.cacheKey):
500
+ return _res
507
501
  self.codeCache[res.ref.cacheKey] = res
508
502
  return res
509
503
 
@@ -4,8 +4,13 @@ from dataclasses import dataclass
4
4
  from typing import Optional
5
5
 
6
6
  from .C_compiler import CCompiler
7
- from .frontend import (DEFAULT_MAX_TABLE_WIDTH, DEFAULT_MIN_TABLE_SIZE,
8
- Frontend, IImplementation, source)
7
+ from .frontend import (
8
+ DEFAULT_MAX_TABLE_WIDTH,
9
+ DEFAULT_MIN_TABLE_SIZE,
10
+ Frontend,
11
+ IImplementation,
12
+ source,
13
+ )
9
14
  from .header import HeaderBuilder
10
15
 
11
16
 
@@ -62,12 +67,20 @@ class Compiler:
62
67
  properties: list[source.Property],
63
68
  header_name: Optional[str] = None,
64
69
  Impl: Optional[IImplementation] = IImplementation(),
70
+ override_llparse_name: bool = False
65
71
  ):
66
72
  """Creates the C and header file..."""
67
73
  info = self.to_frontend(root, properties, Impl)
68
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
+
69
82
  return CompilerResult(
70
- CCompiler(header_name, self.debug).compile(info), hb.build()
83
+ cdata , hb.build()
71
84
  )
72
85
 
73
86
 
@@ -117,6 +130,7 @@ class LLParse(source.Builder):
117
130
  maxTableElemWidth: Optional[int] = None,
118
131
  minTableSize: Optional[int] = None,
119
132
  header_name: Optional[str] = None,
133
+ override_llparse_name:bool = False
120
134
  ):
121
135
  """Builds Graph and then compiles the data into C code , returns with the header and C file inside of a Dataclass"""
122
136
 
@@ -128,7 +142,8 @@ class LLParse(source.Builder):
128
142
  minTableSize if minTableSize else DEFAULT_MIN_TABLE_SIZE,
129
143
  )
130
144
 
131
- 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
+
132
147
 
133
148
  def to_frontend(
134
149
  self,