openscad-pyoptimizer/src/openscad_pycustomizer/scad_parser.py
2021-08-16 23:28:31 +01:00

168 lines
3.6 KiB
Python

import dataclasses
from dataclasses import dataclass
import json
"""
Types that must be supported:
* int
* float
* string
* bool
* list
"""
@dataclass
class Element:
pass
@dataclass
class Variable(Element):
text: str
value: str
description: str
@dataclass
class IntVariable(Variable):
value: int
@dataclass
class FloatVariable(Variable):
value: float
@dataclass
class StringVariable(Variable):
value: str
@dataclass
class BoolVariable(Variable):
value: bool
@dataclass
class Section(Element):
text: str
elements: list[Element]
@dataclass
class CustomizerData:
elements: list[Element]
@staticmethod
def flatten(data):
"""
Return a list of parameters
"""
elems = {}
for elem in data.elements:
if isinstance(elem, Section):
for param in elem.elements:
elems[param.text] = param.value
else:
elems[elem.text] = elem.value
return elems
class EnhancedJSONEncoder(json.JSONEncoder):
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
return super().default(o)
class CustomizerProfileEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, CustomizerData):
return CustomizerData.flatten(o)
return super().default(o)
def parse_type(value):
# Parse type
if ((value[0] == "\"" or value[0] == "'")
and (value[-1] == "\"" or value[-1] == "'")):
value = value.strip("\"").strip("'")
elif value == "true" or value == "false":
value = bool(value)
elif value[0] == "[" and value[-1] == "]":
value = value[1:-2].split(",")
for index in range(len(value)):
value[index] = parse_type(value[index])
elif len(value.split(".")):
value = float(value)
else:
value = int(value)
return value
def parse(file):
with open(file) as scad_file:
section = None
all_elems = []
elems = []
description = None
for line in scad_file.readlines():
line = line.strip()
# Checking for section title
if line[0:2] == "/*":
(middle, end) = line[2:].strip().split("*/")
middle = middle.strip()
if section is None:
all_elems.extend(elems)
else:
all_elems.append(Section(section, elems))
section = middle
elems = []
# Checking for comment
elif line[0:2] == "//":
description = line[2:].strip()
# Checking for text
elif len(line.strip()) > 0 and len(line.split("=")) == 2:
(name, value) = line.split("=")
name = name.strip()
value = value.split(";")[0].strip()
try:
value = parse_type(value)
except ValueError as e:
print(f"Error parsing a value: {e}")
print("Stopping parsing")
break
elems.append(
Variable(
name,
value,
"" if description is None else description
)
)
description = None
elif len(line) == 0:
pass
else:
break
all_elems.append(Section(section, elems))
data = CustomizerData(all_elems)
return data