ssc_codegen 0.1.13__tar.gz → 0.2.0__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 ssc_codegen might be problematic. Click here for more details.
- ssc_codegen-0.2.0/PKG-INFO +77 -0
- ssc_codegen-0.2.0/README.md +52 -0
- {ssc_codegen-0.1.13 → ssc_codegen-0.2.0}/pyproject.toml +15 -10
- ssc_codegen-0.2.0/ssc_codegen/__init__.py +4 -0
- ssc_codegen-0.2.0/ssc_codegen/_cli.py +175 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/base.py +65 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/dart_universal_html.py +382 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/py_bs4.py +331 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/py_parsel.py +328 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/py_scrapy.py +330 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/py_selectolax.py +318 -0
- ssc_codegen-0.2.0/ssc_codegen/converters/utils.py +9 -0
- ssc_codegen-0.2.0/ssc_codegen/document.py +358 -0
- ssc_codegen-0.2.0/ssc_codegen/generator.py +200 -0
- ssc_codegen-0.2.0/ssc_codegen/objects.py +203 -0
- ssc_codegen-0.2.0/ssc_codegen/queries.py +65 -0
- ssc_codegen-0.2.0/ssc_codegen/schemas.py +79 -0
- ssc_codegen-0.2.0/ssc_codegen/template.py +96 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/dart/universal_html/baseStruct.j2 +41 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/dart/universal_html/dictStruct.j2 +54 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/dart/universal_html/itemStruct.j2 +45 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/dart/universal_html/listStruct.j2 +55 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/bs4/baseStruct.j2 +38 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/bs4/dictStruct.j2 +39 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/bs4/itemStruct.j2 +35 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/bs4/listStruct.j2 +43 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/parsel/baseStruct.j2 +38 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/parsel/dictStruct.j2 +39 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/parsel/itemStruct.j2 +36 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/parsel/listStruct.j2 +44 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/scrapy/baseStruct.j2 +41 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/scrapy/dictStruct.j2 +39 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/scrapy/itemStruct.j2 +35 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/scrapy/listStruct.j2 +44 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/selectolax/baseStruct.j2 +38 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/selectolax/dictStruct.j2 +39 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/selectolax/itemStruct.j2 +36 -0
- ssc_codegen-0.2.0/ssc_codegen/templates/python/selectolax/listStruct.j2 +43 -0
- ssc_codegen-0.2.0/ssc_codegen/validate.py +84 -0
- ssc_codegen-0.1.13/PKG-INFO +0 -293
- ssc_codegen-0.1.13/README.md +0 -268
- ssc_codegen-0.1.13/ssc_codegen/analyzer.py +0 -309
- ssc_codegen-0.1.13/ssc_codegen/cli.py +0 -119
- ssc_codegen-0.1.13/ssc_codegen/configs/__init__.py +0 -0
- ssc_codegen-0.1.13/ssc_codegen/configs/codegen_tools.py +0 -300
- ssc_codegen-0.1.13/ssc_codegen/configs/dart/__init__.py +0 -0
- ssc_codegen-0.1.13/ssc_codegen/configs/dart/dart_html.j2 +0 -98
- ssc_codegen-0.1.13/ssc_codegen/configs/dart/dart_html.py +0 -254
- ssc_codegen-0.1.13/ssc_codegen/configs/python/__init__.py +0 -0
- ssc_codegen-0.1.13/ssc_codegen/configs/python/python_any.j2 +0 -75
- ssc_codegen-0.1.13/ssc_codegen/configs/python/python_bs4.py +0 -202
- ssc_codegen-0.1.13/ssc_codegen/configs/python/python_parsel.py +0 -185
- ssc_codegen-0.1.13/ssc_codegen/exceptions.py +0 -28
- ssc_codegen-0.1.13/ssc_codegen/lexer.py +0 -216
- ssc_codegen-0.1.13/ssc_codegen/objects.py +0 -259
- ssc_codegen-0.1.13/ssc_codegen/parser.py +0 -88
- ssc_codegen-0.1.13/ssc_codegen/render.py +0 -37
- ssc_codegen-0.1.13/ssc_codegen/template_utils.py +0 -78
- ssc_codegen-0.1.13/ssc_codegen/tools.py +0 -36
- ssc_codegen-0.1.13/ssc_codegen/yaml_parser.py +0 -149
- {ssc_codegen-0.1.13 → ssc_codegen-0.2.0}/LICENSE +0 -0
- {ssc_codegen-0.1.13/ssc_codegen → ssc_codegen-0.2.0/ssc_codegen/converters}/__init__.py +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ssc_codegen
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: generate selector schemas classes from dsl-like language based on python
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: vypivshiy
|
|
7
|
+
Requires-Python: >=3.10,<4.0
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
|
+
Classifier: Topic :: Internet
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Text Processing
|
|
19
|
+
Requires-Dist: Jinja2 (>=3.1.2,<4.0.0)
|
|
20
|
+
Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
|
|
21
|
+
Requires-Dist: cssselect (>=1.2.0,<2.0.0)
|
|
22
|
+
Requires-Dist: lxml (>=4.9.3,<5.0.0)
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Selector schema codegen
|
|
26
|
+
|
|
27
|
+
ssc_codegen - generator of parsers for various programming languages (for html priority) using
|
|
28
|
+
python-DSL configurations with built-in declarative language.
|
|
29
|
+
|
|
30
|
+
Designed to port parsers to various programming languages and libs
|
|
31
|
+
|
|
32
|
+
# Motivation
|
|
33
|
+
- ~~interesting in practice write DSL-like language~~
|
|
34
|
+
- decrease boilerplate code for web-parsers
|
|
35
|
+
- write once - convert to other mainstream http parser libs
|
|
36
|
+
- minimal operations for easy add another libs and languages in future
|
|
37
|
+
- include css, xpath, attributes operations, regex, minimal string formatting operations
|
|
38
|
+
- pre validate css/xpath queries and logic before generate code
|
|
39
|
+
- standardisation: generate classes with minimal dependencies and documented parsed signature
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
### pipx (recommended for CLI usage)
|
|
44
|
+
|
|
45
|
+
```shell
|
|
46
|
+
pipx install ssc_codegen
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### pip
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
pip install ssc_codegen
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Supported libs and languages
|
|
56
|
+
|
|
57
|
+
| language | lib | xpath | css | formatter |
|
|
58
|
+
|----------|--------------------------------------------------------------|-------|-----|-------------|
|
|
59
|
+
| python | bs4 | NO | YES | black |
|
|
60
|
+
| - | parsel | YES | YES | - |
|
|
61
|
+
| - | selectolax (modest) | NO | YES | - |
|
|
62
|
+
| - | scrapy (based on parsel, but class init argument - Response) | YES | YES | - |
|
|
63
|
+
| dart | universal_html | NO | YES | dart format |
|
|
64
|
+
|
|
65
|
+
### Quickstart
|
|
66
|
+
|
|
67
|
+
see [example](example) and read code with comments
|
|
68
|
+
|
|
69
|
+
### Recommendations
|
|
70
|
+
|
|
71
|
+
- usage css selector: they can be **guaranteed** converted to xpath (if target language not support CSS selectors)
|
|
72
|
+
- usage simple operations for more compatibility other libraries.
|
|
73
|
+
- Some libraries may not fully support selector specifications
|
|
74
|
+
- for example, `#product_description+ p` selector in `parsel` works fine, but not works in `selectolax`, `dart` libs
|
|
75
|
+
- there is a xpath to css converter for simple queries **without guarantees of functionality**.
|
|
76
|
+
For example, in css there is no analogue of `contains` from xpath, etc.
|
|
77
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Selector schema codegen
|
|
2
|
+
|
|
3
|
+
ssc_codegen - generator of parsers for various programming languages (for html priority) using
|
|
4
|
+
python-DSL configurations with built-in declarative language.
|
|
5
|
+
|
|
6
|
+
Designed to port parsers to various programming languages and libs
|
|
7
|
+
|
|
8
|
+
# Motivation
|
|
9
|
+
- ~~interesting in practice write DSL-like language~~
|
|
10
|
+
- decrease boilerplate code for web-parsers
|
|
11
|
+
- write once - convert to other mainstream http parser libs
|
|
12
|
+
- minimal operations for easy add another libs and languages in future
|
|
13
|
+
- include css, xpath, attributes operations, regex, minimal string formatting operations
|
|
14
|
+
- pre validate css/xpath queries and logic before generate code
|
|
15
|
+
- standardisation: generate classes with minimal dependencies and documented parsed signature
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
### pipx (recommended for CLI usage)
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pipx install ssc_codegen
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### pip
|
|
26
|
+
|
|
27
|
+
```shell
|
|
28
|
+
pip install ssc_codegen
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Supported libs and languages
|
|
32
|
+
|
|
33
|
+
| language | lib | xpath | css | formatter |
|
|
34
|
+
|----------|--------------------------------------------------------------|-------|-----|-------------|
|
|
35
|
+
| python | bs4 | NO | YES | black |
|
|
36
|
+
| - | parsel | YES | YES | - |
|
|
37
|
+
| - | selectolax (modest) | NO | YES | - |
|
|
38
|
+
| - | scrapy (based on parsel, but class init argument - Response) | YES | YES | - |
|
|
39
|
+
| dart | universal_html | NO | YES | dart format |
|
|
40
|
+
|
|
41
|
+
### Quickstart
|
|
42
|
+
|
|
43
|
+
see [example](example) and read code with comments
|
|
44
|
+
|
|
45
|
+
### Recommendations
|
|
46
|
+
|
|
47
|
+
- usage css selector: they can be **guaranteed** converted to xpath (if target language not support CSS selectors)
|
|
48
|
+
- usage simple operations for more compatibility other libraries.
|
|
49
|
+
- Some libraries may not fully support selector specifications
|
|
50
|
+
- for example, `#product_description+ p` selector in `parsel` works fine, but not works in `selectolax`, `dart` libs
|
|
51
|
+
- there is a xpath to css converter for simple queries **without guarantees of functionality**.
|
|
52
|
+
For example, in css there is no analogue of `contains` from xpath, etc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ssc_codegen"
|
|
3
|
-
version = "0.
|
|
4
|
-
description = "generate selector schemas classes from
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "generate selector schemas classes from dsl-like language based on python"
|
|
5
5
|
authors = ["vypivshiy"]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "MIT"
|
|
@@ -17,6 +17,18 @@ classifiers = [
|
|
|
17
17
|
"Topic :: Text Processing"
|
|
18
18
|
]
|
|
19
19
|
|
|
20
|
+
[tool.poetry.group.dev.dependencies]
|
|
21
|
+
bs4 = "^0.0.2"
|
|
22
|
+
selectolax = "^0.3.20"
|
|
23
|
+
parsel = "^1.8.1"
|
|
24
|
+
pytest = "^8.0.0"
|
|
25
|
+
mypy = "^1.6.1"
|
|
26
|
+
black = "^23.10.1"
|
|
27
|
+
isort = "^5.12.0"
|
|
28
|
+
ruff = "^0.1.4"
|
|
29
|
+
pre-commit = "^3.5.0"
|
|
30
|
+
scrapy = "^2.11.0"
|
|
31
|
+
|
|
20
32
|
[project.urls]
|
|
21
33
|
Documentation = "https://github.com/vypivshiy/selector_schema_codegen#readme"
|
|
22
34
|
Issues = "https://github.com/vypivshiy/selector_schema_codegen/issues"
|
|
@@ -30,16 +42,9 @@ Jinja2 = "^3.1.2"
|
|
|
30
42
|
cssselect = "^1.2.0"
|
|
31
43
|
lxml = "^4.9.3"
|
|
32
44
|
|
|
33
|
-
[tool.poetry.dev-dependencies]
|
|
34
|
-
mypy = "^1.6.1"
|
|
35
|
-
black = "^23.10.1"
|
|
36
|
-
isort = "^5.12.0"
|
|
37
|
-
ruff = "^0.1.4"
|
|
38
|
-
pre-commit = "^3.5.0"
|
|
39
|
-
pytest = "^7.4.3"
|
|
40
45
|
|
|
41
46
|
[tool.poetry.scripts]
|
|
42
|
-
ssc-gen="ssc_codegen.
|
|
47
|
+
ssc-gen="ssc_codegen._cli:main"
|
|
43
48
|
|
|
44
49
|
[build-system]
|
|
45
50
|
requires = ["poetry-core>=1.0.0"]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import NamedTuple
|
|
4
|
+
import argparse
|
|
5
|
+
import importlib.util
|
|
6
|
+
|
|
7
|
+
from ssc_codegen import render_code
|
|
8
|
+
from ssc_codegen.converters import py_scrapy, py_bs4, py_parsel, py_selectolax, dart_universal_html
|
|
9
|
+
from ssc_codegen.schemas import BaseSchemaStrategy
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_CONVERTER_NAMESPACES = {
|
|
13
|
+
"py.bs4": py_bs4.converter,
|
|
14
|
+
"py.parsel": py_parsel.converter,
|
|
15
|
+
"py.selectolax": py_selectolax.converter,
|
|
16
|
+
"py.scrapy": py_scrapy.converter,
|
|
17
|
+
"dart": dart_universal_html.converter,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_EXT_PYTONIC = {"py.bs4", "py.parsel", "py.selectolax", "py.scrapy"}
|
|
22
|
+
_EXT_DART = {"dart", }
|
|
23
|
+
|
|
24
|
+
# formatters
|
|
25
|
+
_FMT_DART = "dart format {}"
|
|
26
|
+
_FMT_PYTHON = "black {}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ArgsNamespace(NamedTuple):
|
|
30
|
+
scenario: str
|
|
31
|
+
lang: str
|
|
32
|
+
out: str
|
|
33
|
+
OVERWRITE: bool
|
|
34
|
+
XPATH_TO_CSS: bool
|
|
35
|
+
CSS_TO_XPATH: bool
|
|
36
|
+
XPATH_PREFIX: str
|
|
37
|
+
NO_FORMAT: bool
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_arguments() -> ArgsNamespace:
|
|
41
|
+
parser = argparse.ArgumentParser(
|
|
42
|
+
prog="Selector schema generator",
|
|
43
|
+
description="Generate selector schemas from config file",
|
|
44
|
+
usage="ssc-gen my_conf.py py.bs4 -o out_file",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
parser.add_argument("scenario", help="ssc_gen python file")
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"lang",
|
|
50
|
+
choices=list(_CONVERTER_NAMESPACES.keys()),
|
|
51
|
+
help="Programming language and lib choice",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"-o",
|
|
56
|
+
"--out",
|
|
57
|
+
default=f"schema.{{}}",
|
|
58
|
+
help="Output directory (default: current working directory/schema.<ext>)",
|
|
59
|
+
)
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"-y",
|
|
62
|
+
dest="OVERWRITE",
|
|
63
|
+
default=False,
|
|
64
|
+
action="store_true",
|
|
65
|
+
help="Suggest overwrite file",
|
|
66
|
+
)
|
|
67
|
+
parser.add_argument("--xpath-to-css",
|
|
68
|
+
dest="XPATH_TO_CSS",
|
|
69
|
+
default=False,
|
|
70
|
+
action="store_true",
|
|
71
|
+
help="Convert xpath selectors to css (work not guaranteed)")
|
|
72
|
+
|
|
73
|
+
parser.add_argument("--css-to-xpath",
|
|
74
|
+
dest="CSS_TO_XPATH",
|
|
75
|
+
default=False,
|
|
76
|
+
action="store_true",
|
|
77
|
+
help="convert css selectors to xpath")
|
|
78
|
+
parser.add_argument("--xpath-prefix",
|
|
79
|
+
dest="XPATH_PREFIX",
|
|
80
|
+
default='descendant-or-self::',
|
|
81
|
+
type=str,
|
|
82
|
+
help="Xpath prefix for --css-to-xpath autoconverter. Default `descendant-or-self::`")
|
|
83
|
+
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"--no-format",
|
|
86
|
+
dest="NO_FORMAT",
|
|
87
|
+
default=False,
|
|
88
|
+
action="store_true",
|
|
89
|
+
help="Disable code format by third party solutions",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
namespace: ArgsNamespace = parser.parse_args() # type: ignore
|
|
93
|
+
return namespace
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _extract_schemas(path: str):
|
|
97
|
+
spec = importlib.util.spec_from_file_location("script_module", path)
|
|
98
|
+
module = importlib.util.module_from_spec(spec)
|
|
99
|
+
spec.loader.exec_module(module)
|
|
100
|
+
schemas: list[BaseSchemaStrategy] = []
|
|
101
|
+
# Check if __all__ is defined in the module
|
|
102
|
+
if hasattr(module, '__all__'):
|
|
103
|
+
for obj_name in module.__all__:
|
|
104
|
+
obj = getattr(module, obj_name)
|
|
105
|
+
if issubclass(obj, BaseSchemaStrategy):
|
|
106
|
+
print("Founded", f"'{obj.__name__}'")
|
|
107
|
+
schemas.append(obj())
|
|
108
|
+
else:
|
|
109
|
+
print("Not founded objects, exit")
|
|
110
|
+
exit(1)
|
|
111
|
+
|
|
112
|
+
if len(schemas) == 0:
|
|
113
|
+
print("Not founded schemas, exit")
|
|
114
|
+
exit(1)
|
|
115
|
+
|
|
116
|
+
return schemas
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _suggest_overwrite(path_out: str, overwrite: bool):
|
|
120
|
+
if Path(path_out).exists() and not overwrite:
|
|
121
|
+
choice = input("Overwrite? (y/n)? ")
|
|
122
|
+
if choice.lower() != "y":
|
|
123
|
+
print("Cancel operation")
|
|
124
|
+
exit(1)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _file_out(out: str, lang: str):
|
|
128
|
+
if out == "schema.{}":
|
|
129
|
+
if lang in _EXT_PYTONIC:
|
|
130
|
+
ext = "py"
|
|
131
|
+
elif lang in _EXT_DART:
|
|
132
|
+
ext = "dart"
|
|
133
|
+
else:
|
|
134
|
+
print("not founded extension, exit")
|
|
135
|
+
exit(1)
|
|
136
|
+
return out.format(ext)
|
|
137
|
+
return out
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main():
|
|
141
|
+
args = parse_arguments()
|
|
142
|
+
if args.CSS_TO_XPATH and args.XPATH_TO_CSS:
|
|
143
|
+
print('Should be choice --css-to-xpath or --xpath-to-css')
|
|
144
|
+
exit(1)
|
|
145
|
+
|
|
146
|
+
converter = _CONVERTER_NAMESPACES.get(args.lang)
|
|
147
|
+
print(f"Load '{args.lang}' converter")
|
|
148
|
+
schemas = _extract_schemas(args.scenario)
|
|
149
|
+
output = _file_out(args.out, args.lang)
|
|
150
|
+
_suggest_overwrite(output, args.OVERWRITE)
|
|
151
|
+
|
|
152
|
+
print("Render code")
|
|
153
|
+
if args.CSS_TO_XPATH:
|
|
154
|
+
print(F"convert CSS to XPATH with prefix '{args.XPATH_PREFIX}'")
|
|
155
|
+
elif args.XPATH_TO_CSS:
|
|
156
|
+
print(f"convert XPATH to CSS")
|
|
157
|
+
|
|
158
|
+
code = render_code(converter,
|
|
159
|
+
*schemas,
|
|
160
|
+
css_to_xpath=args.CSS_TO_XPATH,
|
|
161
|
+
xpath_to_css=args.XPATH_TO_CSS,
|
|
162
|
+
xpath_prefix=args.XPATH_PREFIX)
|
|
163
|
+
print(f"Save to {output}")
|
|
164
|
+
Path(output).write_text(code)
|
|
165
|
+
if not args.NO_FORMAT:
|
|
166
|
+
print("Format code...")
|
|
167
|
+
if args.lang.startswith('py.'):
|
|
168
|
+
subprocess.call(_FMT_PYTHON.format(output), shell=True)
|
|
169
|
+
elif args.lang == "dart":
|
|
170
|
+
subprocess.call(_FMT_DART.format(output), shell=True)
|
|
171
|
+
print("done.")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if __name__ == '__main__':
|
|
175
|
+
main()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
|
|
3
|
+
from ssc_codegen.objects import TokenType, Node
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
__all__ = ['CodeConverter', "VAR_L", "VAR_R"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def var_left(node: Node, prefix: str) -> str:
|
|
10
|
+
"""get next variable name"""
|
|
11
|
+
return prefix.format(node.id or 0)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def var_right(node: Node, prefix: str) -> str:
|
|
15
|
+
"""get previous variable name"""
|
|
16
|
+
return prefix.format(node.prev_node.id or 0)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Shortcuts hooks variable name
|
|
20
|
+
VAR_L = partial(var_left, prefix='var_{}')
|
|
21
|
+
VAR_R = partial(var_right, prefix='var_{}')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CodeConverter:
|
|
25
|
+
"""Translate Expressions into the parser code"""
|
|
26
|
+
|
|
27
|
+
def __init__(self,
|
|
28
|
+
indent: str = " " * 4,
|
|
29
|
+
end: str = "",
|
|
30
|
+
intent_inner_try: str = " " * 4 * 2,
|
|
31
|
+
templates_path: str = ""):
|
|
32
|
+
|
|
33
|
+
self.indent = indent
|
|
34
|
+
self.end = end
|
|
35
|
+
self.indent_inner_try = intent_inner_try
|
|
36
|
+
self.definitions: Dict[TokenType, Callable[[Node], str]] = {} # type: ignore
|
|
37
|
+
self._templates_path: str = templates_path
|
|
38
|
+
|
|
39
|
+
self._in_inner_try: bool = False
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def templates_path(self) -> str:
|
|
43
|
+
return self._templates_path
|
|
44
|
+
|
|
45
|
+
def __call__(self, for_definition: TokenType):
|
|
46
|
+
def decorator(func):
|
|
47
|
+
self.definitions[for_definition] = func
|
|
48
|
+
return func
|
|
49
|
+
|
|
50
|
+
return decorator
|
|
51
|
+
|
|
52
|
+
def convert(self, node: Node) -> str:
|
|
53
|
+
if callback := self.definitions.get(node.token):
|
|
54
|
+
if node.token == TokenType.OP_DEFAULT_START:
|
|
55
|
+
self._in_inner_try = True
|
|
56
|
+
return self.indent + callback(node)
|
|
57
|
+
|
|
58
|
+
elif node.token == TokenType.OP_DEFAULT_END:
|
|
59
|
+
self._in_inner_try = False
|
|
60
|
+
return self.indent + callback(node)
|
|
61
|
+
|
|
62
|
+
if self._in_inner_try:
|
|
63
|
+
return self.indent_inner_try + callback(node) + self.end
|
|
64
|
+
return self.indent + callback(node) + self.end
|
|
65
|
+
return ""
|