You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.4 KiB
107 lines
2.4 KiB
import pprint |
|
from dataclasses import dataclass |
|
from typing import List, Tuple |
|
|
|
from sly import Lexer, Parser |
|
|
|
|
|
@dataclass |
|
class Vertex: |
|
coords: Tuple[float, float, float] |
|
|
|
def __repr__(self): |
|
return "VERTEX(%f,%f,%f)" % self.coords |
|
|
|
|
|
@dataclass |
|
class Facet: |
|
vertices: Tuple[Vertex, Vertex, Vertex] |
|
normal: Vertex |
|
|
|
def __repr__(self): |
|
return "\t FACET({normal})\n\t\t{vertices}".format( |
|
normal=repr(self.normal), |
|
vertices="\n\t\t".join(repr(vertex) for vertex in self.vertices) |
|
) |
|
|
|
|
|
@dataclass |
|
class Solid: |
|
name: str |
|
facets: List[Facet] |
|
|
|
def __repr__(self): |
|
return "SOLID({name})\n{facets}\n".format( |
|
name=self.name, |
|
facets="\n".join(repr(facet) for facet in self.facets) |
|
) |
|
|
|
|
|
class STLLexer(Lexer): |
|
tokens = {"SOLID_START", "SOLID_END", |
|
"FACET_START", "FACET_END", "NAME_LITERAL", |
|
"LOOP_START", "LOOP_END", |
|
"NAME_LITERAL", "VERTEX_TAG", "FLOAT"} |
|
|
|
@_(r"[ \t\n]+") |
|
def ignore_whitespace(self, t): |
|
self.lineno += t.value.count("\n") |
|
|
|
SOLID_START = r"solid" |
|
SOLID_END = r"endsolid" |
|
FACET_START = r"facet normal" |
|
FACET_END = r"endfacet" |
|
LOOP_START = r"outer loop" |
|
LOOP_END = r"endloop" |
|
VERTEX_TAG = r"vertex" |
|
|
|
@_("[+-]?\d+(\.\d*(e[+-]?\d+)?)?") |
|
def FLOAT(self, t): |
|
t.value = float(t.value) |
|
return t |
|
|
|
NAME_LITERAL = r"\w+" |
|
|
|
|
|
class STLParser(Parser): |
|
tokens = STLLexer.tokens |
|
start = "stl" |
|
|
|
@_("solid") |
|
def stl(self, p): |
|
return p.solid |
|
|
|
@_("SOLID_START NAME_LITERAL { facet } SOLID_END") |
|
@_("SOLID_START NAME_LITERAL { facet } SOLID_END NAME_LITERAL") |
|
def solid(self, p): |
|
return Solid(name=p[1], facets=p.facet) |
|
|
|
@_("FACET_START triplet loop FACET_END") |
|
def facet(self, p): |
|
return Facet(vertices=p.loop, normal=Vertex(p.triplet)) |
|
|
|
@_("LOOP_START vertex vertex vertex LOOP_END") |
|
def loop(self, p): |
|
return p[1], p[2], p[3] |
|
|
|
@_("VERTEX_TAG triplet") |
|
def vertex(self, p): |
|
return Vertex(p.triplet) |
|
|
|
@_("FLOAT FLOAT FLOAT") |
|
def triplet(self, p): |
|
return p[0], p[1], p[2] |
|
|
|
def error(self, token): |
|
pass |
|
|
|
|
|
if __name__ == "__main__": |
|
lexer = STLLexer() |
|
parser = STLParser() |
|
|
|
with open("star.stl") as stl_file: |
|
# pprint.pprint(list(lexer.tokenize(stl_file.read()))) |
|
solid = parser.parse(lexer.tokenize(stl_file.read())) |
|
|
|
print(solid) |