llparse 0.1.0__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.
llparse/C_compiler.py ADDED
@@ -0,0 +1,204 @@
1
+ from typing import Optional
2
+
3
+ from .compilator import Compilation, ICompilerOptions, Node
4
+ from .constants import *
5
+ from .frontend import IFrontendResult
6
+
7
+
8
+ class CCompiler:
9
+ """The Final HeadPeice where the Main C-Code gets compiled to..."""
10
+
11
+ def __init__(
12
+ self, header: Optional[str] = None, debug: Optional[str] = None
13
+ ) -> None:
14
+ # NOTE Unlike in typescript llparse Containers are not Required since I'm using a different methoad to translate those parts...
15
+ self.options = ICompilerOptions(debug, header)
16
+
17
+ def compile(self, info: IFrontendResult):
18
+ compilation = Compilation(
19
+ info.prefix,
20
+ info.properties,
21
+ list(info.resumptionTargets),
22
+ options=self.options,
23
+ )
24
+
25
+ out: list[str] = []
26
+
27
+ out.append("#include <stdlib.h>")
28
+ out.append("#include <stdint.h>")
29
+ out.append("#include <string.h>")
30
+ out.append("")
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 */')
58
+
59
+ out.append("")
60
+ out.append(
61
+ f'#include "{self.options.header if self.options.header else info.prefix}.h"'
62
+ )
63
+ out.append("")
64
+ out.append(f"typedef int (*{info.prefix}__span_cb)(")
65
+ out.append(f" {info.prefix}_t*, const char*, const char*);")
66
+ out.append("")
67
+
68
+ # Start Queuing span callbacks
69
+ # otherwise we will have nothing
70
+ # but mess which is not what we want - Vizonex
71
+ compilation.reserveSpans(info.spans)
72
+
73
+ rootState: Node = compilation.unwrapNode(info.root)
74
+ rootName = rootState.build(compilation)
75
+ # Bring in the rest of the variables...
76
+ compilation.buildGlobals(out)
77
+ out.append("")
78
+
79
+ out.append(f"int {info.prefix}_init({info.prefix}_t* {ARG_STATE}) " + "{")
80
+ out.append(f" memset({ARG_STATE}, 0, sizeof(*{ARG_STATE}));")
81
+ out.append(f" {ARG_STATE}->_current = (void*) (intptr_t) {rootName};")
82
+ out.append(" return 0;")
83
+ out.append("}")
84
+ out.append("")
85
+
86
+ # TODO (Vizonex) Make llparse_state_t's Name Optional and alterable incase mixed with
87
+ # llhttp or another parser
88
+ out.append(f"static llparse_state_t {info.prefix}__run(")
89
+ out.append(f" {info.prefix}_t* {ARG_STATE},")
90
+ out.append(f" const unsigned char* {ARG_POS},")
91
+ out.append(f" const unsigned char* {ARG_ENDPOS}) " + "{")
92
+ out.append(f" int {VAR_MATCH};")
93
+ out.append(
94
+ " switch ((llparse_state_t) (intptr_t) "
95
+ + f"{compilation.currentField()}) "
96
+ + "{"
97
+ )
98
+
99
+ # Now build resumption states... These are states what will have a 'case block' next to them...
100
+ # However I'm not refering to the characters those will be handles in thier inner switches,
101
+ # I'm talking about the major states...
102
+ tmp = []
103
+ compilation.buildResumptionStates(tmp)
104
+ compilation.indent(out, tmp, " ")
105
+
106
+ # Final Resumption State... Very important!
107
+ out.append(" default:")
108
+ out.append(" UNREACHABLE;")
109
+ out.append(" }")
110
+
111
+ tmp = []
112
+ compilation.buildInternalStates(tmp)
113
+ compilation.indent(out, tmp, " ")
114
+
115
+ out.append("}")
116
+ out.append("")
117
+
118
+ out.append(
119
+ f"int {info.prefix}_execute({info.prefix}_t* {ARG_STATE}, "
120
+ + f"const char* {ARG_POS}, const char* {ARG_ENDPOS}) "
121
+ + "{"
122
+ )
123
+ out.append(" llparse_state_t next;")
124
+ out.append("")
125
+
126
+ out.append(" /* check lingering errors */")
127
+ out.append(f" if ({compilation.errorField()} != 0) " + "{")
128
+ out.append(f" return {compilation.errorField()};")
129
+ out.append(" }")
130
+ out.append("")
131
+
132
+ tmp = []
133
+ self.restartSpans(compilation, info, tmp)
134
+ compilation.indent(out, tmp, " ")
135
+ args = [
136
+ compilation.stateArg(),
137
+ f"(const unsigned char*) {compilation.posArg()}",
138
+ f"(const unsigned char*) {compilation.endPosArg()}",
139
+ ]
140
+ out.append(f" next = {info.prefix}__run({(', ').join(args)});")
141
+ out.append(f" if (next == {STATE_ERROR}) " + "{")
142
+ out.append(f" return {compilation.errorField()};")
143
+ out.append(" }")
144
+ out.append(f" {compilation.currentField()} = (void*) (intptr_t) next;")
145
+ out.append("")
146
+
147
+ tmp = []
148
+ self.executeSpans(compilation, info, tmp)
149
+ compilation.indent(out, tmp, " ")
150
+
151
+ out.append(" return 0;")
152
+ out.append("}")
153
+
154
+ # JOIN ALL OF THEM!
155
+ return "\n".join(out)
156
+
157
+ def restartSpans(self, ctx: Compilation, info: IFrontendResult, out: list[str]):
158
+ if len(info.spans) == 0:
159
+ return
160
+
161
+ out.append("/* restart spans */")
162
+ for span in info.spans:
163
+ posField = ctx.spanPosField(span.index)
164
+
165
+ out.append(f"if ({posField} != NULL) " + "{")
166
+ out.append(f" {posField} = (void*) {ctx.posArg()};")
167
+ out.append("}")
168
+ out.append("")
169
+
170
+ def executeSpans(self, ctx: Compilation, info: IFrontendResult, out: list[str]):
171
+ if not info.spans:
172
+ return
173
+
174
+ out.append("/* execute spans */")
175
+ for span in info.spans:
176
+ posField = ctx.spanPosField(span.index)
177
+
178
+ if len(span.callbacks) == 1:
179
+ cb = ctx.unwrapCode(span.callbacks[0], True)
180
+ callback = ctx.buildCode(cb)
181
+
182
+ else:
183
+ # TODO (Vizonex) Merge lines 139 & 140 together in a future update
184
+ callback = (
185
+ f"({info.prefix}__span_cb)"
186
+ + ctx.spanCbField(span.index)
187
+ + f"({callback})"
188
+ )
189
+
190
+ args = [ctx.stateArg(), posField, f"(const char*) {ctx.endPosArg()}"]
191
+
192
+ out.append(f"if ({posField} != NULL) " + "{")
193
+ out.append(" int error;")
194
+ out.append("")
195
+ out.append(f" error = {callback}({', '.join(args)});")
196
+
197
+ # TODO (Vizonex): Deduplicate when indutny updates his side so we can all make our changes accordingly...
198
+ out.append(" if (error != 0) {")
199
+ out.append(f" {ctx.errorField()} = error;")
200
+ out.append(f" {ctx.errorPosField()} = {ctx.endPosArg()};")
201
+ out.append(" return error;")
202
+ out.append(" }")
203
+ out.append("}")
204
+ out.append("")
llparse/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from .dot import Dot
2
+ from .llparse import LLParse